#[non_exhaustive]pub struct ExecutionLimits {
pub max_turns: usize,
pub max_total_tokens: usize,
pub max_duration: Duration,
pub max_consecutive_identical_tool_calls: Option<usize>,
}Expand description
Execution limits for the agent loop
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.max_turns: usizeMaximum number of turns (LLM calls)
max_total_tokens: usizeMaximum tokens the model processes in one run (each prompt /
continue_loop starts again at 0): every turn adds its whole prompt
(input + cache_read + cache_write) plus its output.
The prompt resends the conversation each turn, so the total is about
turns × context size — quadratic in turns while the conversation is
still growing. At a 60K-token context the 1M default is reached around
turn 16, cached or not. It is checked before each turn, so the last
turn can go over by one turn’s tokens. For long agentic runs raise it
(or set usize::MAX and rely on max_turns).
max_duration: DurationMaximum wall-clock time of one run (default 10 minutes); checked between turns. A single long agentic run reaches it; raise it for those.
max_consecutive_identical_tool_calls: Option<usize>Consecutive identical tool calls tolerated before intervening.
The cheapest catastrophic failure mode is a model calling one tool with the same arguments forever. The other three limits all fire eventually, but only after burning the full turn, token and wall-clock budget — so the run costs its maximum to discover it achieved nothing.
Consecutive, and that word is load-bearing. A different signature
resets the streak, so a model alternating [a, b, a, b, …] forever is
not detected. That is a deliberate trade, not an oversight: an agent
working through a list calls one tool repeatedly and legitimately, and
a detector that fired on interleaved repeats would be worse than none.
See an_interleaved_different_call_resets_the_counter. Widening this
to a windowed count is tracked separately.
None disables the check. Some(0) also disables it — there is no
streak length below which a call has not been made. Some(1) steers on
the very first tool call of a run, which is almost never wanted.
Default Some(3).
Implementations§
Source§impl ExecutionLimits
impl ExecutionLimits
Sourcepub fn with_max_turns(self, turns: usize) -> Self
pub fn with_max_turns(self, turns: usize) -> Self
Cap on turns before the run stops.
Sourcepub fn with_max_total_tokens(self, tokens: usize) -> Self
pub fn with_max_total_tokens(self, tokens: usize) -> Self
Cap on tokens processed in one run — every turn’s whole prompt plus
its output, so it grows much faster than the conversation. See
max_total_tokens.
Sourcepub fn with_max_duration(self, duration: Duration) -> Self
pub fn with_max_duration(self, duration: Duration) -> Self
Wall-clock cap on the run.
Sourcepub fn with_max_consecutive_identical_tool_calls(
self,
calls: Option<usize>,
) -> Self
pub fn with_max_consecutive_identical_tool_calls( self, calls: Option<usize>, ) -> Self
Consecutive identical tool calls tolerated before steering, then
stopping. None disables loop detection entirely.