maxSteps and the tool loop

By default streamText stops after the first model response. If the response contains a tool call, the tool runs, but the model never sees the result. maxSteps lifts that ceiling. Set it to five and the model can call a tool, observe, reason, call another tool, observe, and finally reply, all inside one user turn. One note on the code you are about to see: it calls getModel() where you previously wired openrouter.chat directly. Read that as a tiny helper that returns your configured model. You will build it for real when we move the provider behind a flag.

app/api/chat/route.ts
typescript
const result = streamText({
  model: getModel(),
  system: SYSTEM_PROMPT,
  messages: convertToModelMessages(messages),
  tools: agentTools,
  // Agent loop: model may call tools, observe results, and respond
  // across up to 5 steps in a single turn.
  maxSteps: 5,
});

Five is a sensible default. Too low and the model truncates mid-thought. Too high and a broken prompt can rack up costs in a loop. Five covers most useful chains.

Imagine a prompt like "What is the weather in Tokyo and what is 47 times 23?" With maxSteps at 1 the model can call only one tool. With maxSteps at 5 the model calls get_weather, observes the result, calls calculator, observes the result, then writes a merged reply. Same model, same tools, different ceiling.

Quiz: Quiz

Loading practice…