如何实现 Agent 间的 Handoff(任务交接)?
难度:中级 分类:Multi-Agent
简短回答
Agent Handoff 是多 Agent 系统中一个 Agent 将控制权、任务和对话上下文转交给另一个 Agent 的过程。最常用的实现是 OpenAI 提出的 transfer_to_XXX 模式——将 Handoff 包装为工具调用,当 Agent 判断任务超出自身能力时,调用 transfer_to_specialist_agent 函数触发交接。关键挑战不在于触发 Handoff,而在于上下文传递的可靠性——大多数"Agent 失败"实际上是 Handoff 时的上下文丢失或格式错误。最佳实践是使用结构化的 Handoff 数据(JSON Schema),而非自由文本。
详细解析
为什么需要 Handoff?
单个 Agent 配备太多工具或过大的上下文时,决策质量会下降。Handoff 允许将任务路由给专精的 Agent:

Handoff 是控制权转移而非工具借用:路由 Agent 判断超纲即 transfer,退货完成后再交接给财务 Agent,全程传递对话上下文。
实现方式 1:Tool-Based Handoff(OpenAI 模式)
将 Handoff 作为工具暴露给 LLM:
代码块
Python
# OpenAI Agents SDK 风格
from agents import Agent, handoff
# 定义专家 Agent
refund_agent = Agent(
name="Refund Agent",
instructions="你负责处理退款请求...",
tools=[execute_refund, check_refund_status],
)
shipping_agent = Agent(
name="Shipping Agent",
instructions="你负责处理物流问题...",
tools=[track_package, update_address],
)
# 路由 Agent 有 Handoff 能力
triage_agent = Agent(
name="Triage Agent",
核心 API 参数:
•
tool_name_override:自定义生成的工具名(默认 transfer_to_<agent_name>)
•
tool_description_override:自定义工具描述
•
on_handoff:Handoff 发生时的回调(用于日志、审计、状态注入)
•
input_filter:过滤传给目标 Agent 的对话历史(OpenAI SDK 提供 handoff_filters.remove_all_tools 等内置 filter)
•
input_type:用 Pydantic 模型约束 Handoff 的入参,强制结构化
工作原理: LLM 足够智能,会在合适的时机调用 transfer_to_XXX。当 Handoff 发生时,新 Agent 接管对话并获得完整的对话历史。
实现方式 2:Supervisor 模式(LangGraph)
代码块
Python
from langgraph.graph import StateGraph
实现方式 3:函数返回 Agent 对象
代码块
Python
# Swarm 风格:工具函数返回 Agent 对象触发 Handoff
def handle_refund(order_id: str):
"""处理退款请求"""
status = check_order(order_id)
if status == "delivered":
# 返回 Agent 对象 = 触发 Handoff
return refund_agent
else:
return f"订单 {order_id} 尚未送达,无法退款"
triage_agent = Agent(
上下文传递策略
Handoff 最大的挑战是上下文传递。三种策略:
代码块
Python
# 策略 1:完整历史传递(简单但可能超出上下文窗口)
def handoff_full_history(target_agent, conversation_history):
return target_agent.invoke(messages=conversation_history)
# 策略 2:摘要传递(节省 token,但可能丢失细节)
def handoff_with_summary(target_agent, conversation_history):
summary = summarize(conversation_history)
return target_agent.invoke(messages=[
{"role": "system", "content": f"前序对话摘要:{summary}"},
conversation_history[-1] # 最新一条用户消息
])
Input Filter(上下文过滤)
代码块
Python
# OpenAI Agents SDK 的 input_filter
from agents import handoff
Handoff 的可靠性设计
代码块
Python
class ReliableHandoff:
编排模式与 Handoff 的关系
#SyOLoksNGwWt text { white-space: pre; }#SyOLoksNGwWt .fb0 { stroke: var(--N900-FG, 0.15); }#SyOLoksNGwWt .fb0 {stroke: rgba(31,35,41, 0.15)}#SyOLoksNGwWt .fx0 { stroke-miterlimit: 10; }#SyOLoksNGwWt .fx0 {stroke-miterlimit: 10}#SyOLoksNGwWt .fa1 { fill: rgb(187, 191, 196); }#SyOLoksNGwWt .fa1 {fill: rgb(187, 191, 196)}#SyOLoksNGwWt .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#SyOLoksNGwWt .fx1 {font-style: normal}#SyOLoksNGwWt .fx2 { text-anchor: middle; }#SyOLoksNGwWt .fx2 {text-anchor: middle}#SyOLoksNGwWt .fx3 { dominant-baseline: central; }#SyOLoksNGwWt .fx3 {dominant-baseline: central}#SyOLoksNGwWt .fx4 { stroke: none; }#SyOLoksNGwWt .fx4 {stroke: none}#SyOLoksNGwWt .fc0 { fill: var(--text-caption); }#SyOLoksNGwWt .fc0 {fill: #646a73}#SyOLoksNGwWt .fa2 { fill: var(--text-link-disabled); }#SyOLoksNGwWt .fa2 {fill: rgb(187, 191, 196)}#SyOLoksNGwWt .fx5 { font: 400 13px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#SyOLoksNGwWt .fx5 {font-style: normal}#SyOLoksNGwWt .fx6 { text-anchor: start; }#SyOLoksNGwWt .fx6 {text-anchor: start}#SyOLoksNGwWt .fx7 { dominant-baseline: alphabetic; }#SyOLoksNGwWt .fx7 {dominant-baseline: alphabetic}#SyOLoksNGwWt .fc1 { fill: rgb(0, 0, 0); }#SyOLoksNGwWt .fc1 {fill: rgb(0, 0, 0)}#SyOLoksNGwWt .fb1 { fill: var(--N900-FG, 0.15); }#SyOLoksNGwWt .fb1 {fill: rgba(31,35,41, 0.15)}#SyOLoksNGwWt .fb2 { fill: rgb(209, 217, 224); }#SyOLoksNGwWt .fb2 {fill: rgb(209, 217, 224)}#SyOLoksNGwWt .fa3 { fill: var(--bg-body); }#SyOLoksNGwWt .fa3 {fill: #fff}ABC12345编排模式SequentialSupervisorDecentralizedHierarchicalHandoff 方式固定顺序传递Supervisor 决定路由Agent 自主 Handoff层级间逐级传递特点可预测,适合简单流程集中控制,灵活但有瓶颈去中心化,灵活但难追踪结构化,适合大型系统
常见误区 / 面试追问
误区:"Handoff 只是把对话历史复制过去" — 自由文本 Handoff 是上下文丢失的主要原因。应该用结构化数据(JSON Schema)传递上下文,像对待公开 API 一样对待 Agent 间接口。
误区:"任何 Agent 都可以 Handoff 给任何 Agent" — 应该限制 Handoff 的路径。每个 Agent 只能 Handoff 给预定义的目标 Agent,防止意外的循环 Handoff 或权限升级。
追问:"如何防止 Handoff 循环?" — 追踪 Handoff 链路,设置最大 Handoff 次数。如果 Agent A → B → A → B 循环出现,触发断路器并升级给人工处理。
追问:"Handoff 和工具调用有什么区别?" — 工具调用后控制权回到原 Agent;Handoff 后控制权完全转移到新 Agent。工具是"用完即还",Handoff 是"交接班"。