调研智能体找到了客户的账户,确认了订阅计划,并获取了最近的四张发票。接着,它将任务交接给计费智能体,只给了一句简短的总结:“客户想要退款。”而对该账户、订阅计划或发票一无所知的计费智能体,一上来却开始询问客户的账户 ID。
第一个智能体收集的所有事实都在交接边界处被丢弃了。这就是“交接问题”(handoff problem),它会带来双重代价:一是重复的 API 调用,二是第二个智能体因掌握的信息比第一个少而导致的错误。
本指南将介绍在交接过程中必须保留的信息、团队传递状态的三种方式及其各自的适用场景、为什么总结丢失的信息比人们预期的要多,以及如何测试交接是否确实传递了声称的内容。我们在关于“智能体在生产环境中为何会崩溃”的文章中,将状态丢失视为一种核心失效模式;而这就是其多智能体版本。
提及 Apifox 是因为,最廉价的解决方案通常是完全停止传递数据,转而传递标识符,但这只有在每个智能体都能以相同方式获取相同记录时才有效。
AI Coding 交流群
如果你也在用 AI 写代码,或者正在研究 Cursor、Claude Code 这些工具,欢迎加入以下交流群。群里平时会聊一些 AI 编程的实际用法、开发工作流,还有各种新工具和新玩法。
究竟有哪些内容需要跨越边界
并非所有内容。复制整个对话的交接方式与什么都不复制一样糟糕,只是走向了另一个极端:第二个智能体继承了完整的上下文窗口,必须自行梳理出哪些部分是重要的。
可以将其分为以下四个类别。
标识符(Identifiers)。 账户 ID、订单 ID、任务 ID、工单号。这些数据体量小、稳定,能让接收端的智能体获取其所需的任何内容。它们是交接中最有价值的信息,却也最容易被遗漏。
已做出的决定。 “根据政策 3,该客户符合退款条件。”接收智能体决不能重新评估这一点。否则,在同一个任务中就会出现两个智能体意见不一致的情况。
约束条件。 预算限制、已获得的批准、已采取的操作。丢失这些信息会导致任务重复扣费或第二次请求相同的批准。这与我们关于 AI 智能体幂等性的文章直接相关。
未决问题。 第一个智能体无法解决的问题。明确传递这些问题可以防止第二个智能体进行盲目假设。
不需要跨越边界的内容包括:原始 API 响应、推理过程记录,以及接收智能体通过单次调用就能自行获取的任何内容。
传递状态的三种方式
传递整个对话。 这种方式很直观,适用于短任务中的两个智能体。但一旦记录变长,它就会失效,因为接收智能体会把大部分 Token 预算花在阅读历史记录上,而关键事实却被埋在了中间。我们关于“如何防止工具响应污染上下文窗口”的文章解释了为什么这个“中间位置”恰恰是模型最容易丢失信息的地方。
传递摘要。第一个 Agent 编写交接信息,第二个 Agent 从该信息开始工作。这是大多数框架中的默认方式,并且它会以一种特定的方式造成信息丢失:模型往往偏向于总结成叙述性文字,而忽略了标识符。如果要求生成摘要,你可能会得到“该客户已订阅两年,目前很沮丧”,而不是“账户 8812,专业版方案,四张发票,已批准对发票 inv_44 进行退款”。
传递结构化的交接 object。第一个 Agent 填充数据模型。第二个 Agent 读取字段,而非散文式的描述。这种方式的配置工作量更大,但却能够经受住考验。
{
"task_id": "task_2026_08_26_0031",
"from_agent": "research",
"to_agent": "billing",
"entities": {
"customer_id": "cus_8812",
"invoice_ids": ["inv_41", "inv_42", "inv_43", "inv_44"],
"subscription_id": "sub_119"
},
"decisions": [
{ "decision": "refund_eligible", "value": true, "basis": "policy 3.2, charged twice in one cycle" }
],
"constraints": {
"max_refund_cents": 4900,
"human_approval_granted": false,
"actions_taken": ["read_invoices"]
},
"open_questions": ["Customer has not confirmed which invoice to refund"],
"summary": "Customer cus_8812 was double-charged in August. Refund of one invoice is approved under policy 3.2, up to 4900 cents. Awaiting the customer's choice of invoice."
}
散文式的描述仍然会出现在 summary 字段中,因为它承载了数据模型所无法表达的细微差别。它与结构化字段并存,而不是取而代之,这正是关键所在。
在执行交接之前验证该 object。如果缺失 customer_id,应在边界处立即报错,而不是让第二个 Agent 在三次调用之后才发现这一问题。
传递引用,而非数据负载
最可靠的交接方式几乎不传递任何数据。它只传递 ID,由接收端 Agent 自行获取其所需的数据。
这之所以行之有效,有三个原因。首先,状态保持最新,因此如果两个 Agent 之间发生变化,第二个 Agent 看到的是本地值,而不是过期的副本。其次,交接的数据量很小,只有几百字节,而不是数万个 Token。第三,审计追踪能力得到提升,因为每次读取都会表现为一次 API 调用,而不是在提示词之间复制的文本。
这需要一个前提:每个 Agent 都能以正确的权限访问同一个 API。这并非没有代价。每个 Agent 都需要拥有与其职责范围相匹配的凭证,这正是我们在关于 Agent 最小权限 API Key 的文章中所阐述的观点。持有只读研究 Token 的账单 Agent 无法执行退款,而持有账单 Token 的研究 Agent 则会带来爆炸半径(安全隐患)问题。
在重新获取数据成本高昂或缓慢的情况下,可以在编排器中缓存该记录,并传递指向该缓存条目的引用。接收端 Agent 仍然会显式地请求数据,因此模式保持不变,但第二次读取的开销会非常低。
交接实际发生故障的地方
大多数事故都归因于以下四种失效场景。
丢失的标识符。 摘要中写着“该客户”但从未给出 ID,因此第二个 Agent 通过名称进行搜索,找到了两个匹配项,并选错了。为了防止这种情况,在允许进行交接之前,先验证所需的实体 ID 是否存在。
重复的操作。 第一个 Agent 已经发送了电子邮件,但交接过程没有记录该操作。第二个 Agent 又发送了一次。在交接 object 中记录 actions_taken,并在执行任何写入操作之前对其进行检查,同时辅以幂等性密钥(idempotency keys)以确保重复执行无害。
丢失的审批。 在第一个 Agent 运行时,人工批准了退款。第二个 Agent 并不知道这一点,于是再次询问。用户会将第二次提示视为系统没有倾听。请将审批作为显式约束进行传递,并将其视为作用于任务(task)本身而非特定 Agent。
自信的捏造。 接收端 Agent 需要一个交接中未携带的值,它没有进行询问,而是捏造了一个符合逻辑的值。这是最危险的故障,因为它看起来像是一个已完成的任务。防范措施是使用 open_questions 字段,并在接收端 Agent 的提示词(prompt)中加入一条硬性规则:如果缺少所需的标识符,立即停止并提问。
循环会让这四种情况变得更糟。当 Agent A 交接给 B,B 又交接回 A 时,状态在每次传递中都会衰减,就像复印件的复印件一样。限制跳数(hops),并在每一次交接中传递原始任务 object,而不是在每个边界处重新构建它。
测试边界,而不单是 Agent
交接是集成点,因此要将它们作为集成点进行测试。
对交接 object 进行断言。针对固定场景运行第一个 Agent,并检查它生成的 object:所需的标识符是否存在、决策是否已记录、操作是否已列出。这是一种对结构化 Payload 的确定性断言,尽管生成它的 Agent 是非确定性的,但这也正是该测试可行的地方。具体的方法可以参考我们关于测试非确定性 Agent 的指南。
独立测试接收端。向计费 Agent 输入一个手工构建的交接 object,并检查它的行为。然后向它输入一个刻意损坏的 object(删除客户 ID),并确认它会发起提问而不是凭空猜测。这第二个测试就是捕获捏造行为的关键。
针对 mock 运行两者。如果交接测试触发了真实的退款,那这个测试你可能只会运行一次。将两个 Agent 都指向 mock 接口,这样测试套件就可以在每次代码变更时运行,这遵循了我们关于针对 mock(而非生产环境)运行 Agent 的文章。在 Apifox 中,mock 源自两个 Agent 所调用的同一个接口定义,因此两者永远不会产生分歧。
记录每次交接。在每个边界处记录带有任务 ID 的完整 object。当多 Agent 运行出错时,交接日志会告诉你哪个 Agent 拥有该信息,以及哪个 Agent 丢失了它,这通常就是排查问题的全部关键。我们关于追踪 Agent 工具调用的文章涵盖了该记录中还应包含哪些其他内容。
框架能为你提供什么
大多数编排框架都自带移交原语,在开始使用之前,了解它们在边界之间实际传递了什么会很有帮助。
OpenAI Agents SDK 移交文档将移交建模为 Agent 可以调用的工具,这意味着由模型来决定何时转移控制权。这很方便,但它将决策交给了系统中确定性最差的部分,因此建议在输出时配合校验。
LangGraph 的多 Agent 指导则采用了相反的方法:状态是一个显式的图 object,每个节点都可以对其进行读写。这与上面描述的结构化移交非常契合,你剩下主要要做的工作就是决定哪些字段是必填的。
Anthropic 关于构建多 Agent 研究系统的文章非常值得一读,其中包含了丰富的运作细节,特别是关于子 Agent 在能够独立有效工作之前需要多少指令。
它们的共同点是:每个框架都会传递一些东西。但没有一个框架会替你决定哪些事实是起关键支撑作用的。这份清单需要你自己来写,并且当运行出错时,它是最值得检查的东西。
将 task object 保持在对话之外
做出一个结构性改变可以避免一大类 bug。将任务状态持久化存储在某个地方,以任务 ID 作为键(key),让每个 Agent 都对其进行读写,而不是通过消息来传递它。
对话并不是存储状态的好容器。它会被压缩、截断,并被自动总结重写,而这些操作都无法预知哪些字段是你绝对不能丢失的。数据库中的一行记录就不会有这个问题。
这个模式非常简单。在一个轮次(turn)开始时,Agent 加载 task object。当它执行某项操作时,它会将记录追加到 actions_taken 并保存。在移交时,它传递任务 ID,接收方的 Agent 就会加载同一个 object。没有任何重要信息会在 prompt 中传递,因此也就不会有重要信息因为总结而被过滤掉。
这还为你提供了一个恢复点。如果运行在第四步挂掉了,task object 依然保留着前三步建立的所有内容,重试可以直接从那里开始,而不是从零开始。
平台可以在哪里保存状态
如果你的 Agent 作为 CLI 运行时在开发人员的机器上运行,那么上面描述的持久化 task object 就需要由你自己来构建。一些 Agent 工作管理平台已经对其进行了建模,在你自己动手编写 hover 之前,了解一下它们的设计方式是很有价值的。
Sharkly 是一个专门围绕该单元构建的、面向人类与 Agent 的工作管理系统。一个 Task 承载了目标、状态、负责人、负责执行该任务的 Agent 或 Crew、评论以及 Agent 的执行状态和结果。一个 Crew 将一个 Leader Agent 与其他 Agent 及人类配对,因此需要多个专家协同的任务会被分配给一个可重用的群体,而不是通过 prompt 手手相传。由于状态存在于 Task 上而不是对话中,两个 Agent 之间的交接并不依赖于其中一方做出良好的总结。
运行时仍然保持您已有的选择。Claude Code、Codex 等在您注册的计算机上执行工作;该平台则提供任务记录、分配以及围绕它们的审查循环。如果您正在自己构建持久任务(durable-task)模式,Sharkly 文档对于了解哪些字段至关重要是一个非常有用的参考。
交接清单
- 为交接定义了明确的数据模型,并在边界处进行校验。
- 实体标识符是必填字段,而非可选字段。
- 决策需附带其依据,以便接收方无需重新进行推理。
- 在执行任何写入操作之前,已采取的操作必须被记录并检查。
- 审批和预算随任务一起流转,而不是随 Agent 流转。
- 未决问题必须明确,接收方应主动询问而非凭空假设。
- 在重新获取数据成本较低的情况下,通过引用传递数据。
- 限制跳转次数(Hop count),并且原始的 task object 在每次跳转中都得以保留。
- 每次交接都必须记录任务 ID 的日志。
- 在 CI 中针对 mock 运行边界测试,包括故意不完整的交接测试。
大多数多 Agent 系统的失败并不是推理失败,而是因为某个事实仅存在于前一个 Agent 中,而未传递给下一个 Agent。将边界设计为接口,配备数据模型和测试,这样第二个 Agent 就不会再重复询问第一个 Agent 已经回答过的问题。下载 Apifox,将 mock 和边界测试与两个 Agent 共同依赖的 API 放在一起。
常见问题解答
对于仅有两个 Agent 的情况,结构化交接值得吗? 对于短任务中的两个 Agent,通常直接传递对话就足够了。但当涉及三个或更多 Agent、长任务,或者交接跨越进程或运行边界时,结构化 object 就能发挥其真正的价值。
应该由模型编写交接 object,还是由代码来构建? 尽可能使用代码构建。标识符、已采取的操作和审批信息应该由您的编排器根据实际发生的情况来填充,而不是依靠模型的记忆。只让模型填写 summary(摘要)和未决问题。
如何防止循环中的上下文衰减? 在整个运行过程中只携带一个 task object 并对其进行更新,而不是在每个边界处重新生成。同时限制跳转次数。如果一个任务需要超过几次跳转,那么任务分解很可能是错误的。
对于内置了交接支持的框架,该如何处理? 直接使用它们,但要检查它们实际传输了哪些内容。许多框架仅传递消息历史记录,这意味着只有当标识符恰好出现在文本中时,它们才会被保留。因此,在框架传输的任何内容之外,建议额外添加一个结构化的 payload。
子 agent 需要独立的 API 凭证吗? 是的,并且应该将权限范围限制在每个 agent 所执行的任务内。在多个 agent 之间共享一个高权限的密钥会让你无法控制受损范围,也无法分辨是哪个 agent 发起了调用。我们关于 agent 最小权限 API 密钥的文章详细介绍了具体的配置方法。
summary 字段应该包含多少内容? 寥寥数句即可,用于说明结构化字段无法容纳的意图和细微特征。如果该字段开始列出 ID 和金额,那么这些内容应该放入结构化字段中,以便对其进行校验。
开发必备:API 全流程管理神器 Apifox
介绍完上文的内容,我想额外介绍一个对开发者同样重要的效率工具 —— Apifox。作为一个集 API 文档、调试、设计、测试、Mock、自动化测试于一体的工具,Apifox 是目前提升研发效率的首选。
如果你正在开发项目,不妨试试其极其友好的界面设计,它完全兼容 Postman 和 Swagger 数据格式,导入数据非常方便,,即使是新手也能很快上手,点击这里即可注册使用。

值得一提的是,除了个人和常规团队使用,针对有高安全合规要求、或需要在内网环境协作的企业,Apifox 还提供了深度定制的私有化部署方案。
获取专属报价与部署方案
详细的私有化部署系统架构与安全白皮书
针对您公司规模的专属报价单
免费的 1v1 专属产品演示 (Demo) 机会