POST /v1/agents/{agent_id}/run, the response returns immediately with a
task_id and status: "running". The agent is still working in the background. To get
the final result you poll one of the task-read endpoints until status is terminal.
If you’d rather not build a polling loop, async=false holds the connection and returns
the result on the same call — see Get the result on the same
call. Polling is still the better fit for runs that
take more than a few minutes.
Pick the right endpoint to poll
A typical production loop looks like: poll
/v1/tasks/{task_id} on a backoff schedule;
once status hits a terminal value, call /summary once.
Terminal vs non-terminal statuses
A real polling loop
Get the result on the same call
If your caller can afford to wait, addasync=false and the API holds the connection
until the run finishes, then returns the result. One call, no polling loop.
Choose what comes back
result tells the API which payload you want. Set it on the request, or once on the agent
in Settings → Synchronous run result so your callers don’t have to repeat it.
These are the same payloads the polling endpoints return, just delivered on the original
call.
result is required. If you leave it off and the agent has no default set, the request
is rejected with 400 rather than guessing which payload you wanted.Read the response
Checkoutcome to see how the wait ended. Don’t match on message — it’s human-readable
text and may change.
Two things to know:
- A run that failed still returns
200. The HTTP call worked; the run didn’t. Checkstatusfor how the run itself went. task_idis on every response, so you can always collect a run however the wait ended.
Keep your polling fallback
async=false can decline to wait and answer with the ordinary 201 plus
X-Sync-Budget-Seconds: 0. That happens when synchronous responses aren’t enabled for
your agent, when the run is queued behind the agent’s concurrency limit, or when the
server is already holding as many requests as it allows.
Large results
Responses are capped. If the payload is bigger than the cap you still get200, but with
result_status: "too_large", the real size in result_bytes, and no result — fetch it
from the matching endpoint in the table above.
The full reasoning trail (result=feed) is the likeliest to hit this; summary and
tool:<tool_name> rarely do.
Rate limits
/v1 can be rate limited per API key, switched on per environment. Where it’s on, going
over returns 429 with Retry-After in seconds.
The limit is shared across the whole /v1 surface rather than per endpoint, so the polls
in your loop draw on the same budget as your runs — another reason to back off rather than
poll tightly.
Cancelling
If you no longer want the result, sendPOST /v1/tasks/{task_id}/cancel. The task moves
to stopped. The step currently executing on the worker is not interrupted; it
finishes naturally, but no further steps are scheduled. Cancel is idempotent: calling on
an already-terminal task returns the current state with 200.
Tasks that legitimately take a long time
Some agents do work that takes minutes (multi-step research, large document extraction). A few rules of thumb:- Keep your client-side timeout generous (≥10 minutes) for those agents.
- Don’t poll faster than every couple of seconds; you won’t get the answer any sooner.
- For very long jobs, persist the
task_idand poll from a background worker, not a user-facing HTTP request.