---
title: ToolLoopAgent
description: API Reference for the ToolLoopAgent class.
---

# `ToolLoopAgent`

Creates a reusable AI agent capable of generating text, streaming responses, and using tools over multiple steps (a reasoning-and-acting loop). `ToolLoopAgent` is ideal for building autonomous, multi-step agents that can take actions, call tools, and reason over the results until a stop condition is reached.

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.

```ts
import { ToolLoopAgent } from 'ai';
__PROVIDER_IMPORT__;

const agent = new ToolLoopAgent({
  model: __MODEL__,
  instructions: 'You are a helpful assistant.',
  tools: {
    weather: weatherTool,
    calculator: calculatorTool,
  },
});

const result = await agent.generate({
  prompt: 'What is the weather in NYC?',
});

console.log(result.text);
```

To see `ToolLoopAgent` in action, check out [these examples](#examples).

## Import

<Snippet text={`import { ToolLoopAgent } from "ai"`} prompt={false} />

## Constructor

### Parameters

<PropertiesTable
  content={[
    {
      name: 'model',
      type: 'LanguageModel',
      isRequired: true,
      description:
        'The language model instance to use (e.g., from a provider).',
    },
    {
      name: 'instructions',
      type: 'string | SystemModelMessage | SystemModelMessage[]',
      isOptional: true,
      description:
        'Instructions for the agent, usually used for system prompt/context.',
    },
    {
      name: 'tools',
      type: 'Record<string, Tool>',
      isOptional: true,
      description:
        'A set of tools the agent can call. Keys are tool names. Tools require the underlying model to support tool calling.',
    },
    {
      name: 'toolChoice',
      type: 'ToolChoice',
      isOptional: true,
      description:
        "Tool call selection strategy. Options: 'auto' | 'none' | 'required' | { type: 'tool', toolName: string }. Default: 'auto'.",
    },
    {
      name: 'stopWhen',
      type: 'StopCondition | StopCondition[]',
      isOptional: true,
      description:
        'Condition(s) for ending the agent loop. Default: stepCountIs(20).',
    },
    {
      name: 'activeTools',
      type: 'Array<string>',
      isOptional: true,
      description:
        'Limits the subset of tools that are available in a specific call.',
    },
    {
      name: 'output',
      type: 'Output',
      isOptional: true,
      description:
        'Optional structured output specification, for parsing responses into typesafe data.',
    },
    {
      name: 'prepareStep',
      type: 'PrepareStepFunction',
      isOptional: true,
      description:
        'Optional function to mutate step settings or inject state for each agent step.',
    },
    {
      name: 'experimental_repairToolCall',
      type: 'ToolCallRepairFunction',
      isOptional: true,
      description:
        'Optional callback to attempt automatic recovery when a tool call cannot be parsed.',
    },
    {
      name: 'experimental_onStart',
      type: 'ToolLoopAgentOnStartCallback',
      isOptional: true,
      description:
        'Callback that is called when the agent operation begins, before any LLM calls are made. Useful for logging, analytics, or initializing state. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first). Experimental (can break in patch releases).',
      properties: [
        {
          type: 'OnStartEvent',
          parameters: [
            {
              name: 'model',
              type: '{ provider: string; modelId: string }',
              description: 'The model being used for the generation.',
            },
            {
              name: 'system',
              type: 'string | SystemModelMessage | Array<SystemModelMessage> | undefined',
              description: 'The system message(s) provided to the model.',
            },
            {
              name: 'prompt',
              type: 'string | Array<ModelMessage> | undefined',
              description:
                'The prompt string or array of messages if using the prompt option.',
            },
            {
              name: 'messages',
              type: 'Array<ModelMessage> | undefined',
              description: 'The messages array if using the messages option.',
            },
            {
              name: 'tools',
              type: 'TOOLS | undefined',
              description: 'The tools available for this generation.',
            },
            {
              name: 'toolChoice',
              type: 'ToolChoice<TOOLS> | undefined',
              description: 'The tool choice strategy for this generation.',
            },
            {
              name: 'activeTools',
              type: 'Array<keyof TOOLS> | undefined',
              description:
                'Limits which tools are available for the model to call.',
            },
            {
              name: 'maxOutputTokens',
              type: 'number | undefined',
              description: 'Maximum number of tokens to generate.',
            },
            {
              name: 'temperature',
              type: 'number | undefined',
              description: 'Sampling temperature for generation.',
            },
            {
              name: 'topP',
              type: 'number | undefined',
              description: 'Top-p (nucleus) sampling parameter.',
            },
            {
              name: 'topK',
              type: 'number | undefined',
              description: 'Top-k sampling parameter.',
            },
            {
              name: 'presencePenalty',
              type: 'number | undefined',
              description: 'Presence penalty for generation.',
            },
            {
              name: 'frequencyPenalty',
              type: 'number | undefined',
              description: 'Frequency penalty for generation.',
            },
            {
              name: 'stopSequences',
              type: 'string[] | undefined',
              description: 'Sequences that will stop generation.',
            },
            {
              name: 'seed',
              type: 'number | undefined',
              description: 'Random seed for reproducible generation.',
            },
            {
              name: 'maxRetries',
              type: 'number',
              description: 'Maximum number of retries for failed requests.',
            },
            {
              name: 'timeout',
              type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined',
              description: 'Timeout configuration for the generation.',
            },
            {
              name: 'headers',
              type: 'Record<string, string | undefined> | undefined',
              description: 'Additional HTTP headers sent with the request.',
            },
            {
              name: 'providerOptions',
              type: 'ProviderOptions | undefined',
              description: 'Additional provider-specific options.',
            },
            {
              name: 'stopWhen',
              type: 'StopCondition<TOOLS> | Array<StopCondition<TOOLS>> | undefined',
              description: 'Condition(s) for stopping the generation.',
            },
            {
              name: 'output',
              type: 'OUTPUT | undefined',
              description:
                'The output specification for structured outputs, if configured.',
            },
            {
              name: 'abortSignal',
              type: 'AbortSignal | undefined',
              description: 'Abort signal for cancelling the operation.',
            },
            {
              name: 'include',
              type: '{ requestBody?: boolean; responseBody?: boolean } | undefined',
              description:
                'Settings for controlling what data is included in step results.',
            },
            {
              name: 'functionId',
              type: 'string | undefined',
              description:
                'Identifier from telemetry settings for grouping related operations.',
            },
            {
              name: 'metadata',
              type: 'Record<string, unknown> | undefined',
              description: 'Additional metadata passed to the generation.',
            },
            {
              name: 'experimental_context',
              type: 'unknown',
              description:
                'User-defined context object that flows through the entire generation lifecycle.',
            },
          ],
        },
      ],
    },
    {
      name: 'experimental_onStepStart',
      type: 'ToolLoopAgentOnStepStartCallback',
      isOptional: true,
      description:
        'Callback that is called when a step (LLM call) begins, before the provider is called. Each step represents a single LLM invocation. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first). Experimental (can break in patch releases).',
      properties: [
        {
          type: 'OnStepStartEvent',
          parameters: [
            {
              name: 'stepNumber',
              type: 'number',
              description: 'Zero-based index of the current step.',
            },
            {
              name: 'model',
              type: '{ provider: string; modelId: string }',
              description: 'The model being used for this step.',
            },
            {
              name: 'system',
              type: 'string | SystemModelMessage | Array<SystemModelMessage> | undefined',
              description: 'The system message for this step.',
            },
            {
              name: 'messages',
              type: 'Array<ModelMessage>',
              description:
                'The messages that will be sent to the model for this step.',
            },
            {
              name: 'tools',
              type: 'TOOLS | undefined',
              description: 'The tools available for this generation.',
            },
            {
              name: 'toolChoice',
              type: 'LanguageModelV3ToolChoice | undefined',
              description: 'The tool choice configuration for this step.',
            },
            {
              name: 'activeTools',
              type: 'Array<keyof TOOLS> | undefined',
              description: 'Limits which tools are available for this step.',
            },
            {
              name: 'steps',
              type: 'ReadonlyArray<StepResult<TOOLS>>',
              description:
                'Array of results from previous steps (empty for first step).',
            },
            {
              name: 'providerOptions',
              type: 'ProviderOptions | undefined',
              description:
                'Additional provider-specific options for this step.',
            },
            {
              name: 'timeout',
              type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number } | undefined',
              description: 'Timeout configuration for the generation.',
            },
            {
              name: 'headers',
              type: 'Record<string, string | undefined> | undefined',
              description: 'Additional HTTP headers sent with the request.',
            },
            {
              name: 'stopWhen',
              type: 'StopCondition<TOOLS> | Array<StopCondition<TOOLS>> | undefined',
              description: 'Condition(s) for stopping the generation.',
            },
            {
              name: 'output',
              type: 'OUTPUT | undefined',
              description:
                'The output specification for structured outputs, if configured.',
            },
            {
              name: 'abortSignal',
              type: 'AbortSignal | undefined',
              description: 'Abort signal for cancelling the operation.',
            },
            {
              name: 'include',
              type: '{ requestBody?: boolean; responseBody?: boolean } | undefined',
              description:
                'Settings for controlling what data is included in step results.',
            },
            {
              name: 'functionId',
              type: 'string | undefined',
              description:
                'Identifier from telemetry settings for grouping related operations.',
            },
            {
              name: 'metadata',
              type: 'Record<string, unknown> | undefined',
              description: 'Additional metadata from telemetry settings.',
            },
            {
              name: 'experimental_context',
              type: 'unknown',
              description:
                'User-defined context object. May be updated from prepareStep between steps.',
            },
          ],
        },
      ],
    },
    {
      name: 'experimental_onToolCallStart',
      type: 'ToolLoopAgentOnToolCallStartCallback',
      isOptional: true,
      description:
        "Callback that is called right before a tool's execute function runs. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first). Experimental (can break in patch releases).",
      properties: [
        {
          type: 'OnToolCallStartEvent',
          parameters: [
            {
              name: 'stepNumber',
              type: 'number | undefined',
              description:
                'The zero-based index of the current step where this tool call occurs. May be undefined in streaming contexts.',
            },
            {
              name: 'model',
              type: '{ provider: string; modelId: string } | undefined',
              description:
                'Information about the model being used. May be undefined in streaming contexts.',
            },
            {
              name: 'toolCall',
              type: 'TypedToolCall<TOOLS>',
              description:
                'The full tool call object containing toolName, toolCallId, input, and metadata.',
            },
            {
              name: 'messages',
              type: 'Array<ModelMessage>',
              description:
                'The conversation messages available at tool execution time.',
            },
            {
              name: 'abortSignal',
              type: 'AbortSignal | undefined',
              description: 'Signal for cancelling the operation.',
            },
            {
              name: 'functionId',
              type: 'string | undefined',
              description:
                'Identifier from telemetry settings for grouping related operations.',
            },
            {
              name: 'metadata',
              type: 'Record<string, unknown> | undefined',
              description: 'Additional metadata from telemetry settings.',
            },
            {
              name: 'experimental_context',
              type: 'unknown',
              description:
                'User-defined context object flowing through the generation.',
            },
          ],
        },
      ],
    },
    {
      name: 'experimental_onToolCallFinish',
      type: 'ToolLoopAgentOnToolCallFinishCallback',
      isOptional: true,
      description:
        "Callback that is called right after a tool's execute function completes (or errors). Uses a discriminated union on the `success` field: when `success: true`, `output` contains the tool result; when `success: false`, `error` contains the error. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first). Experimental (can break in patch releases).",
      properties: [
        {
          type: 'OnToolCallFinishEvent',
          parameters: [
            {
              name: 'stepNumber',
              type: 'number | undefined',
              description:
                'The zero-based index of the current step where this tool call occurred. May be undefined in streaming contexts.',
            },
            {
              name: 'model',
              type: '{ provider: string; modelId: string } | undefined',
              description:
                'Information about the model being used. May be undefined in streaming contexts.',
            },
            {
              name: 'toolCall',
              type: 'TypedToolCall<TOOLS>',
              description:
                'The full tool call object containing toolName, toolCallId, input, and metadata.',
            },
            {
              name: 'messages',
              type: 'Array<ModelMessage>',
              description:
                'The conversation messages available at tool execution time.',
            },
            {
              name: 'abortSignal',
              type: 'AbortSignal | undefined',
              description: 'Signal for cancelling the operation.',
            },
            {
              name: 'durationMs',
              type: 'number',
              description:
                'The wall-clock duration of the tool execution in milliseconds.',
            },
            {
              name: 'functionId',
              type: 'string | undefined',
              description:
                'Identifier from telemetry settings for grouping related operations.',
            },
            {
              name: 'metadata',
              type: 'Record<string, unknown> | undefined',
              description: 'Additional metadata from telemetry settings.',
            },
            {
              name: 'experimental_context',
              type: 'unknown',
              description:
                'User-defined context object flowing through the generation.',
            },
            {
              name: 'success',
              type: 'boolean',
              description:
                'Discriminator indicating whether the tool call succeeded. When true, output is available. When false, error is available.',
            },
            {
              name: 'output',
              type: 'unknown',
              description:
                "The tool's return value (only present when `success: true`).",
            },
            {
              name: 'error',
              type: 'unknown',
              description:
                'The error that occurred during tool execution (only present when `success: false`).',
            },
          ],
        },
      ],
    },
    {
      name: 'onStepFinish',
      type: 'ToolLoopAgentOnStepFinishCallback',
      isOptional: true,
      description:
        'Callback invoked after each agent step (LLM/tool call) completes. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first).',
    },
    {
      name: 'onFinish',
      type: 'ToolLoopAgentOnFinishCallback',
      isOptional: true,
      description:
        'Callback that is called when all agent steps are finished and the response is complete. Receives step results, total usage, experimental_context, functionId, and metadata. If also specified in `generate()` or `stream()`, both callbacks are called (constructor first).',
    },
    {
      name: 'experimental_context',
      type: 'unknown',
      isOptional: true,
      description:
        'Experimental: Custom context object passed to each tool call.',
    },
    {
      name: 'experimental_telemetry',
      type: 'TelemetrySettings',
      isOptional: true,
      description: 'Experimental: Optional telemetry configuration.',
    },
    {
      name: 'experimental_download',
      type: 'DownloadFunction | undefined',
      isOptional: true,
      description:
        'Experimental: Custom download function for fetching files/URLs for tool or model use. By default, files are downloaded if the model does not support the URL for a given media type.',
    },
    {
      name: 'maxOutputTokens',
      type: 'number',
      isOptional: true,
      description: 'Maximum number of tokens the model is allowed to generate.',
    },
    {
      name: 'temperature',
      type: 'number',
      isOptional: true,
      description:
        'Sampling temperature, controls randomness. Passed through to the model.',
    },
    {
      name: 'topP',
      type: 'number',
      isOptional: true,
      description:
        'Top-p (nucleus) sampling parameter. Passed through to the model.',
    },
    {
      name: 'topK',
      type: 'number',
      isOptional: true,
      description: 'Top-k sampling parameter. Passed through to the model.',
    },
    {
      name: 'presencePenalty',
      type: 'number',
      isOptional: true,
      description: 'Presence penalty parameter. Passed through to the model.',
    },
    {
      name: 'frequencyPenalty',
      type: 'number',
      isOptional: true,
      description: 'Frequency penalty parameter. Passed through to the model.',
    },
    {
      name: 'stopSequences',
      type: 'string[]',
      isOptional: true,
      description:
        'Custom token sequences which stop the model output. Passed through to the model.',
    },
    {
      name: 'seed',
      type: 'number',
      isOptional: true,
      description: 'Seed for deterministic generation (if supported).',
    },
    {
      name: 'maxRetries',
      type: 'number',
      isOptional: true,
      description: 'How many times to retry on failure. Default: 2.',
    },
    {
      name: 'providerOptions',
      type: 'ProviderOptions',
      isOptional: true,
      description: 'Additional provider-specific configuration.',
    },
    {
      name: 'headers',
      type: 'Record<string, string | undefined>',
      isOptional: true,
      description:
        'Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.',
    },
    {
      name: 'callOptionsSchema',
      type: 'FlexibleSchema<CALL_OPTIONS>',
      isOptional: true,
      description:
        'Optional schema for custom call options that can be passed when calling generate() or stream().',
    },
    {
      name: 'prepareCall',
      type: 'PrepareCallFunction',
      isOptional: true,
      description:
        'Optional function to prepare call-specific settings based on the call options.',
    },
    {
      name: 'id',
      type: 'string',
      isOptional: true,
      description: 'Custom agent identifier.',
    },
  ]}
