← Course index

The tool loop in a route

Match the Tool Calling lab: streamText, Zod tool schemas, and stopWhen in one API route.

Day 1: Agent loops·~16 min read

On this page

After this topic

You will have a Route Handler that is the Tool Calling lab: streamText, a Zod tool, a step cap, the same UI stream as chat. You will know what the model sees (the schema) and what it never sees (execute).

Route handler

Same stream as chat — the new part is the tools map and a step cap.

This is the same pattern as the Tool Calling lab. inputSchema uses Zod directly — the SDK validates arguments before execute runs. If the model invents a field, you never hit your function with garbage (or you fail closed — better than a wrong city in production).

stopWhen: stepCountIs(5) allows up to five model steps (tool rounds plus the final answer). Tune n to the task: weather-and-compare might need three; a research agent might need more, with a higher bill.

toUIMessageStreamResponse() is the same last line as streaming chat. Tool calls show up as parts on the assistant message. The client does not need a second API.

The agent loop. Each step, the model either writes a final answer or asks your server to run a tool. Results go back on the thread until it can stop — or until you cap the steps.
  1. 01

    tools is a map of functions the model may call

    Each tool has a description (when to use it), inputSchema (arguments), and execute (your code). The model never sees execute — only the schema.

  2. 02

    stopWhen caps the loop

    stepCountIs(5) allows up to five model steps. Without a cap, a confused model can call tools forever and run up cost.

  3. 03

    Same stream as Day 3 chat

    toUIMessageStreamResponse() still feeds useChat. Tool calls appear as parts on the message, not as a separate API.

What runs on which machine

The model, in a datacenter, emits a tool name and JSON arguments. Your Route Handler, on Vercel, runs execute. The browser never runs the tool. That split is the same as the chat key: side effects belong on the server.

Weather in this snippet is fake data so the lesson does not need a third-party key. In a product, execute hits your API, your database, or a vendor. Same shape. Real consequences.

Trade-offs

Too few steps and the task stops mid-way (one city, no comparison). Too many and a stuck model burns tokens. Start small, log steps, raise n when you see real multi-call tasks.

Use generateText with tools when you are debugging — you get the full step list in one object. Use streamText for the chat UI.

When the same agent must run from a route, a cron, and a job, look at ToolLoopAgent in the official agents docs. For this lesson, one Route Handler is the right size.

  • Cap the loop (stopWhen)always
  • Descriptions and schemas decide whether tools get called correctly (next day)
  • Destructive execute belongs behind approval

Further reading

The official Building Agents guide covers ToolLoopAgent when you want a shared agent object across routes and jobs. The catalog Tool Calling lab is this route with a UI.

Common questions

What is “The tool loop in a route”?
Match the Tool Calling lab: streamText, Zod tool schemas, and stopWhen in one API route.
What will I be able to do after this lesson?
You will have a Route Handler that is the Tool Calling lab: streamText, a Zod tool, a step cap, the same UI stream as chat. You will know what the model sees (the schema) and what it never sees (execute).
How long does this lesson take?
About 16 minutes of reading. It is a free chapter in the AI SDK Patterns TypeScript course.
When should I not use this?
Too few steps and the task stops mid-way (one city, no comparison). Too many and a stuck model burns tokens. Start small, log steps, raise n when you see real multi-call tasks.

Written by Akash Panchal·Updated August 29, 2026