Client Tools

By default, tools execute on your server where you have access to databases and APIs. However, some tools are better suited for client-side execution:

  • Browser-only operations — Geolocation, clipboard, local storage
  • Interactive UIs — Confirmation dialogs, form inputs, selections
  • Real-time feedback — Progress indicators, approval workflows

How Client Tools Work

When the agent calls a tool, the Server SDK checks for a registered handler:

  1. Handler exists → Execute on server, continue automatically
  2. No handler → Forward to client as client-tool-request event

The client SDK receives pending tool calls, executes them (automatically or via user interaction), and sends results back to continue the conversation.

Rendering diagram...

Setup

Server Side

Define tools in your protocol but don't register handlers for client tools:

typescript

Client Side

Register client tool handlers when creating the chat:

typescript

Automatic Client Tools

Automatic tools execute immediately when called. Use these for browser operations that don't require user input.

Example: Geolocation

typescript

Example: Clipboard

typescript

Context Object

Automatic handlers receive a context object:

typescript

Use the signal to cancel long-running operations:

typescript

Tools that produce files (e.g., screenshots) can call ctx.addFile() to attach them to the result. Attached files are sent to the platform alongside the tool result so the LLM can see them as visual content on the next turn.

Interactive Client Tools

Interactive tools require user input before completing. Use these for confirmations, forms, or any UI that needs user action.

Mark a tool as interactive by setting its handler to 'interactive':

typescript

Accessing Pending Tools

Interactive tools appear in pendingClientTools, keyed by tool name:

typescript

Rendering Interactive UIs

tsx

Example: Confirmation Dialog

tsx

Example: Form Input

tsx

Status: awaiting-input

When interactive tools are pending, the chat status changes to 'awaiting-input':

typescript

Use this to:

  • Disable the send button
  • Show "Waiting for input" indicators
  • Prevent new messages until tools complete
tsx

Mixed Server and Client Tools

Tools can be split between server and client based on where they should execute:

typescript

When the LLM calls multiple tools in one turn:

  1. Server tools execute first on the server
  2. Server results are included in the client-tool-request event
  3. Client tools execute (automatic immediately, interactive waits)
  4. All results are sent together to continue

HTTP Transport

The HTTP transport handles client tool continuation automatically via a unified request pattern:

typescript

Your API route handles both request types:

typescript

Socket Transport

The socket transport sends a continue message with tool results:

Client → Server Messages

typescript

Server Handler

typescript

Error Handling

Automatic Tool Errors

Errors in automatic handlers are caught and sent back to the LLM:

typescript

The LLM receives: "Tool error: User denied geolocation"

Interactive Tool Cancellation

When users cancel interactive tools, provide a reason:

typescript

The LLM receives the cancellation reason and can respond appropriately.

Missing Handlers

If a client tool has no handler registered, an error is sent automatically:

text

Best Practices

1. Keep Server Tools on Server

Don't move database or API operations to client tools:

typescript

2. Use Interactive for Confirmations

Any destructive or important action should confirm with the user:

typescript

3. Handle Cancellation Gracefully

Always provide cancel buttons for interactive tools:

tsx

4. Validate Results

Validate user input before submitting:

typescript

Type Reference

typescript