多个 Agent 并行执行时如何管理全局状态并避免竞争?

考查重点:并行写入与状态合并。并行分支各写独立结果,按字段 reducer 或版本校验合并;共享计数用原子操作,避免直接覆盖全局状态

本题目录

参考答案

核心回答

我会按任务隔离、写入归属、合并规则和原子提交管理状态,尽量减少多个Agent直接修改同一个字段。

  1. 全局只在当前任务内共享:用户和任务标识明确,子Agent保留自己的执行过程,公共状态只放协作必需的信息。
  2. 并行分支分别交结果:各自写对应结果槽或提交带ID的更新,最终结论由一个归并节点写入。
  3. 按字段定义合并语义:列表是否去重、消息怎样按ID更新、计数怎样累计,不能统一用覆盖或拼接。
  4. 共享修改用原子机制保护:进程内用短临界区或单写者;数据库用条件更新、版本或事务,冲突后重新判断。
  5. 处理重复、迟到和接管:结果带任务版本和归属,旧执行不能覆盖新状态;外部业务操作另有幂等保障。

例如两个检索Agent并行收集资料,应分别返回各自来源,再统一合并;不能都基于旧的 sources 列表生成完整新列表,谁晚返回就覆盖谁。

展开说明

1. 把共享State当作有职责的数据,而不是全局变量

可以保存目标、任务版本、分支状态、结果引用、预算和最终产物。对话、工具中间记录以及只供某角色使用的信息留在各自运行状态里。不同用户、会话和运行不能复用一份无范围的可变字典。

共享字段应明确谁能写:子Agent提交局部结果,调度者更新运行状态,归并者生成最终输出。线程安全Map只能避免容器结构损坏,无法判断“哪个Agent的结论应该成为最终结果”。把这些职责分开,往往比给整个State加一把锁更有效。

2. LangGraph中,局部更新也需要正确的reducer

节点通常返回变化的字段,由框架按字段应用reducer。同一super-step的并行节点若写入不支持多次更新的同一字段,可能触发 INVALID_CONCURRENT_GRAPH_UPDATE;不能假定框架会自动选择最后一条。

可独立的结果用不同字段保存;确需共同汇入一个列表或映射时,定义合并规则。例如资料按稳定来源ID去重,分支结果按任务与角色定位。普通列表相加只是拼接,不会自动去重;add_messages 则会根据消息ID追加或更新,语义不同。

并行完成顺序不应成为业务顺序。需要固定顺序时,结果附带章节号或其他排序键,归并后明确排序。自定义reducer要检查空值、重复更新、顺序和重放;若规则不能安全合并,就保留单写者,不必强求所有字段并发可写。

3. 数据库条件写要保护实际状态转换

假设两个执行者都读到任务版本5,随后都想推进任务:提交时要求“当前版本仍为5,状态仍允许本次转换”,并在同一个原子更新中写入新状态和版本。第一个成功后,第二个的条件不再成立,应重新读取并判断结果是否仍有效,不能把旧整份State再次覆盖回去。

跨多个字段的不变量可以用适当事务或锁保护。事务隔离级别有不同保证;发生版本冲突、序列化失败或接管变化时,要明确重试哪些逻辑。进程内锁只协调本进程,多个服务实例不能靠各自的一把锁保护同一数据库记录。

网络或模型调用可能很慢,不宜一直占着全局锁或长事务等待。可以先读取版本并执行局部工作,再用条件提交检查是否仍适用。被取消、目标已更新或已由新执行接管的结果,应拒绝发布到当前权威状态。

4. 重复投递、费用和外部副作用分别处理

结果提交带稳定ID和任务版本,可以避免同一结果重复归并。预算统计却需要记录每次实际模型或工具尝试:重试真的产生了费用,不能因为最终结果去重就把这部分消耗抹掉。

若任务分布在远程Worker,失联接管可使用租约,并让状态写入端校验递增的接管版本或fencing token,拒绝旧Worker恢复后的迟到写入。单进程能够直接取消和等待的任务,通常不必提前引入这套机制。

检查点负责保存执行状态,不能替代所有并发控制;数据库事务也不能自动让远程发单、通知等操作只发生一次。存在外部副作用时,还需要业务幂等标识、回执与状态查询,避免恢复或竞争后重复执行。

5. 用交错顺序验证不变量

至少检查两个分支同时提交、重复提交、旧版本迟到、取消后返回,以及一个分支失败时怎样归并。应确认资料不丢失、同一结果不重复、终态不会被旧结果改回运行中,最终产物来自规定的归并逻辑。

失败是否允许部分交付由任务定义;分支进入失败或超时终态,不代表它成功完成。观察记录应能关联任务、分支、尝试、输入版本与提交结果,才能定位是计算错误、合并错误还是过期写入。

常见追问

有checkpoint就不会竞争了吗?

不会。它保存执行进度和状态,但同一任务的并发推进、应用外部数据库的修改及旧Worker接管,仍需相应的单写或条件提交机制。还要遵循所用框架对同一线程并发运行的支持方式。

所有字段都用operator.add可以吗?

不可以。它对列表是拼接,对数值是相加,不能判断哪个结果有效,也不自动去重。最终结论、状态转换、消息更新和费用事件有不同语义,应分别设计。

需要给整个系统上分布式锁吗?

不一定。先通过任务隔离、分支分槽和单一归并减少争用。只有确实跨实例竞争同一资源时,再选择数据库条件写、事务或适当锁机制;锁的范围、超时和接管后的旧写入也要处理。

对应教程

  • LangGraphAPI:图与状态:比较默认更新、add_messages、列表累加及自定义reducer,理解状态字段的合并语义。同step并发更新的限制还需结合框架当前说明判断。

参考资料

  • 国内:JavaGuide:共享状态与并发归并:借鉴按角色分槽、权威字段单写及远程接管的设计,说明正文中为何需要业务合并规则,以及何时才引入 lease 与 fencing。
  • 国内:ranxi2001:共享状态读写职责:依据任务范围、读写分离与版本控制,说明正文中如何减少多个 Agent 共同修改同一字段。
  • 国内:WeThinkIn:异步写入与版本一致性:依据预期版本、重复和迟到更新的处理,说明正文中状态条件提交及冲突后的重判策略。
  • 国外:LangGraph:Graph API:依据 super-step、局部更新与逐字段 reducer 的约定,解释正文中框架如何合并并行更新与消息。
  • 国外:PostgreSQL:Transaction Isolation:依据并发条件检查、隔离保证和事务重试,说明正文中数据库原子保护的范围及其对远程副作用的限制。

相关面经

3 篇

百度

AI 测试开发工程师
一面
查看原面经 →
项目追问
拷打项目:不过基本上是围绕测试进行的,比如如何构建测试集,怎么评测agent输出的效果,并行节点遇到冲突怎么解决?项目开发系统怎么构建trace,如何定位问题等等,agent返回结果不理想怎么排查问题?

字节跳动

后端开发工程师
一面
查看原面经 →
项目追问
两个任务会不会发生竞争,同时推进同一个状态?

阿里巴巴

Agent 应用开发工程师
一面
查看原面经 →
这块问的是State管理和Checkpoint机制怎么实现的。还追问了多个Agent并行跑的时候状态竞争怎么避免,以及State全局管理是怎么做的。

收录题集

3 个来源,共3 份题集

Agent 机制与项目追问

Guide · JavaGuide · 2 条原题

查看题集 →

Agent 面试题

小林 Coding · 个人整理 · 1 条原题

查看题集 →

多智能体协作:角色分工、通信机制与冲突仲裁

Onefly · zero2Agent · 1 条原题

查看题集 →

相关题目

4 题