POST /api/v2/agents,
POST /api/v2/agents/{id}/runs, and each poll of
GET /api/v2/agents/{id}/runs/{runId} returns the same run
object. This page explains the fields you branch on.
Status
status is the single discriminator for a run’s lifecycle. Branch on it — non-completed
terminal states are reported here, not as HTTP errors.
| Status | Meaning | What to do |
|---|---|---|
running | Work is in progress. | Keep polling; honor the Retry-After header. |
completed | The agent finished cleanly. | Read response. |
needs_input | The agent asked a question before it could continue. | Answer with a follow-up run (see Pending questions). |
incomplete | The step finished but a tool call could not be parsed, so the loop ended early. | Recoverable — send a follow-up run on the same agent. |
step_cap_hit | The run reached your plan’s step limit. | Send a follow-up run to continue, or upgrade for a higher cap. |
cancelled | You cancelled the run. | Whatever the agent built so far is kept. |
errored | The run failed. | response.text is null; retry or contact support. |
timed_out | The run exceeded the wall-clock ceiling. | response.text is null; send a follow-up run. |
Retry-After header (currently 15 seconds) is present only while status is
running. Its absence on a response is the signal to stop polling.
Response
response is null while the run is running. Once the run is terminal, it carries the
agent’s prose plus the structured work it did.
response.text
The cleaned, user-facing summary of what the agent did. Internal markup is stripped
server-side. It is null on errored and timed_out runs.
response.actions[]
The structured workspace mutations the agent performed, in the order they fired. Each
action has a type and a tableId; other fields depend on the type. v2 speaks “leads”
rather than “rows”, so row mutations use leads_added, leads_deleted, and
leads_restored. Use this as the audit trail of what changed. It is empty when the run
made no mutations (for example, when it stopped on a question).
response.tables[]
The full table objects for every table the run touched — the same shape as a single
GET /api/v2/tables/{id} response. This is the quickest way
to see lead counts and table URLs without a second call. To read the actual rows, pass a
table id to GET /api/v2/tables/{tableId}/rows.
Optional projections
GET /api/v2/agents/{id}/runs/{runId} takes an include query parameter — a comma-separated
list of opt-in projections. Unknown tokens are ignored.
| Token | Effect |
|---|---|
stats | Attaches the economics block (credits per lead, qualification, funnel, lead sources) to every response.tables[] entry, per table and per column. |
transcript | Returns the full public transcript on response.transcript. |
Pending questions
When the agent needs a decision before it can continue, the run finishes withstatus: "needs_input" and todo.pendingQuestions[] is populated. Surface the question to
your user, then answer it by sending a follow-up run on the same agent with
POST /api/v2/agents/{id}/runs — any free-text prompt is
accepted. todo.nextActions[] carries the agent’s suggested next steps, each with a label
you can show and an optional typed type you can act on directly.