Defining Tools
Create tools with tool(), group them in BaseToolset or StaticToolset, and attach them to an Agent.
tool()
The tool() helper builds a Tool with JSON Schema input validation and structured error handling:
import { tool } from "@maniac-ai/agents";
import { z } from "zod";
const lookupOrder = tool({
name: "lookup_order",
description: "Look up an order by id.",
inputSchema: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"]
},
parse: z.object({ order_id: z.string() }), // optional Zod narrowing
handler: ({ order_id }) => ({ order_id, status: "in_transit" })
});handler return values become ToolResult.value. Thrown errors produce ok: false with a typed cause (kind: "validation" | "runtime").
Attach tools on the agent spec:
const spec: Agent = {
id: "support",
instructions: "Use tools to answer questions.",
model,
tools: [lookupOrder]
};BaseToolset
BaseToolset is the abstract base for dynamic tool collections. Subclasses implement listTools() and inherit invoke, searchTools, and asDelegated():
import { BaseToolset, tool } from "@maniac-ai/agents";
import type { Tool } from "@maniac-ai/agents";
class OrdersToolset extends BaseToolset {
constructor() {
super({ name: "orders", description: "Order lookup tools." });
}
async listTools(): Promise<Tool[]> {
return [lookupOrder];
}
}searchTools(query, k) builds a lexical index on first call for large tool surfaces.
StaticToolset
When the tool list is fixed at construction time, use StaticToolset:
import { StaticToolset, tool } from "@maniac-ai/agents";
const orders = new StaticToolset({
name: "orders",
description: "Order lookup tools.",
tools: [lookupOrder]
});
const spec: Agent = {
id: "support",
instructions: "...",
model,
toolsets: [orders]
};Tool results
Every invocation returns a ToolResult:
type ToolResult = {
ok: boolean;
value?: unknown;
error?: string;
metadata?: Record<string, unknown>;
cause?: { kind: "validation" | "runtime"; name: string; message: string; ... };
};Trace events on tool completed / failed phases include an optional result_preview (JSON-safe, ~16 KB cap) for UIs without joining raw messages.
Argument validation
Malformed provider tool-call JSON no longer silently coerces to {}. The runner emits tool_arguments_invalid failures instead of invoking handlers with empty args.