Lifecycle
Create a session
Run an agent on a task.
POST
/
api
/
v2
/
sessions
# `holo run` creates the session and blocks until the agent answers
holo run "Find the best-rated sushi restaurants in San Francisco" \
--agent h/web-surfer-flash
from hai_agents import Client
client = Client()
session = client.sessions.create_session(
agent="h/web-surfer-flash",
messages="Find the best-rated sushi restaurants in San Francisco",
)
print(session.id)
import { HaiAgentsClient } from "hai-agents";
const client = new HaiAgentsClient();
const session = await client.sessions.createSession({
body: {
agent: "h/web-surfer-flash",
messages: "Find the best-rated sushi restaurants in San Francisco",
},
});
console.log(session.id);
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "h/web-surfer-flash",
"messages": [
{"type": "user_message", "message": "Find the best-rated sushi restaurants in San Francisco"}
]
}'
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"request": {
"agent": {"name": "h/web-surfer-flash", "model": "holo4-35b-a3b", "...": "..."},
"messages": [
{"type": "user_message", "message": "Find the best-rated sushi restaurants in San Francisco"}
],
"...": "..."
},
"status": {
"status": "pending",
"error": null,
"error_code": null,
"outcome": null,
"steps": 0,
"usage_per_model": [],
"subagent_session_ids": []
},
"agent_view_url": "https://platform.hcompany.ai/agents/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"latest_answer": null,
"created_at": "2026-05-07T14:30:00Z",
"started_at": null,
"finished_at": null
}
Behavior
With a free slot, the session startspending and moves to running once the agent launches. Above your concurrency limit it is accepted as queued and starts when a slot frees up (set queue: false to get a 429 instead).
Headers
string
Optional idempotency key (1 to 255 characters). Safe retry within 24 hours: the same key returns the original session. Reusing it with a different body returns
422.Request body
string | object
required
A catalog identifier (for example A catalog ID runs the agent’s latest revision. Append
"h/web-surfer-flash") or an inline agent, which follows the same rules: environments is required (at most one per kind) and may be [] only with subagents or custom tools. The session reads environments, skills, and subagents from the agent."agent": "h/web-surfer-flash"
:N to run a fixed one, for example "agent": "my-research-bot:3"."agent": {
"name": "weather-agent",
"description": "Looks up weather by city",
"environments": [
{
"id": "browser",
"kind": "web",
"mode": {"type": "visual", "width": 1280, "height": 720},
"start_url": "https://www.bing.com/"
}
]
}
string | object | object[]
The initial task, queued before the agent’s first step: a plain string (one user message), one message object, or a list.
"messages": [
{"type": "user_message", "message": "Book a flight from Paris to Tokyo on June 15"}
]
string
"user_message", the default.string
required
The instruction or task.
string[]
Base64 data URIs to attach (for example
data:image/png;base64,...).object[]
Files to attach, up to 10 and 7 MB in total. Each is
{ name, source, type: "base64", media_type? } (media_type is guessed if omitted). Saved under files/ in a code sandbox workspace, and ~/Downloads on a cloud browser.string
The sender. Defaults to
user. Leave it unset for normal user input.object[]
Skills for this message only, as inline skill objects.
string | null
IANA timezone the agent uses for dates and times, for example
"Europe/Paris". null or omitted means UTC. An unknown name returns 422. Child sessions a manager spawns inherit it.integer
Cap on steps, where each step is one decide-and-act cycle. Minimum
1. At the cap the agent is asked for a final answer from what it has so far (it is not hard-killed). Omit to run uncapped.number
Cap on wall-clock seconds per answer, greater than
0. Idle time between answers doesn’t count. At the cap, as with max_steps, the agent is asked for a final answer. If it is still running 60 seconds later, the session ends failed, not timed_out, with error_code timeout. Omit to run uncapped.integer
Switches between one-shot and interactive. Leave it
null for a one-shot task: the session ends when the agent answers. Set it (seconds, greater than 0) to keep the session open for follow-up messages: after each answer the session goes idle and waits this long for your next message. At your concurrency limit, a session idle for 120 seconds can end sooner to make room for your next one.integer | null
Minutes after the session finishes before it is deleted, with its events and screenshots. Minimum
1. Omit it to keep the session for the retention period in your privacy settings. A value deletes it sooner. null adds no expiry beyond that period.integer | null
Minutes after the session finishes before its screenshots are deleted, to expire visual data sooner than the session. Minimum
1. Omit it or pass null to keep screenshots as long as the session.boolean
default:"true"
At your concurrency limit, accept the session as
queued instead of rejecting it with 429. Queued sessions don’t count against your quota and start oldest first as running sessions finish. Set false to fail fast.string
Tag for grouping related sessions. Filter on it with
GET /sessions?group_id=....string
Parent session ID, for subagent sessions. The parent’s status lists this session in
subagent_session_ids. Child sessions never queue: at capacity the create fails with 429 even when queue is true, since a child queued behind its own parent would deadlock it.object
Per-session tweaks applied after the agent (and its environments, skills, and subagents) are resolved, so you can adjust a catalog agent for one session. Each key is a path into the resolved request, and its value replaces what the path points to:
- Dots walk into objects:
agent.instructions,agent.model,agent.answer_format(structured answer). [field=value]picks a list member:agent.environments[kind=web].start_url,agent.environments[kind=web].mode.
422 at creation, before the agent runs."overrides": {
"agent.environments[kind=web].start_url": "https://www.bing.com/",
"agent.answer_format": {
"type": "object",
"properties": {"price": {"type": "number"}},
"required": ["price"]
}
}
Response
201 with the created session object, status pending or queued.
# `holo run` creates the session and blocks until the agent answers
holo run "Find the best-rated sushi restaurants in San Francisco" \
--agent h/web-surfer-flash
from hai_agents import Client
client = Client()
session = client.sessions.create_session(
agent="h/web-surfer-flash",
messages="Find the best-rated sushi restaurants in San Francisco",
)
print(session.id)
import { HaiAgentsClient } from "hai-agents";
const client = new HaiAgentsClient();
const session = await client.sessions.createSession({
body: {
agent: "h/web-surfer-flash",
messages: "Find the best-rated sushi restaurants in San Francisco",
},
});
console.log(session.id);
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "h/web-surfer-flash",
"messages": [
{"type": "user_message", "message": "Find the best-rated sushi restaurants in San Francisco"}
]
}'
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"request": {
"agent": {"name": "h/web-surfer-flash", "model": "holo4-35b-a3b", "...": "..."},
"messages": [
{"type": "user_message", "message": "Find the best-rated sushi restaurants in San Francisco"}
],
"...": "..."
},
"status": {
"status": "pending",
"error": null,
"error_code": null,
"outcome": null,
"steps": 0,
"usage_per_model": [],
"subagent_session_ids": []
},
"agent_view_url": "https://platform.hcompany.ai/agents/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"latest_answer": null,
"created_at": "2026-05-07T14:30:00Z",
"started_at": null,
"finished_at": null
}
More examples
With idempotency key
session = client.sessions.create_session(
agent="h/web-surfer-flash",
messages="Search for direct flights from CDG to NRT on June 15",
idempotency_key="my-unique-key-123",
)
const session = await client.sessions.createSession({
idempotencyKey: "my-unique-key-123",
body: {
agent: "h/web-surfer-flash",
messages: "Search for direct flights from CDG to NRT on June 15",
},
});
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-unique-key-123" \
-d '{
"agent": "h/web-surfer-flash",
"messages": [
{"type": "user_message", "message": "Search for direct flights from CDG to NRT on June 15"}
]
}'
With an inline agent
Pass an inline agent instead of a catalog ID to set environments (or any other field) per session. Environments nest underagent.
session = client.sessions.create_session(
agent={
"name": "web-price-finder",
"description": "Web browsing agent with a custom browser config",
"environments": [
{
"id": "browser",
"kind": "web",
"mode": {"type": "visual", "width": 1280, "height": 720},
"start_url": "https://www.bing.com",
}
],
},
messages="Find the current price of the Framework 13 laptop and report the lowest you find",
)
const session = await client.sessions.createSession({
body: {
agent: {
name: "web-price-finder",
description: "Web browsing agent with a custom browser config",
environments: [
{
id: "browser",
kind: "web",
mode: { type: "visual", width: 1280, height: 720 },
startUrl: "https://www.bing.com",
},
],
},
messages: "Find the current price of the Framework 13 laptop and report the lowest you find",
},
});
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": {
"name": "web-price-finder",
"description": "Web browsing agent with a custom browser config",
"environments": [
{"id": "browser", "kind": "web", "mode": {"type": "visual", "width": 1280, "height": 720}, "start_url": "https://www.bing.com"}
]
},
"messages": [
{"type": "user_message", "message": "Find the current price of the Framework 13 laptop and report the lowest you find"}
]
}'
Child session
A child session of a manager:session = client.sessions.create_session(
agent="h/web-surfer-flash",
parent_session_id=parent_session_id,
group_id="trip-planning-001",
messages="Find hotels near Shinjuku station under $150/night",
)
const session = await client.sessions.createSession({
body: {
agent: "h/web-surfer-flash",
parentSessionId,
groupId: "trip-planning-001",
messages: "Find hotels near Shinjuku station under $150/night",
},
});
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "h/web-surfer-flash",
"parent_session_id": "'"$PARENT_SESSION_ID"'",
"group_id": "trip-planning-001",
"messages": [
{"type": "user_message", "message": "Find hotels near Shinjuku station under $150/night"}
]
}'
Errors
| Status | Cause |
|---|---|
400 | The resolved request is invalid (for example an override producing an impossible configuration). |
403 | An environment kind that isn’t available publicly yet. detail[].type is environment_not_public. |
404 | The agent is not found, or not in your organization. |
409 | An Idempotency-Key from a still in-flight request was reused before it completed. Retry after Retry-After. |
410 | The agent pins a name:N revision whose stored spec fails current validation. |
422 | Body failed validation (for example an unknown timezone), or an Idempotency-Key was reused with a different body. |
429 | Concurrency quota exceeded with queue: false, the queue itself is full, or the create carries a parent_session_id while at capacity. detail[].type says which limit was hit. |
Was this page helpful?
⌘I
# `holo run` creates the session and blocks until the agent answers
holo run "Find the best-rated sushi restaurants in San Francisco" \
--agent h/web-surfer-flash
from hai_agents import Client
client = Client()
session = client.sessions.create_session(
agent="h/web-surfer-flash",
messages="Find the best-rated sushi restaurants in San Francisco",
)
print(session.id)
import { HaiAgentsClient } from "hai-agents";
const client = new HaiAgentsClient();
const session = await client.sessions.createSession({
body: {
agent: "h/web-surfer-flash",
messages: "Find the best-rated sushi restaurants in San Francisco",
},
});
console.log(session.id);
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "h/web-surfer-flash",
"messages": [
{"type": "user_message", "message": "Find the best-rated sushi restaurants in San Francisco"}
]
}'
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"request": {
"agent": {"name": "h/web-surfer-flash", "model": "holo4-35b-a3b", "...": "..."},
"messages": [
{"type": "user_message", "message": "Find the best-rated sushi restaurants in San Francisco"}
],
"...": "..."
},
"status": {
"status": "pending",
"error": null,
"error_code": null,
"outcome": null,
"steps": 0,
"usage_per_model": [],
"subagent_session_ids": []
},
"agent_view_url": "https://platform.hcompany.ai/agents/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"latest_answer": null,
"created_at": "2026-05-07T14:30:00Z",
"started_at": null,
"finished_at": null
}