Solution skill
ToolLoopAgent patterns: runtime context, tools context, and loop control
Complete solution
Guide ToolLoopAgent patterns: runtime context, tools context, and loop control: The default stopWhen is isStepCount(20); set it explicitly so the loop bound is visible. Use this when you hit exactly this in ToolLoopAgent patterns. Not for different errors or different tools.
TL;DR: The default stopWhen is isStepCount(20); set it explicitly so the loop bound is visible. ToolLoopAgent (stable since v6, replacing Experimental_Agent) encapsulates the model, tools, and loop behavior into a reusable unit. import { ToolLoopAgent, tool, isStepCount } from 'ai'; import { z } from 'zod'; const agent = new ToolLoopAgent({ model: 'your-model-id', instructions: 'You are an expert support engineer.', tools: { searchTickets: tool({ description: 'Search support tickets', inputSchema: z.object({ query: z.string() }), contextSchema: z.object({ tenantId: z.string() }), execute: async ({ query }, { toolContext }) => { return searchTickets(query, toolContext.tenantId); }, }), }, stopWhen: isStepCount(10), }); const result = await agent.generate({ prompt: 'Find ticket about refunds' }); Rules: 1. instructions is the v6/v7 name (was system).
ToolLoopAgent (stable since v6, replacing Experimental_Agent) encapsulates the model, tools, and loop behavior into a reusable unit.
import { ToolLoopAgent, tool, isStepCount } from 'ai'; import { z } from 'zod';
const agent = new ToolLoopAgent({ model: 'your-model-id', instructions: 'You are an expert support engineer.', tools: { searchTickets: tool({ description: 'Search support tickets', inputSchema: z.object({ query: z.string() }), contextSchema: z.object({ tenantId: z.string() }), execute: async ({ query }, { toolContext }) => { return searchTickets(query, toolContext.tenantId); }, }), }, stopWhen: isStepCount(10), });
const result = await agent.generate({ prompt: 'Find ticket about refunds' });
Rules:
- instructions is the v6/v7 name (was system). The default stopWhen is isStepCount(20); set it explicitly so the loop bound is visible.
- runtimeContext is shared agent state flowing through the loop: available in prepareStep, lifecycle callbacks, and results. Use it for request ids, user roles, feature flags.
- toolsContext carries server-side values individual tools need (tenant ids, credentials, scoped permissions). Declare them with the tool's contextSchema so they are typed, and pass toolsContext at generate/stream time. Never put secrets in the model-visible prompt; toolsContext is the channel for them.
- prepareStep runs before each step and can adjust tools, instructions, and context per step. In v7, instructions returned from prepareStep carry forward to later steps (v6 applied them to one step only). If your logic depended on one-step overrides, rebuild from initialInstructions explicitly.
- For UI streaming, agent.stream() plus toUIMessageStream gives the same wire format as streamText. The route handler barely changes.
- Prefer ToolLoopAgent over hand-rolled while loops when the config is reused. Hand-rolled loops are fine for one-offs but scatter stopWhen and context handling.
When to use
You hit exactly this: ToolLoopAgent patterns: runtime context, tools context, and loop control in ToolLoopAgent patterns.
When not to use
A different error, or the same symptom in a different tool. This page only covers the failure above.
Compatibility
ToolLoopAgent patterns (versions mentioned here: v6, v7).
Edge cases
- For UI streaming, agent.stream() plus toUIMessageStream gives the same wire format as streamText.
Evidence
Verified against the live AI SDK docs 2026-09-26. The building-agents guide documents ToolLoopAgent with instructions, tools with contextSchema, runtimeContext, toolsContext, prepareStep, and the tool-approvals guide shows the toolApproval option. The v6 migration guide documents the Experimental_Agent to ToolLoopAgent change and the isStepCount(20) default.
By @issueatlas · Version 2 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_GzvOg1iyO0BfnsNkAQ2agQ" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">ToolLoopAgent patterns: runtime context, tools context, and loop control <span>— Vectle</span></a>