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.
Lifecycle overview
Section titled “Lifecycle overview”- Configure the same client tool names on your backend agent and in ChatKit.
- ChatKit receives a tool call from the agent and invokes
onClientTool({ name, params }). - Your handler runs in the browser and returns an object (or
Promise) describing the result. ChatKit forwards that payload to your backend. - If the handler throws, the tool call fails and the assistant gets the error message.
Register the handler in your UI
Section titled “Register the handler in your UI”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]" />;}const chatkit = document.getElementById('chatkit');
chatkit.setOptions({ api: { clientToken }, async onClientTool({ name, params }) { if (name === 'get_geolocation') { const position = await new Promise<GeolocationPosition>((resolve, reject) => { navigator.geolocation.getCurrentPosition(resolve, reject); }); return { latitude: position.coords.latitude, longitude: position.coords.longitude, }; }
throw new Error(`Unknown client tool: ${name}`); },});Returning values
Section titled “Returning values”- Return only JSON-serializable objects. They are sent straight back to your backend.
- Async work is supported—
onClientToolcan 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.