☰
多Agent协同实战:从上下文污染到任务交接的完整指南
2026/10/5 12:38:00 网站建设 项目流程

1. 为什么说让 Codex 一个人包打天下是一场豪赌

1.1 上下文污染:单 Agent 的天花板

如果你至今还在把需求文档、数据库设计、接口定义、前端页面、测试用例一股脑丢进同一个 Codex 会话,大概率已经体验过那种诡异的感觉:前面明明已经把报表接口的设计敲定了,后面让它改一个按钮样式时,它却把接口字段也顺手改了;明明让它只处理前端组件,它却在帮你"优化"后端逻辑。这不是 Codex 太笨,而是上下文污染在发作。

拿一个 128k token 的上下文窗口来算笔账:一份需求文档可能占 3k-5k,一次仓库扫描要吃掉 8k-15k,再加上前面十几轮对话累积的问答记录,真正留给"当前任务决策"的空间往往不到 40k。也就是说,越干到后面,Codex 手里真正能用的"工作台"越小。它会开始遗忘你早期定的约束,开始返回已经废弃的代码模式,甚至把两个互斥的需求同时缝合进一个实现里,因为它的记忆已经被海量历史会话撑爆了。

这个场景就像让同一个服务员同时给十桌客人点菜:第一桌要辣、第二桌忌口、第三桌催单、第四桌加菜,信息全堆在他脑子里。前十分钟他还能记住谁是谁,半个小时后他端上来的菜大概率会串味。单 Agent 不是不能干长任务,而是每干一步都要把大量上下文重新加载进窗口,代价非常高。

1.2 上下文窗口不等于团队配置

很多人把上下文窗口理解成"模型越强,我给它塞的任务就可以越多",这个想法恰恰是单 Agent 翻车的根源。上下文窗口只是容量,不是组织能力。真正做项目时,我们需要的不是"一个记性好的全才",而是"多个职责明确、交接清晰的专才"。

我举一个实际例子。假设任务是为一个内部工具增加导出 CSV 的功能。这不是单纯的写代码:需要先看数据表的字段定义,然后确定后端路由,再改前端导出按钮,还要考虑导出超大的文件时要不要走异步任务。让单个 Codex 全程处理时,它会在后端和前端两套逻辑之间来回横跳。它在写 SQL 查询的时候,脑子里还挂着前端的 loading 状态;它在调按钮交互的时候,又被后端返回格式的 bug 干扰。每一次角色切换都不是免费的,它需要"忘掉"上一套项目上下文,才能把注意力集中在当前模块上。

更麻烦的是环境状态是全局的。Agent 在早期改了一个接口签名,后期做前端对接时它自己都不一定记得住。如果你把任务拆给两个独立的 Agent 会话,情况就不同了:后端 Agent 只需要关心接口契约,前端 Agent 只需要按照契约文档写调用,两者不需要互相理解彼此的完整背景。

当然也要说句公道话,单 Agent 在特定场景下依然有不可替代的价值。改动范围在单文件级别、需求非常明确的任务,比如"帮我给这个函数增加一个重试参数"、"修复这个数组越界报错",让 Codex 一个人干完反而最省事。多 Agent 是为复杂组织型任务准备的,不是为了所有场景服务的银弹。

1.3 什么时候单 Agent 仍是正确选择

我不建议一上来就把所有项目都改成多 Agent,那样只会给自己添乱。我的判断标准有三个:修改文件数是否超过 3 个、是否涉及跨技术栈、是否需求本身还没收敛。三条都不占的,单 Agent 快速解决就好;占了任何一条,才值得考虑拆人。

一个很典型的判断方式是把任务写在一张便签上,如果你自己都需要翻四五份材料才能说清要做的事情,那单 Agent 几乎没戏。多 Agent 的本质不是把任务分给多个人,而是把"一个人脑子里纠缠不清的多重职责"拆成"多个互不干扰的单项职责"。想通了这一点,后面一切就好办了。

2. 多 Agent 协同的三种编排模式

2.1 协调者-执行者模式:适合大多数常规项目

这是我最推荐新手入手的第一种模式,也叫星型模式。它的核心是一个中枢协调者负责拆任务、派活、验收成果,底下的 Worker Agent 只做被分配的那一件工作,做完交结果,不负责看全局。

