卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
秋招投递表
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
秋招投递表
代码随想录 (opens new window)
  • 本栏必读

    • 卡码大模型专栏介绍
  • 大模型面经

  • 大模型动态

  • Claude学习专栏

  • 入门认知

  • Prompt与调用基础

  • RAG检索增强

  • Agent智能体

    • AI Agent学习路线(专攻Agent先看)
    • Agent到底是什么?和普通问答有什么区别
    • ReAct、Reflection、规划执行怎么选
    • Agent vs Workflow:什么时候不需要Agent
    • 工具设计决定Agent上限
    • MCP协议:Agent工具调用的新标准
    • Agent为什么容易翻车
    • Agent的记忆:短期、长期、RAG的关系
    • Agent怎么评估:任务完成率与可靠性度量
    • Plan-and-Execute怎么落地成DAG执行器
    • Planner、Worker、Reviewer怎么分工
    • 多Agent上下文、消息和Token怎么治理
      • 面试官会怎么问
      • 简要回答
      • 为什么多个Agent不能共享一条消息历史
      • 子Agent到底应该收到什么
      • 为什么消息里只传引用,不传完整产物
      • 并行消息怎么保证不乱序
      • Token预算为什么要在派发前预留
      • 预算快用完时怎么降级
      • 子Agent还能创建子Agent怎么办
      • 模型路由怎么和预算配合
      • 出错以后怎么恢复,而不是整棵树重跑
      • 怎么验证治理真的有效
      • 面试时怎么讲
      • 知识拓展
      • 写在最后
  • 微调认知

  • 部署与工程化

  • 多模态入门

  • Transformer原理

  • 手撕Transformer

  • 模型家族与Llama架构

# 多Agent上下文、消息和Token怎么治理

KamaClaude

上一篇《Planner、Worker、Reviewer怎么分工》讲了角色边界:Planner定义任务,Worker交付Artifact和证据,Reviewer负责验收,编排器执行硬约束。

但角色拆开以后,系统才刚开始变复杂。

三个Agent如果复制同一份聊天记录、把并行结果按返回时间拼接、允许子Agent继续无限派生,角色虽然分开了,上下文、状态和预算却还是一锅粥。

这篇就解决一个问题:多Agent跑起来以后,怎么让每个Agent只看到该看的信息,让消息可追踪、可去重,让Token在失控前被系统截住。

# 面试官会怎么问

“你们多个Agent之间怎么传上下文?并行消息怎么保证不乱序?子Agent还能创建子Agent时,怎么防止Token爆掉?”

很多录友会回答:

“主Agent把历史发给子Agent,子Agent完成后把结果传回来;上下文太长就做摘要,Token超了就停止。”

这个回答的问题很具体。

第一,完整复制历史会把角色污染掉。 Worker会看到与当前任务无关的讨论、其他Worker的猜测和过期工具结果,不仅浪费Token,还可能把未经验证的内容当成事实。

第二,按返回时间拼消息会破坏因果。 并行任务谁先完成只代表谁更快,不代表它应该先被消费。重试还可能把同一结果送两遍。

第三,超限后才停止已经太晚。 多个子Agent并发执行时,如果没有预留和原子扣减,每个Agent都以为预算还有剩余,总消耗很容易一起穿透上限。

面试官真正想听的是:上下文怎样隔离和按需组装,事件怎样标识因果与幂等,预算怎样分配、回收、降级和熔断。

