多 Agent 如何隔离上下文和状态?

考查重点:角色上下文与状态作用域。上下文、状态、工具范围分别隔离,任务/Agent标识绑定记录,子Agent只交必要结果,资源访问按权限核

本题目录

参考答案

核心回答

多 Agent 的隔离要落在三处:每个 Agent 看什么、运行状态写到哪里、工具能访问什么。

我会让每个子任务拥有独立的消息历史和局部状态,只接收完成任务需要的目标、约束和证据;用会话、任务、Agent 或分支标识定位检查点、记忆和产物,避免复用可变的全局上下文。协作时通过明确的输入和结果契约交换信息,共享字段由指定角色更新。文件和外部资源的访问范围则由工具执行层校验。

例如两个用户同时生成报告,即使都使用同一套 Agent 定义,也必须分别读取自己的历史、附件和工作目录,结果回到对应请求。独立上下文能减少信息干扰,实际资源安全还需要权限和执行环境保证。

展开说明

1. 模型上下文按任务组装,子任务过程留在本地

对子 Agent,传入清楚的子目标、必要约束、已有结论、证据引用及输出要求。它自己的工具交互和工作过程保存在局部会话中;完成后返回结论、来源、缺失项和产物引用,主 Agent 不必接收全部检索日志。

这样既减少无关信息,又避免一个角色的临时判断被另一个角色当成确定事实。但隔离不等于只传一句话:日期范围、单位、用户更正等关键条件必须随任务传递,需要核查时还应能按引用取得原始证据。

框架的默认继承规则也要看清楚。有的委派创建新消息历史,有的支持继承父会话;即使消息隔离,业务状态或文件 Backend 仍可能共享。应明确允许传递和回写的字段,而不是根据“子 Agent”这个名称推断所有内容都已独立。

2. 运行状态按作用域保存,避免隐式全局变量

把认证主体、会话、任务、分支和工作目录等组成明确的执行上下文,按函数参数传给 Agent 与工具,或者使用框架提供的请求级上下文。不同会话使用不同历史和检查点;同一会话内并行的子任务还要有独立运行标识,不能只靠角色名区分。

存储可以共享同一数据库,但记录键和查询条件要包含相应作用域。用户长期记忆按用户和租户范围读取,当前任务草稿按任务和角色范围保存;共享连接池或无状态模型客户端,不代表要共享对话列表。

异步 Python 服务可以用 ContextVar 传递当前任务信息,设置后在 finally 中用 token 恢复,避免后续调用沿用旧值。不过它只管理程序中的上下文绑定,不能自动深拷贝里面的可变字典,也不会自动把信息传到远程服务。共享可变对象仍需拆开或按明确规则访问。

3. 共享结果通过边界交付,权限在工具端执行

共享状态只放协作需要的信息,例如各子任务状态、已确认的结果和引用。各 Agent 更新自己的结果槽,协调者负责最终汇总;不能让多个分支随意覆盖同一份最终答案。具体并发合并方式可见多 Agent 共享上下文同步管理。

对于文件,分别设置任务工作目录,并在读写工具中校验解析后的路径和访问权限;需要执行不可信代码时,再使用具备相应权限限制的执行环境。仅给目录起不同名字、在提示词写“只访问当前目录”,都不能约束一个本来能访问整个文件系统的进程。数据库、检索和缓存也要遵循当前调用者的范围,身份不能由模型自由填写。

4. 隔离还要覆盖超时、重试和结果归属

一个子任务失败,错误和部分产物应先归属到它自己的运行记录,再由协调者决定是否重试或继续。超时后即使旧结果迟到,也要检查任务与尝试版本,避免写进已结束或已重开的任务。

可以用两个用户、两个并行子任务、相同文件名的场景验证:交错执行后,模型输入、工具路径、记忆读取、回调和最终输出是否都保持正确归属;再加入超时及重试检查旧结果是否被接收。这比只检查是否生成了两个 session_id 更能发现串数据的问题。

5. 教程中哪些做法对应这些边界?

研搜教程用 thread_id 区分会话检查点,为会话建立 output/session_... 目录,并通过 ContextVar 向深层工具和消息推送传递当前会话信息;执行结束后恢复上下文。这些做法分别处理历史定位、产物组织和异步调用归属。

