Skip to content

多 Agent 的文件与产物协作 ​

产物是任务留下的可读取结果,例如代码文件、报告、数据集和图表。多 Agent 协作除了传递结论,还需要约定谁修改产物、基于哪个版本修改,以及各份结果如何组成最终交付。

假设写作 Agent 与审查 Agent 都在处理 report.md。写作 Agent 读到旧文件后重写第二节;审查 Agent 在同一节补了一条限定条件。如果两者都按各自读到的全文覆盖保存,后落盘的版本可能丢掉另一方的修改。即使工具采用局部 patch,两个修改也可能基于不同上下文,合在一起后出现重复或矛盾。

解决方式取决于任务能否分开:可以让不同 Agent 直接修改各自负责的文件,可以在隔离工作区中独立实现,也可以让它们提交 patch 后统一应用。没有一种策略适合所有任务。

先看哪些修改能够独立进行 ​

策略工作方式适合的任务合并时仍需检查什么
独立文件所有权每个 Agent 直接修改指定文件,约定共享文件由谁处理文档拆篇、边界稳定的模块修改交叉引用、接口和共同约定是否一致
隔离工作区每个 Agent 在独立目录或 Git worktree 中修改,最后汇总差异跨多个文件的功能实现、需要各自运行验证的任务文本冲突、接口变化、依赖及整体行为
patch 队列执行者提交修改和基线,合并者按顺序应用多方需要改同一文件、写入范围需集中校验的任务patch 是否过期、是否越界、语义能否同时成立

例如整理一组教程时,A 可以负责 communication.md,B 负责 lifecycle.md,导航文件由协调者统一更新。这些文件可以并行直接落盘,没必要先把每次修改都转换成 patch。

但文件名分开不等于任务完全独立。A 将任务终态命名为 completed,B 使用 done,各自文档都能通过 Markdown 检查,整组教程仍然不一致。分派前应约定公共术语或接口,并明确这些公共定义变化后由谁通知其他执行者。

同文件的不同章节也可以划分所有权,不过标题位置和行号会随编辑变化。章节标识通常比“第 40—80 行”更稳定。自动格式化、批量重命名和全文件重写会越过分区,因此需要集中执行或串行处理。

隔离工作区隔离了什么 ​

在独立工作区中,两个 Agent 可以从同一个基线版本开始,各自修改和验证,不会直接覆盖对方的工作文件。Git worktree 允许同一仓库拥有多个检出目录,适合把不同任务的文件状态分开;普通独立目录也能实现文件层面的隔离,但需要另外管理基线和差异。

text
共同基线 v1
    ├─ 工作区 A:修改资料读取模块 → 产物 A
    └─ 工作区 B:修改报告生成模块 → 产物 B
                         ↓
                    汇总两份差异
                         ↓
             检查接口衔接与集成后的行为

隔离工作区仍可能共享 Git 对象库、包缓存、数据库、外部服务或测试端口。它提供的是文件修改空间,不自动等于权限隔离,也不保证运行中的副作用互不影响。需要并行运行程序时,应检查它们写入的实际位置和使用的服务资源。

汇总时保留任务基线、修改意图和验证结果,比只交一个目录路径更有用。如果 A 改了函数返回结构,B 还按旧结构调用,合并者需要协调接口。两个分支能被 Git 自动合并,只说明文本层面存在可用的合并结果。

patch 队列怎样应用一次修改 ​

需要集中处理同一份报告时,可以让写作 Agent 提交修改差异。任务分派先带上目标文件、读取版本和允许修改的范围:

json
{
  "task_id": "revise-handoff-section",
  "artifact": "report.md",
  "base_version": "v1",
  "target_section": "上下文交接",
  "intent": "解释结果交接需要保留的证据与未完成项",
  "constraints": ["保留其他章节", "不改变已确认的任务条件"],
  "deliverable": "unified diff 及修改说明"
}

执行者读取这份基线后生成 patch,返回时仍保留基线标识:

json
{
  "task_id": "revise-handoff-section",
  "artifact": "report.md",
  "base_version": "v1",
  "patch_ref": "patches/revise-handoff.diff",
  "intent": "补充证据引用和部分完成的交付方式",
  "validation": {
    "checked": ["目标章节的引用关系", "修改范围"],
    "not_checked": ["与其他待合并修改的衔接"]
  }
}

v1 可以对应一份不可变快照,也可以由内容哈希或 Git 提交标识表示。行号只帮助定位,不能证明修改依据的内容仍然相同。patch_ref 指向的内容也要固定,不能在合并者检查之后悄悄替换。

合并者读取当前文件,核对任务范围与基线,检查 patch 是否可应用,再进行实际写入。如果另有程序或人也可能在检查之后修改文件,应使用能覆盖这些写入者的锁,或将版本比较与写入作为一个原子操作。只在写入前再次读取版本,依然留有被其他写入抢先的间隙。

应用后,新的文件版本、已处理的 patch ID 和检查结果一起记录,便于避免重复应用,也便于后续修改确定自己的基线。合并者可以是确定性的程序、负责集成的 Agent 或人,不要求每次普通写入都人工确认。

旧版本 patch 该怎样处理 ​

沿用同一份教程,写作 Agent 调整“上下文交接”的结构,审查 Agent 补充来源标记。两者最初都读到 v1:

时刻发生的动作当前文件
1写作 Agent 基于 v1 返回 patch Av1
2审查 Agent 基于 v1 返回 patch Bv1
3合并者应用 A,第二节已经重新组织v2
4合并者检查 B,发现修改区域与 A 重叠保留 v2,B 暂不应用
5审查 Agent 读取 v2,确认原意见是否仍然成立,生成 B2v2
6合并者应用 B2,并检查前后文v3

B2 未必是把 B 换几个行号。如果 A 已经补上了部分说明,审查 Agent 只需要提出尚未解决的问题;如果 A 改变了表达方式,原来的插入位置也可能不再合适。

基线不同说明修改需要重新核对,不代表所有旧 patch 都必须废弃。如果两次修改作用于独立段落,可以比较基线、当前版本和目标修改,使用三方合并或在最新版上重新应用,再检查结果。范围重叠、事实前提改变或修改意图已被覆盖时,要求执行者基于最新版重新生成通常更清楚。

人中途编辑了文件,也按同样原则保留当前内容并比较意图。不能为了应用一个旧 patch,先把文件恢复到 Agent 最初读到的状态。

文本合并之后,还要看产物是否成立 ​

文本冲突通常能被差异工具发现:同一行被改成两种内容,或者 patch 找不到预期上下文。语义冲突可能出现在完全不同的文件里。

改动组合文本层面需要处理的问题
A 修改函数返回字段,B 新增调用方可能自动合并调用方是否仍按旧字段取值
A 将报告预算改为 5500 元,B 在结论推荐 5999 元方案可以没有重叠行结论是否使用最新条件
A 移动章节,B 新增到旧路径的链接各自文件语法正确链接是否失效
A、B 各补一段相同机制说明可以自动合并是否重复、术语是否一致

验证要跟修改的关系走。代码需要覆盖受影响接口和组合后的行为;文档需要检查链接、示例前提、术语以及结论与证据的对应。执行者可以分别验证自己的部分,集成者还要检查相互依赖的部分。

当冲突涉及不同事实结论,应回查来源与适用条件;涉及不同实现方案,则按任务要求选择或组合,具体见审查、辩论与结果裁决。如果现有要求不足以决定取舍,才需要补充决策输入。通过格式检查不会自动解决这些判断。

交付时返回最终产物的版本、改动范围、已执行的检查与未完成事项,下游才能确认自己读取的内容与这次交付一致。这种产物引用也可以放入任务结果和共享状态,无须把整个文件复制进每个 Agent 的聊天记录。

参考资料 ​

持续学习,持续实践。