Middleware · API Reference

LangGraph.js client-tool helpers

bindClientTools() is the main helper from @threadplane/middleware/langgraph. It binds your server tools plus the current run's client-tool catalog onto a LangChain chat model.

import {
  bindClientTools,
  clientToolsChannel,
  clientToolsRouter,
} from '@threadplane/middleware/langgraph';

There is no root JavaScript entry point for @threadplane/middleware; import from the /langgraph subpath. The Python package exposes equivalent snake_case helpers from threadplane.middleware.langgraph.

Related helpers in the same entry point include clientToolsChannel(), clientToolsRouter(), clientToolSpecs(), clientToolNames(), hasClientToolCall(), hasServerToolCall(), routeAfterAgent(), and lastMessage().

bindClientToolsfunction

Bind server tools + the client catalog stubs onto `llm`. Call this INSIDE the agent node (per-run) — the client catalog arrives in state and may differ per run.

bindClientTools(llm: M, serverTools: unknown[], state: ClientToolsState): ReturnType<M["bindTools"]>

Parameters

ParameterTypeDescription
llmM
serverToolsunknown[]
stateClientToolsState

Returns

ReturnType<M["bindTools"]>
clientToolsChannelfunction

State channels for the client-tools catalog. Spread into Annotation.Root so a graph declares the `tools` (primary) and `client_tools` (fallback) slices in one line: const State = Annotation.Root({ ...MessagesAnnotation.spec, ...clientToolsChannel() }); Both are last-value-wins channels (the catalog is replaced per run, not accumulated).

clientToolsChannel(): object

Returns

object
clientToolsRouterfunction

A prebuilt conditional-edge callback. serverToolNames is bound once at construction; the returned function takes only state. graph.addConditionalEdges('agent', clientToolsRouter([]), ['tools', END]);

clientToolsRouter(serverToolNames: Iterable<string>, opts: object): (state: ClientToolsState) => string

Parameters

ParameterTypeDescription
serverToolNamesIterable<string>
opts?object

Returns

(state: ClientToolsState) => string
clientToolSpecsfunction

The client catalog as OpenAI function-tool dicts for `model.bindTools`.

clientToolSpecs(state: ClientToolsState): OpenAIFunctionTool[]

Parameters

ParameterTypeDescription
stateClientToolsState

Returns

OpenAIFunctionTool[]
clientToolNamesfunction

The set of tool names declared by the client in this run.

clientToolNames(state: ClientToolsState): Set<string>

Parameters

ParameterTypeDescription
stateClientToolsState

Returns

Set<string>
hasClientToolCallfunction

True if the last message calls at least one client tool.

hasClientToolCall(state: ClientToolsState): boolean

Parameters

ParameterTypeDescription
stateClientToolsState

Returns

boolean
hasServerToolCallfunction

True if the last message calls at least one server (non-client) tool. A call is server-side when its name is in serverToolNames OR is not a known client tool (unknown tools are assumed server-side).

hasServerToolCall(state: ClientToolsState, serverToolNames: Iterable<string>): boolean

Parameters

ParameterTypeDescription
stateClientToolsState
serverToolNamesIterable<string>

Returns

boolean
routeAfterAgentfunction

Routing helper for a LangGraph conditional edge. Returns `toolsNode` when the last message has a server tool call (dispatch to the server ToolNode); otherwise `end` (client-only calls — the browser executes them — and no-tool-call turns both end).

routeAfterAgent(state: ClientToolsState, serverToolNames: Iterable<string>, opts: object): string

Parameters

ParameterTypeDescription
stateClientToolsState
serverToolNamesIterable<string>
opts?object

Returns

string
lastMessagefunction

The last message from state.messages, or undefined.

lastMessage(state: ClientToolsState): BaseMessage<MessageStructure<MessageToolSet>, MessageType> | undefined

Parameters

ParameterTypeDescription
stateClientToolsState

Returns

BaseMessage<MessageStructure<MessageToolSet>, MessageType> | undefined