Budgets
- A step is a round, not a tool call. Four tools called in one reply are one step.
- Each re-prompt restarts the step budget. A run without a result is re-prompted up to twice, so
max_steps: 25can mean 75 rounds.timeout_secondsis the real bound;max_stepsis the runaway-loop guard. - Provider tools spend time, not steps. A
web_searchruns inside one round on the provider’s side, so a run that searches heavily fails astimeoutwith steps to spare, and raisingmax_stepsdoes nothing. - Entered by an agent,
max_stepsis not used: the task runs on the calling agent’s ownmax_steps(null means 4 on voice and video, 25 on text).timeout_secondsstill applies and is the only limit on how long the task holds the caller, so keep it short for voice. See agent tasks.
error.type
A failed standalone run has status: "failed" and error: {type, message}; a canceled one has status: "canceled" and error.type: "canceled". A task entered by an agent has no run record; it fails as an ordinary tool failure in that call.
Retries
Only background runs are retried, at most 3 tries in all, and only when:- the worker running the try stopped (a deploy or a crash), whatever it had done; or
- it failed with
provider_errorthat the provider marks as transient (a5xx, a rate limit, a dropped connection), or withplatform, and no tool oron_enterhook ran in that try.
platform, the worker running this stopped; gave up after 3 tries, or with its last error. tries, usage and provider_cost on the run cover every try.
Refused at run time
POST /v1/task-runs and POST /v1/task-runs/batch refuse before anything runs, with no run recorded. A batch is refused whole, each problem prefixed runs[i]:.
Refused at save
Every create andPATCH is checked; a failure is a 400 listing every problem, and nothing is stored.
Refused at publish
POST /v1/tasks/{task_id}/validate runs these without publishing; POST /v1/tasks/{task_id}/publish refuses on them.
The last two also refuse a rollback to a version with the same problem.