LangGraph Client Tools
Client tools are frontend-declared tools that the model can call but the browser executes. The backend only exposes tool schemas to the model and decides whether a turn should continue on the server or end so the client can run a local tool.
#State shape
The middleware reads this state slice:
Each ClientToolSpec is:
tools is the primary channel. client_tools is a fallback for raw run input keys.
#Catalog conversion
clientToolSpecs(state) filters out nameless entries and converts each client tool into the OpenAI function-tool shape accepted by LangChain chat models:
bindClientTools(llm, serverTools, state) binds server tools first, then appends the client-tool stubs for the current run.
#Routing behavior
clientToolsRouter(serverToolNames) creates a conditional-edge router.
The router sends the graph to the server tool node when the last model message includes a server tool call. A call is treated as server-side when its name appears in serverToolNames or when the name is unknown to the current client catalog.
The router returns END when the last model message has only known client-tool calls or no tool calls.
Use serverToolNames to disambiguate tools you actually execute on the backend.
#Mixed tool calls
When a model message contains both server and client tool calls, server work runs first. This keeps backend-owned side effects on the backend and lets the client tool call surface after the graph resumes.
That behavior comes from hasServerToolCall(): any server or unknown tool call routes to the server tool node.
#Lower-level helpers
Use these helpers when you need custom routing:
routeAfterAgent(state, serverToolNames, opts) is the primitive behind clientToolsRouter(). The default destinations are 'tools' and '__end__', but you can override them:
#Frontend contract
The backend middleware does not execute browser tools. The frontend must:
- send the catalog into the run input;
- observe the model's tool call;
- execute the local tool in the browser;
- resume the graph with a
ToolMessagecontaining the result.
The @threadplane/chat client-tools helpers provide the browser-side declaration and execution pieces.