/>

## Methods

### `generate()`

Generates a response and triggers tool calls as needed, running the agent loop and returning the final result. Returns a promise resolving to a `GenerateTextResult`.

```ts
const result = await agent.generate({
  prompt: 'What is the weather like?',
});
```

<PropertiesTable
  content={[
    {
      name: 'prompt',
      type: 'string | Array<ModelMessage>',
      description: 'A text prompt or message array.',
    },
    {
      name: 'messages',
      type: 'Array<ModelMessage>',
      description: 'A full conversation history as a list of model messages.',
    },
    {
      name: 'abortSignal',
      type: 'AbortSignal',
      isOptional: true,
      description:
        'An optional abort signal that can be used to cancel the call.',
    },
    {
      name: 'timeout',
      type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number }',
      isOptional: true,
      description:
        'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, and/or chunkMs properties. The call will be aborted if it takes longer than the specified timeout. Can be used alongside abortSignal.',
    },
    {
      name: 'options',
      type: 'CALL_OPTIONS',
      isOptional: true,
      description:
        'Custom call options when the agent is configured with a callOptionsSchema.',
    },
    {
      name: 'experimental_onStart',
      type: 'ToolLoopAgentOnStartCallback',
      isOptional: true,
      description:
        'Callback that is called when the agent operation begins, before any LLM calls are made. If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).',
    },
    {
      name: 'experimental_onStepStart',
      type: 'ToolLoopAgentOnStepStartCallback',
      isOptional: true,
      description:
        'Callback that is called when a step (LLM call) begins, before the provider is called. If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).',
    },
    {
      name: 'experimental_onToolCallStart',
      type: 'ToolLoopAgentOnToolCallStartCallback',
      isOptional: true,
      description:
        "Callback that is called right before a tool's execute function runs. If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).",
    },
    {
      name: 'experimental_onToolCallFinish',
      type: 'ToolLoopAgentOnToolCallFinishCallback',
      isOptional: true,
      description:
        "Callback that is called right after a tool's execute function completes (or errors). If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).",
    },
    {
      name: 'onStepFinish',
      type: 'ToolLoopAgentOnStepFinishCallback',
      isOptional: true,
      description:
        'Callback invoked after each agent step (LLM/tool call) completes. If also specified in the constructor, both callbacks are called (constructor first, then this one).',
    },
    {
      name: 'onFinish',
      type: 'ToolLoopAgentOnFinishCallback',
      isOptional: true,
      description:
        'Callback that is called when all agent steps are finished and the response is complete. If also specified in the constructor, both callbacks are called (constructor first, then this one).',
    },
  ]}
