
1. 从提示词到上下文多智能体系统真正的分水岭做多智能体系统Multi-Agent System的人几乎都经历过同一个阶段一开始把全部精力砸在提示词上反复打磨角色设定、语气、输出格式甚至给每个 Agent 写几百字的“人设”。结果跑起来发现单个 Agent 表现还行一旦多个 Agent 协同整个系统就开始“精神分裂”——A 说的话 B 接不住B 的结论 C 又推翻最后输出一堆自相矛盾的内容。问题出在哪不在提示词而在上下文工程Context Engineering。提示词工程解决的是“怎么让一个模型说好一句话”上下文工程解决的是“怎么让一群模型在同一个信息场里协同推理”。这两件事的难度差了一个数量级。提示词是静态的、单点的上下文是动态的、流动的、跨 Agent 共享的。你给三个 Agent 分别写了完美的提示词但它们各自看到的上下文不一样推理链条就会分叉最后拼出来的东西自然对不上。这一篇是“多智能体系统上下文工程”系列的第五部分前面几篇分别聊了上下文的分层结构、RAG 在 Agent 间的注入方式、推理链的透明化设计以及上下文窗口的预算管理。这一篇要解决的是一个更底层的问题如何构建一个让上下文与推理都“透明可查”的架构引擎。换句话说不只是让系统跑起来而是让系统跑得“看得见”——每一步推理用了哪些上下文、上下文从哪来、为什么这么选全部可追溯、可调试、可复现。这套东西适合谁如果你正在用 LangChain、LangGraph、AutoGen、CrewAI 这类框架搭多智能体系统或者自己在写 Agent 编排逻辑并且已经踩过“Agent 之间信息不同步”的坑那这篇就是写给你的。如果你还在单 Agent 阶段也可以先看看因为多智能体的上下文问题本质上在单 Agent 做复杂任务时就已经埋下了种子。我个人的判断是未来多智能体系统的核心竞争力不在于模型多强而在于上下文架构多透明。模型能力会趋同但谁能把上下文管好、把推理链讲清楚谁的系统就能真正落地到生产环境。下面我把这套架构引擎的设计思路、核心模块、实操细节和踩坑经验完整拆一遍。2. 为什么“透明架构”是多智能体系统的刚需2.1 黑箱推理在生产环境里根本活不下去先讲一个我亲身经历的场景。之前做一个多 Agent 的合同审查系统三个 Agent 分别负责条款提取、风险识别、合规校验。测试阶段表现很好准确率能到 85% 以上。但上线之后业务方问了一个问题“这条风险提示是怎么得出来的”我们打开日志一看只有最终输出中间推理过程全丢了。Agent B 为什么判定这条条款有风险它引用了 Agent A 提取的哪段原文用了哪个知识库的哪条规则全查不到。这就是黑箱推理的致命伤。在实验室里你只看结果就行在生产环境里每一个结论都必须能追溯到它的上下文来源和推理路径。否则出了问题没法定位业务方不敢信审计过不了迭代也没方向。透明架构要解决的就是这件事让上下文的流动和推理的每一步都留下痕迹。不是简单的日志打印而是结构化的、可查询的、带因果关系的追踪。2.2 上下文污染比提示词写错更可怕提示词写错了你改一改重新跑就行影响范围可控。但上下文污染是“慢性病”。什么叫上下文污染就是某个 Agent 往共享上下文里塞了一条错误或过时的信息其他 Agent 基于这条信息继续推理错误被层层放大最后整个系统的输出全歪了。我见过一个典型例子一个多 Agent 的竞品分析系统Agent A 负责抓取网页信息Agent B 负责总结Agent C 负责对比。有一次 Agent A 抓到了一个旧版本的页面把“2023 年市场份额”写进了上下文。Agent B 没校验时间直接总结成“当前市场份额”。Agent C 拿这个数据去对比得出了完全错误的结论。整个链条上没有任何一个环节发现这个问题因为上下文里没有标注信息的来源、时间和可信度。透明架构的一个核心设计就是每一条进入共享上下文的信息都必须带上元数据——谁写的、什么时候写的、从哪来的、置信度多少。这样下游 Agent 在消费上下文时可以自己做判断而不是无脑信任。2.3 调试多智能体系统靠打印日志是不够的单 Agent 调试你打印一下 prompt 和 output 基本就能定位问题。多 Agent 调试你需要知道的是在某个时间点Agent X 看到了哪些上下文这些上下文是怎么组合成它的 prompt 的它的推理链是什么它的输出又怎么影响了 Agent Y 的上下文这是一张动态的、跨 Agent 的因果图。靠print()或者普通日志根本还原不出来。你需要一个专门的架构引擎来记录和可视化这张图。这也是为什么我说多智能体系统的上下文工程本质上是一个架构问题不是提示词问题。3. 透明架构引擎的核心模块拆解3.1 上下文总线所有 Agent 共享的信息高速公路整个架构的地基是一个上下文总线Context Bus。你可以把它理解成一个所有 Agent 都能读写的共享内存但不是简单的字典而是一个带版本控制、带元数据、带访问控制的结构化存储。为什么需要总线因为多智能体系统里Agent 之间的通信如果靠点对点传递很快就会变成一团乱麻。A 传给 BB 传给 CC 又回头问 A消息路径复杂到没法追踪。总线模式把所有信息集中管理每个 Agent 从总线读、往总线写路径清晰追踪也方便。总线的数据结构我一般这么设计class ContextEntry: key: str # 上下文键名如 contract_clause_3 value: Any # 实际内容 source_agent: str # 哪个 Agent 写入的 timestamp: float # 写入时间 confidence: float # 置信度 0-1 ttl: int # 生存时间秒过期自动失效 dependencies: list # 依赖的其他上下文 key version: int # 版本号每次更新递增这里面几个字段很关键。confidence让下游 Agent 知道这条信息有多可信ttl防止过时信息一直留在上下文里dependencies记录了这条信息是基于哪些其他信息推导出来的这是构建因果图的基础version解决并发写入的冲突问题。提示上下文总线不要用普通的 dict 实现并发场景下会出现读写冲突。建议用带锁的存储或者直接上 Redis 这类支持原子操作的外部存储。我在早期项目里用 dict 踩过坑两个 Agent 同时写同一个 key结果丢了一条。3.2 推理追踪器把每一步思考都钉在时间轴上总线解决了“信息在哪”的问题推理追踪器解决“信息怎么被用的”问题。每个 Agent 在推理时都要经过追踪器记录它读了总线上哪些 key、这些 key 的版本号是多少、它用了什么提示词模板、它的中间推理步骤是什么、最终输出了什么。追踪器的核心是一个**推理事件Reasoning Event**结构class ReasoningEvent: event_id: str agent_id: str timestamp: float input_context_keys: list # 读取了哪些上下文 input_context_versions: dict # 对应的版本号 prompt_template_id: str # 用了哪个提示词模板 reasoning_steps: list # 中间推理步骤 output_key: str # 输出写到了哪个 key output_value: Any duration_ms: int # 推理耗时有了这个结构你就能还原出任意一个输出的完整因果链。比如最终报告里的某句话你可以反查它是 Agent C 在 14:32:05 生成的读了clause_3和risk_rule_7两个上下文clause_3是 Agent A 在 14:30:12 写入的risk_rule_7来自知识库检索……一路追到源头。这套追踪机制在生产环境里价值极大。业务方质疑某个结论你直接把因果链拉出来给他看比任何解释都有说服力。3.3 上下文组装器动态决定每个 Agent 看到什么这是整个引擎里最“聪明”的部分。每个 Agent 在推理前不应该看到总线上所有信息而应该只看到跟当前任务相关的、可信的、未过期的上下文。上下文组装器就是干这个的。组装逻辑分三步第一步是过滤。按ttl过滤掉过期信息按confidence过滤掉低可信信息按 Agent 的权限过滤掉无权访问的信息。第二步是排序。相关度高的排前面时间新的排前面置信度高的排前面。排序策略可以配置不同任务用不同权重。第三步是裁剪。上下文窗口是有限的组装器要根据预算决定放多少条进去。超出的部分要么丢弃要么做摘要压缩。def assemble_context(agent_id, task, bus, budget_tokens): candidates bus.query( filterlambda e: e.ttl 0 and e.confidence 0.5, permissionagent_id ) ranked rank_by_relevance(candidates, task) selected [] used_tokens 0 for entry in ranked: entry_tokens count_tokens(entry.value) if used_tokens entry_tokens budget_tokens: break selected.append(entry) used_tokens entry_tokens return selected这个组装器是透明架构的关键。因为每次组装的结果都被记录你可以清楚地知道“Agent X 在那一刻看到了什么”。调试时如果发现 Agent 表现异常第一件事就是看它的组装结果往往问题就出在组装环节——要么该给的信息没给要么给了不该给的干扰信息。3.4 一致性校验层在错误扩散前拦住它前面三个模块保证了透明这个模块保证正确。一致性校验层在上下文写入总线前做检查主要查三类问题矛盾检测新写入的信息和已有信息是否冲突。比如总线上已经有“合同金额 100 万”新写入“合同金额 120 万”校验层就要报警让 Agent 决定是覆盖还是并存。依赖完整性新信息的dependencies里引用的 key 是否都存在且未过期。如果依赖的上下文已经失效这条新信息也不应该被信任。循环依赖A 依赖 BB 依赖 CC 又依赖 A这种循环会导致推理死锁。校验层要能检测并打断。注意一致性校验不要做得太严格否则会频繁打断正常流程。我的经验是矛盾检测用“警告”而非“拒绝”让 Agent 自己决定怎么处理依赖完整性和循环依赖才用“拒绝”因为这两类问题一定会导致错误。3.5 回放引擎让任何一次运行都能复现最后一个模块是回放引擎。它把总线的版本历史、推理事件的时间轴、组装器的决策记录全部存下来支持按时间点回放。你可以选择回到任意一个时刻看当时所有 Agent 的状态、上下文的内容、正在进行的推理。这个功能在排查偶发 bug 时是救命稻草。多智能体系统的 bug 往往跟时序有关同样的输入跑十次错一次。没有回放你根本没法复现。有了回放你可以精确定位到出错的那一次逐步回看每个 Agent 的动作。回放引擎的存储成本不低我的建议是生产环境存最近 7 天的完整回放更早的只存关键节点。关键节点包括每个 Agent 的最终输出、总线的重大变更、校验层的报警事件。这样既控制了成本又保留了排查能力。4. 实操从零搭一个最小可用的透明架构4.1 环境准备与技术选型先说选型。这套架构不依赖特定框架但有几个组件建议这么选组件推荐方案理由上下文总线Redis 自定义封装支持原子操作、TTL 原生支持、性能好推理追踪SQLite开发/ PostgreSQL生产结构化查询方便回放时按时间轴查很快向量检索本地向量库或轻量检索服务RAG 场景下用于上下文的相关度排序Agent 编排LangGraph 或自研状态机需要精确控制 Agent 间的流转可视化自研 Web 面板或直接用查询工具因果图可视化排查时直观如果你只是想快速验证可以全部用 Python 标准库 SQLite 起步跑通了再换生产级组件。我一开始就是用 SQLite 做的原型验证了架构可行性之后才迁移到 PostgreSQL。4.2 上下文总线的落地实现先实现总线。核心是保证并发安全和版本控制import threading import time from dataclasses import dataclass, field dataclass class ContextEntry: key: str value: object source_agent: str timestamp: float field(default_factorytime.time) confidence: float 1.0 ttl: int 3600 dependencies: list field(default_factorylist) version: int 1 class ContextBus: def __init__(self): self._store {} self._lock threading.RLock() self._history [] def write(self, entry: ContextEntry): with self._lock: if entry.key in self._store: old self._store[entry.key] entry.version old.version 1 self._store[entry.key] entry self._history.append(entry) def read(self, key: str): with self._lock: entry self._store.get(key) if entry and entry.ttl 0: if time.time() - entry.timestamp entry.ttl: return None return entry return None def query(self, filter_fnNone, permissionNone): with self._lock: results [] for entry in self._store.values(): if time.time() - entry.timestamp entry.ttl: continue if filter_fn and not filter_fn(entry): continue results.append(entry) return results这段代码的关键点是RLock保证并发写安全version在每次覆盖时递增_history保留所有历史版本供回放使用。实际生产里_store和_history要换成 Redis 和数据库但逻辑是一样的。4.3 推理追踪的埋点方式追踪器要嵌入到每个 Agent 的推理流程里。我一般用一个装饰器或者上下文管理器来做避免侵入业务代码class ReasoningTracer: def __init__(self, storage): self.storage storage def trace(self, agent_id, prompt_template_id): return _TraceContext(self, agent_id, prompt_template_id) class _TraceContext: def __init__(self, tracer, agent_id, template_id): self.tracer tracer self.event ReasoningEvent( event_idgenerate_id(), agent_idagent_id, timestamptime.time(), prompt_template_idtemplate_id, input_context_keys[], input_context_versions{}, reasoning_steps[], output_keyNone, output_valueNone, duration_ms0 ) self.start time.time() def __enter__(self): return self def record_input(self, entry): self.event.input_context_keys.append(entry.key) self.event.input_context_versions[entry.key] entry.version def record_step(self, step_desc): self.event.reasoning_steps.append({ time: time.time(), desc: step_desc }) def record_output(self, key, value): self.event.output_key key self.event.output_value value def __exit__(self, *args): self.event.duration_ms int((time.time() - self.start) * 1000) self.tracer.storage.save(self.event)用的时候这样with tracer.trace(agent_b, risk_analysis_v3) as t: context assemble_context(agent_b, task, bus, budget4000) for entry in context: t.record_input(entry) t.record_step(开始分析条款风险) result llm_call(build_prompt(context, task)) t.record_step(模型返回风险判定) t.record_output(risk_result, result) bus.write(ContextEntry( keyrisk_result, valueresult, source_agentagent_b, confidence0.85, dependencies[e.key for e in context] ))这样每个 Agent 的推理过程就完整记录下来了。dependencies字段把输出和输入关联起来因果图就能自动构建。4.4 上下文组装器的参数调优组装器的核心参数是budget_tokens也就是给这个 Agent 分配多少上下文预算。这个值怎么定我的经验公式是budget 模型上下文窗口 - 提示词模板长度 - 预期输出长度 - 安全余量安全余量一般留 15% 到 20%。比如模型窗口 128K提示词模板 2K预期输出 4K那预算大概是(128 - 2 - 4) * 0.8 ≈ 97K。但实际用的时候不要给满因为上下文太长会导致模型注意力分散反而降低质量。我一般把实际预算控制在理论值的 60% 到 70%。排序权重也要调。默认我用0.5 * 相关度 0.3 * 置信度 0.2 * 新鲜度但不同任务要改。比如做事实核查置信度权重应该更高做实时监控新鲜度权重应该更高。这些权重最好做成配置项方便按任务切换。4.5 一致性校验的规则配置校验规则我用 YAML 配置方便非开发人员调整rules: - name: amount_conflict type: contradiction trigger: key matches amount_.* check: abs(new_value - old_value) / old_value 0.1 action: warn - name: dependency_missing type: integrity check: any(dep not in bus for dep in entry.dependencies) action: reject - name: circular_dependency type: cycle check: detect_cycle(entry.key, bus) action: rejectaction分三档warn只记录不拦截reject拒绝写入escalate升级给人工处理。大部分矛盾检测用warn就够了因为很多“矛盾”其实是合理的多视角信息强行拦截反而丢信息。5. 踩坑实录那些文档里不会写的问题5.1 上下文膨胀总线越跑越慢第一个坑是上下文膨胀。系统跑了一段时间后总线上的 key 越来越多查询越来越慢组装器每次要遍历几千条记录。我一开始没做清理结果跑了三天单次组装耗时从 50ms 涨到了 2 秒。解决办法是三层清理机制第一层是ttl自动过期短期信息设短 TTL第二层是定期归档把超过一定时间的历史信息移到冷存储第三层是重要性淘汰当总线条目超过阈值时按“被引用次数 置信度”排序淘汰末尾的。提示TTL 的设置要跟任务周期匹配。比如一个分析任务平均跑 10 分钟那中间上下文的 TTL 设 30 分钟就够了没必要设几小时。5.2 版本冲突两个 Agent 同时写同一个 key第二个坑是并发写冲突。两个 Agent 几乎同时往summary这个 key 写内容后写的覆盖了先写的先写的那条信息就丢了。虽然加了锁不会崩但逻辑上还是有问题。我的解法是引入命名空间。每个 Agent 写自己的命名空间比如agent_a.summary和agent_b.summary需要合并时由专门的合并 Agent 处理。这样避免了直接冲突合并逻辑也集中在一处好维护。5.3 追踪数据爆炸存不起也查不动第三个坑是追踪数据量。每个 Agent 每次推理都存一条事件一个中等规模的任务跑下来几千条事件一天几万条。SQLite 很快就撑不住了查询也慢。优化方案是分级存储热数据最近 1 小时存内存温数据最近 7 天存 PostgreSQL冷数据更早压缩后存对象存储。查询时按时间范围路由到不同存储。另外reasoning_steps里的详细步骤可以只存摘要完整内容按需加载。5.4 回放不一致环境变了结果复现不出来第四个坑最隐蔽。回放时发现结果跟当时不一样排查半天发现是外部依赖变了。比如当时调用的模型版本更新了或者知识库内容变了回放时用的是新版本自然复现不出来。解法是把外部依赖也纳入版本管理。模型调用记录模型版本号知识库检索记录索引版本号回放时用相同版本。如果某个依赖无法固定版本就在追踪数据里标注“不可复现”至少让排查的人知道原因。5.5 常见问题速查表现象可能原因排查方向解决Agent 输出自相矛盾上下文污染查组装结果和依赖链加一致性校验系统越跑越慢上下文膨胀看总线条目数和查询耗时加 TTL 和归档偶发错误无法复现时序问题用回放引擎定位固定外部依赖版本某 Agent 表现异常组装结果不对看它当时看到了什么调排序权重或预算信息丢失并发写冲突查版本历史用命名空间隔离6. 透明架构带来的实际收益6.1 调试效率的提升是数量级的上了透明架构之后最直观的变化是调试时间。以前排查一个多 Agent 的 bug平均要两三个小时因为要反复加日志、重跑、猜。现在有了因果图和回放大部分问题 15 分钟内能定位。因为你可以直接看到“Agent B 当时看到了什么、基于什么推理、输出了什么”问题往往一眼就能看出来。我印象最深的一次一个风险识别 Agent 总是漏掉某类条款。查了因果图发现是上游的条款提取 Agent 把这类条款归到了“其他”类别下游 Agent 的组装器按类别过滤时把它排除了。整个链条上没有任何报错但信息在组装环节被静默丢弃了。没有透明架构这种问题能查一整天。6.2 业务方的信任度完全不一样以前给业务方演示他们总问“这个结论靠谱吗”。现在我可以直接打开追踪面板展示完整的推理链这条结论基于哪几条原文、用了哪条规则、置信度多少、有没有矛盾信息。业务方看到这个信任度完全不一样。他们不一定懂技术但“能追溯”这件事本身就让人放心。6.3 迭代方向变得清晰有了上下文和推理的完整数据迭代不再是拍脑袋。你可以统计哪些上下文被引用最多、哪些 Agent 的推理耗时最长、哪些环节最容易出矛盾。数据会告诉你优化重点在哪。我做过一次统计发现 70% 的矛盾报警都来自两个特定 Agent 的交互于是重点优化了它们之间的上下文协议整体质量提升明显。6.4 团队协作的摩擦大幅降低多智能体系统往往是多人协作开发的每个人负责几个 Agent。没有透明架构时A 改了 Agent 的提示词B 的 Agent 表现变差了两人互相甩锅。有了追踪数据谁改了什么、影响了哪些下游一目了然。责任清晰了协作自然顺畅。7. 架构的扩展方向7.1 从透明到自适应现在这套架构是“记录 校验”下一步可以往“自适应”走。比如组装器根据历史数据学习最优的排序权重校验层根据误报率自动调整阈值追踪数据反过来训练一个“异常检测”模型提前预警可能的上下文污染。这些都不难做因为数据基础已经打好了。7.2 跨系统的上下文联邦如果多个多智能体系统需要协作可以把上下文总线做成联邦式的——每个系统有自己的总线通过协议互相查询。这样既保持了各系统的独立性又能共享关键上下文。这个方向在复杂业务场景里很有价值比如一个系统负责合同审查另一个负责财务核算两者需要共享合同金额这类关键信息。7.3 上下文的可解释性输出现在追踪数据主要是给开发者和运维看的。未来可以做成面向最终用户的可解释性输出——用户看到结论时可以点开看“这个结论是怎么来的”。这在金融、医疗、法律这些高合规要求的领域几乎是刚需。7.4 与 RAG 的深度整合上下文工程和 RAG 是天然互补的。RAG 解决“从外部知识库检索相关信息”上下文总线解决“在 Agent 间管理和流转信息”。把两者整合起来检索到的知识直接进总线带上来源和置信度元数据下游 Agent 消费时就能做更精细的判断。我最近在做的项目就是把 RAG 的检索结果作为总线的一等公民效果比之前把检索结果直接塞进 prompt 好很多。7.5 性能优化的空间当前架构的性能瓶颈主要在追踪数据的写入和查询。优化方向有几个批量写入代替逐条写入、异步落盘、追踪数据分级采样不是每条都存完整数据按重要性采样。这些优化能把开销降到可接受范围让透明架构在大规模系统里也能跑得动。我个人在实际操作中的体会是透明架构的投入产出比非常高。前期多花一两天搭基础设施后期每次调试、每次迭代、每次跟业务方沟通都在省时间。尤其是系统规模上去之后没有透明架构的多智能体系统基本就是不可维护的。所以如果你正在做多智能体强烈建议把上下文和推理的透明化当成第一优先级而不是等出了问题再补。