Skip to Content
Run limits

Run limits and loop safety

An agent that works on its own decides its next step itself. Run limits make sure it cannot go on forever or run up a bill: every run (one job an agent does, such as answering one question) stops after a set number of steps, a set amount of money or a set time, whichever comes first. For example, “stop after 50 steps, $1 or 15 minutes”.

If you set nothing, every run already has sensible limits. You only change them when an agent needs more room or less.

Change an agent’s limits

  1. Open the agent and click Edit.
  2. Find Run limits. On an autonomous agent it is part of the page; on a workflow agent click Settings in the toolbar above the canvas and it opens above the graph.
  3. The section shows, in one line, what a run will get, for example “Stops after 50 steps, $1 or 15 minutes, whichever comes first.”
  4. Open Advanced to change the fields below. Leave a field empty to keep the default; empty never means zero.
  5. Save the agent.
FieldWhat it limitsDefault
Max stepshow many times the agent may go round its loop50
Spending cap ($)what the run may spend on models$1
Token budgethow much text the run may send and receive in total (counted in tokens, the unit model vendors bill by)500,000
Timeout (seconds)how long the run may take15 minutes
Max tool callshow many times it may use a tool100
Tool error retrieshow often a failing tool is tried again3
When the context budget runs outDrop the oldest turns, Summarise the older turns, or Stop the rundrop the oldest
When a tool call failsShow the agent the full error, Show a one-line summary, or Only say that it failedfull error

A run can also start helper agents, and those can start their own. That nesting stops after 3 levels. This one has no field on the page.

Organization defaults

Admins set defaults for every agent in Settings → Organization → Details, under Agent defaults: Max cost per run ($) and Max steps per run.

How the limits combine

Limits can be set in four places: by whoever runs almyty (the hard ceiling), by the organization, on the agent, and for a single run. The smallest number wins. A narrower place can only tighten a limit, never loosen it, so an agent author cannot go past what the organization set, and nobody inside the product can go past the hard ceiling. By default that ceiling is 100 steps, $5, one hour, 200 tool calls, 2,000,000 tokens and 5 levels of helper agents.

So a default of 15 minutes under a ceiling of one hour means a run may be given up to an hour, and gets 15 minutes if nobody says otherwise.

Limits are worked out while the run is going, not when you save. If the organization tightens a limit, running agents follow it from their next step.

Helper agents share their parent’s limits rather than getting fresh ones. Without that, an agent allowed one dollar could start ten helpers allowed one dollar each. A loop step inside a workflow is bound too: a loop asking for 100 rounds inside a run capped at 25 steps gets 25.

When a limit is reached

The run stops and says why in a sentence you can act on, for example that it reached its spending cap. It never just goes quiet. You can then try again with a smaller request, raise the limit, or pass it to a person.

Checking which limits applied

Every run records the limits it actually ran under, not just what was asked for. Months later you can still see which ceilings governed a particular run, even if the policy has changed since.

For developers

Scopes, from widest to narrowest:

environment floor RUN_LIMIT_MAX_* operator, cannot be raised from inside organization agentDefaults org admin agent agentConfig.runLimits agent author run per-call overrides the caller

For each numeric limit the resolver takes the smallest value any scope specified, then clamps it to the environment floor (resolveRunLimits in backend/src/modules/agents/run-limits.ts). The enum limits are ranked by restrictiveness so a narrower scope cannot loosen them: truncation fail beats summarise beats drop_oldest; tool error feedback suppressed beats summarised beats full.

Defaults and fields: maxSteps 50, maxTokens 500000, maxCostCents 100, maxDurationMs 900000, maxToolCalls 100, maxRecursionDepth 3 (depth 0 is the run itself), truncationPolicy drop_oldest, toolErrorRetries 3, toolErrorFeedback full. Tool error feedback summarised keeps the first line, capped at 200 characters; suppressed tells the model the call failed without the text.

The environment floor:

VariableDefault
RUN_LIMIT_MAX_STEPS100
RUN_LIMIT_MAX_TOKENS2000000
RUN_LIMIT_MAX_COST_CENTS500
RUN_LIMIT_MAX_DURATION_MS3600000
RUN_LIMIT_MAX_TOOL_CALLS200
RUN_LIMIT_MAX_RECURSION_DEPTH5

Self-hosters own these; they are the only ceiling no in-product role can raise.

One ledger. The run-scoped accumulator is the agent_runs row: currentStep, totalTokens, totalCost, executionTime, toolCallCount, recursionDepth. A nested run (sub-agent, called agent, temporary agent) inherits its parent’s resolved limits and increments recursionDepth.

Workflow runs. The timeout is the tighter of the agent’s settings.maxExecutionTime (5 minutes when unset) and the resolved timeout; the spending cap is the tighter of settings.budgetLimit and the resolved cost cap. A workflow run stops with status timeout and Execution timed out after <n>ms, or failed and Budget limit ($<cap>) exceeded: $<spent>, checked between steps; a step running when the cap is crossed is aborted. Max tool calls counts every tool_call node, tool error retries apply to each, and max recursion depth bounds sub_agent nesting.

Trip codes. The code lands on run.metadata.limitTrip and on the run.failed event:

CodeMeaning
MAX_STEPS_EXCEEDEDThe run reached its step ceiling
BUDGET_EXCEEDEDThe run reached its cost cap
TIMEOUTThe run reached its wall-clock limit
TOKEN_LIMIT_EXCEEDEDThe run reached its token budget
TOOL_CALL_LIMIT_EXCEEDEDThe run reached its tool-call ceiling
RECURSION_DEPTH_EXCEEDEDSub-agents nested deeper than allowed
CONTEXT_BUDGET_EXCEEDEDContext was exhausted and the policy is fail

Audit. Every run emits a run_start audit event carrying the resolved limits snapshot.