# 简要回答

  • 每个Agent使用独立Thread。 子Agent不继承完整聊天,只接收结构化任务包、必要约束、依赖Artifact引用和本任务工具。
  • 大结果放Artifact Store。 消息只传状态、摘要、证据引用和版本,不在线程之间反复复制日志、网页和代码全文。
  • 消息顺序按因果关系处理。 单个Agent用seq_no保序,跨Agent用task_id、DAG依赖和parent_event_id判断谁依赖谁,不按墙上时钟强行排成一条总序列。
  • 预算由编排器统一记账。 派发前预留子任务额度,运行中同时限制输入、输出、工具结果、重试、步数和时间,不能让Agent靠Prompt自觉省Token。
  • 递归派生默认关闭。 必须开启时,限制最大深度、子节点数量和祖先环,并让子Agent的额度从父Agent剩余预算中分配。
  • 不同任务走不同模型。 摘要、分类、格式转换可以路由到小模型,复杂规划、最终合成和高风险审查再使用强模型,但路由必须经过评测。

多Agent治理不是把一个大上下文切成几份,而是把对话变成独立工作区,把协作变成带因果的事件,把Token变成可预留、可回收的资源。

多Agent上下文治理链路

这张图回答的是:一个子任务从编排器派发到最终汇总,如何通过独立Thread隔离过程、通过Artifact与事件引用交接结果,并让所有并行分支共同受全局预算和递归边界约束。

# 为什么多个Agent不能共享一条消息历史

假设主Agent要完成一份线上故障报告,同时派出三个Worker:

  • Worker A查监控;
  • Worker B查日志;
  • Worker C查发布记录。

如果三个Worker共享一个messages数组,A返回的几千行指标、B返回的错误堆栈、C看到的版本信息会不断混在一起。

问题不只是“窗口容易满”。

A的一句“可能是连接池问题”会进入B的上下文,B后面更容易围绕这个假设找证据;C的一次工具超时也可能被其他角色误解为“没有发布记录”。

共享历史会让并行探索变成相互暗示,多个Agent看似独立,错误却高度相关。

多Agent共享历史混乱

更稳的做法是每个Agent维护独立Thread:

root thread
├── worker-a thread:任务包A + A的工具调用 + A的局部状态
├── worker-b thread:任务包B + B的工具调用 + B的局部状态
└── worker-c thread:任务包C + C的工具调用 + C的局部状态
1
2
3
4

独立Thread不是完全断开联系。

编排器知道它们属于同一个run_id,也知道每个子任务的父节点和依赖;只是它不会把一个Agent的完整过程自动广播给所有人。

如果B确实需要A的监控结论,编排器传的是经过验收的Artifact引用,而不是A从第一轮到最后一轮的全部对话。

这和《Context Engineering入门》里的原则一致:给当前推理最少但足够的高信号信息。 多Agent只是把这个原则从“一个窗口怎么编排”扩展到了“多个窗口怎么隔离”。

# 子Agent到底应该收到什么

子Agent收到的不是父Agent聊天记录,而是一份可校验的任务包。

{
  "run_id": "incident-20260908",
  "task_id": "inspect-payment-logs",
  "parent_task_id": "find-root-cause",
  "goal": "检查22:00至23:00支付服务错误日志",
  "acceptance_criteria": ["给出错误峰值时间", "结论附日志证据引用"],
  "context_refs": ["artifact://release-record/v2"],
  "allowed_tools": ["search_logs", "read_trace"],
  "output_schema": "worker_result_v1",
  "budget": {"max_input_tokens": 12000, "max_output_tokens": 2000, "max_steps": 8},
  "deadline_ms": 45000
}
1
2
3
4
5
6
7
8
9
10
11
12

组装子Agent上下文时,可以固定成六层:

  1. 不可覆盖的全局安全规则;
  2. 当前角色的职责与禁止项;
  3. 当前任务包;
  4. 已通过依赖的Artifact摘要与引用;
  5. 当前任务允许使用的工具Schema;
  6. 剩余步数、时间和Token预算。

父Agent的语气、闲聊、完整思考过程,以及其他分支尚未验收的猜测,都不应该默认继承。

如果任务缺信息,子Agent要返回BLOCKED和缺失字段,由编排器补充或退回Planner。不要为了让子Agent“更懂背景”,先把所有历史都塞过去。

# 为什么消息里只传引用,不传完整产物