其中 InMemorySaver 保存的是当前进程内的检查点;会话目录属于应用层组织方式。若要提供跨用户安全访问,应继续在资源入口实施身份、权限和路径校验,而不是把目录结构直接当成操作系统沙箱。

常见追问

每个 Agent 都新建一个模型对象,就能隔离吗?

不能。串数据往往来自共用消息列表、同一个检查点键、全局工作目录或缺少范围条件的记忆查询。应检查状态和资源的归属。无状态客户端能否复用则取决于其并发支持,不必为了隔离一律重复创建。

主子 Agent 能共用 thread_id 吗?

要看框架如何区分子图和检查点命名空间。重点是独立运行不会误读或覆盖彼此状态,并且需要恢复时能定位到正确执行。自定义子 Agent 若直接复用同一存储键而没有额外命名空间,就可能冲突;也不能为同一段连续对话每轮随意换 ID,导致历史丢失。

独立上下文后,怎么避免关键条件传丢?

给委派输入定义必要字段,保留目标、约束、已完成与待完成事项,以及可取回的证据引用。接收方先检查字段和任务版本;缺少关键信息时补取或澄清。摘要是一种交付形式,不能替代字段完整性检查。

使用 A2A 就不会串上下文了吗?

A2A 可以统一远程任务和消息交换,但内部状态、身份授权、存储范围及回调归属仍由应用实现。协议中的任务标识帮助关联,不会自动变成业务数据访问权限。

对应教程

  • 主智能体搭建与异步执行:阅读会话目录、thread_id、ContextVar 的设置与恢复,理解消息历史、产物和异步调用为什么需要分别管理。

参考资料

  • 国内:JavaGuide:多 Agent 系统:采用显式任务上下文、私有会话与共享状态的分工,说明为何仅靠角色名称或线程安全容器不够。
  • 国内:zero2Agent:多 Agent 协作:参考分层共享与交接摘要,解释如何在隔离过程信息的同时传递关键条件和证据。
  • 国内:WeThinkIn:记忆与上下文工程:参考独立运行标识、记忆主体和读取范围,把隔离落实到历史与持久数据的键和查询条件。
  • 国外:LangChain:Subagents:依据独立委派与继承父上下文的区别,说明正文中消息隔离和共享状态的边界需按框架版本确认。
  • 国外:Python:contextvars:依据异步上下文变量、token 恢复与浅复制机制,说明正文中程序作用域能解决的问题及可变对象仍需处理的边界。

深度研搜Python

基于 deepsearch-agents

核心回答

深度研搜把子任务的模型消息、会话检查点、运行上下文和文件目录分别管理。DeepAgents 通过 task 工具委派网络、数据库或知识库子任务,子智能体独立完成工具交互,再把结果交回主智能体。应用以 session_id 作为 thread_id 定位会话状态,同时为该会话建立附件与报告目录,用 ContextVar 把当前目录和会话标识传给深层工具及事件推送。

这样,共用一套 Agent 定义也能让不同会话使用各自的历史、附件和产物。同一会话的上下文可以继续使用;其中 InMemorySaver 保存的是进程内检查点,磁盘文件保存的是附件和报告,两者不能互相替代。

主子智能体怎样交换上下文

主智能体根据专家的 description 选择委派对象,把子目标和必要背景传给 task。例如数据库助手需要统计对象、时间范围与口径,知识库助手需要待核实的问题;网络检索的完整过程不必因此广播给数据库助手。

在本项目使用的 DeepAgents 0.5.7 中,委派会用任务描述建立子智能体的新消息输入,完成后将其最终消息作为 ToolMessage 交回主智能体。因此主智能体可以汇总结果,而不必接收每轮工具对话。不过,独立消息不等于所有状态都独立:框架仍会传递或合并部分非消息字段,共享内容要按具体字段管理。该版本的委派实现可以看到输入过滤和结果回写。

会话标识怎样串起历史、附件和报告

