Hotdry.

Article

基于 OpenAI Agents Python 的 Handoffs 机制与跨代理状态传递工程实践

深入解析 OpenAI 官方多代理框架的 Handoffs 机制,给出工作流编排、输入过滤与信任边界的工程参数配置清单。

2026-04-16ai-systems

在构建复杂多代理系统时,代理间的控制权转移与状态传递是核心挑战。OpenAI Agents Python SDK 提供了 Handoffs 机制,允许一个代理在执行过程中将控制权委托给另一个代理,而无需重启对话流程。这一机制的设计既保留了模型决策的显式性,又通过丰富的自定义选项满足了工程化需求。本文将从机制原理、参数配置、状态传递与安全边界四个维度,给出可落地的工程实践参数。

Handoffs 机制核心原理

Handoffs 的本质是将代理间的切换操作暴露为 LLM 可调用的工具。当一个代理配置了 Handoff 目标时,该目标会以类似 transfer_to_<AgentName> 的工具形式出现在模型的工具列表中。如果配置了多个目标,模型可以在推理过程中自主选择最合适的目标进行委托。这种设计确保了代理切换是显式的、可追溯的,而非隐式发生。

从执行流程来看,当模型决定触发 Handoff 时,SDK 会执行以下步骤:首先解析模型输出的 Handoff 动作;其次调用目标 Handoff 对象配置的 on_handoff 回调函数;最后将控制权与上下文传递给目标代理。值得注意的是,整个过程发生在单次 Runner.run() 调用内部,Handoff 不会创建新的独立会话。

在基本用法中,开发者可以通过两种方式配置 Handoff:一是直接将目标 Agent 实例放入当前代理的 handoffs 参数列表;二是使用 handoff() 函数创建更精细的 Handoff 对象。后者提供了丰富的自定义能力,包括工具名称覆盖、描述覆盖、回调函数、输入类型过滤等。

关键工程参数配置

在实际工程实践中,以下参数是需要重点配置的核心选项:

目标代理配置参数:创建 Handoff 时必须指定目标 Agent,可选参数包括 tool_name_override 用于自定义工具名称(默认为 transfer_to_<agent_name>)、tool_description_override 用于自定义工具描述文本、is_enabled 用于运行时动态控制(可以是布尔值或返回布尔值的函数)。

数据传递参数input_type 定义 Handoff 工具调用时的参数 schema,通常使用 Pydantic 模型定义,例如传递升级原因、优先级或摘要信息;input_filter 允许在 Handoff 发生前对历史消息进行处理,可以过滤敏感信息或精简对话历史;on_handoff 回调函数接收代理上下文与 input_type 解析后的数据,可用于日志记录、数据预取或权限检查。

历史记录管理参数nest_handoff_history 控制是否将之前的对话转录折叠为单条摘要消息并包裹在 <CONVERSATION HISTORY> 块中,默认关闭以保证稳定性;RunConfig.handoff_history_mapper 允许自定义映射函数替换默认生成的摘要消息;可通过 set_conversation_history_wrappers 自定义包装文本。

推荐在所有参与 Handoff 的代理指令中加入官方建议的前缀,可通过 agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX 获取,或直接调用 prompt_with_handoff_instructions 自动注入。

跨代理状态传递实践

跨代理状态传递是 Handoffs 机制的核心价值之一。根据不同的业务场景,开发者应选择合适的传递方式:

对于模型在 Handoff 决策时生成的小型元数据(如升级原因、语言偏好、优先级),应使用 input_type 参数。这种数据由模型在触发 Handoff 时主动生成,通过 Pydantic schema 定义后,SDK 会验证 JSON 格式并将解析后的对象传递给 on_handoff 回调。例如,分类代理可以携带 { "reason": "duplicate_charge", "priority": "high" } 将上下文传递给退款代理。

对于应用层已有的状态和依赖项,应通过 RunContextWrapper.context 传递,而非依赖 Handoff 的 input_type。这是两种不同的数据通道:context 存放应用状态,input_type 存放模型决策产生的元数据。两者互不替代,应分别使用。

对于需要过滤或转换历史消息的场景,input_filter 提供了细粒度控制。该函数接收 HandoffInputData 对象,包含 input_historypre_handoff_itemsnew_items 等字段,可返回修改后的对象。SDK 在 agents.extensions.handoff_filters 中预置了常用过滤器,如 remove_all_tools 自动移除历史中的所有工具调用,避免敏感工具暴露给下游代理。

在多级 Handoff 场景下,启用 nest_handoff_history 可以避免对话历史无限膨胀。该功能将之前的所有消息折叠为单条摘要,但目前处于 opt-in beta 阶段,生产环境使用需评估稳定性。如果在单次运行中发生多次 Handoff,该功能会将新的对话轮次持续追加到同一摘要块中。

信任边界与安全考量

理解 Handoffs 的安全边界对于生产部署至关重要。官方文档明确指出:输入 guardrail 仅作用于链条中的第一个代理,输出 guardrail 仅作用于最终产生输出的代理。这意味着中间代理之间的数据传输不受 guardrail 保护。如果需要在每个自定义函数工具调用周围添加检查,应使用工具级别的 guardrail。

在设计多代理架构时,建议遵循最小权限原则:每个代理应仅配置其职责所需的 Handoff 目标,避免过度暴露;使用 is_enabled 参数根据运行时状态动态禁用某些 Handoff 路径;通过 input_filter 过滤敏感信息,仅传递任务完成所需的最少上下文。

对于涉及合规要求的场景,应在 on_handoff 回调中实现审计日志,记录每次 Handoff 的时间、源代理、目标代理及携带的元数据。同时考虑在回调中执行权限验证,确保当前用户上下文允许触发目标代理。

监控与调试要点

生产环境中,建议监控以下关键指标:Handoff 触发频率与模式,异常高的频率可能表明代理职责划分不清或指令不够明确;Handoff 决策延迟,从模型输出 Handoff 动作到控制权转移的时间;on_handoff 回调的执行时长,特别是涉及外部数据预取的场景。

调试时,可通过 RunConfig.handoff_history_mapper 注入自定义映射函数,将 Handoff 相关的中间消息输出到独立日志通道,便于追踪状态传递路径。

小结

OpenAI Agents Python SDK 的 Handoffs 机制为多代理协作提供了清晰的控制权转移框架。通过合理配置 input_typeinput_filteron_handoff 等参数,开发者可以实现结构化的状态传递与安全过滤。工程实践中应特别注意 guardrail 的作用范围边界,避免产生安全盲区。

资料来源:OpenAI Agents Python SDK 官方文档(https://openai.github.io/openai-agents-python/handoffs/)

ai-systems