Skip to content
Docs menu

agent

The hub's cloud agent (A1/A2) — a session works toward a goal with the hub's own tools and a sandboxed shell, as a short-lived key scoped below its creator's; spends past a pre-approved budget wait for a person, and everything it does is an append-only event stream.

14 operations · 28 schemas

GET /v1/agent/sessions

List agent sessions

listAgentSessions · scope key:read

Sessions visible to the caller (owner, creator, or a member of the owning org), newest first. No session is public.

Parameters

listAgentSessions parameters
NameInTypeDescription
statusqueryAgentSessionStatus
limitqueryinteger

default 20 · ≥ 1 · ≤ 100

Page size.

cursorquerystring

length ≤ 512

Opaque cursor from the previous page's next_cursor.

Responses

listAgentSessions responses
StatusDescriptionBody
200

Page of sessions.

AgentSessionPage
401

Missing or invalid credentials.

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/agent/sessions

Start an agent session (the hub's cloud agent works toward a goal)

createAgentSession · scope key:train

{goal, robot?, campaign?, budget_usd, cap_usd?, scopes?, owner?} → a session whose first turn is queued at once. The agent loop runs on the hub (one arq job per turn, state in Postgres): a frontier model behind the coach's model interface, extended with tool use, calls the hub's MCP tools in-process as the session's own short-lived key and, where the deployment configures one, a Modal sandbox shell whose network reaches only the hub.

Keys. The hub mints a key for every turn, bound to the session (api_keys.agent_session_id), expiring on its own and revoked when the turn yields or the session ends. Its scope is the one the session was granted — scopes, never above the creator's own — and no agent key can call a session-scoped operation, approve its own spend (resolveAgentApproval is 403 to every agent key), create another session, or approve a device handoff.

Money. Two numbers. budget_usd is the spend a person pre-approves for the tools that cost money (submit_training on a priced executor, a Modal rollout_in_sim, serve_model on Modal, plan_task, the coach's two paid tools): inside it the tool runs and says so; above it the session pauses with an approval_requested event (waiting_on_you) until a person answers. cap_usd (default $10) caps the session's own model + sandbox spend. The model is billed at list price with 0 % markup — each call reserves count_tokens + max_tokens first and settles on the reported usage, cache fields included; the next call is refused at the cap. The sandbox is billed at Modal's sandbox rate × 1.28, only while active. Every call and every sandbox interval is one ledger_entries row. Until a payment system exists every account (an org shares one) gets a $5 monthly allowance for model + sandbox and nothing beyond it: 402 when it is spent. On the allowance only claude-sonnet-5 is offered. AG1: an account may run up to AGENT_MAX_LIVE_SESSIONS (3) working sessions at once — running, waiting on an event or waiting on you; a sleeping session does not count — and a fourth is 409 naming the three (A1's one-live-session rule is lifted; the money caps are unchanged).

Plan first (AG1, the founder's rule). Nothing billable runs before a person approves a plan: the agent's first move on a task that needs compute is a plan (listAgentPlans), and until one is approved every training run, round, rollout, render, endpoint and M16 plan the agent asks for is refused — by its tools and, for its key, by the hub's own routes. Model turns may run, and a session that only answers a question needs no plan.

Context (K3). context[] names the hub objects a session starts with ("Ask the agent about this model"): each one is checked as the caller (missing, private and the wrong kind are one 422 at context[i]), stored on the session, and handed to the model on its first turn as a compact summary built from the hub's own reads — a notice event (code: context) the page shows too.

Spends model dollars: key:train.

Request body

application/json · required · AgentSessionCreate

createAgentSession request body
FieldTypeDescription
goalrequiredstring

length 1–8000

What the agent should achieve, in plain words.

robotstring | null

length ≤ 160

owner/slug of a robot repo the goal is about. Validated like Recipe.robot: missing, private and malformed are one 422.

campaignstring | null

length ≤ 64

A campaign (C3) the session works inside, by id or slug. C3b: it must be an active campaign of the session's owner that the creator can see (422 otherwise), and it is resolved on every spending call: a round the agent proposes INTO this campaign is auto-approved only when its cap is at or under the campaign's per_run_limit_usd and fits in spend.remaining_usd; anything else waits for a person. Spends that are not this campaign's (a round of another campaign, a standalone run, a coach call) are judged by the workspace's rules, because the campaign's budget does not pay for them.

budget_usdnumber | null

≥ 0 · ≤ 1000

A total a person pre-approves for the session's spending tools (GPU training on a priced executor, a Modal rollout, a Modal endpoint, a plan, a coach call), on top of the per-run limit: a call is auto-approved only while every approved call's cap, this one's included, fits in it. Null: no session total — the per-run limit alone decides. 0: every spending call asks. Not the model or sandbox spend (that is cap_usd and the allowance).

auto_approve_per_run_usdnumber | null

≥ 0 · ≤ 1000

This session's per-call auto-approve limit, which may only LOWER the workspace's (AGENT_AUTO_APPROVE_PER_RUN_USD, $3.00): a spending call whose cap is above it asks a person. Inside a campaign the campaign's own rules apply instead. Null: the workspace's.

cap_usdnumber | null

> 0 · ≤ 1000

Cap on the session's own model + sandbox spend (AGENT_DEFAULT_CAP_USD, $10, when null). The next model call is refused at it.

modelstring | null

length ≤ 64

The model the loop runs on (AGENT_MODEL, claude-sonnet-5, when null). On the free allowance no other model is offered (422).

scopesarray of ApiKeyScope | null

items ≤ 3

Scopes the session's keys carry — the session acts with the highest one named, which may not exceed what the creating credential was granted (403 otherwise). Null: the creator's own.

ownerstring | null

length ≤ 64

Who the session is billed to: the creator (null) or an org handle the creator is a member of. The allowance and the working-session cap (AG1) are per owner.

sandboxboolean

default true

Offer the agent a sandbox shell (when the deployment configures one).

contextarray of AgentContextRef

items ≤ 8

K3 — hub objects the session starts with. Each is checked as the caller (422 at context[i] for missing, private or the wrong kind — never an existence oracle) and summarised for the model's first turn from the hub's own reads: a run's status, gate, config groups and checkpoint gates; a model's card, contract and the run that trained it; a robot's card and interface; a dataset's meta; a rollout's verdict.

Responses

createAgentSession responses
StatusDescriptionBody
201

Session created; its first turn is queued.

AgentSession
401

Missing or invalid credentials.

Problemapplication/problem+json
402

The account's monthly allowance for agent model + sandbox spend is used up.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json
503

A service this endpoint needs is not configured in this deployment (M0's boot guarantee: the API boots with zero secrets, and an endpoint that needs one says so instead of returning a stack trace).

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}

Get an agent session (status, spend, what it waits on, pending approvals)

getAgentSession · scope key:read

Everything a page needs beside the event stream: status and why, the three spend lines (model at list price, sandbox × 1.28, GPU committed from the budget), the allowance, what the agent waits on, the pending approvals, the sandbox's state, and last_event_id — where streamAgentEvents resumes. A session you may not see is 404.

Parameters

getAgentSession parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

Responses

getAgentSession responses
StatusDescriptionBody
200

The session.

AgentSession
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json

POST /v1/agent/sessions/{session_id}/messages

Send the agent a message (a user turn)

postAgentMessage · scope key:train

Appends a user message and queues a turn. AG1: a message wakes any session that is not canceled or failed — a sleeping one, a waiting_on_you one (a reply in words is how a person changes a proposed plan; the agent answers with a new version), a waiting_on_event one (it interrupts the wait) and a done one, which it reopens. On a running one it is handed to the model at its next step. 409 only on a canceled or failed session. A message never counts against the working-session cap. Spends model dollars: key:train; an agent's own key is 403.

Parameters

postAgentMessage parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

Request body

application/json · required · AgentMessageCreate

postAgentMessage request body
FieldTypeDescription
textrequiredstring

length 1–8000

Responses

postAgentMessage responses
StatusDescriptionBody
202

Message recorded; a turn is queued.

AgentSession
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}/events

Stream a session's events (SSE, resumable)

streamAgentEvents · scope key:read

Server-Sent Events from the session's append-only event table, in the order they were written. Every frame carries id: <event id> (a ULID), event: <kind> and data: <AgentEvent JSON>; a reconnecting EventSource sends Last-Event-ID and the stream resumes strictly after it (after does the same as a query parameter). With follow=true the stream stays open, sending : keepalive comments while nothing happens, until the session ends; event: end always closes it, with the session's status. Same shape as streamRunLogs. The kinds — message, tool_use, tool_result, terminal, approval_requested, approval_resolved, status, usage, sandbox, notice, error, and since AG1 plan, decision and round — and each one's data are AgentEvent's. Replaying the stream plus getAgentSession (and AG1's digest, objects and decisions) is everything the agent page needs.

Parameters

streamAgentEvents parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

followqueryboolean

default false

Keep the stream open until the session ends.

afterqueryId

Resume strictly after this event id (the Last-Event-ID header wins when both are sent).

Last-Event-IDheaderId

The id of the last event the client saw (sent by EventSource on reconnect).

Responses

streamAgentEvents responses
StatusDescriptionBody
200

SSE event stream.

stringtext/event-stream
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/agent/sessions/{session_id}/approvals/{approval_id}

Approve or deny a spend the agent asked for

resolveAgentApproval · scope key:train

A spend the rules do not allow — since AG1 any compute call outside the approved plan, whatever it costs, and a coach call over the per-run limit or the budget — is a spend decision (approval_requested); this answers it. AG1 made the wait non-blocking: the agent keeps working while it waits, and on approve its next turn runs the held call exactly as it was asked for (no longer a dry run) before anything else; deny tells it the call did not run and why. raise_budget_to approves this call and grants the session a standing allowance for the rest of its life: later compute calls whose caps fit in what is left of it run without asking (the rule reads session_grant), and the session's budget is raised to cover it. A call outside the approved plan is decided only by a signed-in person's session — the founder's rule that it asks a person, and a key is not a person: every API key is 403, the owner's train key included. A1's coach call over the per-run limit or the budget may still be decided by the owner's train key; every agent session key is 403 for everything, including this session's own — an agent never approves its own spend. 409 once the approval is decided or expired (expires_at, the session's window) or the session is canceled / failed.

Parameters

resolveAgentApproval parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

approval_idrequiredpathId

Agent spend approval id (aappr_...).

Request body

application/json · required · AgentApprovalDecision

resolveAgentApproval request body
FieldTypeDescription
decisionrequiredstring

one of approve · deny

notestring | null

length ≤ 1000

Shown to the agent with the decision.

raise_budget_tonumber | null

≥ 0 · ≤ 1000

AG1, approve only — "approve up to $X for the rest of the session": this call runs, and from now on compute calls whose caps fit in what is left of $X (this call's cap included) run without asking, even outside the plan; the session's budget_usd is raised to cover it. Must be at least this call's cap_usd (422 otherwise).

Responses

resolveAgentApproval responses
StatusDescriptionBody
200

The decided approval.

AgentApproval
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/agent/sessions/{session_id}/cancel

Cancel an agent session

cancelAgentSession · scope key:train

Ends the session now (canceled): pending approvals are withdrawn, the sandbox is terminated and its last interval billed, the session's keys are revoked. A model call already in flight finishes and is billed (the ledger records it); nothing the model asked for after it runs. Runs, rollouts or plans the agent started are not touched — cancel them on their own pages. 409 when the session already ended.

Parameters

cancelAgentSession parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

Responses

cancelAgentSession responses
StatusDescriptionBody
200

The canceled session.

AgentSession
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json

POST /v1/agent/sessions/{session_id}/end

End an agent session (done; a reply reopens it)

endAgentSession · scope key:train

AG1 — the person ends the session: status done, stop_code: ended. Unlike cancelAgentSession it is not final: its sandbox snapshot is kept and a message reopens it (postAgentMessage wakes a done session). Pending decisions are withdrawn (a spend or a plan nobody answered does not survive the end), the session's keys are revoked, and runs, rollouts or rounds it started are not touched. 409 on a canceled or failed session, or one that is already done. An agent's own key is 403.

Parameters

endAgentSession parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

Responses

endAgentSession responses
StatusDescriptionBody
200

The ended session.

AgentSession
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}/plans

The plans the agent proposed in this session, newest version first

listAgentPlans · scope key:read

AG1 — every version of the session's plan. The agent proposes a plan before anything that costs compute (the founder's rule: nothing billable before a person approves a plan); a person approves the latest version (approveAgentPlan, session-only) or replies in words and the agent proposes the next version (the one it replaces reads edited). Only the latest version can be approved.