一次日志查询可能返回5万行,一次代码检查可能产生上百KB的Diff。

这些内容如果从Worker复制给Reviewer,再从Reviewer复制给主Agent,同一份材料会重复进入多个上下文。Agent越多,Token复制越严重。

所以要把“消息”和“产物”拆开:

  • 消息负责协调:任务状态、简短摘要、失败原因、证据引用;
  • Artifact负责承载内容:报告、补丁、日志快照、测试结果、结构化数据;
  • 事件日志负责审计:谁在什么时候基于哪个版本做了什么判断。

Worker的完成消息可以很小:

{
  "event_type": "TASK_COMPLETED",
  "task_id": "inspect-payment-logs",
  "status": "completed",
  "summary": "22:14起第三方回调超时集中升高",
  "artifact_refs": ["artifact://payment-log-analysis/v3"],
  "evidence_refs": ["trace://log-query/8841"],
  "unresolved": ["22:14至22:16网关日志缺失"]
}
1
2
3
4
5
6
7
8
9

Reviewer需要细节时,再按引用局部读取对应段落或证据。

这里有一条底线:摘要可以帮助定位,不能替代原始证据。 Artifact必须带版本、内容哈希或不可变快照,不能让Reviewer验收v3时,底层内容已经悄悄变成v4。

# 并行消息怎么保证不乱序

多Agent系统通常不需要一个“全局绝对顺序”。

Worker A在10:00:03完成,Worker B在10:00:02完成,并不能说明B的结果应该先进入汇总。真正重要的是:B是否依赖A,某条消息是否是另一条消息触发的,以及同一任务内部事件的先后关系。

一个最小事件信封可以包含:

{
  "event_id": "evt-9382",
  "run_id": "incident-20260908",
  "task_id": "inspect-payment-logs",
  "agent_id": "worker-log-02",
  "seq_no": 7,
  "parent_event_id": "evt-9310",
  "idempotency_key": "inspect-payment-logs:completed:v3",
  "event_type": "TASK_COMPLETED",
  "artifact_refs": ["artifact://payment-log-analysis/v3"]
}
1
2
3
4
5
6
7
8
9
10
11

这几个字段各管一件事:

字段 解决的问题
run_id 把同一次用户任务的事件串起来
task_id、agent_id 定位事件属于哪个子任务和执行者
seq_no 保证单个Agent线程内部顺序
parent_event_id 记录“谁触发了谁”的因果关系
idempotency_key 重试或重复投递时避免重复写入和重复汇总
artifact_refs 指向确定版本的产物,不复制正文

编排器收到事件后,不是立刻把它拼进主Prompt,而是先做三步:

  1. 用event_id或idempotency_key去重;
  2. 检查seq_no是否连续,缺号就暂存并等待或补拉;
  3. 检查DAG依赖与parent_event_id,依赖满足后才推进状态。

同一个Agent的seq_no=8先于seq_no=7到达,可以暂存在Inbox里;两个互不依赖的Worker同时完成,则都标记成功,等汇总节点的前置条件全部满足后再触发。

不要用时间戳代替因果关系。 分布式环境会有时钟偏差、网络延迟和重试,谁先到不等于谁先发生,更不等于谁先被业务消费。

# Token预算为什么要在派发前预留

很多系统有max_tokens,却依然会超预算,因为它只限制了一次模型输出。

多Agent真正消耗的是一整棵任务树:

多Agent预算闸门

总消耗 = 根Agent输入输出
       + 所有子Agent输入输出
       + 工具结果进入上下文的Token
       + 重试与返工
       + 最终汇总和验收
1
2
3
4
5

如果总预算是100K,根Agent同时派出4个“最多30K”的Worker,理论上限已经到120K,还没有给Reviewer和最终回答留额度。

因此,预算要像并发系统里的资源配额一样管理。

派发子任务时,编排器先从父任务的可用额度里原子预留一块预算。预留成功才启动,预留失败就缩小任务、排队、换模型或拒绝派生。任务结束后,未使用的额度再回收到父任务。

