Skip to content

Chats

Get a chat’s current state — status, full message history, recorded outcomes, cost, and any pending human-input request. Poll this until status is no longer “running”.

The messages history holds only user/assistant text turns. Human input requests and the answers they got are NOT messages — they come back in hitl_requests (every request for the chat, with its response_text), while pending_hitl_request holds only the one still waiting. When the request offered ui (buttons/choice/text/info — the same shape request_human_input accepts), it’s included on both so you can see exactly what a human would be asked to pick from before calling respond_to_hitl.

When the agent recorded an outcome, its summary IS the answer, and the last assistant message carries it (tagged kind: "outcome_summary") even if the model’s own closing turn was empty — so messages alone is enough to read the result. outcomes remains the graded record.

stop_reason says why a chat is no longer moving: “cost_limit” (raise the agent’s per-chat budget and start again), “awaiting_input” (a human must answer), “timer” — the agent set its own timer and sleeps until waiting_until, so it is still working and nobody need act —, “queued” (waiting for a free slot), “awaiting_children” (waiting on chats it spawned) and “environment_offline” (its remote machine is not connected; the turn starts by itself when the machine comes back), all likewise self-resolving, “model_unpriced” — the model the chat runs on has no price we can charge credits against, so the turn was refused before it was sent; the organisation’s balance is untouched and topping up changes nothing, so move the agent to another model or ask support to price this one. That stop and “credits_exhausted” are both continuable: once the blocker is lifted, a person can carry the same chat on from where it stopped rather than starting over —, “goal_failed” — the agent recorded a failed goal and closed the chat itself, so its status is “errored” by decision rather than by breakage and the summary says why — or “no_outcome”, the agent replied and stopped without calling goal_complete, so outcomes is empty and nothing was declared. It is idle, not running: stop polling and treat the result as unverified.

Pass include_trace=true to also get a trace array of the underlying events (tool calls + results with name/args/result preview), oldest first — useful to see why the agent did something or which tool failed.

ParameterTypeRequiredDescription
chat_idstringyes
include_tracebooleanno
orgstringno

List recent chats for an agent (by id or slug), newest first.

Paged: the response carries total, has_more and next_offset — pass next_offset back as offset to walk the rest.

status alone never means “finished”. Chats have no terminal “completed” status — a chat that ran to a successful goal_complete still reports status: "active", indistinguishable from one still working. To tell them apart, use the same two fields get_chat exposes:

  • outcome_status — the chat’s rolled-up outcomes status (“success” / “failed” / “partial”), or null if it hasn’t recorded one yet. When a chat recorded more than one outcome, any success wins over an earlier failure/partial; otherwise the most recently recorded outcome’s status is reported.
  • stop_reason — why the chat stopped moving: “cost_limit”, “awaiting_input”, “timer”, “queued”, “awaiting_children”, “environment_offline”, “goal_failed”, “no_outcome” (it replied and stopped without declaring a result), or null while it’s still running. See get_chat’s docstring for the full vocabulary.

A chat is actually finished when outcome_status is non-null (or stop_reason is one of the terminal reasons above) — not merely because status reads “active”.

ParameterTypeRequiredDescription
agentstringyes
limitintegernoMax rows to return (1–200).
offsetintegernoRows to skip — pass the previous response’s next_offset.
orgstringno

Answer a pending human-input request (from a paused chat) and resume the agent. Use action (“approve”/“reject”, or one of the request’s ui buttons) for approvals and button choices, selection for one of the ui choice options, selections when the request asks more than one question, text for a free-text answer. At least one is required.

get_chat’s pending_hitl_request.ui always spells out what is on offer: a request that declared no ui of its own resolves to the default for its type, so an approval really does offer Approve/Reject. When the resolved ui lists buttons/choice, action/selection must be one of those options — a value that isn’t gets rejected with the valid options listed. A ui that is free-text only accepts anything.

More than one question in one request. Each {"choice": [...]} element in the resolved ui carries a key (and often a label). To answer them all, pass selections as {key: chosen_value} — e.g. {"environment": "Staging", "rollback_window": "24 hours"}. Every value is checked against its own group’s options. A bare selection is only accepted when the request offers a single choice group; otherwise it cannot say which question it answers and is rejected with the keys and their options listed. selection and selections are mutually exclusive — send one or the other, never both.

ParameterTypeRequiredDescription
actionstringno
orgstringno
request_idstringyes
selectionstringno
selectionsobjectno
textstringno

Send a user message to an existing chat and dispatch the agent turn. A message to a paused chat resumes it. Runs asynchronously — poll get_chat for the result.

To attach files, first use create_upload_url to get presigned upload URLs, PUT your files to those URLs, then pass the returned upload_ids in attachment_upload_ids. Each upload_id is single-use: attaching is all-or-nothing, so if any id has already been attached (or has expired) the call is refused naming that id, and no message is sent.

ParameterTypeRequiredDescription
attachment_upload_idsstring[]no
chat_idstringyes
messagestringyes
orgstringno

Start a new chat with an agent (by id or slug) and send the first message. Returns the chat_id; the turn runs asynchronously — poll get_chat for the result.

By default the chat runs the agent’s published (active) revision. To test an unpublished instruction without deploying it, pass use_draft=true (pins the agent’s current draft revision) OR revision_version=N (pins a specific past version). The pin holds for the chat’s whole life. The two options are mutually exclusive.

Where the chat runs is environment. Pass an environment’s slug, id, or unambiguous name — list_environments shows what this org has. A remote_daemon environment is a machine the user owns: their files, their installed tools, in place. Nothing else reaches that machine, so a request to run something on the user’s computer needs this argument; without it the chat runs where the org’s default puts it, and a command that only exists on their machine fails there for reasons that look nothing like the real cause.

sandbox_enabled=true is the narrower, older switch: it turns on our built-in Linux sandbox — an isolated filesystem + network on our infrastructure, persisting across the conversation — for substantial coding, data, or file-heavy work. It only ever adds capability on top of the agent’s own sandbox setting, and it is not a way to reach any particular machine.

model_mode_override (‘trivial’ | ‘normal’ | ‘high_effort’, shown as Trivial / Standard / High) changes the agent’s own model_mode for this chat only — the one model lever an org whose plan selects effort rather than models has, in either direction: trivial drops routine work onto a cheaper model, high_effort buys a dearer one. It is sticky: it applies to this turn and every later send_message on the chat. Only meaningful for such an org; an org with direct model choice is refused it (the value would be inert) and picks a model on the agent instead.

To attach files, first use create_upload_url to get presigned upload URLs, PUT your files to those URLs, then pass the returned upload_ids in attachment_upload_ids. Each upload_id is single-use: attaching is all-or-nothing, so if any id has already been attached (or has expired) the call is refused naming that id, and no chat is created.

ParameterTypeRequiredDescription
agentstringyes
attachment_upload_idsstring[]no
environmentstringno
messagestringyes
model_mode_overridestringno
orgstringno
revision_versionintegerno
sandbox_enabledbooleanno
titlestringno
use_draftbooleanno