真实项目很少只存在于一台机器上。前端可能在本机运行浏览器,后端需要公司内网,编译任务需要更大的内存,发布验证又要放在一台长期在线的机器上。传统做法是频繁切换窗口、重复 SSH、复制日志,再把上下文手工搬到另一个终端。

当多个 Codex Task 可以被统一查看和调度时,问题就变成了一个路由问题:什么任务应该放在哪个项目、哪个工作树和哪台主机上?什么时候只需要给另一条会话发消息,什么时候必须迁移整个执行位置?本文围绕这些边界展开,不把跨主机协作写成“自动拥有所有权限”,而是把环境、权限和责任分别说明。

一、先把四个执行概念分开

Local:直接使用当前工作树

Local 适合需要复用当前开发环境的工作,例如打开已经运行的 dev server、使用本地浏览器、查看现有未提交改动,或者与人实时协作。它的优点是反馈快,缺点是多个写任务共享同一份目录,互相能看到未提交文件。

同一个 Local 工作树不适合同时承载多个互不知情的写入任务。除非你明确知道它们修改的文件不重叠,并且会在执行前后检查 diff,否则应该使用 Worktree 或串行执行。

Worktree:隔离同一仓库的并行改动

Worktree 是 Git 仓库的独立工作树。它适合多方案竞赛、同一仓库的并行修复和需要独立测试的候选实现。每个候选拥有自己的文件树和分支,结果可以分别查看 diff、运行测试,再决定是否合并。

Worktree 解决的是文件隔离,不解决服务依赖。例如两个 Worktree 仍然可能争用同一个本地端口、数据库或缓存目录。需要额外配置端口和测试数据,不能因为文件隔离就认为运行环境完全隔离。

SSH Host:使用另一台机器的能力

SSH Host 适合本机不具备的环境:内网访问、特定系统依赖、大内存编译器、专用测试设备或持续运行的服务。Task 的 shell、文件和工具环境都在远端,因此派工时必须把工作目录、分支和凭据可用性说明清楚。

SSH 连接本身不等于权限已经具备。Agent 仍然只能使用连接用户能够访问的目录和服务;敏感操作、生产环境和对外发送数据应继续保留显式确认。

Handoff:执行位置迁移,不是责任交接

Handoff 容易被误解为“把任务交给另一个 Agent”。更准确的理解是:同一个 Task、同一段历史和同一个责任主体,执行位置从一个 Host 迁移到另一个 Host。它适合本机无法继续编译、需要切换到内网或需要使用另一套依赖的场景。

如果是“调研 Agent 把结论交给实现 Agent”,这属于语义层的责任交接,需要自己打包目标、已完成项、未完成项、产物和限制,再发送给目标会话。不要把这两种 Handoff 混在一起。

二、按主机能力设计路由表

在多主机环境中,建议先写一张简单路由表。它不必绑定具体机器名,可以先按能力描述:

任务类型 首选环境 原因 交接前检查
UI、浏览器和人工验收 Local 需要现有浏览器和可视化反馈 dev server、端口、当前工作树
内网接口和服务联调 SSH 内网开发机 具备内网访问条件 网络、凭据、服务地址
大型编译和集成测试 高内存或高核数主机 降低资源争用 编译器、缓存、磁盘空间
长时间发布验证 常在线主机 不依赖个人电脑保持开启 任务日志、超时、回滚路径
同仓库多方案实现 Worktree 隔离文件和 Git 状态 分支、端口、测试数据

路由决策应该基于任务前置条件,而不是基于 Agent 名字。例如“前端 Agent”如果只是修改组件代码,不一定要在本机;只有需要打开浏览器、查看视觉结果时才需要 Local。反过来,一个“后端 Agent”如果需要访问内网服务,就必须进入满足网络条件的 Host。

三、跨项目协作时先传递契约

跨项目交付最容易出错的地方不是派工,而是接口理解不一致。后端、前端、SDK、测试和文档各自派一个 Agent,如果每个 Agent 都从自己的角度解释需求,最后往往会得到多份互相矛盾的契约。

更可靠的流程是先让探索者并行收集事实,再由一个架构角色输出唯一契约:

后端探索者:列出现有接口、错误码和兼容约束
前端探索者:列出调用方、状态处理和展示假设
SDK 探索者:列出公共类型、版本和生成代码影响
        -> Architect 汇总为 contract.md
        -> 各项目 Agent 只按 contract.md 实现
        -> 集成任务在统一环境运行跨项目测试

契约文档应该包含版本、字段类型、错误处理、兼容窗口、迁移顺序和验证命令。它不是“建议”,而是下游任务共同读取的输入。如果契约发生变化,应创建新版本或记录变更,不要在多个会话中分别修改同一份解释。

