Agents are large language models (LLMs) that use tools in a loop to accomplish tasks.
They don’t just answer questions — they take action.
These three parts work together:
LLMs think — they process input and decide what to do next
Tools act — they extend what the model can do (read data, call APIs, write files)
Loop coordinates — it runs the process until the task is complete
The loop manages:
Context management – keeping track of what’s happened so far
Stopping conditions – deciding when the job is done
Think of it like this: Model decides → Tool executes → Result feeds back → Repeat until done.
The Agent Class
The Agent class ties these parts together.
It connects the model, tools, and loop into a reusable system that can reason through multi-step tasks.
Here’s an example of an agent that finds and converts the weather:
weather-agent.tsimport { Experimental_Agent as Agent, stepCountIs, tool } from "ai"import { z } from "zod"const weatherAgent = new Agent({ model: "openai/gpt-4o", tools: { weather: tool({ description: "Get the weather in a location (in Fahrenheit)", parameters: z.object({ location: z.string().describe("The location to get the weather for"), }), execute: async ({ location }) => ({ location, temperature: 72 + Math.floor(Math.random() * 21) - 10, }), }), convertFahrenheitToCelsius: tool({ description: "Convert temperature from Fahrenheit to Celsius", parameters: z.object({ temperature: z.number().describe("Temperature in Fahrenheit"), }), execute: async ({ temperature }) => { const celsius = Math.round((temperature - 32) * (5 / 9)) return { celsius } }, }), }, stopWhen: stepCountIs(20),})const result = await weatherAgent.generate({ prompt: "What is the weather in San Francisco in celsius?",})console.log(result.text) // agent's final answerconsole.log(result.steps) // steps taken by the agent
Here’s what happens automatically:
The model calls the weather tool to get the temperature
It then calls convertFahrenheitToCelsius
Finally, it writes a natural-language answer
The agent runs the reasoning loop, manages context, and knows when to stop.
You define the pieces — it handles the rest.
Why Use the Agent Class?
The Agent class is the easiest way to build useful, reliable agents with the AI SDK.
It handles all the orchestration for you:
Less boilerplate – no need to manually manage loops or messages
Reusable – define once, use anywhere
Easy to maintain – update model, tools, or logic in one place
Use Agent for most cases.
When you need fine-grained control (like custom branching or deterministic flows), use lower-level functions like generateText or streamText.
Structured Workflows
Agents are powerful but non-deterministic — they reason dynamically, so the same input might take different paths.
When you need strict, predictable control (for example, billing or compliance tasks), use structured workflows instead.
Combine:
generateText for controlled reasoning
Conditional logic (if, switch) for branching
Reusable functions for logic
Error handling for robustness
These patterns give you the reliability of code with the flexibility of LLMs.
You can control both execution flow and settings at each step of the agent loop.
The AI SDK provides two built-in controls:
stopWhen – defines when to stop execution
prepareStep – modifies settings (model, tools, messages, etc.) between steps
Stop Conditions
The stopWhen parameter tells the agent when to stop looping.
By default, agents stop after one step with stepCountIs(1).
When you specify stopWhen, the agent continues running until a condition is met.
You can combine built-in, multiple, or custom conditions.
Use Built-in Conditions
agent-stop-condition.tsimport { Experimental_Agent as Agent, stepCountIs } from "ai"const agent = new Agent({ model: "openai/gpt-4o", tools: { // your tools }, stopWhen: stepCountIs(20), // Stop after 20 steps})const result = await agent.generate( "Analyze this dataset and create a summary report")
Combine Multiple Conditions
Stop when any condition is met:
multiple-stop-conditions.tsimport { Experimental_Agent as Agent, hasToolCall, stepCountIs } from "ai"const agent = new Agent({ model: "openai/gpt-4o", tools: { // your tools }, stopWhen: [ stepCountIs(20), hasToolCall("someTool"), // Stop after calling 'someTool' ],})const result = await agent.generate("Research and analyze the topic")
Create Custom Conditions
Define your own stopping logic:
custom-stop-condition.tsimport { Experimental_Agent as Agent, StopCondition, ToolSet } from "ai"const tools = { /* your tools */} satisfies ToolSetconst hasAnswer: StopCondition<typeof tools> = ({ steps }) => { return steps.some((step) => step.text?.includes("ANSWER:")) ?? false}const agent = new Agent({ model: "openai/gpt-4o", tools, stopWhen: hasAnswer,})const result = await agent.generate( 'Find the answer and respond with "ANSWER: [your answer]"')
When you need total control, build your own loop using the AI SDK Core functions (generateText, streamText).
This lets you customize every part of execution — from message handling to stopping logic.
Agents aren’t magic — they’re systems that think through problems one step at a time.
Understand the pieces, wire them together clearly, and you’ll have a machine that can reason, act, and adapt — all without the guesswork.