new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

AI SDK · Cookbook · all subjects

agent patterns

13 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

ToolLoopAgent creates reusable multi-step agents

ToolLoopAgent creates a reusable AI agent capable of generating text, streaming responses, and using tools over multiple steps in a reasoning-and-acting loop. Unlike single-step calls like generateText(), an agent can iteratively invoke tools, collect tool results, and decide next actions until completion or user approval is required.

ToolLoopAgent constructor parameters

ToolLoopAgent constructor accepts the following parameters: model (LanguageModel, required); instructions (Instructions, optional) for system prompt/context; allowSystemInMessages (boolean, optional) to allow or reject system messages in prompt/messages fields (default rejects to prevent prompt injection); tools (Record<string, Tool>, optional) for tools the agent can call; toolChoice (ToolChoice, optional) with options 'auto'|'none'|'required'|{type:'tool', toolName:string}, default 'auto'; stopWhen (StopCondition|StopCondition[], optional) for ending agent loop, default isStepCount(20); activeTools (ActiveTools<TOOLS>, optional) to limit available tools; toolOrder (ToolOrder<TOOLS>, optional) to control tool ordering to provider; toolApproval (ToolApprovalConfiguration<TOOLS, RUNTIME_CONTEXT>, optional) for approval handling; experimental_toolCallers (Experimental_ToolCallers<TOOLS>, optional) for configuring which caller tools may invoke each tool; output (Output, optional) for structured output specification; prepareStep (PrepareStepFunction, optional) to mutate step settings per agent step; include ({requestBody, requestMessages, responseBody, rawChunks}, optional) for controlling data in results; repairToolCall (ToolCallRepairFunction, optional) for automatic tool call recovery; experimental_refineToolInput (ToolInputRefinement<TOOLS>, optional) for refining parsed tool inputs; onStart, onStepStart, onToolExecutionStart, onToolExecutionEnd, onStepEnd, onEnd lifecycle callbacks (all optional); runtimeContext (CONTEXT, optional) for user-defined shared runtime state; toolsContext (InferToolSetContext<TOOLS>) for per-tool context map; telemetry (TelemetryOptions, optional) for telemetry configuration; experimental_download (DownloadFunction, optional) for custom file downloading; maxOutputTokens, temperature, topP, topK, presencePenalty, frequencyPenalty (all number, optional); stopSequences (string[], optional); seed (number, optional); maxRetries (number, optional, default 2); providerOptions (ProviderOptions, optional); headers (Record<string, string|undefined>, optional); callOptionsSchema (FlexibleSchema<CALL_OPTIONS>, optional); prepareCall (PrepareCallFunction, optional); id (string, optional) for custom agent identifier.

ToolLoopAgent.generate() method

The generate() method generates a response and triggers tool calls as needed, running the agent loop and returning the final result as a GenerateTextResult. Parameters: prompt (string|Array<ModelMessage>) for text prompt or message array; messages (Array<ModelMessage>) for full conversation history; abortSignal (AbortSignal, optional) to cancel the call; timeout (number|{totalMs, stepMs, firstChunkMs, chunkMs}, optional) in milliseconds; experimental_sandbox (Experimental_SandboxSession, optional) for sandbox environment; options (CALL_OPTIONS, optional) for custom call options when callOptionsSchema is configured; lifecycle callbacks (onStart, onStepStart, onToolExecutionStart, onToolExecutionEnd, onStepEnd, onEnd, all optional) that are called in addition to constructor callbacks (constructor first).

ToolLoopAgent.stream() method

The stream() method streams a response from the agent including agent reasoning and tool calls as they occur, returning a StreamTextResult. Parameters: prompt (string|Array<ModelMessage>) for text prompt or message array; messages (Array<ModelMessage>) for full conversation history; abortSignal (AbortSignal, optional) to cancel the call; timeout (number|{totalMs, stepMs, firstChunkMs, chunkMs}, optional) where firstChunkMs limits wait for first content-bearing output in each model-call step and chunkMs limits gaps between later content-bearing output chunks; experimental_sandbox (Experimental_SandboxSession, optional) for sandbox environment; options (CALL_OPTIONS, optional) for custom call options; experimental_transform (StreamTextTransform|Array<StreamTextTransform>, optional) for optional stream transformations; lifecycle callbacks (onStart, onStepStart, onToolExecutionStart, onToolExecutionEnd, onStepEnd, onEnd, all optional) with constructor callbacks called first.

ToolLoopAgent basic example with tools

```ts import { ToolLoopAgent, isStepCount } from 'ai'; import { weatherTool, calculatorTool } from './tools'; const assistant = new ToolLoopAgent({ model: __MODEL__, instructions: 'You are a helpful assistant.', tools: { weather: weatherTool, calculator: calculatorTool, }, stopWhen: isStepCount(3), }); const result = await assistant.generate({ prompt: 'What is the weather in NYC and what is 100 * 25?', }); console.log(result.text); console.log(result.steps); // Array of all steps taken by the agent ```

ToolLoopAgent with tool approval workflow

```ts import { ToolLoopAgent, ModelMessage, ToolApprovalResponse, tool } from 'ai'; import { z } from 'zod'; const agent = new ToolLoopAgent({ model: __MODEL__, instructions: 'You are an agent with access to a weather API.', tools: { weather: tool({ description: 'Get the weather in a location', inputSchema: z.object({ location: z.string(), }), execute: async ({ location }) => ({ location, temperature: 72, }), }), }, toolApproval: { weather: 'user-approval', }, }); const messages: ModelMessage[] = [ { role: 'user', content: 'Is it raining in Paris today?' }, ]; const result = await agent.generate({ messages }); const approvals: ToolApprovalResponse[] = []; for (const part of result.content) { if (part.type === 'tool-approval-request') { approvals.push({ type: 'tool-approval-response', approvalId: part.approvalId, approved: true, }); } } messages.push(...result.responseMessages); messages.push({ role: 'tool', content: approvals }); const approvedResult = await agent.generate({ messages }); console.log(approvedResult.text); ```

ToolLoopAgent toolApproval configuration

The toolApproval parameter in ToolLoopAgent constructor accepts ToolApprovalConfiguration<TOOLS, RUNTIME_CONTEXT> which can be a GenericToolApprovalFunction to handle all tool calls in one callback, or a per-tool object where each key can be: a status string ('not-applicable', 'approved', 'denied', or 'user-approval'), an object form such as {type: 'denied', reason: 'blocked by policy'}, or a SingleToolApprovalFunction that receives tool input and options (toolCallId, messages, toolContext, runtimeContext). Functions may return undefined for the same effect as 'not-applicable'. The default execution path is 'not-applicable' which runs the tool without approval metadata. Use 'approved', 'denied', or their object forms for explicit automatic approval request/response parts in output. This setting takes precedence over a tool's needsApproval default.

ToolLoopAgent prepareStep function for per-step customization

The prepareStep parameter in ToolLoopAgent constructor accepts a PrepareStepFunction that allows mutation of step settings or injection of state for each agent step. This includes per-step model call settings such as temperature, maxOutputTokens, sampling controls (topP, topK), penalties (presencePenalty, frequencyPenalty), stopSequences, seed, and reasoning. Model call setting overrides from prepareStep apply only to the current step.

ToolLoopAgent lifecycle callbacks execution order

ToolLoopAgent supports lifecycle callbacks: onStart (called when agent operation begins), onStepStart (called when each step begins before provider call), onToolExecutionStart (called right before tool execute function runs), onToolExecutionEnd (called right after tool execute function completes or errors), onStepEnd (called after each agent step completes), and onEnd (called when all agent steps are finished). If a callback is specified both in constructor and in generate()/stream(), both are called with constructor callback executed first.

ToolLoopAgent include parameter for result filtering

The include parameter in ToolLoopAgent constructor controls what data is included in step results with options: requestBody (boolean, optional), requestMessages (boolean, optional), responseBody (boolean, optional), and rawChunks (boolean, optional). For generate(), requestBody, requestMessages, and responseBody apply. For stream(), requestBody, requestMessages, and rawChunks apply.

ToolLoopAgent telemetry configuration

The telemetry parameter in ToolLoopAgent constructor accepts TelemetryOptions with properties: includeRuntimeContext ({[KEY in keyof CONTEXT]?: boolean}, optional) to specify top-level runtime context properties included in telemetry (runtime context properties excluded unless explicitly set to true); includeToolsContext ({[TOOL_NAME in keyof InferToolSetContext<TOOLS>]?: {[KEY in keyof InferToolSetContext<TOOLS>[TOOL_NAME]]?: boolean}}, optional) to specify top-level tool context properties included in telemetry per tool. Lifecycle callbacks and returned results still receive the full runtimeContext and toolsContext.

InferAgentUIMessage type helper

InferAgentUIMessage is a type helper that infers the UI message type for a given ToolLoopAgent instance. It accepts the agent instance as the first type argument. Optionally, a second type argument can be provided to customize metadata for each message, useful for tracking rich metadata returned by the agent such as createdAt, tokens, and finish reason.

ToolLoopAgent timeout configuration options

The timeout parameter in generate() and stream() methods can be specified as either a number (timeout in milliseconds) or an object with properties: totalMs (total timeout for entire operation), stepMs (timeout per agent step), firstChunkMs (limits wait for first content-bearing output in each model-call step, stream-only), and chunkMs (limits gaps between later content-bearing output chunks, stream-only). Can be used alongside abortSignal.

Give your agent this brain