Tools

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.

typescript
// 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:

  1. Global defaults — all tools are available by default unless restricted
  2. Agent tools.allow — if non-empty, only listed tools are allowed
  3. Agent tools.deny — listed tools are always denied, regardless of allow list
  4. Spawn restrictions — sub-agents are restricted to the intersection of parent and target allow lists
Deny always wins. If a tool appears in both tools.allow and tools.deny, it is denied.
yaml
agents:
  - id: my-agent
    tools:
      allow:
        - web_search
        - file_read
        - shell_exec
      deny:
        - file_delete    # Never allow this, even if listed in allow

Tool execution context

Every tool's execute function receives a context object as its second argument:

typescript
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.

typescript
// 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:

typescript
// src/tools/index.ts
import './web-search';
import './file-read';
import './shell-exec';
import './my-tool';   // Add your new tool here