Client tools need code on your side. For tools that call an HTTP endpoint from Fish Audio’s side, use webhook tools. For built-in capabilities like hanging up, see system tools.
How it works
1
Declare the tool on the agent
Add a tool of type
client to the agent’s tool list, alongside any webhook tools. The name, description, and arguments tell the model what the tool does and when to call it.2
Register a handler in your app
Pass a handler for the same tool name when starting a session with
@fishaudio/agent-client.3
The agent calls the tool
During the conversation, the agent invokes the tool with parameter values. The SDK dispatches the call to your handler.
4
Your result goes back to the agent
The handler’s return value is JSON-serialized and sent back, and the agent continues with the result — unless the tool is fire-and-forget.
Declare a client tool
Client tools sit alongside webhook tools in the agent’s tool list. A declaration looks like this:Tool definition
Naming rules
Tool names must match^[a-zA-Z][a-zA-Z0-9_-]{0,63}$ — start with a letter, then letters, digits, underscores, or hyphens, up to 64 characters total.
- Built-in tools live under a leading underscore (like
_transfer_call), which the pattern makes unreachable — your names never collide with them. - Names must be unique per agent — declaring a duplicate fails with a
400.
Handle the call in your app
Register handlers with theclientTools option when starting a session, or later with registerClientTool:
callId and toolName. It can be synchronous or async:
Handler signature
What the agent receives
The agent is never left hanging: while
expects_response is true the agent suspends that tool call until your result arrives or the timeout fires, then continues either way. Errors and timeouts return to the model as tool errors, so the agent can recover in conversation (“I couldn’t open that page — let me try something else”). To change the handler timeout, pass clientToolTimeoutMs (in milliseconds) when starting the session. Note there is a second, server-side deadline: the agent stops waiting after the tool’s timeout_seconds (default 30 s, settable 1–120 on the tool), and a handler result arriving after that is ignored — so clientToolTimeoutMs can only tighten the client-side deadline, not extend the agent’s wait.
Fire-and-forget tools
Setexpects_response to false for tools that are pure side effects — the agent triggers your handler and keeps talking without waiting. Any return value is ignored.
This suits UI actions where confirmation adds nothing: scrolling, opening a panel, firing an analytics event. If the agent should react to the outcome (“the page is open, now walk the user through it”), keep expects_response: true.
Observe tool activity
Every tool call — client and webhook alike — emitstoolCallStarted, toolCallCompleted, and toolCallFailed events on the session, with the call ID, tool name, and payloads. The events are on by default; sessions created with tool_events: false don’t emit them. Use them to render tool activity in your UI. See the Web SDK for the event reference.
Going further
Web SDK
Full
@fishaudio/agent-client API: sessions, events, audio.Webhook tools
Tools that call your HTTP endpoints server-side.
System tools
Built-in capabilities you toggle per agent.
Tools overview
How the agent chooses and combines tools.

