Skip to main content

Building Agents

The ToolLoopAgent provides a structured way to encapsulate LLM configuration, tools, and behavior into reusable components. It handles the agent loop for you, allowing the LLM to call tools multiple times in sequence to accomplish complex tasks. Define agents once and use them across your application.

Why Use the ToolLoopAgent Class?

When building AI applications, you often need to:
  • Reuse configurations - Same model settings, tools, and prompts across different parts of your application
  • Maintain consistency - Ensure the same behavior and capabilities throughout your codebase
  • Simplify API routes - Reduce boilerplate in your endpoints
  • Type safety - Get full TypeScript support for your agent’s tools and outputs
The ToolLoopAgent class provides a single place to define your agent’s behavior.

Creating an Agent

Define an agent by instantiating the ToolLoopAgent class with your desired configuration:

Configuration Options

The ToolLoopAgent accepts all the same settings as generateText and streamText. Configure:

Model and System Instructions

Tools

Provide tools that the agent can use to accomplish tasks:

Loop Control

By default, agents run for 20 steps (stopWhen: stepCountIs(20)). In each step, the model either generates text or calls a tool. If it generates text, the agent completes. If it calls a tool, the AI SDK executes that tool. To let agents call multiple tools in sequence, configure stopWhen to allow more steps. After each tool execution, the agent triggers a new generation where the model can call another tool or generate text:
Each step represents one generation (which results in either text or a tool call). The loop continues until:
  • A finish reasoning other than tool-calls is returned, or
  • A tool that is invoked does not have an execute function, or
  • A tool call needs approval, or
  • A stop condition is met
You can combine multiple conditions:
Learn more about loop control and stop conditions.

Tool Choice

Control how the agent uses tools:
You can also force the use of a specific tool:

Structured Output

Define structured output schemas:

Define Agent Behavior with System Instructions

System instructions define your agent’s behavior, personality, and constraints. They set the context for all interactions and guide how the agent responds to user queries and uses tools.

Basic System Instructions

Set the agent’s role and expertise:

Detailed Behavioral Instructions

Provide specific guidelines for agent behavior:

Constrain Agent Behavior

Set boundaries and ensure consistent behavior:

Tool Usage Instructions

Guide how the agent should use available tools:

Format and Style Instructions

Control the output format and communication style:

Using an Agent

Once defined, you can use your agent in three ways:

Generate Text

Use generate() for one-time text generation:

Stream Text

Use stream() for streaming responses:

Respond to UI Messages

Use createAgentUIStreamResponse() to create API responses for client applications:

Lifecycle Callbacks

Experimental callbacks are subject to breaking changes in incremental package releases.
Agents provide lifecycle callbacks that let you hook into different phases of the agent execution. These are useful for logging, observability, debugging, and custom telemetry.
The available lifecycle callbacks are:
  • experimental_onStart: Called once when the agent operation begins, before any LLM calls. Receives model info, prompt, settings, and telemetry metadata.
  • experimental_onStepStart: Called before each step (LLM call). Receives the step number, model, messages being sent, tools, and prior steps.
  • experimental_onToolCallStart: Called right before a tool’s execute function runs. Receives the tool call object with tool name, call ID, and input.
  • experimental_onToolCallFinish: Called right after a tool’s execute function completes or errors. Receives the tool call, durationMs, and a success discriminator (output when successful, error when failed).
  • onStepFinish: Called after each step finishes. Receives step results including usage, finish reason, and tool calls.
  • onFinish: Called when all steps are finished and the response is complete. Receives all step results, total usage, and telemetry metadata.

Constructor vs. Method Callbacks

All lifecycle callbacks can be defined in the constructor for agent-wide tracking, in the generate()/stream() call for per-call tracking, or both. When both are provided, both are called (constructor first, then the method callback):

End-to-end Type Safety

You can infer types for your agent’s UIMessages:
Use this type in your client components with useChat:

Next Steps

Now that you understand building agents, you can: