Skip to content

Client tools

Client tools let your backend agent delegate work to the browser. When the agent calls a client tool, ChatKit pauses the response until your UI resolves onClientTool.

Use this option to reach APIs that only exist in the browser (local storage, UI state, hardware tokens, etc.) or when client views need to update in step with server-side changes. Return a JSON-serializable payload back to the server after you’re done.

  1. Configure the same client tool names on your backend agent and in ChatKit.
  2. ChatKit receives a tool call from the agent and invokes onClientTool({ name, params }).
  3. Your handler runs in the browser and returns an object (or Promise) describing the result. ChatKit forwards that payload to your backend.
  4. If the handler throws, the tool call fails and the assistant gets the error message.
import { ChatKit, useChatKit } from '@openai/chatkit-react';
import type { ChatKitOptions } from '@openai/chatkit';
type ClientToolCall =
| { name: 'send_email'; params: { email_id: string } }
| { name: 'open_tab'; params: { url: string } };
export function SupportInbox({ clientToken }: { clientToken: string }) {
const { control } = useChatKit({
api: { clientToken },
onClientTool: async (toolCall) => {
const { name, params } = toolCall as ClientToolCall;
switch (name) {
case 'send_email':
const result = await sendEmail(params.email_id);
return { success: result.ok, id: result.id };
case 'open_tab':
window.open(params.url, '_blank', 'noopener');
return { opened: true };
default:
throw new Error(`Unhandled client tool: ${name}`);
}
},
} satisfies ChatKitOptions);
return <ChatKit control={control} className="h-[600px] w-[320px]" />;
}
  • Return only JSON-serializable objects. They are sent straight back to your backend.
  • Async work is supported—onClientTool can return a promise.
  • Throwing an error surfaces the message to the agent and halts the tool call.
  • If a tool does not need to return data, return {} to mark the invocation as success.