run_deep_agent() 为一次会话完成四项关联:

  1. 定位历史。 把 session_id 放入 configurable.thread_id,交给配置了 InMemorySaver 的主智能体。同一标识用于延续该会话,不是操作系统线程编号。
  2. 整理文件。 创建 app/output/session_{session_id},把 app/updated/session_{session_id} 中的上传文件复制进去,并把文件名和工作目录加入本轮输入。模型仍需调用 read_file_content 才能读取附件内容。
  3. 传递运行上下文。 将目录与会话标识写入两个 ContextVar。文件工具读取目录,monitor 读取会话标识,将执行事件发送到对应前端连接;模型不需要在每个工具参数里重新填写这两个值。
  4. 恢复绑定。 流式执行结束、取消或异常后,在 finally 中用设置时取得的 token 恢复上下文,结束本轮绑定的作用域。

主执行入口负责这些关联,上下文模块负责设置、读取与恢复绑定。

例如两个会话都上传 材料.pdf 并生成 报告.md,各自的目录提供文件归属,thread_id 提供历史归属,当前运行上下文让文件工具找到对应目录。只修改报告文件名,解决不了读取错会话历史或把进度发给另一连接的问题。

这些机制各自解决到哪一层

ContextVar 避免用一个可变全局变量保存“当前会话”,但它不保存长期记忆,也不会自动深拷贝其中的可变对象。会话目录便于组织附件和交付物,也便于继续读取文件;服务重启后能否恢复 Agent 状态,还取决于检查点是否持久化。

文件访问权限是另一层。本项目的 resolve_path() 会处理相对路径和重复目录,但仍允许目录外的真实绝对路径,因此当前工作目录不能当作文件沙箱。若用于多用户服务,需要在资源入口核验身份和归属,并在路径解析后检查允许范围;这些约束由程序执行。路径解析源码展示了现有行为。

对应教程

参考资料

  • 国内:JavaGuide:多 Agent 协作系统设计:采用独立任务、显式交接和共享结果的分工,解释主智能体为何不需要广播全部工具历史。
  • 国内:zero2Agent:多智能体协作:借鉴公共约束、子任务过程与交付结果的分层,说明委派时应保留必要条件。
  • 国内:WeThinkIn:记忆与上下文工程:参考记忆主体、读取作用域和派生副本,区分文件存在、状态已保存与模型实际取得的内容。
  • 国内:zero2Agent:记忆与上下文:参考异步任务污染及会话文件命名空间,解释运行上下文、检查点和磁盘产物各自的职责。
  • 国外:LangChain:Deep Agents Subagents:采用委派任务、独立工具过程和精简结果交付的说明;本例具体的状态传递行为以 0.5.7 实现为准。
  • 国外:Python 3.12:contextvars:依据异步上下文变量、token 恢复与浅复制机制,解释当前会话绑定如何传递,以及它与持久化和资源权限的区别。

相关面经

7 篇

美团

AI 全栈开发工程师
校招秋招二面
查看原面经 →
追问
多Agent并行执行,怎么防止上下文和状态互相污染

字节跳动

AI Agent 开发工程师
校招秋招一面
查看原面经 →
多个 Agent 之间上下文和状态怎么做到互不串?

小红书

Agent 开发工程师
实习秋招二面
查看原面经 →
延伸问题
多 Agent 怎么做的上下文和状态的隔离?

滴滴

AI Agent 后端开发
查看原面经 →
多 Agent 或多异步任务场景下,怎么防止上下文污染?

字节跳动

Agent
春招
查看原面经 →
多 Agent / 多异步任务下,如何防止上下文污染?
展开剩余 2 篇面经

携程

Agent 开发
社招
查看原面经 →
子agent怎么避免上下文污染

字节跳动

后端开发(Agent 方向)
实习春招一面
查看原面经 →
多 Agent / 多异步任务下,如何防止上下文污染?

收录题集

3 个来源,共3 份题集

编码Agent与AgentOS工程

Rocky Ding · AIGC-Interview-Book · 1 条原题

查看题集 →

Agent开发面试题

摸鱼酱mio · 个人整理 · 1 条原题

查看题集 →

记忆与上下文:长对话不丢信息的实战方案

Onefly · zero2Agent · 1 条原题

查看题集 →

相关题目

4 题