The agent's per-session state, so ctx.state is typed
rather than Record<string, unknown>. Inferred when the handler
annotates its context; otherwise pass it explicitly. A tool defined
without it still composes into a stateful agent — execute is declared
method-style, so it stays assignable — it just sees untyped state.
import { tool } from "@alexkroman1/aai";
import { z } from "zod";
const greet = tool({
description: "Greet someone by name",
inputSchema: z.object({ name: z.string() }),
execute: ({ name }) => `Hello, ${name}!`,
});
import { tool, type ToolContext } from "@alexkroman1/aai";
import { z } from "zod";
type Cart = { items: string[] };
const add = tool({
description: "Add an item to the cart",
inputSchema: z.object({ item: z.string() }),
// The annotation is what infers S; `ctx.state.items` is string[] here.
execute: ({ item }, ctx: ToolContext<Cart>) => {
ctx.state.items.push(item);
return ctx.state.items.length;
},
});
Define a tool with a typed input schema and execute function.
Identity function for type inference — returns the input unchanged. Follows the Vercel AI SDK
tool()pattern (inputSchemanames the same field it does there). The schema is any Standard Schema that converts to JSON Schema; Zod is the documented default.