资讯动态

Codex调度Claude Code:Termexo MCP多Agent协作实践

发布时间:2026/10/14 6:47:10 来源:尧图企业网站定制
最近在搞 Agent 协同工作流遇到一个很有意思的用法让 Codex 给 Claude Code 发任务中间通过 Termexo MCP 做调度。一开始我也觉得绕后来发现这个组合解决了一个非常实际的问题——单个 Agent 再强也没法在一个上下文里同时完成代码编写、仓库审查、测试执行和文档更新。你可以在 Codex 会话里直接发起一个跨 Agent 任务让 Claude Code 去跑仓库分析再让另一个 Agent 去更新文档。这篇文章就围绕这个场景拆解MCP 链路怎么搭、Termexo 怎么同时挂载 5 种 Agent、Codex 怎么把任务发下去以及我在实际配置中踩过的坑。适合已经玩过 Codex 或 Claude Code、想把它们串成自动化流水线的人。1. 为什么需要 Agent 之间互相派活1.1 单 Agent 的边界在哪里先别急着聊 MCP 配置想清楚为什么要让一个 Agent 给另一个 Agent 发任务。Codex 在代码生成这件事上很强你给它一个清晰的任务描述它能在你指定的文件里产出结构完整的代码。Claude Code 在理解存量代码、做审查、梳理调用关系方面又很有一套。问题是当你面对一个真实项目时需求往往是复合的你要写一个新模块同时要保证它和现有模块兼容还要跑通测试、更新文档、提交变更说明。单靠一个 Agent 来完成所有环节很快你就会碰到三个麻烦。第一个麻烦是上下文窗口不够用。Agent 的上下文是有限的你让它分析整个仓库的同时还要写代码它会把大量 token 花在无关文件上写出来的东西反而容易偏离方向。第二个麻烦是工具集不匹配。有的 Agent 擅长读写文件有的 Agent 擅长执行命令有的 Agent 适合做网页操作没有任何一个 Agent 能天然覆盖所有工具。第三个麻烦是任务不可恢复。单 Agent 执行一个多步骤长任务中间任何一步出错经常只能从头开始日志还不一定完整。把这些任务拆给不同的 Agent反而清晰。所以我开始尝试一种新的组织方式让一个 Agent 当调度中心其他 Agent 当执行单元。Codex 负责理解你的总体意图然后通过 MCP 调用一个调度服务由这个服务把具体任务派给 Claude Code 以及其他 Agent。这个调度服务就是 Termexo MCP。听起来有点绕但它把“人肉复制粘贴结果”变成了“标准协议自动传递结果”整个流程可记录、可重试、可审计。1.2 从人肉搬运到 MCP 调度以前没有 MCP 这套东西的时候想让两个 Agent 协作最常见的做法就是人肉搬运。我打开 Codex让它生成一段代码然后把代码复制到另一个终端让 Claude Code 去 review再手动把 review 结论贴回给 Codex。这条链路最大的问题不是慢而是丢失上下文。Codex 看不到 review 结论里的具体行号Claude Code 也看不到 Codex 当初的设计约束。你只能靠复制粘贴来传递复制过程中还会因为格式问题丢掉缩进、特殊字符甚至关键注释。MCP 出现之后这个局面就变了。MCP 的全称是 Model Context Protocol说白了就是把“模型需要使用外部工具”这件事标准化。客户端这边Codex 只需要知道有哪些工具可用工具长什么样子参数是什么。服务器这边Termexo 把真实能力封装成一个个工具比如dispatch_task、list_agents、get_task_result。Codex 发起一个工具调用MCP 服务器收到后执行再把结果返回给 Codex。整个过程对 Codex 来说就是“调用了一个函数”。MCP 不是某个平台的私有限定协议它更像一个通用接口标准。拿生活里的例子类比以前每个设备都有自己的充电线现在一个 Type-C 口能接多种设备。Termexo 在这里就是那个多口扩展坞。你不需要让 Codex 去理解 Claude Code 的启动参数、配置文件、API 鉴权方式它只需要知道dispatch_task这个工具以及target_agent这个参数。剩下的协议转换全部交给 Termexo。1.3 Termexo MCP 到底承担什么角色Termexo 本身不是一个模型它不负责生成代码也不负责理解业务。它是一个多 Agent 网关一个 MCP 服务器。它的核心工作有三块接收 Codex 发来的工具调用请求解析目标 Agent 和任务参数然后通过对应的适配器去调用下游 Agent。下游 Agent 跑完以后Termexo 再把结果清洗、截断、包装成标准格式返回给 Codex。我理解 Termexo 最值得称道的一点是它把“异构”变成了“同构”。五个不同的 Agent接入方式可以完全不同。Claude Code 走命令行某个文档 Agent 走 HTTP 接口某个浏览器自动化 Agent 走 WebSocket某个脚本执行器只需要本地 shell。如果没有 Termexo你要分别写五个对接逻辑而且每个对接逻辑都要暴露给 Codex。有了 Termexo所有 Agent 在 Codex 眼里只是同一套 MCP 工具名区别只在于参数里的target_agent值不同。但这不代表 Termexo 是银弹。它解决的只是调度和协议转换真正的智能还是来自两端的模型。Codex 还是要理解用户意图决定要不要派活、派给谁。Claude Code 还是要真正读懂代码、给出高质量的审查结论。Termexo 能保证的是任务被准确送达结果被完整回收。这个定位听起来不华丽但在实际工作流里非常关键。2. 环境准备与工具选型2.1 基础环境清单在开始配置之前先把基础环境准备好。我本地跑这套链路时用到的环境大致如下你可以按需裁剪。Node.js 18 以上是必须的Termexo 这类 MCP Server 大多数通过 npx 启动实际上也就是 Node 生态。Python 3.10 以上建议也装好后面写自定义适配器或者做数据处理时会用到。Codex 和 Claude Code 这两个命令行入口必须先各自跑通确保它们能在终端里正常输出。还有个很容易被忽略的点环境变量。Codex 和 Claude Code 通常各自需要 API Key 或者身份认证信息。不要把 Key 写死在配置文件里而是放到环境变量让子进程继承。Termexo 在启动的时候会读取当前 shell 的环境变量然后把这些变量传给下游 Agent 的子进程。你要是用 Docker 方式跑 Termexo就得额外注意把容器内的环境变量映射对不然下游 Agent 会一直报鉴权失败。Git 也建议准备好因为后面不管是克隆 Termexo 源码还是让下游 Agent 做 CI 类型的自动提交都会用到。Docker 属于可选如果你不想在宿主机上装太多运行时可以把 Termexo 打进容器但标准stdio传输模式下容器和宿主机之间的进程通信会稍微麻烦一点我自己的习惯是优先用本地进程跑 Termexo减少一层转发。2.2 安装与初始化 TermexoTermexo 的安装方式不同版本会有差异常见的有两种。第一种是直接用 npm 全局安装或者 npx 临时运行命令大致是npx -y termexo-mcplatest --init。--init这个参数会生成一个初始配置文件里面预置了几个 Agent 模板方便你快速改。第二种是我更常用的方式把仓库 clone 到本地然后手动构建。这种方式的好处是改适配器代码的时候可以立刻看到效果不用每次发版都等 npm 包更新。初始化之后会得到一个termexo.yml配置文件和/adapters目录。配置文件用来声明有哪些 Agent、怎么连接、超时多久、并发多少。适配器目录放的是每种 Agent 的对接实现。这里我给你一个最基本的目录结构参考termexo/ ├── config/ │ └── termexo.yml ├── adapters/ │ ├── cli_adapter.py │ ├── http_adapter.py │ └── ws_adapter.py ├── tools/ │ ├── dispatch_task.py │ ├── list_agents.py │ └── get_task_result.py └── main.py安装完先别急着配 Codex我们先在终端里直接启动 Termexo确认它能正常跑起来。一个很简单的验证方法是用 MCP Inspector 这类调试工具连接stdio传输的服务器。连接成功之后你会看到服务器暴露了哪些工具以及每个工具的参数 schema。如果这一步通了后面接 Codex 就只是配置问题而不是代码问题。2.3 在 Codex 中挂载 Termexo MCPCodex 作为 MCP 客户端需要在它的配置文件里声明要加载哪些 MCP Server。不同的 Codex 版本配置位置不一样但核心结构类似都是mcpServers字段。我这边用了一段时间之后总结出一份比较稳妥的配置{ mcpServers: { termexo: { command: npx, args: [ -y, termexo-mcp, --config, /absolute/path/to/termexo/config/termexo.yml ], env: { LOG_LEVEL: info } } } }这里有一个特别值得注意的地方--config后面的路径必须是绝对路径。MCP Server 在stdio传输模式下启动时当前工作目录可能和 Codex 的运行目录不一致如果你写相对路径Termexo 大概率找不到配置文件然后静默退出。Codex 那边看到的症状就是“MCP 工具加载失败”或者“工具列表为空”排查起来很隐蔽。配置好之后需要完全重启 Codex 会话让客户端重新连接 MCP Server。重启完成后你可以在会话里问 Codex“你能看到哪些 MCP 工具”正常情况下Codex 会回答出termexo_dispatch_task这类工具名。如果它说看不到任何工具优先检查 Codex 的日志和 Termexo 的输出看看握手阶段是不是有报错。3. 核心配置让 Codex 给 Claude Code 发任务3.1 最小任务链从 list_agents 到 dispatch_task第一次跑通最小链路的时候不需要搞太复杂的任务。我会先让 Termexo 暴露一个list_agents工具用来枚举当前配置了哪些下游 Agent。这个工具非常适合验证 MCP 链路是否正常因为它不涉及真正的业务逻辑。在 Codex 会话里输入“请调用 termexo.list_agents 看一下当前可用 Agent。”然后观察 Codex 的反应。如果链路正常它会调用工具然后返回类似下面的结果当前有 5 个 Agent包括 claude-code、codex-skill、shell-runner、doc-writer、browser-helper。这说明 Codex 已经成功通过 MCP 连上了 Termexo并且 Termexo 成功读取了配置。接下来试真正的任务派发。对 Codex 说“调用 termexo.dispatch_task让 claude-code 检查 src/core 目录下的代码结构输出包含主要函数名的列表。”Codex 会生成一个工具调用把target_agent设置为claude-code把action设置为某个你定义好的动作名比如inspect_repo。Termexo 收到请求后会去找 claude-code 的适配器然后通过 CLI 启动 Claude Code执行仓库分析。整个过程大约几十秒到几分钟取决于仓库大小。最终 Termexo 会把 Claude Code 的结论返回给 CodexCodex 再用自己的语言组织给你看。这个最小任务链的好处是你只需要确认三个节点都通了后面再扩展其他 Agent 就是加配置的事。第一个节点是 Codex 到 Termexo 的 MCP 连接第二个节点是 Termexo 到 Claude Code 的 CLI 调用第三个节点是结果回收和返回。任何一个节点出问题都能通过日志快速定位。3.2 五类 Agent 接入方式和分工标题里提到“操控 5 种 Agent”这 5 种并不是固定死的而是我按照实际需求拼出来的一套组合。每种 Agent 的接入方式不同Termexo 通过适配器屏蔽差异。我直接给一张表方便你看清楚各自的位置标识接入方式典型职责配置要点claude-codeCLI 子进程代码审查、仓库结构分析、重构建议开启 JSON 输出关闭颜色codex-skillCLI/SDK局部代码生成、补全、解释代码片段限制工作目录防止越权改写shell-runner本地 shell跑测试、Git 操作、执行脚本白名单命令禁止危险操作doc-writerHTTP 接口更新 README、生成 CHANGELOG指向内部文档服务做好格式约束browser-helperWebSocket网页信息抓取、UI 自动化验证Headless 模式强制超时断开这几种 Agent 的接入方式可以看成三个类型。CLI 类型最直接Termexo 用create_subprocess_exec启动子进程传参数读 stdout。HTTP 类型适合那些已经在跑的服务Termexo 只需要把任务 POST 到某个 URL。WebSocket 类型适合需要持续交互的 Agent比如浏览器自动化Termexo 维护一个长连接发送任务并等待事件消息。我建议你把 codex-skill 这个 Agent 设置为默认不启用或者至少在权限上严格限制。因为 Codex 已经在上层了如果 Termexo 还能下发任务给另一个 Codex 实例很容易出现循环调用。让一个 Codex 给另一个 Codex 发任务听起来很酷实际跑起来大概率是死循环加 token 快速耗尽。所以 5 种 Agent 的配置本身要给足但权限边界也要画清楚。3.3 任务参数与模板设计Termexo 暴露给 Codex 的dispatch_task工具参数设计非常关键。这里是我整理出来的核心参数表参数必填说明target_agent是目标 Agent 标识比如 claude-codeaction是要执行的动作名比如 inspect_repopayload是动作所需的参数对象比如路径、关键词timeout_ms否单次任务超时默认 180000priority否low / normal / high默认 normalidempotency_key否幂等键防止任务重复执行callback_url否异步任务完成后回调的地址重点说一下 payload 的设计。很多人第一次写的时候喜欢直接把一大段自然语言 prompt 传给下游 Agent这不是不行但会让上层调度很难做权限控制。更好的做法是把任务结构化。比如你希望 Claude Code 检查某个目录就传{path: src/core, focus: dependencies}而不是传一大段话。Termexo 的适配器再根据action把结构化参数拼成下游 Agent 能理解的提示词。这样改动提示词模板的时候不需要改 Codex 侧逻辑也方便审计。idempotency_key可能是最容易被忽略但又最重要的参数。MCP 调用如果超时Codex 有时候会重试同一个工具调用。如果没有幂等键下游 Agent 可能把同一个任务执行两遍。比如自动提交 Git commit 的任务重复执行两次就会产生两条一模一样的提交记录。有了幂等键Termexo 可以先查一下这个任务是否已经执行过执行过就直接返回上次的结果。4. 实操过程与核心环节实现4.1 一次完整任务流转实录拿一个我实际跑过的例子来走一遍。我有一个仓库src/core目录下函数依赖关系有点乱我想让 Claude Code 先分析再决定要不要重构。用户对 Codex 说的话很简单“调用 termexo.dispatch_task让 claude-code 检查 src/core 目录里所有函数的调用关系输出 JSON 数组字段包括函数名、被谁调用、是否导出。”Codex 收到这个指令后会决定调用 MCP 工具。它向 Termexo 发送一个 JSON-RPC 请求方法名是tools/call结构类似下面这样{ jsonrpc: 2.0, id: 17, method: tools/call, params: { name: termexo_dispatch_task, arguments: { target_agent: claude-code, action: inspect_repo, payload: { path: src/core, focus: call_graph }, timeout_ms: 180000, idempotency_key: task-20250101-001 } } }Termexo 拿到这个请求后先做参数校验再查配置。它看到target_agent是claude-code于是去找 claude-code 适配器。适配器把action和payload拼成一个 Claude Code 能懂的提示词然后启动子进程命令大概等价于claude -p 分析 src/core 目录下的函数调用关系以 JSON 数组输出... --output-format jsonClaude Code 跑完之后会产生一个 JSON 结果可能还夹杂着一些日志信息。Termexo 的适配器要做的第一件事就是清理这些噪音只保留真正的结果。清理之后的 JSON 通过 MCP 的tools/call响应返回给 Codex。Codex 拿到结果后再把它整理成一句人话“分析完成一共发现 32 个函数其中 5 个函数存在循环依赖。” 到这一步整个任务流转就闭环了。这个流程最关键的一点是 Termexo 对结果的标准化处理。如果结果没有清洗直接返回原始 stdoutCodex 可能会被日志干扰甚至完全无法解析。所以适配器里最值得花时间的不是怎么把任务发出去而是怎么把结果洗干净。4.2 适配器配置与自定义 Agent 接入Termexo 的配置文件是把所有 Agent 组装在一起的枢纽。我贴一个简化版的termexo.yml你可以在这个基础上改server: name: termexo transport: stdio agents: claude-code: type: cli command: claude args: [-p, --output-format, json] env: NO_COLOR: 1 timeout_ms: 240000 shell-runner: type: cli command: bash args: [-lc] allowed_prefixes: - pytest - git status - git log timeout_ms: 60000 doc-writer: type: http url: http://127.0.0.1:8790/doc-writer timeout_ms: 120000配置本身不复杂复杂的是适配器。每种type对应一个适配器类。比如cli类型它的实现核心就是创建子进程、等待退出、读取输出。下面这段是我经常改的 Python 适配器骨架算是伪代码你理解原理即可class CliAdapter: def __init__(self, cfg): self.cfg cfg async def run(self, action, payload): prompt build_prompt(action, payload) cmd [self.cfg[command]] self.cfg.get(args, []) env {**os.environ, **self.cfg.get(env, {})} proc await asyncio.create_subprocess_exec( *cmd, prompt, stdoutasyncio.subprocess.PIPE, stderrasyncio.subprocess.PIPE, envenv ) try: out, err await asyncio.wait_for( proc.communicate(), timeoutself.cfg.get(timeout_ms, 180000) / 1000 ) except asyncio.TimeoutError: proc.kill() raise TimeoutError(f{self.cfg[command]} timeout) return parse_output(out, err, proc.returncode)如果你想接入一个新的 Agent不用改 Codex也不用改 MCP 层的代码。你只需要写一个新的适配器类然后在termexo.yml里加一段配置。比如你有一个内部服务只能通过 HTTP 访问那你就写一个HttpAdapter把action和payload转成 HTTP 请求再把响应转成统一格式。这是 Termexo 这类设计最舒服的地方新增 Agent 的成本被降到最低。4.3 结果回收、超时和重试策略任务发出去之后怎么定义“成功”是一个需要细想的问题。我通常定义三个条件同时满足才算成功子进程退出码为 0stdout 能被解析解析出来的结果里没有明确的错误字段。Claude Code 有时候进程退出码是 0但输出里写着“无法完成分析”这种情况不能算成功。Termexo 内部会有一个validate_result的环节对不同 Agent 配置不同的校验器。超时策略我建议按 Agent 类型分开设置。代码分析类任务相对较重240 秒不算过分。跑测试类任务取决于测试体量我一般 60 到 120 秒。浏览器类任务最容易卡住我反而会把超时压到 90 秒以内因为页面加载失败重试比一直等可靠。超时之后不是简单重试就完事必须先杀掉整个子进程组否则会有残留进程占着资源下一轮任务可能受影响。重试策略也要考虑幂等性。Termexo 里我习惯配置execution: max_concurrency: 2 retry_limit: 2 retry_backoff_seconds: 5 result_max_chars: 8000max_concurrency设为 2 是因为多个下游 Agent 同时操作同一个工作目录时很容易出现文件锁或者相互覆盖的问题。retry_limit设为 2 表示最多重试两次超过就不再重试避免雪崩。result_max_chars尤其重要它防止下游 Agent 返回几万行输出把你上层 Codex 的上下文塞爆。如果结果超长Termexo 会把完整结果存到临时文件只把摘要和一个读取路径返回给 Codex。5. 常见问题与排查技巧实录5.1 握手失败和 Agent 列表为空我刚开始接入 Termexo 的时候踩过的第一个坑就是 Codex 里看不到任何 termexo 工具。后来排查发现是配置文件路径用了相对路径。Codex 启动 MCP Server 时工作目录不是你配置文件的目录Termexo 启动后找不到termexo.yml直接退出。这个问题的表现很隐蔽Codex 界面不会报明显错误只说工具加载失败。遇到 MCP 工具列表为空我建议按下面的顺序排查症状可能原因处理方式Codex 中看不到 termexo 工具配置文件路径错误改为绝对路径重启 Codexlist_agents 返回空列表YAML 缩进错误或 agents 段为空检查配置文件格式直接看 YAML 日志Termexo 启动后立即退出npx 拉包失败或 Node 版本过低升级 Node手动 npx 测试下游 Agent 连接失败CLI 不在 PATH 中在 Termexo 启动环境中配置 PATH还有一个很高效的排查工具就是 MCP Inspector。它不需要启动 Codex直接把 Termexo 作为子进程连进去你能看到完整的 JSON-RPC 日志。握手阶段如果出错它会告诉你initialize请求是否成功工具列表是否返回。这一层确认没问题再回到 Codex 里查能省很多时间。5.2 输出解析失败和上下文污染Comparable 常见的问题是下游 Agent 的输出混杂了日志、ANSI 颜色码、警告信息导致 Termexo 解析 JSON 失败。Claude Code 在非交互模式跑任务时即使指定了 JSON 输出也可能在 stdout 里带一些非 JSON 前缀。我第一次跑的时候解析出来的 JSON 总是报错后来把原始输出打出来才发现前面多了一行类似[request started]的日志。解决方案分三层。第一层环境变量加NO_COLOR1去掉颜色控制符。第二层在适配器里做内容清洗只从 stdout 中提取合法的 JSON 部分。第三层在 Termexo 配置里增加结果过滤器按 Agent 定义不同的提取规则。下面这段是常用的清洗逻辑供参考import json, re def extract_json(text): start text.find({) end text.rfind(}) 1 if start 0 or end start: return None try: return json.loads(text[start:end]) except json.JSONDecodeError: return None这个逻辑不完美但对于大多数以 JSON 为输出的 Agent 足够用。如果下游 Agent 的模型会把 JSON 解释性地描述在你的框架里建议修改提示词要求只输出 JSON不要任何 Markdown 代码块标记。上下文污染还有个常见来源是result_max_chars设置过大。Codex 的上下文是它的命根子返回字段尽量保持精简完整结果可以考虑持久化后让用户按需读取。5.3 循环调用、权限失控和资源耗尽当多个 Agent 互相都能通过 MCP 访问 Termexo 时最危险的就是循环调用。Codex 给 Claude Code 发任务Claude Code 在任务过程中如果也能调用同一套 Termexo 工具它可能又反过来给 Codex 发任务。这种循环一旦跑起来很难靠人工打断两个模型会在上下文里反复传递中间结果token 消耗速度非常恐怖。Termexo 的配置里需要显式加安全限制。我建议开启allow_loop: false并且在每个 Agent 的工具可见范围上做限制。比如 claude-code 只能使用inspect_repo、run_tests、write_doc这三个动作不允许它去调用dispatch_task。最好在服务端做强制校验不能只靠模型自觉。权限失控是另一个需要注意的点。Termexo 一旦暴露了shell-runnerCodex 理论上是可以通过这个 Agent 执行任意 shell 命令的。如果我不在白名单里限制就等于把本机 shell 权限交给了模型。我的做法是shell-runner只允许预先定义好的命令前缀比如pytest、git status、git log其他命令一律拒绝。还要警惕的是 API 额度Claude Code 跑一个长任务可能消耗不少 token如果并发 5 个任务同时跑可能很快触达限额。给每个 Agent 设置max_turns或max_tokens上限能显著降低预算风险。6. 几条实操心得6.1 我踩过的坑第一个坑是 ANSI 颜色码。最初让 Claude Code 输出 JSON 时结果里经常混入\x1b[0m之类的颜色控制符。单独看文本没感觉放到 JSON 解析器里就是致命错误。后来我只要跑 CLI 类型 Agent就在环境变量里加NO_COLOR1问题基本绝迹。第二个坑是环境变量隔离。Termexo 通过 Codex 启动时它继承的是 Codex 进程的环境而不是你自己 shell 里的完整环境。我在本机明明配置好了 API KeyTermexo 就是读不到。后来我把 Termexo 的启动脚本改成先在脚本里source一份.env再启动 MCP Server问题解决。你要是有类似问题先看一眼 Termexo 的日志确认它有没有把关键环境变量传给下游。第三个坑是任务颗粒度。一开始我让 Claude Code 一次性分析整个仓库结果跑了很久之后超时。后来我把任务拆成按目录分发几个目录并行跑每次都只返回精简的分析结论整体耗时反而更短。这个经验对做 Agent 调度的人应该都有参考价值任务越具体模型越容易做好超时风险也越低。6.2 后面还能怎么扩展这套链路的扩展空间很大。你可以给 Termexo 加一个 SQLite 存储把每次任务请求、结果、耗时都记下来这样后续可以做任务复盘和成本分析。也可以接入异步回调机制dispatch_task返回一个任务 ID真正执行完成后通过callback_url通知上层这样就不会因为长任务阻塞 Codex 的会话。定时调度、人工审批流、失败告警都是比较自然的方向。最后再分享一个小技巧在 Termexo 里加一个dry_run工具。它的作用是让 Codex 在真正派发任务之前先预览一下将要发送给下游 Agent 的原始提示词。这个工具对调试提示词非常有帮助很多时候你以为 Codex 已经正确传达了意图实际看一眼dry_run就会发现参数被拼得乱七八糟。我自己在配置好这套链路之后每次都先跑一次dry_run再执行真实任务踩坑概率减少了一大半。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