Cori
Reference

Retries and timeouts

Default retry counts and per-attempt timeouts for each activity kind, and how to override them.

Defaults by activity kind

KindDefault max_attemptsWhyDefault per-attempt timeout
code3Pure computation — transient failures are uncommon but retrying is safe30 seconds
llm3API rate limits and transient model errors are common300 seconds
cli1External commands may have non-idempotent side effects60 seconds
mcp_tool1MCP tool calls may have non-idempotent side effects60 seconds

Why cli and mcp_tool default to 1 attempt: these steps often write to external systems. Retrying a write unexpectedly is worse than failing fast and letting the operator decide. If your cli or mcp_tool step is idempotent, you can safely increase max_attempts.

schedule_to_start_timeout

Every activity has a 30-second schedule_to_start_timeout. If no worker picks up the activity within 30 seconds of it being scheduled, the activity fails with a "no worker on this queue" error. This fails fast rather than waiting indefinitely for a worker that may never come online.

If you see this error, run cori status to check whether the expected worker is online.

Overriding retries and timeouts

Per step, in the step file:

export default step.cli({
  description: 'Idempotent write to S3',
  command: ({ input }) => `aws s3 cp ${input.file} s3://my-bucket/`,
  parse_output: (stdout) => ({ success: true }),
  retries: {
    max: 3,
    backoff: 'exponential',
  },
  timeout_ms: 120_000,  // 2 minutes
});
export default step.llm({
  description: 'Translate a large document',
  model: 'gpt-4o',
  prompt: ({ input }) => `Translate to French:\n\n${input.text}`,
  output_schema: output,
  timeout_ms: 600_000,  // 10 minutes for large documents
});

Retryable vs. non-retryable errors

Backoff strategies

When retrying a failed step, the worker waits between attempts using the backoff strategy:

  • "exponential" (default) — backoff coefficient 2.0; each retry waits twice as long as the previous
  • "linear" — backoff coefficient 1.0; each retry waits the same interval

Both strategies start with an initial interval of 1 second and cap at a maximum of 60 seconds between attempts.

Example with linear backoff:

export default step.cli({
  retries: { max: 5, backoff: 'linear' },
  command: () => ['gws', 'sheets'],
});

Retryable vs. non-retryable errors

Error classRetried?
Transient API error (rate limit, 5xx)Yes, up to max
Non-zero exit code from a cli stepYes, up to max
MCP tool errorYes, up to max
schedule_to_start timeout (no worker)No — fails immediately
Manifest validation failureNo — fails immediately, fix required
TypeScript compilation errorNo — fails immediately, fix required

On this page