Parameters

listAgentPlans parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

Responses

listAgentPlans responses
StatusDescriptionBody
200

The plans.

AgentPlanPage
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}/plans/{plan_id}

One version of the session's plan

getAgentPlan · scope key:read

AG1 — the plan as the Plan board draws it: its rounds (each a campaign round's locked-spec-to-be — one change and its keys, gates with the prediction written beside each, the hypothesis shown beside the gates and never counted, the gate while training, the stop rules, the estimate and the cap), contingent rounds and their condition, "then", "not doing", and the total cap. Estimates are the hub's own (estimateRun's function); nothing in a plan is spent until a person approves it.

Parameters

getAgentPlan parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

plan_idrequiredpathId

Agent plan id (aplan_...), one version of the session's plan (AG1).

Responses

getAgentPlan responses
StatusDescriptionBody
200

The plan.

AgentPlan
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json

POST /v1/agent/sessions/{session_id}/plans/{plan_id}/approve

Approve the agent's plan (a signed-in person only)

approveAgentPlan · scope session

AG1 — session-only, like a device approval: no API key of any scope approves a plan, so no agent can approve its own. The plan is the contract: approving it pre-approves each round's cap. In a session with a campaign, every round of the plan that can start now (no contingent_on, no parent_from) is created and locked through createRound's own path in this request — the three rules and the campaign's budget are checked, and a refusal (422 with the rule reasons, 409 on the budget) records nothing and leaves the plan proposed. In a session without a campaign each such round's run is created through createRun's path. The later rounds start when the agent asks for them by key (start_planned_round), exactly as approved. Anything the agent then wants that the plan does not name asks a person again, whatever it costs. 409 when the plan is not the latest version, is not proposed, or the session is canceled or failed.

Parameters

approveAgentPlan parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

plan_idrequiredpathId

Agent plan id (aplan_...), one version of the session's plan (AG1).

Request body

application/json · AgentPlanApprove

approveAgentPlan request body
FieldTypeDescription
notestring | null

length ≤ 1000

Shown to the agent with the approval.

Responses

approveAgentPlan responses
StatusDescriptionBody
200

The approved plan, with the rounds it created.

AgentPlan
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}/decisions

The session's decisions — plan, spend, shortlist, handoff

listAgentDecisions · scope key:read

AG1 — the typed decision cards, one shape: a plan (answered by approveAgentPlan, or a reply in words), a spend outside the approved plan (resolveAgentApproval, with expires_at and raise_budget_to), a shortlist of checkpoints for the real robot (decideRound {action: shortlist} — the 20-seed scan runs first, then one consent request per checkpoint), and a handoff — a device consent request, which only links to the consent page and is never approved here. answer_via names the operation that answers each. Newest first; status filters.

Parameters

listAgentDecisions parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

statusqueryAgentDecisionStatus

Responses

listAgentDecisions responses
StatusDescriptionBody
200

The decisions.

AgentDecisionPage
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}/digest