举个例子,假设要开发一个"销售统计报表页"。协调者会把任务拆成四份:

  • 数据库 Agent:建一张销售事实表,编写初始化 SQL。
  • 后端 Agent:在backend/app/routes下新增统计接口,按天/按产品维度聚合。
  • 前端 Agent:在web/src/pages下新增报表页面,对接统计接口。
  • 测试 Agent:补接口和页面的关键用例,并跑一轮冒烟测试。

每个 Worker 只拿到一份简洁的任务书,里面写清楚输入、输出路径、完成标准,它不需要理解整条业务链路。这样做的好处是上下文互不污染:后端 Agent 不会因为看到前端代码而分心,前端 Agent 也不会因为数据库表结构改动而怀疑人生。

这个模式的瓶颈也很明显:协调者是所有信息的汇聚点,一旦协调者拆的任务书含糊不清,下面所有 Worker 都会跟着歪楼。因此协调者必须花时间把任务书写得足够细——不是把实现细节写死,而是把边界、验收标准、依赖关系写死。

2.2 流水线模式:适合前后端完全解耦的项目

流水线模式是一环扣一环,前一个 Agent 的输出作为后一个 Agent 的输入。比如"生成数据模型 → 生成接口实现 → 生成对接文档 → 生成前端页面"。它最适合顺序依赖强、步骤边界清晰的项目。

流水线最大的坑是中间任一步出错,整个链条都要回滚重来。所以每一步之间必须有一份显式的交付物,而不是口头说"我改好了"。我会要求每个环节至少产出一个独立的文件,比如docs/api-contract.md、backend/routes/statistics.py,下一个 Agent 被派发任务时,输入就是这些文件路径。这样如果后面发现问题,可以直接定位是哪个环节的交付物不合格,再决定只重跑那一环还是整链重跑。

我个人的经验是流水线步骤不要超过 4 步。超过 4 步后,错误传播的路径太长,排查复杂度和重跑成本都呈指数级上升。真需要那么多步骤,应该把部分步骤合并,或者改用协调者-执行者模式。

2.3 黑板模式:适合并行探索型任务

黑板模式借鉴了早期人工智能里的"共享存储"思想:所有 Agent 不直接互相通信,而是把信息、进度、结论写在一块共享区域(黑板)上,谁需要谁去读。落到工程实践里,黑板可以是一份docs/task-board.md文档,也可以是 git 仓库里一个共享分支。

这种模式最适合做模块边界清晰的并行开发。比如一个项目有独立的用户管理、订单管理、商品管理三大模块,三个 Agent 可以并行开工,各自在任务板上登记"我改了什么、接下来谁需要关注什么"。由于模块间几乎没有共享文件,冲突概率低,并行度很高。

但黑板模式对强耦合任务非常不友好。如果两个 Agent 需要频繁修改同一个核心文件,黑板上的信息流转根本赶不上代码冲突的速度,最终只会变成一场 Overwrite 大混战。因此使用黑板模式前,必须先确认模块间的依赖确实被物理隔离了。

三种模式的对比,我整理了一个速查表,方便读者按项目特征做选择:

模式适用场景核心优点主要风险
协调者-执行者需求明确、任务可拆解、步骤多职责清晰,全局可控协调者质量决定一切
流水线顺次依赖、交付物明确每步可验收,错误可定位单点错误会级联放大
黑板模块独立、并行开发并行度高,自由度大强耦合任务容易冲突

3. 实战落地:先把角色和交接规范定下来

3.1 先定角色,再谈工具

很多团队处理"多 Agent 协同"时,第一反应是要不要上个框架、用哪个平台。我的建议完全相反:先为当前项目定义角色表,再决定用什么工具承载这些角色。工具只是容器,角色才是灵魂。

以我最近做的一个内部数据看板为例,我把 Agent 分成四个角色:

角色职责边界典型输入典型输出
需求 Agent梳理非功能需求,产出任务清单产品初始文字描述docs/tasks.md
架构 Agent划模块边界、定数据契约、定接口签名任务清单、现有代码扫描docs/contract.md
实现 Agent按契约编写代码,只改指定目录契约文档、任务书对应模块代码
验收 Agent跑测试、审查变更、检查回归代码 diff、测试报告验收单/驳回说明

