LangGraph middleware for binding client-declared tool stubs and routing client tool calls to END so the browser executes them.
Project description
threadplane-middleware
LangGraph middleware for binding client-declared tool stubs and routing
client tool calls to END so the browser executes them.
How it works
When a browser client sends a tool catalog ({name, description, parameters}
dicts) along with a run request, the graph can expose those tools to the LLM
and route their calls back to the browser instead of executing them
server-side. The browser then executes the call and re-runs the graph with a
ToolMessage carrying the result.
The catalog is read from state["tools"], falling back to
state["client_tools"] if tools is absent.
Installation
pip install threadplane-middleware
Usage
from langgraph.graph import END, StateGraph
from threadplane.middleware.langgraph import bind_client_tools, route_after_agent
# Server-side tools your graph owns
SERVER_TOOLS = [search_tool, calculator_tool]
base_llm = ChatOpenAI(model="gpt-4o")
def agent_node(state):
# bind_client_tools must be called per-run inside the node because
# the client catalog arrives in state and may differ between runs.
llm = bind_client_tools(base_llm, SERVER_TOOLS, state)
response = llm.invoke(state["messages"])
return {"messages": [response]}
def router(state):
# Returns "tools" for server tool calls, "__end__" otherwise.
# Map "__end__" to LangGraph's END in add_conditional_edges.
return route_after_agent(state, [t.name for t in SERVER_TOOLS])
graph = StateGraph(...)
graph.add_node("agent", agent_node)
graph.add_node("tools", ToolNode(SERVER_TOOLS))
graph.add_conditional_edges("agent", router, {"tools": "tools", "__end__": END})
What happens with a client tool call
- The LLM emits a tool call whose name matches a client-declared tool.
route_after_agentreturns"__end__"— the graph run ends.- The browser receives the partial output, executes the tool locally, and
re-runs the graph with a
ToolMessagecontaining the result. - The LLM continues from there as if it had called a server tool.
Lower-level helpers
from threadplane.middleware.langgraph import (
client_tool_specs, # → list of OpenAI function-tool dicts
client_tool_names, # → set[str] of client tool names
has_client_tool_call, # → bool
has_server_tool_call, # → bool
last_message, # → last message from state["messages"]
)
Development
uv venv
uv pip install -e '.[test]'
uv run pytest -q
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file threadplane_middleware-0.0.1.tar.gz.
File metadata
- Download URL: threadplane_middleware-0.0.1.tar.gz
- Upload date:
- Size: 95.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60c931d0248ed2e701a3aa1330c6fd647e611a949500269c5ba82f3607102cef
|
|
| MD5 |
a4940329541b8c7eb1d8e3d780d47e53
|
|
| BLAKE2b-256 |
015ffee360e3547bede9388bb72a9ad20ca811935582b989c78dafeaae57558a
|
File details
Details for the file threadplane_middleware-0.0.1-py3-none-any.whl.
File metadata
- Download URL: threadplane_middleware-0.0.1-py3-none-any.whl
- Upload date:
- Size: 4.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c14e49d506e8bd3078f54df381c150d390f2d129f844694d8f5154a2cd8710ea
|
|
| MD5 |
36d612a131b94576c89538ec944fa3d5
|
|
| BLAKE2b-256 |
725528e6b752f3f53f2c5d2c2fa3ef27ac62a255a3b29376384f2dfc96d8acb0
|