Agent runs
Start an agent on a set of files, then answer what it asks — sign-offs and human steps, over the API.
An agent is a multi-step automation with human sign-off built into it. An agent run (agr_…) is one execution of it, and these six routes are the whole surface:
Pick an agent
Read tasks[] and actions[] before you start: they tell you which steps will come back to you as human work, and which actions will stop for a sign-off. GET /v1/agents/:id returns the same shape for one agent.
Start a run
There is no ttl: files you pass by URL join your reusable corpus and are never purged on a deadline, because a run can wait days on a person.
What comes back
The call holds open up to ?wait= seconds (default 60, max 120, 0 returns immediately) and releases early the moment the run either finishes or blocks on a person.
The 202 is a graceful degrade, never an error — the run id is yours either way. Sending an idempotency-key header makes retries safe: a replay returns the original run with an idempotent-replay: true response header.
A queued run has to be polled. Its files are still being prepared — minutes, for scans or long audio — and reading the run is what picks it up once they’re ready. A run that hasn’t started has nothing to report, so waiting on a webhook alone leaves it queued forever. Once it’s running, events are delivered as they happen.
Poll the run
?wait= (0–120, default 0 here) holds the request until the run finishes or blocks on a person, so a loop of long polls costs one request per minute instead of one per second.
Decide an approval
Read the outstanding ones from approvals[], then answer one by id:
run.status tells you whether the run moved on, finished, or blocked on the next thing — ?wait= holds the request while it picks the work back up.
params and files together must stay under 1 MiB. Deciding the same approval twice is a 409: the first answer stands.
An API key has no person behind it, so the run records your organization’s key as the actor rather than a named individual.
Complete a human step
The steps that are yours are the ones in tasks[] with executor: "human" and status: "ready". Closing one releases everything that was waiting on it:
Both body fields are optional — send {} if you have neither. note is ≤ 2000 characters; files is up to 20 ids you registered or that the run already holds, and they show up in the run’s output.files.
End to end
The whole loop, with a webhook doing the waiting:
Start the run
POST /v1/agent-runs with {agent, files: [{url}], metadata, webhook: {url}} → 202, status: "queued". Keep the agr_ id.
Poll once to pick it up
GET /v1/agent-runs/:id?wait=60. This is what starts a queued run once its files are ready. From here events flow.
A sign-off is requested
agent_run.approval_requested arrives. It’s deliberately minimal, so re-read the run and take the params and files from approvals[].
Answer it
POST /v1/agent-runs/:id/approvals/:approvalId with {"decision": "approve"}. The response’s run.status says what the run did next.
What this surface does not have
- No list. There is no
GET /v1/agent-runs— hold theagr_id from create, or tag runs withmetadatayou already know. - No cancel, no delete. An agent run runs until it finishes, parks, or reaches
expiresAt. - Not in
GET /v1/runs. That list is capability runs only (extract_run,parse_run, …), and the TTL andkeepstory on Runs doesn’t apply here: an agent run’s inputs are persistent files and it has nottl.