Loop Control

Purpose and Scope

Loop control is the part of an AI SDK agent that decides whether another model step should run after tool activity. A step is one pass through the agent loop: the model receives messages, may emit text or tool calls, and the SDK records the resulting step information. Without explicit loop control, an agent that keeps receiving tool results could continue making more calls than the application intended. The documented agent loop therefore treats stopping as a first-class design concern rather than an incidental side effect of tool execution.

Sources: content/docs/03-agents/04-loop-control.mdx

The Loop Control documentation defines two user-facing controls: stopWhen and prepareStep. stopWhen describes stopping conditions for the loop, while prepareStep lets an application modify settings between steps, including the model, tools, messages, and related call configuration. This separation is important: stopping policy answers whether the loop should continue, and step preparation answers how the next step should be configured if the loop does continue. Together they let developers build agents that are capable of multi-step work without giving up operational bounds.

Sources: content/docs/03-agents/04-loop-control.mdx

Relevant Source Files

  • content/docs/03-agents/04-loop-control.mdx — First-party documentation for agent loop control, including the stop reasons, default step limit, built-in stop conditions, examples for ToolLoopAgent, and custom StopCondition patterns.

Agent Loop Termination Model

The agent loop continues only while the previous step leaves useful work for another step. The documentation lists four ways the loop can stop: the model returns a finish reasoning other than tool calls, a called tool lacks an execute function, a tool call needs approval, or an explicit stop condition is met. These cases distinguish natural completion from application-controlled interruption. Natural completion happens when the model stops asking for tools. Interruption happens when the SDK cannot or should not execute a requested tool, or when the developer's policy says enough steps have occurred.

Sources: content/docs/03-agents/04-loop-control.mdx

Tool calls drive iteration because the loop is specifically concerned with what happens after tool results exist in the last step. If a model calls a tool and the tool executes, the result can be fed back into the next model step so the agent can reason over the result and decide whether to answer, call another tool, or continue decomposing the task. The stopWhen parameter is evaluated in this multi-step context. It does not replace tool execution; it bounds the repeated model-tool-model cycle that makes agents useful for research, analysis, coding, and other staged tasks.

Sources: content/docs/03-agents/04-loop-control.mdx

Stop Conditions

By default, agents stop after 20 steps by using isStepCount(20). The documentation frames this as a safety measure that protects applications from runaway loops, excessive API calls, and unexpected cost. This default matters even for well-designed tools because a model can repeatedly decide that another lookup, calculation, or file operation is needed. Raising or removing the limit should therefore be a deliberate product decision based on the task shape, the cost model, and the confidence that the tool loop will eventually converge.

Sources: content/docs/03-agents/04-loop-control.mdx

When an application provides stopWhen, the agent continues after tool calls until a condition is met. A single condition can encode a simple maximum step count, while an array represents an OR policy: execution stops when any listed condition becomes true. This array behavior is useful for combining a global budget with domain-specific completion markers. For example, an agent can stop after 20 steps or as soon as it calls a tool named done, whichever happens first. The result is a readable policy that constrains cost while still allowing a semantic exit hatch.

Sources: content/docs/03-agents/04-loop-control.mdx

Built-in Conditions and Reference

The documented built-in conditions cover the most common loop policies. Use isStepCount(count) when the main concern is a hard upper bound. Use hasToolCall(...toolNames) when the model's selection of a particular tool is the completion signal. Use isLoopFinished() when the application wants the model to run until it naturally stops making tool calls, with no maximum step limit. The documentation explicitly warns that isLoopFinished() should be used cautiously because an unbounded loop can run indefinitely or incur significant costs if the model keeps requesting tools.

Sources: content/docs/03-agents/04-loop-control.mdx

