[控场AI]
· 5 分钟阅读· 2,805 字

OpenAI Agents SDK 中的 handoff:一个 Agent 如何交接对话

OpenAI Agents SDK 中的 handoff:一个 Agent 如何交接对话

OpenAI Agents SDK 把 Agent 交接建模成普通工具调用,用 handoffs 声明关系、用 input filter 控制上下文。

文章解析了 OpenAI Agents SDK 中 handoff 机制的设计思路。核心观点是:对模型而言,交接只是调用一个名为 transfer 的普通工具,因此无需学习新的协作协议,直接复用其已有的工具选择能力。开发者通过 handoffs 参数声明某个 Agent 可以交接给哪些目标,SDK 会为每个目标生成带 transfer 名称的工具暴露给模型;交接后新 Agent 默认继承完整对话历史,也可用 input filter 裁剪实际传入的上下文。这一设计把多 Agent 系统的复杂度从「让模型理解交接」转移到「设计清晰的职责边界与传递规则」,作者建议从分诊、执行、收尾等明确分工入手,用 handoffs 显式表达协作关系。

在多 Agent 协作的架构里,最关键的一环往往不是单个 Agent 有多聪明,而是它们之间怎么交接任务。OpenAI Agents SDK 给出的答案是 handoff(交接)——让一个 Agent 把对话的控制权交给另一个 Agent。

handoff 的本质:对模型来说,它只是一个工具

这套机制最反直觉的地方在于:对模型而言,handoff 就是一个普通的工具调用。

设想一个客服场景:用户提出退款请求,负责分诊的 triage agent 并不需要自己处理退款,它只需要调用名为 transfer_to_refund_agent 的工具。模型看到的,就是这个工具;模型决定调用它,交接就发生了。

A customer wants a refund, so the triage agent calls transfer to refund agent.

这意味着你不需要教模型一套全新的「交接协议」。模型仍然在做它最擅长的事——在合适的时机选择调用合适的工具,只不过这次工具调用的结果是换了一个 Agent 继续对话。

工具调用(Tool Calling / Function Calling) 是大模型的一项基础能力:开发者在请求中声明若干可用工具(名称、参数 schema、用途描述),模型在生成回复时可以选择输出一个结构化的调用请求,由外部程序执行后把结果回填给模型,模型再继续生成。它本质上是一种「让模型表达意图、由代码执行动作」的协议,模型本身并不真正执行任何操作。

理解这一点,就能明白为什么把 handoff 建模成工具调用如此自然:SDK 只是把「切换到另一个 Agent」也定义成一种可被模型请求的动作,复用已有的调用—回填循环。模型不需要理解「Agent」这个抽象概念,它只需要在各种工具里选出一个名为 transfer 的工具并给出调用参数。控制权的转移实际发生在 SDK 一侧:它接收到这个特定的调用请求后,不执行普通函数,而是切换当前活跃的 Agent。

配置方式:handoffs 参数与 transfer 工具

在 OpenAI Agents SDK 里,一个 Agent 可以向哪些 Agent 交接,是通过 handoffs 参数声明的。

In the OpenAI Agents SDK, a handoff lets one agent delegate to another.

你在这个参数里列出允许交接的目标 Agent,SDK 会为每一个目标生成对应的工具,并带上 transfer 名称。

You list the agents it may hand off to in its handoffs parameter.

Each one shows up to the model as a tool with a transfer name.

这样的设计带来两个直接好处:

  • 声明式配置:交接关系写在代码里,而不是散落在提示词中,可读性和可维护性都更好。
  • 模型友好:目标 Agent 以工具形式暴露,模型用已有的工具调用能力就能完成移交,不需要额外的推理负担。

声明式(declarative)与命令式(imperative) 是两种常见的配置思路。命令式写法要求在提示词或流程代码里逐步描述「什么条件下做什么」;声明式写法只描述「存在哪些关系和目标」,具体触发时机交给模型判断。

handoffs 参数属于后者:你只声明某 Agent 可以交接给谁,SDK 自动生成对应的 transfer 工具及其描述,至于何时调用,由模型根据当前对话内容自行决定。这种做法的代价是控制粒度较粗——你无法精确规定「第几轮之后才能交接」;收益则是配置集中、不易随提示词改动而失效。如果确实需要在交接前后插入校验逻辑(如权限检查、日志记录),可以借助 SDK 提供的回调钩子,在交接发生时执行自定义代码。

上下文传递:默认全量,输入过滤器负责裁剪

交接发生之后,新接手的 Agent 默认会看到此前完整的对话历史。这个默认值符合多数场景的直觉——退款 Agent 当然需要知道用户前面说了什么。

但当上下文过长、或者包含敏感信息、又或者新 Agent 只需要部分信息时,全量传递就成了负担。SDK 提供了 input filter,让你决定新 Agent 实际收到什么。这也是「handoff 之后由谁接着对话」这个问题的关键控制点:交接的目标是谁,以及它看到的是什么,是两件可以分开配置的事。

实践中的取舍在于:

  • 全量历史让新 Agent 理解更完整,但 token 成本更高,也可能引入无关噪音;
  • 过滤后的输入更聚焦、更省成本,但需要你判断哪些信息对下一个 Agent 真正必要。

上下文(context) 在这里指 Agent 每次向模型发起请求时所携带的消息序列,通常包括 system 提示、此前所有用户与助手消息、以及工具调用的请求与结果。它既是模型做出判断的依据,也是 token 消耗的主要来源——对话越长,每次请求携带的内容越多,成本和延迟也越高。

值得注意的是,多 Agent 系统里存在两类容易混淆的状态:一是对话历史,即用户可见的消息流,它在 handoff 后默认被完整传递;二是应用侧共享状态,例如用户 ID、订单号、已执行的查询结果等,这类数据通常通过 SDK 提供的 context 对象在 Agent 之间共享,不依赖消息历史传递。设计职责边界时,分清「哪些信息应该进入对话历史」和「哪些信息应该放在共享上下文中」可以显著减少不必要的消息膨胀。

这套设计说明了什么

把 handoff 建模成工具调用,是 OpenAI Agents SDK 一个相当务实的选择。它复用了模型已经训练得很好的能力(工具选择),而不是要求模型学习一套新的协作语义。对开发者来说,多 Agent 系统的复杂度也就从「如何让模型理解交接」转移到了「如何设计清晰的职责边界和传递规则」——后者恰恰是更值得投入的地方。

如果你正在拆分一个单体 Agent,可以从明确的职责划分开始:谁负责分诊、谁负责执行、谁负责收尾,然后用 handoffs 把这些关系显式地写出来。

#OpenAI Agents SDK#handoff#多 Agent 协作#Agent 交接#input filter#工具调用#AI Agent 开发
分享:

相关推荐