第 16 章:Handoff 机制:让 Agent 之间丝般顺滑地“交接棒”

40 阅读6分钟

第 16 章:Handoff 机制:让 Agent 之间丝般顺滑地“交接棒”

如果说编排器是指挥,Agent 是乐手,那么 Handoff(交接)就是空气中传播的声波。没有它,乐手们就是在演默剧,谁也听不见谁。

0001页.png

想象这样一个场景: 你安排 Agent A 去搜集特斯拉的财报,安排 Agent B 去计算利润率。 Agent A 辛辛苦苦搜到了 100 页 PDF,任务完成,退场了。 Agent B 上场了,一脸茫然:“数据呢?A 也没给我啊?”

这就是 Handoff(交接)缺失的后果。

在简单的单体程序里,变量是共享的,A 算出的 x,B 直接读就行。 但在分布式 Agent 系统里,A 和 B 可能跑在不同的服务器上,甚至相隔几天执行。如何保证 A 的产出能 精确、完整、可理解 地传递给 B?

本章我们来拆解 Agent 协作的三种通信模式。

01. 通信的三个层级:从简单到复杂

并不是所有场景都需要复杂的通信协议。架构设计的原则永远是 KISS (Keep It Simple, Stupid)

层级一:接力棒模式 (Dependency Injection)

场景:线性的 DAG 任务(A -> B -> C)。 比喻:4x100 米接力赛。 逻辑

  • Agent A 跑完,把手里的棒子(结果数据)直接塞给 Agent B。
  • Agent B 拿着棒子继续跑。
  • 优点:极其简单,零延迟。
  • 缺点:耦合度高,A 必须明确知道 B 存在。

层级二:黑板模式 (Workspace)

场景:多个 Agent 并行工作,或者需要数据共享。 比喻:教室里的黑板。 逻辑

  • Agent A 查到了数据,写在黑板的“财经区”(Topic)。
  • Agent B 需要计算,抬头看一眼黑板,读走数据。
  • Agent C 需要写报告,也抬头看一眼黑板,读走数据。
  • 优点解耦。A 根本不需要知道 B 和 C 的存在,只管写黑板就行。
  • 缺点:需要引入中间件(如 Redis),架构稍微复杂一点。

层级三:谈判桌模式 (P2P Messaging)

场景:复杂的动态协作。 比喻:自由市场。 逻辑

  • Agent A:“谁能处理这个 Python 报错?”(广播需求)
  • Agent B:“我能,但我现在忙,预计 5 分钟后。”(协商)
  • Agent A:“行,等你。”(确认)
  • 优点:极度灵活,支持自组织。
  • 缺点最复杂,容易死锁或超时,除非必要,尽量别用。

架构师建议: 90% 的场景,用 前两层 就够了。不要为了炫技去搞 P2P。

02. Plan IO:先签合同,再干活

在代码层面,Agent 之间怎么知道传什么数据?靠 Plan IO 协议。 这就好比两个微服务之间的 API 文档(Swagger/OpenAPI)。

在任务分解阶段,每个 Agent 必须声明两件事:

  1. Produces(我生产什么) :承诺输出的数据主题。
  2. Consumes(我消费什么) :执行任务必须依赖的数据主题。
# 伪代码:任务定义
Task_Fetch_Data:
    produces: ["financial_report"]  # 我承诺产出财报

Task_Analyze:
    consumes: ["financial_report"]  # 我需要财报才能开工
    dependencies: ["Task_Fetch_Data"]

编排器(Orchestrator)看到这个协议,就会明白: “哦,Analyze 必须等 Fetch_Data 完工,并且要把 Fetch_Data 的产出注入给 Analyze。”

03. 工程实战:前序结果注入(Context Injection)

对于最常用的 接力棒模式,实现非常简单粗暴。

当 Agent B 启动时,系统会自动把 Agent A 的运行结果(Result)塞进 B 的 Prompt 上下文 里。

Agent B 收到的 Prompt 可能是这样的:

