Tools Overview
Tools are the callable functions that agents use to take actions in the world. Every tool has a name, a description, a Zod parameter schema, and an execute function. Tools self-register at import time — there is no central registry file to update manually.
Tool registration pattern
Every tool follows the same pattern: define a Zod schema, call registerTool() at module scope, and import the file in tools/index.ts. The import in index.ts is what triggers registration at startup.
// src/tools/my-tool.ts
import { z } from 'zod';
import { registerTool } from './registry';
const Params = z.object({
query: z.string().describe('The search query'),
maxResults: z.number().default(10).describe('Number of results to return'),
});
registerTool({
name: 'my_tool',
description: 'Searches for something and returns results',
parameters: Params,
execute: async (params, ctx) => {
// params is typed as z.infer<typeof Params>
// ctx includes: agentId, userId, workspaceId, sessionId
const results = await doSearch(params.query, params.maxResults);
return { results };
},
});Allow/deny policy
Every agent has a tool policy that determines which tools it can call. The policy is evaluated in this order:
- Global defaults — all tools are available by default unless restricted
- Agent
tools.allow— if non-empty, only listed tools are allowed - Agent
tools.deny— listed tools are always denied, regardless of allow list - Spawn restrictions — sub-agents are restricted to the intersection of parent and target allow lists
tools.allow and tools.deny, it is denied.agents:
- id: my-agent
tools:
allow:
- web_search
- file_read
- shell_exec
deny:
- file_delete # Never allow this, even if listed in allowTool execution context
Every tool's execute function receives a context object as its second argument:
interface ToolContext {
agentId: string; // Which agent is calling this tool
userId: string; // The user making the request
workspaceId: string; // The workspace scope
sessionId: string; // The current session
signal: AbortSignal; // Abort signal — respect this for long operations
}Tool results and errors
Tools return a ToolResult which is either a success payload (any JSON-serializable value) or an error string. The agent loop is resilient to tool errors — a failed tool call is fed back to the model as an error message and the loop continues.
// Success
return { data: [...], count: 42 };
// Error — return an error string, do not throw
return { error: 'API returned 401 — check API key configuration' };Startup registration
After creating a new tool file, add its import to src/tools/index.ts. This single file is the only place you need to add the import:
// src/tools/index.ts
import './web-search';
import './file-read';
import './shell-exec';
import './my-tool'; // Add your new tool here