四、一个跨主机联调的完整例子

假设后端 Task 运行在公司开发机上,已经修改了接口;前端 dev server 和浏览器运行在 Local。目标不是把后端 Task 整个搬回来,而是让本机会话执行浏览器验证,再把结果反馈给后端会话。

步骤可以这样设计:

  1. 后端 Task 产出接口变更摘要、启动方式和测试前置条件;
  2. 后端 Task 找到负责本地 UI 验证的 Task;
  3. 通过 Codex App 的跨会话消息能力发送结构化联调请求;
  4. 本地 Task 检查 dev server、接口地址和浏览器状态;
  5. 本地 Task 执行验证,记录浏览器现象、网络请求和控制台错误;
  6. 将结果回传,并注明成功路径和未覆盖的情况;
  7. 后端 Task 根据失败证据定点修复,不重复让本地 Agent猜原因。

消息不应只写“帮我测一下”。建议包含:

目标:验证登录过期后前端是否正确跳转到登录页。
前置条件:后端接口 /api/session 已部署到测试地址,测试账号为预先配置的非生产账号。
步骤:登录、等待会话过期或使用测试开关、刷新页面、观察跳转和网络请求。
输出:页面结果、请求状态、控制台错误、截图或日志路径、未覆盖项。
禁止:不要修改前端代码,不要使用生产账号,不要清理共享数据库。

这条链路只传递工作,不传递不必要的权限。需要浏览器的 Task 使用 Local,需要内网的 Task 留在 SSH Host;只有执行环境本身必须变化时才使用位置 Handoff。

五、跨仓库迁移的路由顺序

修改一个被多个仓库消费的 API 时,推荐采用“先扫、再定、后改”的顺序。

第一步:并行扫描生产者和消费者

不同仓库的 Explorer 只读分析真实调用路径、版本约束和测试入口,输出统一格式。每份结果都要标明仓库、分支、文件位置和证据日期,避免把旧分支上的结果当成当前事实。

第二步:生成一份契约产物

Architect 读取所有扫描结果,解决冲突,输出唯一的迁移契约。它需要明确哪些消费者必须同步升级,哪些可以通过兼容层过渡,哪些变更需要人工确认。

第三步:按仓库和 Worktree 并行实现

每个仓库使用自己的工作树和分支。仓库内部再由 Worker 实现、Reviewer 检查,避免多个 Agent 直接写同一目录。所有实现都引用同一版本的契约产物。

第四步:统一集成验证

集成测试应放在具备完整依赖的主机上运行。单仓库测试全绿不代表跨仓库契约正确,因此要增加版本组合、错误路径和回滚路径的验证。

第五步:发布任务接收结构化结果

发布 Task 只接收已完成的仓库列表、构建产物、测试摘要、迁移顺序和回滚条件。它不应该在发布阶段才重新阅读每个仓库的全部上下文。

六、位置迁移前后的检查清单

迁移前

迁移后

迁移后的第一步不应是直接跑完整构建,而是执行低成本的环境检查。先确认路径、分支、运行时和最小命令,再进入耗时任务,可以避免在错误主机上浪费一小时。

七、安全边界不能由编排自动推断

多主机协作会扩大可见范围,因此要把权限和数据边界写进任务描述。至少注意以下问题:

主机路由解决的是“在哪里执行”,不是“可以做什么”。权限、审批和数据分类仍需要单独设计。

八、如何验证路由是否带来收益

可以选一条跨项目任务做对比,不要只看 Agent 是否成功返回。记录以下指标:

上下文搬运次数:是否还需要手工复制日志和说明
环境切换次数:是否把任务放到了正确的主机
等待时间:任务是否被不必要的串行步骤拖慢
失败定位时间:能否从证据直接定位到项目或节点
重复执行次数:是否在错误环境中反复重跑
权限异常:是否出现跨主机访问不该访问的资源

如果跨主机编排让消息更多、环境检查更复杂,却没有减少上下文丢失和重复执行,就说明路由粒度太细。优先合并相邻步骤,只有在环境能力确实不同的时候才增加一个新 Host 或新 Task。

结语

跨项目跨主机协作的关键,是把 Project、Host、Worktree 和 Task 的职责分开:Project定义工作域,Host提供执行能力,Worktree隔离并行改动,Task保存持续上下文。Handoff只处理执行位置迁移,责任交接则需要用结构化产物完成。

先建立一张按能力划分的路由表,再用一个真实联调任务验证。只要每次交接都带着目标、前置条件、证据要求和禁止事项,多个环境就不会只是更多窗口,而会变成可以统一观察和调度的执行节点。