注意我把"实现 Agent"拆成了两个独立会话:一个只负责后端目录,一个只负责前端目录。很多人会图省事让同一个 Codex 会话兼任前后端,美其名曰"全栈",结果就是上下文污染的高发地。既然拆成两个人不花多少钱,为什么不拆清楚呢?

这里的核心原则是:每个 Agent 只拥有一小块世界。它不需要知道别的角色怎么实现,只需要知道自己的输入从哪来、输出给谁、完成标准是什么。这个原则贯穿我后续所有的 Agent 配置和任务书编写。

3.2 AGENTS.md:仓库里的"团队章程"

要让多个 Agent 在同一仓库里协作不打架,必须有一份它们共同遵守的规范文件。我习惯把它放在仓库根目录,命名为AGENTS.md。这个名字的灵感来自很多项目里的CONTRIBUTING.md,但内容是专门写给 Agent 看的,而不是给人看的。

一份典型的 AGENTS.md 我会写成这样:

# 项目协作章程 ## 角色与目录边界 - backend-agent:只允许修改 backend/ 目录 - frontend-agent:只允许修改 web/ 目录 - docs-agent:只允许修改 docs/ 目录 ## 工作流 - 开工前先读 docs/contract.md - 每个任务在独立分支 feat/xxx 上完成 - 完成后更新 docs/board.md 的交接记录 - 禁止跨目录改动,如有需要先提出契约变更 ## 代码规范 - 遵守项目现有 lint 规则 - 公共函数必须写类型标注 - 新接口必须同步更新 api-contract.md

写 AGENTS.md 的过程,本质上就是把以前散布在开发者脑子里的默契显式化。我踩过的最大坑是写得太空泛,比如"请遵循最佳实践"。这句话对 Agent 毫无约束力,它不知道该查哪份文档、该用哪种模式。只有把它变成机器可执行的边界条件,比如"只允许修改哪个目录",才能真正约束行为。

3.3 一个轻量编排器示例:CLI + 队列 + 交接单

在早期项目里,我不建议急着引入 MetaGPT、CrewAI 这类成熟框架,它们功能强大但也带来额外的学习成本。我更倾向于用几十行代码写一个轻量编排器,直接把 Codex CLI 串起来。这么做的好处是每一步都可控、可日志、可回滚,不会被框架的黑盒逻辑绑架。

下面是我常用的编排思路,用 Python 写了一个最小示例:

import subprocess import yaml def run_codex(task_file: str, agent_role: str): prompt = f"你是{agent_role},请严格依据任务书 {task_file} 执行,只改动规定目录。完成后更新交接文档。" cmd = [ "codex", "exec", "--skip-git-repo-check", "-t", "你的模型标识符", prompt ] result = subprocess.run(cmd, capture_output=True, text=True) return result.returncode, result.stdout def load_tasks(board_file: str): with open(board_file, "r", encoding="utf-8") as f: return yaml.safe_load(f) if __name__ == "__main__": tasks = load_tasks("docs/board.yaml") for task in tasks: code, output = run_codex(task["task_file"], task["role"]) print(f"[{task['role']}] exit={code}") if code != 0: print(output) raise SystemExit("任务失败,终止流水线")

这段代码做的事很简单:读取一个 YAML 格式的任务看板,遍历里面的任务,依次调用codex exec让 Agent 干活。YAML 任务看板的长这样:

- role: backend-agent task_file: docs/tasks/001-export-api.md - role: frontend-agent task_file: docs/tasks/002-export-button.md - role: reviewer-agent task_file: docs/tasks/003-review.md

很多读者看到这里估计会问:这跟把任务图省事全丢给它有啥区别?区别在两点:第一点是每个codex exec是全新的会话,上一个任务留下的上下文不会污染下一个任务;第二点是每个任务的文件边界都由 AGENTS.md 约束,即使某一个 Agent 中途跑偏,也只会污染自己的目录,不会波及其他 Agent 的成果。

这里我不讨论重型框架,是因为在项目早期,真正卡住效率的瓶颈从来不是编排算法,而是任务拆解质量和交接清晰度。等你把上面这套轻量流程跑通了,再评估是否引入更复杂的框架也不迟。

4. 核心环节实现:任务交接与回滚机制

4.1 交接单字段设计的思路

