Hosts

AI SDK

toAiTool turns a definition into an AI SDK tool. The TypeBox schema goes in as it is and nobody writes it again in Zod
IDai04 / 04ai
Host / AI SDK

AI SDK tool

An AI SDK tool whose output is the details plus the text.

title
Text Slug
inputSchema
jsonSchema()
output
details + text
failure
thrown

Access

Importimport { toAiTool } from "@agntn/tools/ai"
Peerai >=7.0.0 <8
Failsthrown, tool error
tsagent.ts
import { toAiTool, toAiTools } from "@agntn/tools/ai";
import { slugTool, tools } from "./tools.ts";

const one = toAiTool(slugTool);
const all = toAiTools(tools); // keyed by tool name

The schema goes through the AI SDK's jsonSchema() with the core's validator attached. So the model sees the same JSON Schema every other host sees, and a bad input gets refused with the same lines. No second schema in Zod. That used to be the fourth copy.

The output

execute returns the details with the text added: { ...details, text }. When details isn't an object, you get { details, text }. That's the object your code finds in toolResults.

The model gets less. toModelOutput hands it text and nothing else, the same text MCP, Pi and OMP put in front of their models. Why not the whole object? The text already says it. A books_text slice used to land twice. Once as text, once escaped as JSON inside details. That came to 2.1 times the characters for one passage. Paying twice to read the same book is a strange hobby.

No text at all, an image and nothing else? Then the model gets the whole object as JSON, same as before.

A details object with its own text field would lose it under the spread, so the adapter throws a ToolDefinitionError instead of guessing. Rename the field.

Failures

A bad input is refused by the input schema before execute. A result with isError throws its text, and the AI SDK turns any throw into a tool error the model can read.

Progress

There's nowhere to put it. progress is undefined in execute, and a tool that calls it with ?. just keeps going.

Questions

Same story. The AI SDK has no person on the line, so ask is undefined. Who'd answer? A tool that checks first does its best without one.

Types

toAiTool keeps the input and details types. When you export the tool from a package, annotate it with your own types, Tool<SearchParams, AiToolOutput<SearchDetails>>. The inferred type points into the bundled TypeBox, and your declaration build can't name it.