Reference for what bounds a task run, what each failure means, and what a task config is refused for.

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: 25 can mean 75 rounds. timeout_seconds is the real bound; max_steps is the runaway-loop guard.
  • Provider tools spend time, not steps. A web_search runs inside one round on the provider’s side, so a run that searches heavily fails as timeout with steps to spare, and raising max_steps does nothing.
  • Entered by an agent, max_steps is not used: the task runs on the calling agent’s own max_steps (null means 4 on voice and video, 25 on text). timeout_seconds still 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_error that the provider marks as transient (a 5xx, a rate limit, a dropped connection), or with platform, and no tool or on_enter hook ran in that try.
An error after a tool ran is never retried, but a worker stop is, from the start, so a side-effecting tool can run twice. Retries wait 30, then 60 seconds. A run that has had its tries fails with 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 and PATCH 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.

Warnings

Returned by validate and publish; they do not block.

Limits