多个 Agent 协作和多人协作一样,成败往往在"交接"这个环节。让我写的最炉火纯青的,就是一份不啰嗦但字段齐全的交接单。每次 Agent 完成任务,必须更新对应任务条目,包含以下字段:

字段作用我的填写要求
任务ID索引用的唯一编号用task-001这类前缀格式
触发条件这个任务为什么现在要做一句话说清楚依赖前置条件
输入上下文从哪里读取必要信息必须是文件路径,拒绝口头描述
期望输出验收的对象文件路径 + 功能行为
验收标准怎样算完成可运行的命令或测试用例
变更清单实际修改了哪些文件git diff 里的文件列表
遗留风险没解决或不确定的地方有就写,没有写"无"

我见过最糟糕的交接单只写一行"已完成功能",等到下游 Agent 接手时完全不知道改了什么、依赖什么、怎么验证。这样的交接单等于没有交接单。反过来,字段太复杂也不好,Agent 会花大量时间在写文档上偏离实际编码。

真实项目中我一般会把"验收标准"写成一个具体命令,比如pytest tests/test_export_api.py -k export。这样验收 Agent 不需要猜测,直接跑命令看结果就行。

4.2 分支与回滚策略:给 Agent 的探索留安全带

多 Agent 协作最怕的一件事是:一个 Agent 在探索时大幅修改了共享文件,结果导致其他 Agent 的成果被破坏。为了应对这种情况,我强烈建议给每个 Agent 分配独立的工作分支。

假设三个 Agent 分别负责新增统计接口、新增报表页面、新增测试用例。我要求它们分别在feat/api-statistics、feat/page-report、feat/test-coverage三个分支上开发,每完成一个里程碑就往主干合一次,并附上交接单摘要。这样一旦主干被某个分支破坏了,可以用git diff main...feat/api-statistics快速定位问题分支,然后单独回滚它,不影响其他 Agent 的进度。

如果遇到更棘手的情况,比如两个分支都改了同一个公共组件,我会用git log --oneline --graph --all查看分叉历史,手动裁决哪个分支的改动应该保留、哪个应该重做。这个过程听起来原始,但恰恰是多 Agent 协作里最可靠的一环——机器可以帮你干活,但合并决策最终还是要靠人来拍板。

关于代码回滚,我的建议是养成小步提交的习惯。Agent 每次完成一个子任务就提交一次,不要攒十个文件一次提交。小步提交的粒度通常控制在半小时以内,这样即使某一个 Agent 的行为失控,回滚带走的也只是半小时内的工作量,而不是一整天的成果。

4.3 配置与模型选型的易错点

在配置 Codex 时,我踩过不少坑,这里集中说一下比较容易翻车的地方。第一个坑是认证令牌失效。如果你用环境变量方式传入认证信息,在脚本里调用codex exec时,常常会遇到"auth token is unavailable"这类报错。原因是环境变量没有传进子进程,或者令牌已经过期。我的排查方式是先跑一下env | grep CODX看环境变量是否存在,再单独在终端里跑一次codex exec排除脚本传参的问题。

第二个坑是模型标识符不匹配。有些报错会提示"model is not supported when using codex with ...",这通常是因为定义的模型名在当前 CLI 版本里不存在,或拼写有误。遇到这类问题,我会用codex --version先确认当前版本,再去查这个版本支持的模型列表,把模型名统一抽成一个环境变量或配置文件,避免每个脚本里各写各的导致排错困难。

第三个坑是被忽略的配置项。Codex 遇到不认识或过时的配置字段时,可能不会直接报错,而是警告"ignoring unrecognized configuration setting"。这类问题非常隐蔽,因为任务看起来照常运行,但实际上你精心设置的参数可能没生效。我的做法是在改动配置后,立刻跑一个最小化任务验证配置是否被读取,而不是直接甩一个大任务。

5. 常见问题与排查技巧实录

5.1 Agent 互相覆盖文件:多开会话的日常灾难

很多刚上手多 Agent 的人会开几个 Codex 窗口同时干活,结果发现一个窗口的改动把另一个的覆盖了。这个问题的根源不是 Codex 本身,而是多个 Agent 共享同一个工作目录,都在处理同一批文件,git 工作区变成了一个没有锁的共享内存。