可派发预算 = 全局上限 - 已消耗 - 已预留 - 根流程保底 - 验收保底
1

这不是精确预测模型一定花多少Token,而是防止多个并行分支同时把同一份余额算给自己。

预算也不能只管输出Token。至少要同时限制:

  • 单次和累计输入Token;
  • 单次和累计输出Token;
  • 工具结果返回大小与分页次数;
  • 模型调用次数、工具调用次数和重试次数;
  • 子Agent数量、递归深度和任务总时长。

关于输入、输出、成本和延迟之间的基础关系,可以先看《Token、成本与延迟》。

# 预算快用完时怎么降级

预算治理不是“用完就报错”,而是提前分级收束。

下面是一组示例阈值,不是行业标准,实际值要根据任务风险和评测结果调整:

预算水位 系统动作
0%—60% 正常执行,仍受单节点上限约束
60%—80% 禁止低价值扩展,压缩旧工具结果,优先复用Artifact
80%—95% 停止新建非关键子Agent,小任务切换到低成本模型
95%以上 强制收束,保留验收与最终回答额度,返回部分结果或升级人工

压缩也有边界。

聊天过程和重复日志可以压缩,订单号、文件路径、错误码、验收标准与原始证据引用不能被“概括掉”。高风险任务宁愿少做一个分支,也不要把验证预算拿去继续探索。

预算应该优先保护最终合成和验收。 Worker全都跑完,Reviewer却没有Token可用,这个任务仍然不能算完成。

# 子Agent还能创建子Agent怎么办

默认答案是:不允许。

Worker发现任务需要继续拆分,可以返回Planner重构DAG。只有层级任务确实需要局部自主拆分时,才开放受限派生能力。

一旦开放,至少加四道硬限制:

  • max_depth:最大递归深度;
  • max_children:每个节点最多创建几个子节点;
  • ancestor_task_ids:记录祖先链,禁止A派生B、B又派生A;
  • child_budget <= parent_available_budget:子节点只能花父节点分出的额度。

还要限制“同义派生”。

有些Agent不会创建完全相同的任务ID,却会连续创建“继续搜索”“补充搜索”“深入搜索”。编排器可以用规范化目标、输入范围和工具集合生成任务指纹,相似任务超过阈值就拒绝,避免换个名字继续烧钱。

这部分和《Agent为什么容易翻车》里的循环控制是一回事:自由派生必须有深度、宽度、相似任务和预算四重停止条件。

# 模型路由怎么和预算配合

不是每个角色都必须使用最强模型,也不能简单规定“Planner用大模型,Worker用小模型”。

路由至少看三个维度:

  • 任务复杂度:抽取、分类、格式转换通常更适合小模型;开放规划和冲突合成需要更强推理;
  • 风险等级:涉及生产写操作、权限和合规时,模型能力之外还要增加规则校验或人工门禁;
  • 可验证性:输出能被Schema、测试或数据库规则直接验证时,可以更积极地使用低成本模型。

一个实用做法是先让离线评测回答:“这个任务类型由小模型执行,质量下降多少,节省多少Token和延迟?”

如果小模型输出变短了,却导致返工次数翻倍,总成本可能更高。模型路由看的是单个合格任务成本,不是单次调用价格。

# 出错以后怎么恢复,而不是整棵树重跑

上下文、消息和预算治理最终都要落到恢复能力上。

如果Worker超时,编排器应该保留它已写入的Artifact和最后确认的事件序号,再决定从Checkpoint重试、换模型、缩小任务,还是降级交付。

如果消息重复,只做幂等确认,不重复触发Reviewer。

如果Artifact版本不一致,只让受影响的汇总节点重新执行,不推翻已经通过的无关分支。

如果全局预算触发熔断,则冻结新派生,取消非关键运行节点,把剩余额度留给状态总结和部分结果交付。

