Skip to main content

Why limits exist

Without limits, a stuck model can loop forever — calling the same tool repeatedly, or an orchestrator delegating endlessly. Each loop costs money and time. The engine enforces these caps at the runtime level, not through prompts. A prompt can ask the model to behave; only the runtime can guarantee it stops.

Default limits

A duplicate is the same tool called with identical arguments in the same run. These defaults apply automatically even with no execution: block in your YAML.

Configuring limits

Add an execution: block to your spec. Any omitted key keeps its default.
Limits are validated at parse time — invalid values (non-integers, wrong types) fail agentctl validate with a clear error.

What happens when a limit is hit

The run degrades gracefully — no exception, no crash.
  • Tool/child-agent limits and duplicates — the call is blocked. The model receives a short message like “Tool call limit reached, finish with what you have.” and naturally wraps up.
  • max_iterations — the node’s loop stops. Its pending tool calls are blocked, and the model gets one final turn to answer with what it has. If that turn has no text, the node answers “I couldn’t finish this request within the allowed number of steps.” instead of returning an empty answer.
The engine logs a warning with the run id, limit name, and current count. It never logs prompts, tool arguments, or secrets.