Skip to main content
Agent tools in cl-pipelines use the Vercel AI SDK v6 tool() factory. A tool has a description the model reads to decide when to call it, a Zod inputSchema that constrains its arguments, and an async execute function that runs the actual logic. The library handles everything else: calling execute, collecting the result, appending it to the message history, and persisting it in the checkpoint.

Defining a tool

Use inputSchema, not parameters. The parameters key is the AI SDK v5 API. In v6, Zod schemas go in inputSchema.

Passing tools to runAgent

Pass your tools as a record keyed by the name the model will use to call them:
The record keys (lookupPolicy, getClientInfo, sendEmail) become the tool names in the model’s context. Choose names that are descriptive — the model uses them alongside description to decide when and how to call each tool.

How tool results flow through the checkpoint

When the model calls a tool, the following happens within a single turn:
  1. The model returns finishReason: "tool-calls" with one or more tool call objects
  2. The AI SDK calls each tool’s execute function with the parsed arguments
  3. The SDK wraps each return value in a role: "tool" message
  4. Those messages are included in result.response.messages
  5. cl-pipelines appends the full result.response.messages array to checkpoint.messages
  6. The checkpoint is written to storage
  7. The next turn runs with the complete history (including tool results) as context
This means tool calls and their results are always persisted before the next generateText call — a crash between turns will not cause a tool to be called twice.

Schema tips

Describe every field

Use .describe() on every field in your inputSchema. The model reads these descriptions to understand what value to pass. Undescribed fields lead to hallucinated or missing arguments.

Keep schemas focused

Each tool should do one thing. Fewer fields in inputSchema means less chance of the model hallucinating arguments or calling the tool incorrectly.

Return structured objects

Return plain objects rather than raw strings. Structured responses give the model richer context and make it easier to write deterministic tests for your tools.

Handle not-found gracefully

Return a { found: false } object rather than throwing when a record doesn’t exist. The model can then decide how to handle the missing data rather than triggering an error phase.

Multiple tools example

Long-running tools

In v0.1, all tool execution is synchronous within a single phase invocation. If a tool call takes longer than your scheduler’s action timeout, the phase will time out and be retried from the last checkpoint — which means the tool call will run again. For expensive tools (e.g. calling an external ML service, processing a large file), extract the work into a dedicated pipeline phase that runs before the agent phase and stores its result in TState. Then pass the result to the agent via the initial messages or system prompt.
v0.2 will introduce pendingToolCalls support, allowing long-running tools to be modeled as pipeline phases that feed results back into the agent loop.