做 Sunny 的跨仓库协作时,我们需要决定一件事:一个功能同时涉及前端和后端,应该让一个 Agent 一起改,还是让两个 Agent 分头做、互相发消息?
两种方式都有吸引力。一个 Agent 能同时看到两边,修改接口时可以一起调整调用方。两个 Agent 可以并行工作;如果前后端已经各有一个长期使用的会话,也能继续沿用各自的上下文。
这里的 session,就是承载 Agent 对话历史和执行过程的会话。我们比较的两种安排是:
| 方式 | 谁负责代码 | 两边如何对齐 |
|---|---|---|
| 单会话、多仓库 | 一个 Agent 访问并修改前后端两个仓库 | 在同一个上下文里决定和修改 |
| 双会话、互发消息 | 两个 Agent 各负责一个仓库 | 通过消息交换接口方案和进度 |
实验分了三轮。前两轮比较这两种安排,先给明确接口,再加入需要协商的接口和已有历史。第二轮暴露出消息可能来得太晚,第三轮才改为比较两种消息投递方式。第三轮两组都是两个 Agent,不再有单 Agent 组。
同一项任务,两种工作方式
三轮分别在比较什么?
每种方式 4 次。每格代表一次结果,按结果分组,不表示发生顺序。三轮不合并排名。
一个会话,还是两个会话?
单会话、多仓库
双会话、互发消息
28 项检查;更正两处显示文本断言后,对全部原产物复验。双会话均时少 12.6%,累计报告 tokens 为 2.17 倍。
第一轮:接口已经定好,分头做有没有收益?
题目是两个独立仓库里的 OAuth 集成,也就是产品里常见的“连接第三方账号”。连接状态要持久化,重启不能丢;要处理重复和并发回调、授权失败、超时、工作区隔离,兼容旧接口,还要在真实浏览器里完成跳转、重试和跨标签页同步。
仓库规模不大,但行为要求并不简单。
两种安排都用 GPT-6.1 Sol,medium 推理强度,并经过 Sunny 的真实执行链路。每一对实验从相同起点完成同一项任务。双会话共享整个任务的预算,不是每个 Agent 各领一份。
模型停止后,外部执行器再运行事先固定的 HTTP 和浏览器检查,不把评分结果发回去让模型补做。执行与评分流程分开,但文件访问仍主要靠指令约束,没有操作系统级权限隔离。
四对、八次运行,最终都通过了 28 项检查。双会话在四对里快了三对,平均实现时间少约 12.6%;累计报告 tokens 则是单会话的 2.17 倍。这个数包含缓存读取,不能直接说成费用翻倍。
这给了双会话一个不错的开局,但有一个前提:两边拿到的是完整、明确的接口约定,路径和字段都已规定好。它们主要需要分工实现,不必自己协商接口。
“全部通过”也经历过一次纠错。一个实现显示 Connected,评分器却要求小写 connected,把合法界面判错。我们保留原始成绩,只修正两处显示文本断言,然后对全部八份原始实现统一复验。模型没有补做,产物没有修改。[1]
因此,第一轮支持的判断很有限:接口明确时,两种安排都能完成这批任务;双会话有一些并行收益,也消耗了更多 tokens。接下来要看的是,接口还没定好时会发生什么。
第一轮:四对任务,分别看耗时
每对起点相同。全部通过 28 项检查。
新会话 1
新会话 2
交接历史 1
交接历史 2
时间少了一点,用量多了多少?
第一轮 · 每种方式 4 次运行的平均报告 tokens
| 每次均值 | 单会话 | 双会话 |
|---|---|---|
| 未缓存输入 | 23,276 | 43,162 |
| 缓存读取 | 266,464 | 592,128 |
| 缓存写入 | 0 | 0 |
| 输出 | 10,231 | 15,029 |
第二轮:两边需要自己协商,还能顺利完成吗?
真实跨仓库工作里,前端往往已经依赖一套字段,后端也要保留既有行为。新功能没写,旧代码和历史决定已经占好了位置。
第二轮从能工作的 OAuth 产品出发,增加安全断开连接的功能。服务端要检查客户端操作的是否仍是当前版本,记录操作,并保证同一个请求重复发送不会重复执行。
一个具体场景是:断开连接已经成功,但浏览器没收到答复。用户后来又建立了新连接,再重试旧请求,不能把新连接也断开。
我们设计了两个场景,每个场景做两对比较:
- 接口协商: 前后端的本地笔记里有互不兼容、尚未正式采用的 API 草案,需要自行统一路径和字段。评分器读取最终约定,再检查行为。
- 已有历史: 先让真实 Sunny 会话完成维护工作,留下代码、测试和完整历史,再接着做新需求。双会话恢复各自原生历史;单会话可以读取两边完整历史文件。
第二个场景让双方都能获得相关信息,但上下文组织和检索成本不同。这也是两种工作方式的实际区别,不能把所有结果简单归因于 Agent 数量。
这一轮仍是四对、八次运行。每个任务共享十分钟、160 万累计报告 tokens 和 2.4 万输出 tokens 的上限。我们分别记录两个结果:停下来时,代码是否通过验收;以及是否在预算内完整完成任务。 代码过关但超出预算,仍算预算内交付失败。
| 第二轮 | 单会话、多仓库 | 双会话、排队发消息 |
|---|---|---|
| 预算内完成并通过全部验收 | 4/4 | 0/4 |
| 停止时产物通过全部 48 项检查 | 4/4 | 1/4 |
双会话四次都触及 token 上限。其中一次代码已经通过全部检查,但没有在预算内完整结束。
第二轮:失败落在哪一对?
| 同一任务 | 单会话 | 双会话 |
|---|---|---|
| 接口协商 1 | 48/48预算内完成 | 48/48超预算 |
| 已有历史 1 | 48/48预算内完成 | 21/48超预算 |
| 已有历史 2 | 48/48预算内完成 | 37/48超预算 |
| 接口协商 2 | 48/48预算内完成 | 21/48超预算 |
具体失败比排名更值得看。一次运行里,两边各自做好了一部分,却用了不同的路径和字段。另一次的接口约定文件已经一致,前端代码却仍在请求旧路径、读取旧字段。消息里同意了,文件里写对了,不代表代码已经跟着改对。
我们于是回头检查消息的时间线。38 条请求都被发送通道接受,但任务停止时,只有 20 条进入了接收方的持久化历史。一个历史场景发了 6 条,停止前一条都没有进入。
当时采用的是 followUp,也就是排队追加:对方忙着执行时,消息先等着,等这轮执行结束后再追加进去。双方都在长时间实现和测试时,影响接口的决定也可能一直在队列里等。
这让“两个 Agent 没做好”多了一种解释:对方发来的消息,可能根本还没有进入它当前的工作上下文。第二轮还不能证明这解释了多少失败,所以我们决定把消息时机单独拿出来测。[2]
第三轮:同样是两个 Agent,早点收到消息会怎样?
这一轮不再比较一个和两个 Agent。两组都是前后端各一个 Agent,复用第二轮的起始代码、历史、题目和预算,只改变消息的投递方式:
| 消息方式 | 对方正在工作时,消息如何进入 |
|---|---|
| 排队追加(followUp) | 等这轮执行结束后追加 |
| 执行途中处理(steer) | 在执行过程中的工具边界进入上下文 |
途中处理也不会打断一个正在运行的工具。预实验还纠正了我们一个过于乐观的假设:由于异步转发,消息不保证赶在紧接着的下一步之前进入,可能再多走一步。
我们用连续三个工具步骤检查链路:排队追加的消息在最后一个工具之后进入;途中处理的消息在第二和第三个工具之间进入。确认这项区别实际存在后,才按预定顺序跑完四对、八次正式任务。
同一条消息,在哪一步进入?
followUp · 排队追加
- 工具 1
- 工具 2
- 工具 3
steer · 途中处理
- 工具 1
- 工具 2
- 工具 3
| 第三轮 | 排队追加 | 执行途中处理 |
|---|---|---|
| 预算内完成并通过全部验收 | 0/4 | 1/4 |
| 停止时产物通过全部 48 项检查 | 1/4 | 4/4 |
| 停止前进入接收方历史的消息 | 14/32 | 45/47 |
发送被接受之后,多少消息真正进入?
第三轮 · 停止前进入接收方持久化历史
只看已进入历史的消息,中位延迟约为 154 秒和 10.7 秒。没有进入的消息不在这个中位数里,所以不能把这两个数包装成交付提速倍数。进入历史,也只说明模型有机会处理,不能直接当作已经理解。
这一轮出现了一段很能说明问题的过程:前端提出方案 A,后端提出方案 B。过了一会儿,前端同意改成 B,后端也同意改成 A。双方都很配合,代码却依然接不上。
途中处理组同样发生了交叉确认。但冲突信息能在工作尚未结束时进入,双方后来明确冻结最终版本,最后实现了相同接口。
那次产物通过全部 48 项检查,却因输出超预算仍算失败。另一次途中处理才在预算内完整完成。排队组也有一次做到 48/48,只是超预算。[3]
这批结果支持消息时机值得改进:途中处理组的最终代码更容易对齐。但四次里只有一次在预算内完成,协商和收尾的成本仍然很高。
第三轮:八次运行,一次次看
| 场景 | 消息方式 | 检查通过 | 预算内交付 |
|---|---|---|---|
| 接口协商 1 | followUp | 21/48 | 输出超预算 |
| 接口协商 1 | steer | 48/48 | 输出超预算 |
| 已有历史 1 | steer | 48/48 | 累计用量超预算 |
| 已有历史 1 | followUp | 21/48 | 累计用量超预算 |
| 已有历史 2 | followUp | 28/48 | 累计用量超预算 |
| 已有历史 2 | steer | 48/48 | 累计用量超预算 |
| 接口协商 2 | steer | 48/48 | 完成 |
| 接口协商 2 | followUp | 48/48 | 输出超预算 |
先确认实验跑对,再谈模型做得怎样
三轮里,也有属于实验自身的失败。
历史恢复副本曾被放进错误目录,被生产路径检查拒绝。修正位置、验证真实恢复后,才继续使用同一份历史。第二轮最后一次单会话又遇到合盖休眠;系统日志确认环境中断,我们保留记录,只重跑这个无效尝试,没有重跑其他正常预算失败的样本。
第一轮还有测试服务未正常退出,以及在运行彻底结束前修改报告脚本、触发源码保护的问题。此后我们要求整个运行和清理结束前冻结 checkout,连报告脚本也不动。
这些记录需要与模型的失败分开。否则,环境中断可能被算成模型失败,人工修正实验的过程也可能从最终成绩里消失。
通过全部检查,能说明多少?
第一轮已经出现过评分器误判。到了第三轮,即使代码通过全部检查,我们也还需要回头看:已有检查漏掉了哪些行为?
我们又做了一次事后补充审计。没有让模型重跑题目,而是先审查需求与已有覆盖,写定 12 项边界组合。比如,无效请求会不会误伤待完成授权;不同工作区的操作回执在重启后是否仍然隔离;响应丢失后又建立了新连接,旧请求重试会不会把它断开。
检查先经过参考实现和四个故意破坏的版本校准:参考实现通过 12 项,四个错误版本都被对应检查抓住。然后对第二、三轮全部 16 份保存产物的副本统一复验,原文件与副本前后哈希都没有变化。
原先通过全部 48 项检查的 10 份产物,这次全部通过新增 12 项。其余六份也都保留在审计里:四份接口约定不一致,后端通过 10 项,浏览器两项无法执行;一份缺少约定,12 项均无法执行;还有一份前端接入未对齐,两个浏览器流程实际失败,与原报告的问题一致。
16 份代码,再过一遍 12 项边界检查
每格代表一份保存产物,按结果分组,不表示运行顺序。
补测没有找到推翻原先全过结果的新反例,让我们对这些具体边界更有把握。但它不能证明检查已经完整。审查者已知之前结果,这也是事后审计,不是盲测或独立团队认证。[4]
我们没有人工修好候选代码再把它算作模型成功,但实验设计、评分器校准、故障处理和记录审阅都有人参与。完整的人工检查与返工时间没有统一计量,目前还不能报告生产意义上的端到端交付时间。
回到最初的问题,我们会怎么选?
如果一个新任务同时涉及两个仓库,我们目前更倾向于让一个 session 明确关联两边。尤其当接口还需要改动和协商时,同一个上下文可以省去一部分跨会话确认。这是结合实验作出的产品判断,不是普遍最优方案的证明。
如果前后端已经各有正在使用的会话,保留历史、继续分工仍有价值。但消息协作不能只做到“发送成功”:我们需要知道它还在排队、已经进入对方上下文,还是已经得到明确回复。第三轮也提醒我们,即使消息更早进入,双方仍可能反复确认、耗尽预算。
这些判断的范围很小。每轮只有四对,第一、二轮之间题目、预算和提示版本也有变化,不能合成一张总榜;所谓已有历史,来自先前维护任务,并非数月自然使用。第二、三轮各有一个双会话样本借用了宿主 Playwright 自测,偏离纯内置依赖前提,结果照样保留并披露。强制握手或指定协调者是否更有效,这几轮也没有测。
我们开始时想比较的是:一个 Agent 做,还是两个 Agent 分头做。真正跑下来,才发现“两个 Agent 能互相发消息”还不是一个足够完整的实验条件。
消息到了哪里、什么时候到、双方最后有没有据此改对代码,都得沿着记录看一遍。
方法与数据
[1] 第一轮:明确接口;包含新会话和预置交接历史。两处显示断言更正,八份原产物统一复验。
[2] 第二轮:接口协商与真实维护历史;四对、八次。预算失败保留,环境无效尝试另记。
[3] 第三轮:两组均为双会话,复用起始快照,只比较 followUp 与 steer。
[4] 补充审计:16 份保存产物、12 项新增检查;170 项通过、2 项失败、20 项受前置条件阻塞。
实验范围与可复核结果
24 次正式模型运行,每轮 8 次;补充审计复验其中 16 份保存产物,没有新增模型运行。GPT-6.1 Sol · medium · pi 1.4.0。消息桥经过生产 prompt、parser 和生命周期,但仍是实验适配器,不代表完整消息产品已经上线。
第一轮共用预算为 480 秒、120 万累计报告 tokens、2 万输出 tokens、24 条消息;后两轮为 600 秒、160 万累计报告 tokens、2.4 万输出 tokens、32 条消息。累计报告用量含缓存读取,不等于费用。第三轮复用第二轮的起始快照,不是接着第二轮失败代码修改。
第三轮按四对交替安排:followUp → steer,steer → followUp,followUp → steer,steer → followUp。前两轮的完整通过记录、第三轮的失败和未投递消息都保留。
下方数据为经过筛选的逐次结果与方法摘要,未公开原始会话、认证资料或本机路径。完整原始记录在本地保留;公开汇总不能替代原始 trace 审查。
AI 辅助起草。每轮只有四对;本文是工程实验记录,不是通用能力排名。