Multi-Agent 不等于并行:Google ADK 中的安全工作流设计
一位开发者在 Dev.to 上发表文章,探讨了多智能体(Multi-Agent)系统设计中的一个常见误区:把任务拆分成多个 Agent 并不意味着它们会并行执行。文章以 Google ADK(Agent Development Kit)为例,介绍了如何设计安全的多 Agent 工作流。
背景:Multi-Agent 的流行
"让我们把它拆成多个 Agent"已经成为 AI 领域的"让我们把它做成微服务"。有时候这种拆分是有用的,有时候它只会制造更多的状态、更多的通信开销和更多的故障点。
多 Agent 系统的流行源于几个因素:
- 职责分离:不同的 Agent 负责不同的任务,类似于软件工程中的模块化
- 专业化:每个 Agent 可以针对特定任务进行优化(如使用不同的模型、提示词、工具)
- 可扩展性:理论上可以通过增加 Agent 来处理更复杂的任务
- 容错性:一个 Agent 失败不一定导致整个系统失败
但多 Agent 系统也带来了新的挑战:
- 协调开销:Agent 之间需要通信和协调,增加了延迟和复杂度
- 状态管理:多个 Agent 共享状态时容易出现一致性问题
- 错误传播:一个 Agent 的错误可能影响其他 Agent
- 调试困难:多 Agent 系统的行为更难预测和调试
核心误区:Multi-Agent ≠ Parallel
文章的核心观点是:把任务拆分成多个 Agent 并不意味着它们会并行执行。
在很多人的想象中,多 Agent 系统是这样的:
用户请求 → [Agent A] [Agent B] [Agent C] → 汇总结果
并行执行 并行执行 并行执行
但实际上,很多多 Agent 系统是这样的:
用户请求 → Agent A → Agent B → Agent C → 结果
串行执行 串行执行 串行执行
每个 Agent 必须等待前一个 Agent 完成才能开始,因为它们之间有数据依赖。这种情况下,多 Agent 不仅没有带来并行加速,反而增加了通信开销和延迟。
什么时候可以真正并行
多 Agent 真正能并行执行的条件是:
- 数据独立:Agent 之间没有数据依赖,每个 Agent 的输入不依赖其他 Agent 的输出
- 资源独立:Agent 之间不共享需要互斥访问的资源(如同一个文件、同一个数据库记录)
- 无副作用冲突:Agent 的操作不会相互干扰(如两个 Agent 同时修改同一个配置)
例如,一个内容生成系统可以这样并行:
用户请求 → [大纲生成]
↓
[正文生成] [配图描述生成] [摘要生成]
并行执行 并行执行 并行执行
↓
[内容组装]
正文生成、配图描述生成和摘要生成都只依赖大纲,彼此之间没有数据依赖,可以真正并行执行。
Google ADK 中的工作流设计
Google ADK(Agent Development Kit)是 Google 推出的 Agent 开发框架,提供了构建多 Agent 工作流的工具。
ADK 的核心概念
- Agent:基本的执行单元,包含模型、提示词、工具等
- Workflow:定义 Agent 之间的执行顺序和数据流转
- State:工作流的共享状态,Agent 之间通过 State 传递数据
- Router:根据条件决定下一步执行哪个 Agent
- Parallel:并行执行多个 Agent
串行工作流
最简单的工作流是串行执行,每个 Agent 按顺序执行:
workflow = LinearWorkflow(
agent_a, # 第一步
agent_b, # 第二步
agent_c, # 第三步
)
这种工作流适用于有明确数据依赖的场景,如:
- 先提取信息,再分析信息,最后生成报告
- 先翻译,再摘要,最后格式化
并行工作流
ADK 支持并行执行多个 Agent:
workflow = ParallelWorkflow(
agent_a, # 并行执行
agent_b, # 并行执行
agent_c, # 并行执行
)
并行执行时,所有 Agent 接收相同的输入,各自独立执行,最后汇总结果。
条件路由工作流
更复杂的工作流可以根据条件动态决定执行路径:
workflow = ConditionalWorkflow(
router_agent, # 决定走哪条路径
{
"path_a": agent_a,
"path_b": [agent_b1, agent_b2], # 路径B内部串行
"path_c": ParallelWorkflow(agent_c1, agent_c2), # 路径C内部并行
}
)
安全工作流的设计原则
文章提出了设计安全多 Agent 工作流的几个原则:
原则 1:明确数据依赖
在设计工作流时,首先要明确每个 Agent 的输入和输出,以及它们之间的数据依赖关系。
- 画出依赖图:在编码之前,先画出 Agent 之间的数据依赖图
- 识别可并行部分:依赖图中没有边连接的 Agent 可以并行执行
- 避免不必要的串行:如果两个 Agent 之间没有真正的数据依赖,不要把它们串行化
原则 2:隔离副作用
Agent 的副作用(如修改数据库、调用外部 API、写入文件)需要 carefully 管理,避免并行执行时产生冲突。
- 只读 Agent 可以安全并行:只读取数据、不修改任何状态的 Agent 可以安全地并行执行
- 有副作用的 Agent 需要协调:修改共享状态的 Agent 需要互斥或使用事务
- 幂等操作更安全:设计 Agent 的操作为幂等的(多次执行结果相同),可以减少并行冲突的影响
原则 3:设置超时和降级
多 Agent 系统中,一个 Agent 的延迟或失败不应该阻塞整个系统。
- 每个 Agent 设置超时:避免一个 Agent 无限期阻塞整个工作流
- 失败降级策略:Agent 失败时,有明确的降级策略(如使用默认值、跳过该步骤、使用缓存结果)
- 部分结果可用:即使某些 Agent 失败,工作流仍能返回部分有用的结果
原则 4:验证和审计
多 Agent 系统的行为更复杂,需要完善的验证和审计机制。
- 输入验证:每个 Agent 在执行前验证输入的合法性
- 输出验证:每个 Agent 的输出经过验证后再传递给下一个 Agent
- 执行日志:记录每个 Agent 的输入、输出、执行时间和状态,便于调试和审计
- 异常检测:监控 Agent 的行为模式,发现异常及时告警
原则 5:避免过度拆分
不是所有任务都需要拆分成多个 Agent。过度拆分会增加系统复杂度而不带来实际收益。
- 拆分前问自己:这个拆分真的有必要吗?它带来了什么好处?
- 考虑通信开销:Agent 之间的通信有延迟和成本,拆分的收益必须大于开销
- 从简单开始:先用单个 Agent 实现,遇到真正的瓶颈时再考虑拆分
- 避免"微服务陷阱":不要为了拆分而拆分,类似于微服务架构中的过度拆分问题
实际案例:内容审核工作流
文章以一个内容审核系统为例,展示了如何设计安全的多 Agent 工作流。
需求
- 接收用户提交的内容
- 进行多维度审核(色情、暴力、政治敏感、广告垃圾)
- 生成审核报告
- 根据审核结果决定是否发布
设计
用户内容 → [内容预处理] (串行:提取文本、图片、元数据)
↓
[色情检测] [暴力检测] [政治敏感检测] [广告检测] (并行:四个维度独立)
↓
[结果汇总] (串行:综合四个维度的结果)
↓
[人工复审?] → 是 → [通知审核员]
↓ 否
[发布内容]
安全考虑
- 并行检测是安全的:四个检测 Agent 都是只读的,只分析内容不修改状态,可以安全并行
- 结果汇总需要验证:汇总 Agent 需要验证四个检测结果的格式和范围,处理缺失或异常的结果
- 发布操作需要人工确认:自动发布有风险,设置阈值,高风险内容必须人工复审
- 完整的审计日志:记录每个检测 Agent 的结果和置信度,便于后续审查
总结
多 Agent 系统设计中的核心误区是认为拆分就等于并行。实际上,只有在数据独立、资源独立、无副作用冲突的情况下,多 Agent 才能真正并行执行。
Google ADK 提供了构建多 Agent 工作流的工具,包括串行、并行和条件路由等模式。但工具只是手段,关键在于设计原则:
- 明确数据依赖:画出依赖图,识别可并行部分
- 隔离副作用:只读 Agent 可以安全并行,有副作用的 Agent 需要协调
- 设置超时和降级:避免一个 Agent 阻塞整个系统
- 验证和审计:完善的输入输出验证和执行日志
- 避免过度拆分:从简单开始,遇到真正瓶颈再拆分
对于正在构建多 Agent 系统的开发者来说,这篇文章提醒我们:不要盲目追求"多 Agent"的时髦,要根据实际需求和数据依赖来设计工作流。好的多 Agent 系统应该是清晰、高效、安全的,而不是复杂、混乱、难以维护的。
原文链接:https://dev.to/raju_dandigam/multi-agent-does-not-mean-parallel-safe-workflows-with-google-adk-3j3