"Since you left" — what happened in the session since the viewer last looked

getAgentDigest · scope key:read

AG1 — generated by the hub from the session's events and the objects they link, never by the model: it costs nothing, is the same on every read, and cannot state a fact the rows do not hold. The agent's own words appear only as quotes (a round card's "Next", a spend's proposal). Lines, in order: runs that finished or failed, the gates their checkpoints got, the round's verdict by its locked gates, the tripwire, videos rendered or rendering, handoffs, and what needs you — each with the ids to open. since defaults to the viewer's last_seen_at (else the session's start). Unless mark=false, reading it moves the viewer's last_seen_at to now (an agent's own key never marks).

Parameters

getAgentDigest parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

sincequerystring (date-time)

Lines about what happened after this instant (default the viewer's last_seen_at).

markqueryboolean

default true

Move the viewer's last_seen_at to now after reading (default true).

Responses

getAgentDigest responses
StatusDescriptionBody
200

The digest.

AgentDigest
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/agent/sessions/{session_id}/objects

The session's objects grouped by state — Needs you, Running, Ready for review, Done

listAgentObjects · scope key:read

AG1 — the overview column of the session page: every object the session touched (derived from its events' links and its plan), one line of facts each, grouped. Needs you: pending decisions, and (P1) the spends a pre-AG1 session still holds the A1 way — pending AgentApprovals with no decision card (kind: approval), so a page never has to patch them in. A render's line says how long is left from the hub's measured render time (AgentRenderRef.expected_s). Running: queued or running runs, renders and the shortlist's scans. Ready for review: checkpoints that PASS the round's locked gates (a shortlist's candidates once one is proposed). Done: finished runs and renders, plan rounds that were not needed. The groups always come back in that order, empty ones included.

Parameters

listAgentObjects parameters
NameInTypeDescription
session_idrequiredpathId

Agent session id (asess_...).

Responses

listAgentObjects responses
StatusDescriptionBody
200

The objects.

AgentObjects
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json

Schemas (28)

The schemas these operations reach before any other tag’s do. A type that links elsewhere is rendered on that tag’s page.

AgentSessionStatus

string

one of running · waiting_on_you · waiting_on_event · idle · sleeping · done · failed · canceled

running — a turn is queued or in progress; waiting_on_you — a decision waits for a person (a plan, a spend, a shortlist: waiting_on.decision_ids; A1's held spend: pending_approvals) — the agent may still be woken by an event meanwhile; waiting_on_event — nothing waits for a person, and the agent yielded until a run, rollout, gate, approval request, plan or endpoint moves (waiting_on); sleeping (AG1) — nothing is pending and the agent waits for a message, its sandbox snapshotted and stopped, so nothing bills (no idle timeout ends it any more); idle — A1's name for the same wait, no longer written (read it as sleeping); done — the person ended it (endAgentSession) or the agent declared the task complete — a message reopens it; failed — a hard stop (the session cap, the monthly allowance, the call cap, a refused or failing model, the creating credential revoked), with stop_code; canceled — cancelAgentSession. Only failed and canceled are final.

AgentSessionPage

object

AgentSessionPage fields
FieldTypeDescription
itemsrequiredarray of AgentSession
next_cursorrequiredstring | null

AgentSessionCreate

object

AgentSessionCreate fields
FieldTypeDescription
goalrequiredstring

length 1–8000

What the agent should achieve, in plain words.

robotstring | null

length ≤ 160

owner/slug of a robot repo the goal is about. Validated like Recipe.robot: missing, private and malformed are one 422.

campaignstring | null

length ≤ 64

A campaign (C3) the session works inside, by id or slug. C3b: it must be an active campaign of the session's owner that the creator can see (422 otherwise), and it is resolved on every spending call: a round the agent proposes INTO this campaign is auto-approved only when its cap is at or under the campaign's per_run_limit_usd and fits in spend.remaining_usd; anything else waits for a person. Spends that are not this campaign's (a round of another campaign, a standalone run, a coach call) are judged by the workspace's rules, because the campaign's budget does not pay for them.

budget_usdnumber | null

≥ 0 · ≤ 1000

A total a person pre-approves for the session's spending tools (GPU training on a priced executor, a Modal rollout, a Modal endpoint, a plan, a coach call), on top of the per-run limit: a call is auto-approved only while every approved call's cap, this one's included, fits in it. Null: no session total — the per-run limit alone decides. 0: every spending call asks. Not the model or sandbox spend (that is cap_usd and the allowance).

auto_approve_per_run_usdnumber | null

≥ 0 · ≤ 1000

This session's per-call auto-approve limit, which may only LOWER the workspace's (AGENT_AUTO_APPROVE_PER_RUN_USD, $3.00): a spending call whose cap is above it asks a person. Inside a campaign the campaign's own rules apply instead. Null: the workspace's.

cap_usdnumber | null

> 0 · ≤ 1000

Cap on the session's own model + sandbox spend (AGENT_DEFAULT_CAP_USD, $10, when null). The next model call is refused at it.

modelstring | null

length ≤ 64

The model the loop runs on (AGENT_MODEL, claude-sonnet-5, when null). On the free allowance no other model is offered (422).

scopesarray of ApiKeyScope | null

items ≤ 3

Scopes the session's keys carry — the session acts with the highest one named, which may not exceed what the creating credential was granted (403 otherwise). Null: the creator's own.

ownerstring | null

length ≤ 64

Who the session is billed to: the creator (null) or an org handle the creator is a member of. The allowance and the working-session cap (AG1) are per owner.

sandboxboolean

default true

Offer the agent a sandbox shell (when the deployment configures one).

contextarray of AgentContextRef

items ≤ 8

K3 — hub objects the session starts with. Each is checked as the caller (422 at context[i] for missing, private or the wrong kind — never an existence oracle) and summarised for the model's first turn from the hub's own reads: a run's status, gate, config groups and checkpoint gates; a model's card, contract and the run that trained it; a robot's card and interface; a dataset's meta; a rollout's verdict.

AgentSession

object

One cloud-agent session. The conversation itself is the event stream (streamAgentEvents); this is the state around it.

AgentSession fields
FieldTypeDescription
idrequiredId
statusrequiredAgentSessionStatus
status_reasonstring | null
stop_codestring | null

Why a failed / done session stopped: session_cap, allowance, max_calls, refusal, model_error, credential_gone, canceled; ended (a person ended it) and complete (the agent declared the task complete) since AG1; A1's expired and idle remain on old rows only.

titlestring | null

length ≤ 200

AG1 — the session's title, set by the agent from the goal (e.g. "Omni walk · R4 lateral feed-forward"); null until it sets one.

summarystring | null

length ≤ 400

AG1 — the status line the agent writes whenever it acts (the Home board's second line): what it last did and what waits. Set with its set_summary tool, else the first sentence of its last message in that turn — always the agent's own words.

summary_atstring (date-time) | null (date-time)
slept_atstring (date-time) | null (date-time)

AG1 — when the session last went to sleep; null while it is awake.

last_seen_atstring (date-time) | null (date-time)

AG1 — when the caller last read the session's digest (per viewer); the digest's default since.

planAgentPlanRef | null

AG1 — the session's latest plan version (approved or not).

approved_plan_idstring | null

AG1 — the plan version in force; null until a person approves one.

pending_decisionsinteger

AG1 — decisions waiting for a person (plan, spend, shortlist).

goalrequiredstring
robotstring | null
campaignstring | null
contextarray of AgentContextRef

K3 — the hub objects the session was started with (AgentSessionCreate.context), as stored.

ownerrequiredRepoOwner
created_byUserPublic | null
modelrequiredstring
backendrequiredstring

anthropic or recorded; a replayed session must never read as a real one.

billingrequiredstring

one of platform · org_key · user_key

Who pays for the model: platform — Lucen, at list price with 0 % markup, drawn from the allowance. org_key / user_key arrive with bring-your-own-key (A4).

scopesrequiredarray of ApiKeyScope

What the session's keys are granted (the highest one is used).

budget_usdrequirednumber | null

The session's pre-approved total for spending tools; null — the per-run limit alone.

auto_approve_per_run_usdrequirednumber

The per-call auto-approve limit in force (the workspace's, or lower for this session).

cap_usdrequirednumber
spendrequiredAgentSpend
allowancerequiredAgentAllowance
callsrequiredinteger
max_callsrequiredinteger
user_turnsinteger
waiting_onAgentWait | null
pending_approvalsrequiredarray of AgentApproval
sandboxrequiredAgentSandbox
last_event_idstring | null

Where streamAgentEvents resumes after (send it as Last-Event-ID).

created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
finished_atstring (date-time) | null (date-time)
expires_atrequiredstring (date-time)

AG1: no longer a kill. The end of the session's current window (AGENT_SESSION_HARD_CAP_S, 24 h, from its start or its latest wake): a spend asked for in it expires then, and the sandbox cannot outlive it. A message or a wake opens the next window.

AgentMessageCreate

object

AgentMessageCreate fields
FieldTypeDescription
textrequiredstring

length 1–8000

AgentApprovalDecision

object

AgentApprovalDecision fields
FieldTypeDescription
decisionrequiredstring

one of approve · deny

notestring | null

length ≤ 1000

Shown to the agent with the decision.

raise_budget_tonumber | null

≥ 0 · ≤ 1000

AG1, approve only — "approve up to $X for the rest of the session": this call runs, and from now on compute calls whose caps fit in what is left of $X (this call's cap included) run without asking, even outside the plan; the session's budget_usd is raised to cover it. Must be at least this call's cap_usd (422 otherwise).

AgentPlanPage

object

AgentPlanPage fields
FieldTypeDescription
itemsrequiredarray of AgentPlan

AgentPlan

object

AG1 — the agent's plan for the session: what it will train, how each round is judged, what it may cost, and what it will not do. Nothing billable runs in a session before a person approves a plan; after that, the plan is the contract and anything outside it asks a person.

AgentPlan fields
FieldTypeDescription
idrequiredId
session_idrequiredId
versionrequiredinteger

≥ 1

1 for the first proposal; each edit is the next version.

statusrequiredAgentPlanStatus
titlestring | null

length ≤ 120

The plan card's title, e.g. "R4, and R4b if needed".

summaryrequiredstring

length ≤ 1200

The agent's own paragraph about the plan, quoted as written.

campaignAgentCampaignRef | null

The session's campaign, whose rounds the plan's rounds become; null without one.

robotstring | null
roundsrequiredarray of AgentPlanRound

items ≤ 4

afterrequiredarray of string

items ≤ 8

"Then" — what follows a PASS (e.g. the 20-seed band scan, a shortlist of up to 2, the robot handoff by consent).

not_doingrequiredarray of string

items ≤ 8

stop_rulesrequiredarray of string

The session-level stop rules in words (its budget, its model cap), hub-generated.

cap_usdrequirednumber

The most the plan can spend on compute — every round's cap, contingent rounds included.

est_usdnumber | null

The expected compute cost of the rounds that start at approval, where the planner models them.

budget_usdnumber | null

The session's budget_usd when the plan was proposed; the plan's cap_usd must fit in it.

model_estimate_usdnumber | null

A rough figure for the agent's own model turns across the plan (a flat per-checkpoint wake cost), from the free allowance.

model_estimate_basisstring | null
proposed_atrequiredstring (date-time)
approved_atstring (date-time) | null (date-time)
approved_byUserPublic | null
approval_notestring | null
superseded_bystring | null

The plan version that replaced this one (edited).

decision_idstring | null

The plan decision that asked a person for it.

AgentPlanApprove

object

AgentPlanApprove fields
FieldTypeDescription
notestring | null

length ≤ 1000

Shown to the agent with the approval.

AgentDecisionPage

object

AgentDecisionPage fields
FieldTypeDescription
itemsrequiredarray of AgentDecision

AgentDigest

object

AgentDigest fields
FieldTypeDescription
session_idrequiredId
sincerequiredstring (date-time)
untilrequiredstring (date-time)
markedrequiredboolean

Whether this read moved the viewer's last_seen_at to until.

linesrequiredarray of AgentDigestLine

AgentObjects

object

AgentObjects fields
FieldTypeDescription
session_idrequiredId
generated_atrequiredstring (date-time)
totalrequiredinteger
groupsrequiredarray of AgentObjectGroupItems

Always the four groups, in the order Needs you, Running, Ready for review, Done.

AgentContextRef

object

AgentContextRef fields
FieldTypeDescription
typerequiredstring

one of model · run · robot · dataset · rollout

refrequiredstring

length 1–160

owner/slug for a model, robot or dataset repo; the id for a run or a rollout.

AgentSpend

object

The session's three lines, USD. model_usd is list price (0 % markup), sandbox_usd Modal's sandbox rate × 1.28 for the intervals it was active; both are sums of the session's ledger rows. gpu_budget_used_usd is what tools committed inside budget_usd (estimates, the most they can cost), gpu_approved_usd what a person approved above it; the GPU itself is billed on its run or endpoint.

AgentSpend fields
FieldTypeDescription
model_usdrequirednumber
sandbox_usdrequirednumber
total_usdrequirednumber

model_usd + sandbox_usd — what counts against cap_usd and the allowance.

reserved_usdrequirednumber

A model call's reservation while it is in flight; 0 between calls.

gpu_budget_used_usdrequirednumber
gpu_approved_usdrequirednumber
callsrequiredinteger

Model calls made, each one a ledger row.

ledger_rowsrequiredinteger
gpu_usdrequirednumber

The header's third line: GPU dollars of the runs this session started — a finished run's cost_usd, a running priced run's cost so far (elapsed seconds x its billed rate, live). Billed on the runs, not on this session; not counted against cap_usd or the allowance.

gpu_runsrequiredarray of AgentGpuRun
sandbox_staterequiredAgentSandboxState

AgentWait

object

What the session is blocked on.

AgentWait fields
FieldTypeDescription
kindrequiredstring

one of approval · run · rollout · approval_request · plan · endpoint · user · decision

approval — a spend a person must answer (approval_ids); run / rollout / approval_request / plan / endpoint — a hub resource the agent asked to be woken about (ref, until); user — the agent answered and waits for a message; decision (AG1) — decisions wait for a person (decision_ids); when the agent is also waiting on a hub resource, event names its kind and ref / until / timeout_at describe it.

decision_idsarray of Id

AG1 — the pending decisions (kind: decision).

eventstring | null

AG1 — with kind: decision, the hub resource the agent also waits on (run, rollout, …).

refstring | null

The resource id waited on.

untilstring | null

What wakes the agent: finish (the resource ended), gate (a gate verdict on the run, a tripwire, or its end), decision (a person decided a device request), claim (a server claimed the endpoint).

approval_idsarray of Id
sincerequiredstring (date-time)
timeout_atstring (date-time) | null (date-time)
messagestring | null

AgentSandbox

object

AgentSandbox fields
FieldTypeDescription
staterequiredAgentSandboxState
sandbox_idstring | null

Modal's id for the current container.

started_atstring (date-time) | null (date-time)

When the current active interval began.

active_secondsrequirednumber

Seconds billed so far over every interval.

cost_usdrequirednumber
expires_atstring (date-time) | null (date-time)

The sandbox's 24 h hard cap, from its first start.

egressrequiredarray of string

The only hosts the sandbox's network may reach — the hub's.

AgentCampaignRef

object

AgentCampaignRef fields
FieldTypeDescription
idrequiredId
slugrequiredstring
namerequiredstring
robotstring | null

owner/slug of the campaign's robot.

AgentPlanRound

object

One round of a plan: what createRound will lock (C3) — a name, the checkpoint it resumes from, the spec (ONE change and its keys, the hypothesis shown beside the gates and never counted, gates each with the prediction written beside it, not-doing, tripwires, the iteration cap) and the recipe — plus what the hub derived from them. In a session without a campaign the same shape describes a run: the recipe is what createRun receives and the spec is the record of the gates and predictions (no C3 verdict is computed without a campaign).

AgentPlanRound fields
FieldTypeDescription
keyrequiredstring

length 1–16 · pattern ^[A-Za-z0-9][A-Za-z0-9._-]*$

The round's short label inside the plan, e.g. R4, R4b; unique per plan.

namerequiredstring

length 1–120

The round's name, e.g. "lateral feed-forward".

contingent_onstring | null

length ≤ 300

A contingent round's condition in words, e.g. "only if R4's vy±0.10 is still over the band at the scan". It never starts at approval; the agent starts it by key when it judges the condition met, and its reading is quoted on the round (note).

parentCheckpointRef | null

The checkpoint it resumes from; null trains from scratch (or from the campaign's root).

parent_fromstring | null

length ≤ 16

Instead of parent: the key of an earlier round of this plan whose checkpoint it resumes from (the step is named when it starts, and C3's resume-from-PASS rule applies then).

specrequiredRoundSpec
reciperequiredRecipe
scanRoundScanRequest | null
startread-onlystring

one of at_approval · later

at_approval — created when the plan is approved; later — contingent, or resuming from another plan round.

gateread-onlyCheckpointGateSpec | null

The gate while training as it will run — the recipe's, else the campaign task's default (L1's poster c_matrix for walk/omni).

estimateread-onlyRunEstimate | null

estimateRun's own arithmetic on the recipe (with the spec's iteration cap written in).

est_usdread-onlynumber | null

What the round is expected to cost where the hardware planner can model the template (recommendRun's cost_usd_est, on a priced executor); null otherwise — the cap is then the only number.

est_hoursread-onlynumber | null

The planner's expected wall-clock hours (recommendRun's est_hours), where it models the template.

cap_usdread-onlynumber

The most the round can cost — estimate.cost_usd_max (0 on an unpriced executor). Approving the plan pre-approves it.

parent_nameread-onlystring | null

What to call the parent checkpoint's run (its display_name, e.g. laika-omni-c2-700).

variablesread-onlyRoundVariables | null

C3's one-variable arithmetic, planned when the plan was proposed (the recipe against the parent's resolved config) — null for a round whose parent is not known yet. A plan whose round breaks a rule is rejected before a person sees it.

warningsread-onlyarray of string

What C3 noticed and would not refuse (a stand round with no push gate, a key that cannot be compared).

stop_rulesread-onlyarray of string

The round's stop rules in words, from its tripwires and its cap (hub-generated).

statusAgentPlanRoundStatus
round_nread-onlyinteger | null

The campaign round it became (C3), once created.

round_idread-onlystring | null
run_idread-onlystring | null

Its training run, once created.

started_atread-onlystring (date-time) | null (date-time)
noteread-onlystring | null

The agent's reading of a contingent condition (quoted), a skip's reason (quoted), or why the hub refused it.

AgentDigestLine

object

AgentDigestLine fields
FieldTypeDescription
kindrequiredAgentDigestLineKind
staterequiredAgentItemState
textrequiredstring

One sentence, hub-generated; the agent's words appear only inside quotes.

shortstring | null

length ≤ 90

P1 — the same line for a phone, at most 90 characters: the same facts with the identifiers, the quotes and the subordinate clauses dropped (docs/API.md "The digest's short form"), e.g. "R4 finished 11:06 — 1,600 it in 29 min, $1.60." Hub-generated like text, never the agent's words.

atstring (date-time) | null (date-time)
linksAgentLinks | null

AgentObjectGroupItems

object

AgentObjectGroupItems fields
FieldTypeDescription
grouprequiredAgentObjectGroup
itemsrequiredarray of AgentObject

AgentGpuRun

object

AgentGpuRun fields
FieldTypeDescription
run_idrequiredId
statusrequiredJobStatus
executorstring | null
cost_usdrequirednumber
liverequiredboolean

True while the run is running and its cost is still accruing.

pricedrequiredboolean

AgentSandboxState

string

one of none · running · snapshotted · terminated · unavailable

none — never started; running — a Modal Sandbox is up and billed; snapshotted — idle, its filesystem snapshotted and the container stopped (not billed; the next shell call restores it); terminated — ended with the session; unavailable — the deployment configures no sandbox (AGENT_SANDBOX_APP), so the agent has no shell.

AgentPlanRoundStatus

string

one of planned · created · refused · not_needed

planned — not started (it starts at approval, or later by key when it is contingent or resumes from another plan round); created — its round (with a campaign) or run (without) exists: round_n, run_id; refused — the hub refused to create it (note carries why; the plan's approval failed with it); not_needed — a contingent round the agent skipped, with its reason quoted in note.

AgentDigestLineKind

string

one of plan · run_finished · run_failed · gates · round · tripwire · render · handoff · needs_you

AgentItemState

string

one of needs_you · running · done · failed · skipped

How a digest line or an object row reads, by word and shape as well as colour: needs_you (◆), running (■), done (●), failed (✕), skipped (○).

AgentObjectGroup

string

one of needs_you · running · ready_for_review · done

AgentObject

object

AgentObject fields
FieldTypeDescription
kindrequiredAgentObjectKind
idrequiredstring

The object's id (a checkpoint's is <run_id>:<step>, a plan round's <plan_id>:<key>).

grouprequiredAgentObjectGroup
namerequiredstring

E.g. "R4 c4r4_side_ff", "step_1600", "Render video".

linerequiredstring

One line of facts, e.g. "9 / 13 · vx+0.30 93 % · video ready".

staterequiredAgentItemState
wordstring | null

The state as a word for the row (Succeeded, rendering, pending, not needed).

sincestring (date-time) | null (date-time)
linksAgentLinks | null

AgentObjectKind

string

one of decision · run · render · scan · checkpoint · plan_round · request · approval

What a row is. P1 added approval: a spend a pre-AG1 session held the A1 way (an AgentApproval with no decision card), listed under Needs you while it is pending; its id is the approval's and it is answered through resolveAgentApproval.