藏在眼皮底下的 agent 协作协议:GitHub issue
我正在开发的 agent(智能体)运行框架 Bram,会在本地 git 仓库中启动,并要求机器上装好 git 和 gh(GitHub 的命令行工具)。Agent 用起这两个工具来,比我们人类熟练得多。以前我知道可以用 git bisect,或者用 hunk staging(按代码块暂存)把纠缠在一起的文件拆开,但真做起来非常费劲。我们一直知道 git 需要更好的用户界面,也长期以为更合理的命令集或更强的 GUI 才是答案。结果并不是。真正的答案是让 agent 代替我们使用这些工具。我们清楚要做什么,它们知道怎么做。
你可能已经体会过把 git 语法和工作流交给 agent 之后带来的威力。还有一种互补的能力:让 agent 用 gh 来写、读、回复 GitHub issue。下面是一些由此实现的协作场景。
跨 agent 协作
Bram 在 Claude Code 和 Codex 外面包了一层 GUI,点一下就能切换 agent。每个 agent 启动时都能访问四类上下文:1)工作清单(计划中、进行中或已提交的条目),2)会话(Claude 和 Codex 的都有),3)提交记录,4)issue。当某个条目正在进行时,我经常切换 agent,让它们互相审查对方的工作。无论是规划还是执行,三个脑袋都比一个强。
在同一台机器上运行时,你可以让每个 agent 读取另一个的会话;这些会话都躺在磁盘上。Bram 会为 Claude Code 和 Codex 的会话文件,以及工作清单历史、提交和 issue 建立索引,并通过 SQLite 全文搜索让 agent 能搜索这些内容,从而把这件事变简单。
跨机器协作怎么办?把一个 GitHub issue 当作共享空间,你、Claude Code 和 Codex 可以在里面互相交流。由于三者共用你的 GitHub 账号,三个脑袋都必须正确表明自己的身份,这一点很关键。Bram 的运行框架会让 agent 这样给消息签名:
Jon 的 Claude(主线程,Opus 5)从 Bram 项目(https://github.com/judell/bram)发言(Windows);Jon 的 Codex(主线程,gpt-5.6-sol)从 XMLUI 项目(https://github.com/xmlui-org/xmlui)发言(Mac)。在同一台机器的场景下,其实还有一条我没考虑过的通道。Codex 发现,它可以通过本地 API 直接跟 Claude 对话:
claude --print --safe-mode --tools '' --permission-mode dontAsk --no-session-persistence --model opus --effort high '<prompt embedding the full issue text>'
接下来发生的事,既好笑又发人深省。看起来像是 Claude 用我的账号在发言,用的是我们后来已经加固过的早期版代理签名。

Foundry
实际上,那条留言是 Codex 作为 Claude 的“书记员”发布的。它启动了一个无头 Claude,讨论了这个问题,然后把对话的两部分都转发到 GitHub,却没有说明 Claude 并非这些文字的直接作者。我看到这一幕时立刻吹哨叫停。我不希望这些东西在背后互相交谈!我要它们在公开记录中对话,在一个它们都无法控制的、可审计的系统里交流。
跨机器协作
有时这种基于 issue 的协作发生在我自己的多台机器之间,比如我们在审核 Bram 的候选发布版本时。Bram 会详尽地记录日志,使用一套覆盖其大部分行为的丰富追踪词汇。当运行在我 Windows 笔记本上的代理报告一个 bug 时,我会让它读取追踪日志、分析发生了什么、开一个协作 issue,并附上日志证据。然后我让运行在 Mac 上的代理接手这个 issue 开始处理,同时 Windows 上的代理继续测试候选发布版本。
跨项目协作
同样的日志在任何由 Bram 管理的项目中都可用。在《当 AI 代理失控时,提交 bug 修复文档——然后测试修复》一文中,我写道:
作为 XMLUI 的共同维护者,我对 agent 构建 XMLUI 应用时犯迷糊这件事格外敏感。有些事本该轻而易举,可 MCP 检索偏偏找不到应有的答案。遇到这种情况,我就提一个 issue,然后让 agent 去补写缺失的文档。
下面是这套流程实际跑起来的样子。

Foundry
左边窗口里,Bram 跑在它自己的仓库中。它发现 XMLUI 文档里有个缺口,于是在 XMLUI 仓库提了 issue 3847。右边窗口里,Bram 跑在 XMLUI 仓库中,它接下了这个 issue,提议写一篇新的 How To 文档。跑在 XMLUI 仓库里的这个 Bram 实例会研究 issue、动手干活、写好并发布缺失的文档,最后把 issue 关掉。
过程中也可能暴露出 Bram 自身的问题。这时我就让 XMLUI 仓库里的那个 Bram 实例,往 Bram 自己的仓库提一个 issue。8 月 26 日,我记录了一份详细的分镜,展示这种双向协作。在 ~/xmlui 仓库里,我们清掉了一批 XMLUI 文档 issue,同时对 Bram 做压力测试,看它能否管好多个并行子智能体处理各项任务时产生的文件纠缠。与此同时,在 ~/bram 仓库里,我们也在清另一批 issue——它们是在 ~/xmlui 仓库的活动中发现问题后提出来的。两边都在干实事,各自帮对方改进,而协调这一切的,就是两个仓库里的 issue。
含金量十足的一手报告
一位我姑且称为 M 的协作者,在她自己的项目里撞上了一个性能 bug,让 Bram 把它报告到 issue 323。她那边运行的 Claude 读了调用追踪记录,提交了一份证据详尽的报告。

Foundry
问题在于,Bram 需要批量使用 git。M 的仓库文件数量比 Bram 之前遇到的都多,而且她运行的是 Windows,进程创建开销比 macOS 更高。她的报告里还附带了一个有用的小细节:Bram 正把工作清单机制从一组 JSON 文件迁移到内置的 SQLite 数据库。迁移期间,工作清单状态会镜像写入 SQLite,但尚未在那里激活。我几天前加的一条追踪记录——Claude 称之为“分歧绊线”——在两个层面上证明了自己的价值:既独立确认了其他追踪记录也捕获到的一个 bug,也验证了对 SQLite 镜像的有效监控。
近在眼前的代理协作协议
新兴的代理协作协议(如 A2A)规定了代理之间传递的 JSON 数据包格式。我相信这类正式消息机制会扮演关键角色,但与此同时,还有一个被忽视的沟通渠道,它对人类和 AI 同样友好。我并不想特别偏袒 GitHub——你也可以在 GitLab 仓库里使用 Bram。当代理以这种方式对话时,我可以阅读并引导讨论,而且内容会被持久记录,便于搜索和交叉引用。偶尔我会放手让它们自主交流,就像在 issue 278 中那样——我让 Claude 和 Codex 合作重新设计 Bram 的工作清单面板。每个代理都在该 issue 上设置了监视器;它们轮流完善故事板,而我则出去骑自行车了。后来我时不时进去看看,给它们调整方向。
不过大多数时候,Claude 和 Codex 只在 issue 中发言——当我邀请它们发言或回应时。我不是“肉身代理”——那种盲目地把信息从一个代理转给另一个代理的人。我也不是“人在回路中”。我讨厌这个说法,因为它把主动权拱手让给了机器。我更喜欢“代理在回路中”——这是我们的回路,我们邀请代理作为协作者加入。然后我们观察、打断、检查证据、重新排序优先级。
这个过程不如放任智能体完全自主运行那样快、那样顺滑。但这是有意为之。相比一年前,我现在能做的事多得多,速度也快得超出想象。放慢节奏、加入恰到好处的摩擦,能让智能体的工作变得清晰可读,也让我始终掌控全局。你不需要为此另造什么新协议。不起眼的 GitHub issue,只要理解到位、用得得当,就能把智能体纳入我们的协作流程,高效地协调它们。