Handoff Tools
In shortcreate_handoff_tool and is_handoff_tool build and detect transfer_to_X tools used to route control between agents in a swarm.
- 2 min read
- 3 sections
- Updated
- v0.9.2
- Markdown
Utilities for creating agent-to-agent transfer tools used in multi-agent swarm patterns.
Import path: tenxgraph.prebuilt.tools.handoff
Handoff tools are special tools that tell an LLM it can transfer control to another agent. When the LLM calls a handoff tool, the graph routing layer intercepts the call and navigates to the target node directly — the tool function body never actually executes. This keeps the conversation history clean (no spurious tool-result messages).
create_handoff_tool
Factory function that creates a transfer_to_<agent_name> tool.
Concept
In a swarm or peer-to-peer multi-agent graph, each agent needs to know which other agents it can route to. create_handoff_tool creates one tool per target. The naming convention transfer_to_<name> is what the graph routing layer detects to perform the handoff.
Agent calls transfer_to_researcher
↓
Graph routing layer detects "transfer_to_" prefix
↓
Graph routes to the RESEARCHER node
(tool body never runs)Signature
def create_handoff_tool(
agent_name: str,
description: str | None = None,
) -> CallableParameters
| Parameter | Type | Description |
|---|---|---|
agent_name |
str |
Name of the target agent/node. Must match a node name in the graph. |
description |
str | None |
LLM-visible description of when to use this handoff. Auto-generated if None. |
Returns
A callable with __name__ = "transfer_to_<agent_name>" and two metadata attributes:
__handoff_tool__ = True__target_agent__ = agent_name
Usage
from tenxgraph.prebuilt.tools.handoff import create_handoff_tool
from tenxgraph.core.graph import Agent, ToolNode
transfer_to_researcher = create_handoff_tool(
agent_name="researcher",
description="Transfer to the research specialist for web searches and fact finding.",
)
transfer_to_writer = create_handoff_tool(
agent_name="writer",
description="Transfer to the writer once all research is complete.",
)
triage_agent = Agent(
model="gpt-4o-mini",
tool_node=ToolNode([transfer_to_researcher, transfer_to_writer]),
system_prompt=[{
"role": "system",
"content": "Route the user's request to the right specialist.",
}],
)In practice, you rarely call create_handoff_tool directly. Use SwarmAgent instead — it generates and injects handoff tools automatically based on the can_handoff_to configuration.
is_handoff_tool
Helper that checks whether a tool name follows the handoff naming convention.
Signature
def is_handoff_tool(tool_name: str) -> tuple[bool, str | None]Returns
(is_handoff, target_agent_name):
- If
is_handoffisTrue,target_agent_namecontains the extracted target name. - If
is_handoffisFalse,target_agent_nameisNone.
Examples
from tenxgraph.prebuilt.tools.handoff import is_handoff_tool
is_handoff_tool("transfer_to_researcher") # (True, "researcher")
is_handoff_tool("calculate") # (False, None)
is_handoff_tool("transfer_to_") # (False, None) — empty targetThis function is used internally by SwarmAgent’s routing functions to detect handoff calls inside state.context[-1].tools_calls. You can use it when building custom routing logic for manual multi-agent graphs.
Manual multi-agent example
from tenxgraph.core.graph import Agent, ToolNode
from tenxgraph.core.graph.state_graph import StateGraph
from tenxgraph.core.state.agent_state import AgentState
from tenxgraph.prebuilt.tools.handoff import create_handoff_tool, is_handoff_tool
from tenxgraph.utils.constants import END
def make_route(allowed: list[str]):
def _route(state: AgentState) -> str:
last = state.context[-1] if state.context else None
if last and last.role == "assistant" and last.tools_calls:
for tc in last.tools_calls:
ok, target = is_handoff_tool(tc.get("name", ""))
if ok and target and target.upper() in allowed:
return target.upper()
return END
return _route
transfer_to_writer = create_handoff_tool("writer", "Send to the writer when research is done.")
researcher = Agent(
model="gpt-4o",
tool_node=ToolNode([transfer_to_writer]),
)
writer = Agent(model="gpt-4o-mini")
graph = StateGraph()
graph.add_node("RESEARCHER", researcher)
graph.add_node("WRITER", writer)
graph.add_conditional_edges("RESEARCHER", make_route(["WRITER"]), {"WRITER": "WRITER", END: END})
graph.add_edge("WRITER", END)
graph.set_entry_point("RESEARCHER")
app = graph.compile()For most use cases, use SwarmAgent rather than wiring handoffs manually.