你是一个财务分析师。
你的任务:计算利润增长率。

--- 上下文数据 (来自 Agent A) ---
【特斯拉2024财报摘要】
营收:960亿美元
净利润:150亿美元
同比增速:19%
-------------------------------

请基于以上数据进行计算...

小技巧:数值提取 如果 A 输出了一大段废话,B 很难解析。 我们可以在 A 结束时加一个 后处理(Post-process) 步骤,用正则提取出关键数值(如 numeric_value: 15000000000),直接传给 B 的代码解释器,这样比传文本更精准。

04. 进阶实战:工作空间(Workspace)

对于 黑板模式,我们通常使用 Redis 作为底层的“黑板”。

核心设计:Topic 与 Seq

  • Topic(主题) :数据的分类,比如 financial_data
  • Seq(序列号) :数据的版本号,全局递增。

**为什么要 Seq?**为了支持 增量读取。 Agent B 可能是一个长期运行的监控任务。它第一次读取了 Seq 1-10 的新闻。过了一小时,它不需要把旧新闻再读一遍,只需要告诉黑板:“给我 Seq > 10 的数据。”

# 伪代码:Agent 写数据
def workspace_append(topic, data):
    seq = redis.incr("global_seq")
    entry = { "seq": seq, "data": data, "timestamp": now() }
    redis.rpush(f"topic:{topic}", entry)

# 伪代码:Agent 读数据
def workspace_list(topic, since_seq):
    # 只返回序列号比 since_seq 大的新数据
    return filter(lambda x: x.seq > since_seq, redis.lrange(topic))

05. 优雅的等待:指数退避(Exponential Backoff)

当 Agent B 依赖 Agent A 的数据,但 A 还没跑完时,B 怎么办?

  • 方案 A:每隔 1 秒问一次:“好了没?”(高频轮询,浪费资源)
  • 方案 B:死等。(不知道等到什么时候)

最佳实践:指数退避。 B 会这样问:

  • 第 1 次:等 1 秒,问一下。
  • 第 2 次:还没好?等 2 秒,问一下。
  • 第 3 次:等 4 秒...
  • 第 4 次:等 8 秒...

这种策略既保证了数据刚产出时能被尽快发现,又在长时间等待时极大地节省了 CPU 和网络资源。这就是系统设计的 “礼貌”

06. 常见的大坑

0013页.png

坑 1:数据太大了

现象:Agent A 查了一篇 5万字的论文,直接塞进 Prompt 传给 B。 后果:B 的 Context Window 爆了,任务崩溃。 解法传引用,不传值。 A 把论文存进 S3(对象存储),只把 s3_link 传给 B。B 需要读哪一段,再去 S3 读。

坑 2:生产者缺位

现象:Plan 里说 B 需要消费 stock_price,但没有任何 Agent 承诺生产 stock_price后果:B 会无限等待,直到超时饿死。 解法:在任务启动前进行 静态检查(Static Analysis) 。检查所有 consumes 的主题,是否都在 produces 列表中有对应。如果有缺口,直接报错,不启动任务。

总结

Handoff 机制是 Agent 系统的 血管

  • 接力棒模式:解决了最基础的串行传参。
  • 黑板模式:解决了复杂的并发数据共享。
  • Plan IO:定义了数据流转的契约。
  • 指数退避:实现了优雅的依赖等待。

搞定了编排(大脑)和交接(血管),你的多 Agent 系统已经是一个健康的有机体了。

Part 6:高级推理模式 预告

到目前为止,我们的 Agent 主要是“做事”——查资料、写代码、发邮件。 但是,面对真正烧脑的难题(比如“推导一个数学定理”或“制定一个商业战略”),普通的思考方式可能不够用了。

下一章,我们将进入 高级推理 领域,探讨 Tree-of-Thoughts(思维树) :当线性思考走到死胡同时,如何让 Agent 学会像人类专家一样,进行多路径探索和回溯。 0015页.png