Timeouts and long-running work
Runtype bounds each continuous run of a Flow with wall-clock timeouts. A continuous run is the stretch of active execution from the start of a Flow to its first pause, or between two pauses. The timeouts limit that stretch, not the total lifetime of the work. A Flow that pauses and resumes gets a fresh budget each time it resumes, so a job can span hours or days. This page lists the limits for each entry point and shows how to structure work that takes longer than one continuous run.
Timeout limits by entry point
Each entry point accepts timeout overrides in its options object. The following table lists the settings, their defaults, and the accepted ranges:
For batches and Schedules, timeoutMs bounds each Record’s whole execution. The per-Flow and per-step settings bound the Flow and each step inside that execution, and the first limit that the run reaches stops it. When a per-Flow or per-step setting is unset, the execution uses the platform defaults of 5 minutes per step and 15 minutes per Flow. The exception is a Schedule that sets timeoutMs and leaves flowTimeoutMs unset: its per-Flow limit equals timeoutMs.
POST /v1/client/chat, the endpoint that browser clients call with a client token session, supports only the following body fields: sessionId, messages, assistantMessageId, turnId, submitMode, metadata, inputs, clientTools, clientToolsFingerprint, identityProof, and voice. The body has no options object, so a client chat request can’t set stepTimeoutMs or flowTimeoutMs. To set either timeout for a run, call POST /v1/dispatch from your backend with an API key.
For the interaction between the step, Flow, and whole-agent budgets, and the smaller 30-second default on execute-agent steps, see Debugging flows. A detached subagent has its own budget, separate from the parent’s budgets. For more information, see Run long phases as detached subagents.
Timeouts bound one continuous run, not the whole job
A timeout measures continuous execution, not elapsed calendar time. A human approval gate, a wait-until step, and an asynchronous crawl all pause the Flow, and the pause doesn’t consume the timeout budget. When the Flow resumes, it starts with a fresh, full budget from the original flowTimeoutMs. An approval that waits two days for an answer doesn’t time out the Flow when someone answers it.
The following patterns keep each continuous run within its budget and use pauses, Records, and separate executions to carry work across hours.
Detach an interactive execution from the client request
When POST /v1/dispatch or POST /v1/agents/{id}/execute might outlive the caller’s HTTP or MCP timeout, send the Prefer: respond-async header. Runtype queues the execution and immediately returns 202 Accepted with an execution handle:
Poll GET {statusUrl} with the same account credential while status is queued or running. A terminal response has the status completed, failed, or cancelled, and includes the result or error. Polling the handle is safe. Retrying the original execution request can duplicate side effects.
A paused status means that the execution waits for input, such as an approval or a tool result. The response’s result field holds the paused result, including its pausedReason. Polling doesn’t resume a paused execution. To continue it, send the approval or tool output to the matching endpoint:
- For a dispatch run, call
POST /v1/dispatch/approveorPOST /v1/dispatch/resume. - For a saved Agent, call
POST /v1/agents/{id}/approveorPOST /v1/agents/{id}/resume.
For the request shapes, see Pause and resume on an agent dispatch.
To read the status endpoint, an API key needs FLOWS:READ or FLOWS:EXECUTE for a Flow execution, or AGENTS:READ or AGENTS:EXECUTE for an Agent execution. For an execution that started through POST /v1/dispatch, DISPATCH:* also works. For an Agent execution, you can stream progress instead of polling. Call GET /v1/executions/{executionId}/events to replay the execution’s Server-Sent Events and receive new ones as they arrive. After a disconnect, pass the last SSE id that you received as the after query parameter to continue without gaps. The events endpoint needs DISPATCH:*, AGENTS:READ, or AGENTS:*, and returns 404 for a Flow run or an inline Agent definition.
The MCP dispatch, run_flow, and execute_agent tools expose asynchronous execution as async: true. Pass the returned executionId to get_execution_status while the execution is queued or running.
Raise the timeouts for a detached Flow
A detached Flow can set both options.flowTimeoutMs and options.stepTimeoutMs as high as 1800000 (30 minutes), which matches the batch per-Record ceiling. The attached limits stay at 15 minutes per Flow and 10 minutes per step. MCP run_flow exposes the same controls as flow_timeout_ms and step_timeout_ms. Values above the attached limits require async: true.
The higher limits apply only to a Flow target. The API returns a 400 validation error whose details array carries the code ASYNC_REQUIRED_FOR_EXTENDED_TIMEOUT in either of the following cases:
- An attached request sets
options.flowTimeoutMsabove 15 minutes oroptions.stepTimeoutMsabove 10 minutes. - An Agent dispatch sets either value above its attached limit, with or without
Prefer: respond-async.
To fix the error, send Prefer: respond-async with a Flow target, or lower the value.
Poll from the TypeScript SDK
The following TypeScript SDK code starts a detached dispatch, polls until the execution leaves the queued and running states, and then handles the result:
For a saved Agent, use client.agents.executeAsync(agentId, request) and poll the returned handle the same way.
Requests that asynchronous dispatch refuses
Asynchronous dispatch doesn’t store live credentials or replay stored history. It returns 400 for the following requests:
- A request with inline
secretsreturnsASYNC_INLINE_SECRETS_UNSUPPORTED. Store the credentials as managed Secrets and reference them with{{secret:NAME}}. - A request with an
identity_proofreturnsASYNC_IDENTITY_PROOF_UNSUPPORTED. Send the request withoutPrefer: respond-async. For more information, see End-user identity and credentials. - A request with
history: "stored"returnsSTORED_HISTORY_UNSUPPORTED. Send the conversation messages in the request, or send the request withoutPrefer: respond-async.
A request to a saved Claude Managed Agent that includes a conversationId can send inline secrets or an identity_proof with Prefer: respond-async.
Wait for slow external work with durable pauses
If a step spends most of its time waiting on an external system, use a wait-until step instead of holding a prompt or api-call step open. Configure the poll object with an HTTP request in http, an intervalMs, a maxAttempts cap, and a success criterion. The Flow pauses between poll attempts, and each attempt is a short request, not continuous execution.
The following step polls a job endpoint every 5 minutes until the job reports done:
In this example, jobId is a Flow variable that an earlier step sets. The step checks the job for about 24 hours (288 attempts at 5-minute intervals) and writes the final response to jobResult.
Durable pauses have the following bounds:
- A
wait-untilpoll runs at most 1,000 attempts. Runtype clamps a largermaxAttemptsvalue, and the Flow validator reports a warning. - The worst-case duration of a
wait-untilor asynchronouscrawlpause must be at most 30 days minus one hour. For a poll, the worst case ismaxAttemptstimes each attempt’s HTTP timeout (2 minutes when unset), plusintervalMsfor each wait between attempts. For a long wait, raiseintervalMs, notmaxAttempts. - A human approval gate holds for up to 7 days. If no one answers within 7 days, the pause expires and Runtype discards the paused state. A later approval returns
404(paused execution not found), so start a new execution instead.
Interactive dispatch, such as POST /v1/dispatch attached or with Prefer: respond-async, can hold a wait-until or crawl pause. Batch runs, evals, and Schedules refuse a Flow with a wait-until or crawl step. An Agent’s inline Flow tools can’t contain a wait-until or crawl step on any entry point, so put the waiting phase in a plain Flow and dispatch that Flow. When a saved Flow can’t run on every entry point, its validation response includes the RUNTIME_LANE_INELIGIBLE recommendation. For more information, see Flow validation warnings.
Run long phases as detached subagents
An attached subagent call waits for the child agent to finish, so the parent’s step budget bounds it. When a phase needs more time than that, run it detached.
A detached subagent runs as its own execution with its own budget. The spawning call returns a run ID immediately, and the parent continues. The budget defaults to 30 minutes and accepts values up to 24 hours:
- For subagents that the model spawns with
spawn_subagent, setdetachedMaxBudgetMsin the agent’ssubagentConfig. - For a saved subagent tool, set
maxBudgetMsin that tool’s execution config.
To allow detached execution for spawned subagents, include "detached" in the executionModes array of subagentConfig. Set defaultExecutionMode to choose the mode when the model doesn’t choose one. The following tools configuration lets the model run a spawned subagent for up to 2 hours:
The completion policy controls what happens when a detached subagent finishes. For spawned subagents, set defaultNotify in subagentConfig. For a saved subagent tool, set notify in that tool’s execution config. The policy accepts the following values:
nonestores the result.narrateposts status into the parent conversation. It’s the default, and it requires a saved parent Agent and aconversationId.
A detached call that requests react is rejected.
To stop a detached subagent, call POST /v1/agents/{id}/executions/{executionId}/cancel. When the run belongs to a parent conversation, pass conversationId as a query parameter. Cancellation is cooperative, and repeating the call is safe. The endpoint returns 202 Accepted.
For more information about subagent configuration, see Runtime tools.
Break large jobs into Records and batches
For a job with hours of model work, model each unit of work as a Record and process the units as batch runs:
- Create a Record for each unit of work, with the unit’s input in the Record fields.
- Run each phase as a batch over those Records. Each Record’s execution gets its own timeout of up to 30 minutes, and the batch runs Records concurrently.
- Persist each phase’s output back onto the Record with an
upsert-recordstep, so the next phase reads its input from the Record rather than from a live execution. - Submit the next phase’s batch when the preceding batch completes. Poll
GET /v1/batch/status/{id}from your own system until the status is terminal:completed,failed, orcancelled. Submit the next batch oncompleted. Onfailedorcancelled, stop the chain and retry or recover the failed Records before you continue.
Schedules can also run phases on a fixed cadence. A Schedule fires by cron rather than on batch completion, so it can’t wait for the preceding phase. If you chain phases with Schedules, make each phase idempotent. Start the phase’s Flow with a check that the Record carries the preceding phase’s output, and skip the Record otherwise. A run that fires before the preceding phase finishes then does no harm, and the next firing picks the Record up.
The total wall-clock time of the job has no limit, because each Record execution is its own continuous run. A 12-hour job becomes a sequence of phases, and each phase finishes in minutes per Record.
Size each phase so that one Record’s work for that phase fits inside 30 minutes. If a single unit’s phase exceeds that, split the phase into smaller phases or split the unit into smaller Records.
Run multi-session agent tasks from the CLI
For a long agent task that you drive from your own machine, the runtype CLI’s Marathon mode runs a saved Agent across many sessions with checkpoints, resumable state, and cost caps. For more information, see Marathon: long-running agent tasks (CLI).
Next steps
- Running flows in batch: process Records concurrently with per-Record timeouts
- Using record steps (get/list/upsert): persist phase output between runs
- Handling batch failures: retry and recover failed Records in a batch
- Automating batch processing: run batch phases on a Schedule
- Using Wait Until steps: pause a Flow for a delay or until a polled condition is met