APIRoleTypical use
stopWhenAgent option for stopping policyLimit or semantically end a tool loop
prepareStepAgent option for per-step changesModify model, tools, messages, or settings between steps
isStepCount(count)Built-in stop conditionStop after a maximum number of steps
hasToolCall(...toolNames)Built-in stop conditionStop when specific tools are called
isLoopFinished()Built-in stop conditionRemove the default step limit and rely on natural completion
StopCondition<typeof tools>Type for custom stop policiesInspect accumulated step information and return a boolean
ToolLoopAgentAgent class used in examplesConfigure a model, tools, and loop control, then call generate

A maximum-step configuration follows the documented pattern: create a ToolLoopAgent, provide a model and tools, set stopWhen, and call agent.generate with a prompt. The example below shows the shape without provider-specific placeholders. The key decision is the selected limit. Increasing the limit from the default of 20 to 50 can be appropriate for dataset analysis or report generation, but it also expands the number of possible model calls, tool executions, and intermediate states the application must tolerate.

import { ToolLoopAgent, isStepCount } from 'ai';
 
const agent = new ToolLoopAgent({
  model,
  tools: {
    // your tools
  },
  stopWhen: isStepCount(50),
});
 
const result = await agent.generate({
  prompt: 'Analyze this dataset and create a summary report',
});

Sources: content/docs/03-agents/04-loop-control.mdx

Custom Conditions

Custom conditions are the escape hatch for application-specific loop policy. The documentation shows a StopCondition<typeof tools> that receives step information and returns a boolean. In one pattern, the condition scans accumulated steps for text that includes a marker such as ANSWER:. This lets the prompt and loop policy cooperate: the prompt asks the model to emit a recognizable completion marker, and the stop condition ends the loop when that marker appears. The condition is typed against the tool set, so the policy can be written with awareness of the agent's configured tools.

Sources: content/docs/03-agents/04-loop-control.mdx

A second custom-policy pattern uses step metadata rather than generated text. The documentation begins an example that computes aggregate usage from all steps by reducing over steps and reading token usage fields such as inputTokens and outputTokens. That pattern is useful when the application wants a budget-aware loop independent of whether the model has found an answer. In practice, a custom condition can combine text inspection, tool-call history, usage totals, or other step-level signals to enforce product-specific stopping rules.

Sources: content/docs/03-agents/04-loop-control.mdx

import { ToolLoopAgent, StopCondition, ToolSet } from 'ai';
 
const tools = {
  // your tools
} satisfies ToolSet;
 
const hasAnswer: StopCondition<typeof tools> = ({ steps }) => {
  return steps.some(step => step.text?.includes('ANSWER:')) ?? false;
};
 
const agent = new ToolLoopAgent({
  model,
  tools,
  stopWhen: hasAnswer,
});

Execution Flow

A practical way to design loop control is to start from the task's expected shape. For short tasks, keep the default 20-step safety limit or set a smaller isStepCount threshold. For open-ended tool use, add a semantic condition such as hasToolCall('done') so the model can explicitly signal completion through a tool. For high-risk or high-cost work, prefer a custom StopCondition that inspects the accumulated steps and stops on budget, completion markers, or other durable signals rather than relying only on the model's next natural finish reason.

Sources: content/docs/03-agents/04-loop-control.mdx

prepareStep belongs in the same design conversation even though it solves a different problem. Once stopWhen has allowed the loop to continue, prepareStep can adjust the next step's settings, such as changing the model, narrowing tools, or modifying messages. This makes it possible to build loops that become more constrained over time: early steps might gather information with a broad tool set, while later steps can use a smaller set or different messages. Treat stopWhen as the guardrail and prepareStep as the per-step steering mechanism.

Sources: content/docs/03-agents/04-loop-control.mdx

Next Steps

After choosing a loop policy, test it with realistic prompts that cause multiple tool calls, not only single-turn happy paths. Confirm that the loop stops when the model finishes naturally, when a requested tool cannot execute, when a tool approval is required, and when your explicit stop condition fires. Then review adjacent agent topics: build the agent and tools first, tune call options with prepareStep where needed, and add approval or memory behavior only after the loop boundaries are clear. Loop control is safest when it is designed before the agent is exposed to broad user input.

Sources: content/docs/03-agents/04-loop-control.mdx