解决方式参考我在 4.2 节里的分支策略:每个 Agent 限定自己的目录和分支。如果只是想快速排查问题,可以用git status先看冲突文件,再用git diff --name-only列出每个分支实际改动过的文件,找出重叠区域。如果是两个 Agent 同时改了同一个文件,这种问题靠删除重来是效率最低的。最稳妥的做法是强制规定"谁最后合入,谁负责解决冲突",因为只有最后一个合入者能看到全局状态,冲突解决起来不会遗漏。

5.2 登录态与令牌排查:三步定位法

很多人在配置环境时遇到"无法加载组织设置"或"认证信息不可用",第一反应就是重新登录。但盲目重新登录往往治标不治本,尤其是当你在脚本里调用 Codex 时,问题大概率出在环境变量没有正确传递。

我总结了一套三步定位法:

  1. 在终端手动登录并确认登录状态正常;
  2. 用env | grep CODX检查环境变量是否存在、值是否正确;
  3. 在脚本里增加一行print(os.environ.get("CODX_AUTH_TOKEN"))确认子进程真的能读取到令牌。

大多数情况下,问题都出在第 1 步和第 2 步之间:终端登录状态正常,但脚本进程没有拿到令牌。如果是这个问题,只需要在启动脚本前统一设置环境变量,或者直接在脚本里显式加载环境配置文件即可。

5.3 上下文超限与模型不支持:配置层面的隐藏炸弹

单 Agent 场景下,上下文超限的典型症状是"对话越长回答越敷衍"。多 Agent 场景下有另一种更隐蔽的表现:某个下游 Agent 看到的输入已经不是上游 Agent 产出时的原始状态了,它会基于不完整的信息做决策,产出的代码会和契约文档矛盾。

针对这种情况,我的建议是宁可多拆两步也不要让单个任务吃得过大。如果一份任务书涉及的文件超过 10 个,我通常先让架构 Agent 做一轮简化,把任务书压缩到 3-5 个关键文件,然后再派给实现 Agent。模型不支持的问题则按 4.3 节里的方式验证模型名和版本匹配关系。

5.4 问题排查速查表

多 Agent 协作场景的问题多而杂,我整理了一张速查表,是我自己在项目中反复用到的"急诊手册":

症状可能原因30秒定位命令标准解法
两个 Agent 互相覆盖共享目录交叉git diff --name-only分支隔离 + 目录限定
配置项被忽略字段名拼错或版本不匹配codex --version+ 配置文件 diff对照版本文档修正字段
认证令牌不可用环境变量未传递或过期env | grep CODX重新设置环境变量并重登
模型提示不支持模型标识符不一致查看完整报错上下文抽成统一配置变量
上下文被撑爆任务粒度过大查看任务书涉及文件数拆小任务、增加检查点
下游得到过期数据交接单未更新查看交接单更新时间强制每次完成提交后更新

这张表的价值不在于每条都精准命中,而在于它帮你建立一个排查顺序:先看 git 历史,再看环境变量,再看配置文件,最后才怀疑模型本身。大多数问题都出在前三层。

6. 我的经验与后续扩展方向

多 Agent 协同这件事,我做了大半年,最大的体会是:它真正的价值不在于堆砌 Agent 数量,而在于建立清晰的边界和严格的交接协议。一开始我天真地以为,只要给同一个 Codex 会话加上一堆角色扮演提示词,它就能"扮演多个专家"协同工作。结果它只是在切换人格时不断失忆,出了错都不知道该怪哪个角色。后来改成物理隔离、独立分支、交接单驱动,稳定性才真正上来。

如果你正在尝试把项目从单 Agent 迁到多 Agent,我的建议是从最小的两步拆起:先把"实现"和"验收"拆成两个独立 Agent,其他保持不变。这一步改动最小,收益却立竿见影——实现者可以放手写代码,验收者可以冷静找问题,两者互不干扰。等这条链路跑顺了,再逐步增加需求梳理、架构设计等前置角色。

我还在继续做的工作,是把交接单和任务看板可视化,给每个 Agent 的耗时和执行路径打日志。这样当某个任务链出问题时,我一眼就能看到是哪一个环节消耗了最多的 token、哪一次交接出现了信息缺失。但这个扩展的前提,依然是先把基础交接协议做得足够扎实。框架可以换、模型可以换,角色边界和交接纪律才是多 Agent 协作真正的地基。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询