/>

#### Returns

The `generate()` method returns a `GenerateTextResult` object (see [`generateText`](/docs/reference/ai-sdk-core/generate-text#returns) for details).

### `stream()`

Streams a response from the agent, including agent reasoning and tool calls, as they occur. Returns a `StreamTextResult`.

```ts
const stream = agent.stream({
  prompt: 'Tell me a story about a robot.',
});

for await (const chunk of stream.textStream) {
  console.log(chunk);
}
```

<PropertiesTable
  content={[
    {
      name: 'prompt',
      type: 'string | Array<ModelMessage>',
      description: 'A text prompt or message array.',
    },
    {
      name: 'messages',
      type: 'Array<ModelMessage>',
      description: 'A full conversation history as a list of model messages.',
    },
    {
      name: 'abortSignal',
      type: 'AbortSignal',
      isOptional: true,
      description:
        'An optional abort signal that can be used to cancel the call.',
    },
    {
      name: 'timeout',
      type: 'number | { totalMs?: number; stepMs?: number; chunkMs?: number }',
      isOptional: true,
      description:
        'Timeout in milliseconds. Can be specified as a number or as an object with totalMs, stepMs, and/or chunkMs properties. The call will be aborted if it takes longer than the specified timeout. Can be used alongside abortSignal.',
    },
    {
      name: 'options',
      type: 'CALL_OPTIONS',
      isOptional: true,
      description:
        'Custom call options when the agent is configured with a callOptionsSchema.',
    },
    {
      name: 'experimental_transform',
      type: 'StreamTextTransform | Array<StreamTextTransform>',
      isOptional: true,
      description:
        'Optional stream transformation(s). They are applied in the order provided and must maintain the stream structure. See `streamText` docs for details.',
    },
    {
      name: 'experimental_onStart',
      type: 'ToolLoopAgentOnStartCallback',
      isOptional: true,
      description:
        'Callback that is called when the agent operation begins, before any LLM calls are made. If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).',
    },
    {
      name: 'experimental_onStepStart',
      type: 'ToolLoopAgentOnStepStartCallback',
      isOptional: true,
      description:
        'Callback that is called when a step (LLM call) begins, before the provider is called. If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).',
    },
    {
      name: 'experimental_onToolCallStart',
      type: 'ToolLoopAgentOnToolCallStartCallback',
      isOptional: true,
      description:
        "Callback that is called right before a tool's execute function runs. If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).",
    },
    {
      name: 'experimental_onToolCallFinish',
      type: 'ToolLoopAgentOnToolCallFinishCallback',
      isOptional: true,
      description:
        "Callback that is called right after a tool's execute function completes (or errors). If also specified in the constructor, both callbacks are called (constructor first). Experimental (can break in patch releases).",
    },
    {
      name: 'onStepFinish',
      type: 'ToolLoopAgentOnStepFinishCallback',
      isOptional: true,
      description:
        'Callback invoked after each agent step (LLM/tool call) completes. If also specified in the constructor, both callbacks are called (constructor first, then this one).',
    },
    {
      name: 'onFinish',
      type: 'ToolLoopAgentOnFinishCallback',
      isOptional: true,
      description:
        'Callback that is called when all agent steps are finished and the response is complete. If also specified in the constructor, both callbacks are called (constructor first, then this one).',
    },
  ]}
/>

#### Returns

The `stream()` method returns a `StreamTextResult` object (see [`streamText`](/docs/reference/ai-sdk-core/stream-text#returns) for details).

## Types

### `InferAgentUIMessage`

Infers the UI message type for the given agent instance. Useful for type-safe UI and message exchanges.

#### Basic Example

```ts
import { ToolLoopAgent, InferAgentUIMessage } from 'ai';

const weatherAgent = new ToolLoopAgent({
  model: __MODEL__,
  tools: { weather: weatherTool },
});

type WeatherAgentUIMessage = InferAgentUIMessage<typeof weatherAgent>;
```

#### Example with Message Metadata

You can provide a second type argument to customize the metadata for each message. This is useful for tracking rich metadata returned by the agent (such as createdAt, tokens, finish reason, etc.).

```ts
import { ToolLoopAgent, InferAgentUIMessage } from 'ai';
import { z } from 'zod';

// Example schema for message metadata
const exampleMetadataSchema = z.object({
  createdAt: z.number().optional(),
  model: z.string().optional(),
  totalTokens: z.number().optional(),
  finishReason: z.string().optional(),
});
type ExampleMetadata = z.infer<typeof exampleMetadataSchema>;

// Define agent as usual
const metadataAgent = new ToolLoopAgent({
  model: __MODEL__,
  // ...other options
});

// Type-safe UI message type with custom metadata
type MetadataAgentUIMessage = InferAgentUIMessage<
  typeof metadataAgent,
  ExampleMetadata
>;
```

## Examples

### Basic Agent with Tools

```ts
import { ToolLoopAgent, stepCountIs } 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: stepCountIs(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
```

### Streaming Agent Response

```ts
const agent = new ToolLoopAgent({
  model: __MODEL__,
  instructions: 'You are a creative storyteller.',
});

const stream = agent.stream({
  prompt: 'Tell me a short story about a time traveler.',
});

for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}
```

### Agent with Output Parsing

```ts
import { z } from 'zod';

const analysisAgent = new ToolLoopAgent({
  model: __MODEL__,
  output: {
    schema: z.object({
      sentiment: z.enum(['positive', 'negative', 'neutral']),
      score: z.number(),
      summary: z.string(),
    }),
  },
});

const result = await analysisAgent.generate({
  prompt: 'Analyze this review: "The product exceeded my expectations!"',
});

console.log(result.output);
// Typed as { sentiment: 'positive' | 'negative' | 'neutral', score: number, summary: string }
```

### Example: Approved Tool Execution

```ts
import { openai } from '@ai-sdk/openai';
import { ToolLoopAgent } from 'ai';

const agent = new ToolLoopAgent({
  model: __MODEL__,
  instructions: 'You are an agent with access to a weather API.',
  tools: {
    weather: openai.tools.weather({
      /* ... */
    }),
  },
  // Optionally require approval, etc.
});

const result = await agent.generate({
  prompt: 'Is it raining in Paris today?',
});
console.log(result.text);
```