这依赖《Plan-and-Execute怎么落地成DAG执行器》里的状态机与Checkpoint。没有持久化状态,所谓“重试”往往只是把整段昂贵流程再跑一遍。

# 怎么验证治理真的有效

只看最终回答对不对不够。至少监控六组指标:

  • 上下文:各角色输入Token、重复Token比例、Artifact局部读取命中率;
  • 消息:乱序暂存数、重复事件率、幂等冲突率、依赖等待时间;
  • 预算:预留量、实际消耗、回收量、各角色占比、熔断次数;
  • 递归:任务树最大深度、分支数、相似任务拒绝次数;
  • 质量:任务完成率、首次验收通过率、关键约束保留率;
  • 业务效率:P95延迟、单个合格任务成本、人工接管率。

还要拿单Agent做基线。

如果多Agent让总Token翻了三倍,任务完成率只提高一点,说明拆分粒度或上下文交接有问题;如果Token下降但关键约束丢失,说明摘要压缩过度;如果成本可控但乱序等待很高,可能是DAG依赖设计得太重。

治理不是让指标都越低越好,而是让质量、成本和延迟的交换关系可解释、可预测。

# 面试时怎么讲

可以这样回答:

我们不会让多个Agent共享同一条消息历史,而是给每个Agent独立Thread。编排器只下发当前任务包、已通过依赖的Artifact引用、允许工具和预算,不复制父Agent的完整聊天。大结果写入带版本的Artifact Store,消息只回传状态、摘要和证据引用。

每条事件带run_id、task_id、agent_id、seq_no、parent_event_id和幂等键。单线程按seq_no保序,跨Agent按DAG依赖和父事件判断因果,重复投递不会重复推进状态。

Token由编排器统一记账。派发前从父任务余额中原子预留,未使用额度可以回收;预算接近上限时先停止非关键派生、压缩旧结果、切换低成本模型,最后保留验收和收束额度。递归默认关闭,开放时限制深度、分支、祖先环和子任务预算。

这套回答比“把上下文传过去,超了就截断”多出的,正是生产系统需要的隔离、因果、幂等和资源治理。

# 知识拓展

# 多个Agent一定要用消息队列吗

不一定。任务量小、进程内执行时,数据库状态表加内存调度器也能完成。消息队列解决的是异步投递、削峰和消费者解耦,但无论用什么基础设施,事件ID、幂等键、因果字段和状态机都不能省。

# seq_no能不能保证跨Agent顺序

不能。seq_no只对某个Agent或某个任务流有意义。跨Agent应该看DAG依赖和parent_event_id;互不依赖的事件不需要强行决定谁是第一。

# Prompt Cache能不能解决多Agent Token成本

它可以减少稳定前缀的重复计算或费用,但不能替代上下文治理。被缓存的无关内容仍可能占窗口并稀释信号,大型工具结果和跨角色历史也不会因为缓存就自动变得有用。

# Artifact和长期记忆有什么区别

Artifact是当前任务产生、可版本化和可验收的工作产物;长期记忆是跨任务保存的用户偏好、稳定事实或经验。Artifact不能自动写成长期记忆,是否保留仍要经过《Agent的记忆》里讲的写入门槛、过期和冲突治理。

# 为什么不能让Agent自己决定还剩多少预算

模型只能看到系统告诉它的数据,也无法和其他并行分支完成原子记账。它可以建议压缩或停止,但真实余额、预留、扣减和熔断必须由编排器执行。

# 写在最后

多Agent最危险的不是某个Worker答错,而是错误历史被复制、重复消息被执行、并行分支同时把预算花穿。

Thread隔离过程,Artifact承载事实,事件表达因果,预算决定边界。少一个,协作都可能重新退化成失控的群聊。

Last Updated: 9/8/2026, 3:08:27 PM

← Planner、Worker、Reviewer怎么分工 SFT、RLHF、DPO:微调方法全景认知 →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