如何统一管理 Codex、Claude、DeepSeek 等不同的 AI Harness,让切换像换编译器一样简单

最近越来越多团队开始同时使用多个 Coding Agent:

  • Codex 擅长在真实代码库中执行任务
  • Claude 在长上下文理解和方案分析上表现突出
  • DeepSeek 成本友好,适合高频调用或私有化场景
  • 未来还会出现更多模型、CLI、IDE 插件和 Agent Runtime

真正的问题已经不是“哪个最好”,而是:

如何避免工作流被某一个 Harness 锁死?

这里说的 Harness,不只是模型,而是包裹在模型外面的整套执行环境:提示词加载、文件访问、Shell、工具调用、权限控制、上下文管理、任务状态和日志记录。

如果直接分别使用这些工具,你很快会遇到几个问题:

  1. 每套工具有自己的配置格式
  2. 同一条规则需要复制到多个文件
  3. 工具权限和执行行为不一致
  4. 会话状态无法迁移
  5. 切换 Harness 时,需要重新解释整个项目
  6. 团队成员得到的执行结果难以复现

解决办法不是再造一个“万能 Agent”,而是在不同 Harness 上面建立一层统一的控制面。

一、先统一任务,而不是统一模型

不要直接把一句自然语言交给某个 Agent。

先把任务定义成与 Harness 无关的结构:

task: id: fix-payment-timeout goal: 修复支付回调偶发超时 workspace: ./services/payment constraints: - 不修改公开 API - 不新增生产依赖 - 保留现有数据库结构 acceptance: - 相关测试全部通过 - 新增超时场景测试 - 输出变更摘要 permissions: filesystem: write shell: restricted network: deny

Codex、Claude 或基于 DeepSeek 构建的 Agent,拿到的都应该是同一份任务定义。

这样切换 Harness 时,变的是执行者,不是问题本身。

二、建立统一的项目上下文

一个项目最好只有一份“事实来源”,例如:

.agent/
├── project.md
├── architecture.md
├── conventions.md
├── commands.yaml
├── policies.yaml
└── tasks/

这里存放:

  • 项目结构与核心模块
  • 架构约束
  • 编码规范
  • 构建、测试、格式化命令
  • 禁止修改的目录
  • 权限与安全策略
  • 任务验收标准

不同 Harness 所需的专属文件,比如 AGENTS.md、CLAUDE.md 或其他配置,应该尽量由这份统一配置生成,而不是人工分别维护。

原则很简单:

业务知识只写一次,平台配置自动适配。

三、为每个 Harness 编写 Adapter

不同 Harness 的差异应该被封装在适配器里。

适配器主要负责五件事:

  1. 把统一任务转换为对应 Harness 的输入
  2. 注入项目上下文和规则
  3. 映射文件、Shell、搜索等工具
  4. 收集执行事件、日志和最终结果
  5. 将结果转换成统一格式

例如:

harnesses: codex: adapter: adapters/codex model: gpt-5 capabilities: - filesystem - shell - patch claude: adapter: adapters/claude model: claude-sonnet capabilities: - filesystem - shell - long-context deepseek: adapter: adapters/openai-compatible model: deepseek-coder capabilities: - filesystem - patch

然后使用统一入口:

agent run fix-payment-timeout --harness codex
agent run fix-payment-timeout --harness claude
agent run fix-payment-timeout --harness deepseek

甚至可以为不同任务设置默认路由:

routing: architecture: claude implementation: codex batch-refactor: deepseek

关键不是配置文件长什么样,而是上层工作流不需要理解每个供应商的内部细节。

四、统一能力接口,不追求功能完全一致

不同 Harness 的工具能力不可能完全相同。

有的支持结构化补丁,有的只能编辑整个文件;有的可以控制浏览器,有的只能调用 Shell;有的支持子 Agent,有的只支持单会话执行。

因此,不要假装它们完全等价,而应该建立能力注册表:

required: - read_files - write_patch - run_tests optional: - browser - subagents - image_input

运行任务前先检查能力:

  • 满足全部必需能力:直接执行
  • 缺少可选能力:降级执行
  • 缺少必需能力:拒绝运行或自动选择其他 Harness

统一管理的目标不是消灭差异,而是让差异变得显式、可检测、可处理。

五、把权限放在 Harness 之外

不要依赖 Agent 自己判断哪些操作安全。

统一控制层应该明确规定:

  • 哪些目录可读
  • 哪些目录可写
  • 哪些命令允许执行
  • 是否可以访问网络
  • 是否可以读取环境变量
  • 哪些操作必须人工确认
  • 是否允许提交代码或创建 PR

例如:

policy: filesystem: read: - src/** - tests/** write: - src/** - tests/** deny: - .env - secrets/** shell: allow: - npm test - npm run lint confirm: - npm install deny: - git push - rm -rf

无论下面运行的是 Codex、Claude 还是 DeepSeek,都必须经过同一个权限层。

这比在提示词里写一句“请不要执行危险操作”可靠得多。

六、让状态属于任务,而不是属于聊天窗口

很多 Agent 工作流难以切换,是因为重要信息全部藏在会话历史里。

更稳妥的做法是把状态外置:

run: task: fix-payment-timeout status: testing base_commit: a18c9f2 completed: - 定位到回调客户端缺少读取超时 - 增加超时配置 - 添加单元测试 pending: - 运行集成测试 - 检查兼容性 artifacts: patch: runs/1042/change.diff log: runs/1042/events.jsonl

这样 Codex 执行到一半,也可以把任务交给 Claude 继续审查;Claude 给出方案后,也可以让 DeepSeek 批量实现。

交接的对象应该是:

任务状态、代码差异、验证结果和待办事项,而不是一大段聊天记录。

七、统一输出格式,才能真正比较

每个 Harness 最终都应返回相同的结果结构:

{ "status": "completed", "summary": "为支付回调增加读取超时和重试边界", "files_changed": [ "src/payment/client.ts", "tests/payment/client.test.ts" ], "checks": { "unit_tests": "passed", "lint": "passed", "integration_tests": "not_run" }, "risks": [ "生产环境需要配置 PAYMENT_READ_TIMEOUT" ] }

同时记录:

  • 完成率
  • 执行时间
  • Token 与费用
  • 工具调用次数
  • 人工介入次数
  • 测试通过率
  • 回滚率
  • 最终补丁质量

没有统一的结果协议,就无法判断某个 Harness 是真的更好,还是只是“说得更像完成了”。

八、切换 Harness 的正确姿势

真正的“随时切换”不是在同一个聊天框里更换模型,而是:

统一任务定义 ↓ 统一上下文与权限 ↓ Harness Adapter ↓ Codex / Claude / DeepSeek ↓ 统一结果、日志与状态

例如:

# 让 Claude 分析问题
agent run payment-timeout --harness claude --stage plan

# 让 Codex 根据同一份计划实现
agent resume payment-timeout --harness codex --stage implement

# 让 DeepSeek 做低成本的批量测试修复
agent resume payment-timeout --harness deepseek --stage verify

同一个任务可以按阶段选择不同 Harness,也可以在失败后自动切换:

fallback: - codex - claude - deepseek

但自动切换之前,必须保留完整的任务状态和工作区快照,否则下一个 Agent 很可能重复工作,甚至覆盖已有修改。

九、一个可落地的最小方案

一开始不需要建设复杂平台。

只需实现四样东西:

  1. 一份统一的项目说明
  2. 一种结构化任务格式
  3. 一个调用不同 Harness 的 CLI
  4. 一套统一的结果与日志格式

目录可以非常简单:

agent-control/
├── agent.yaml
├── context/
├── tasks/
├── adapters/
│   ├── codex.sh
│   ├── claude.sh
│   └── deepseek.sh
└── runs/

先解决“同一任务可以被不同 Harness 接收和验证”,再逐步加入:

  • 能力发现
  • 权限沙箱
  • 自动路由
  • 失败回退
  • 成本控制
  • 并行执行
  • 多 Agent 协作
  • 质量评测

最后

未来大概率不会由某一个模型或 Harness 统治所有开发场景。

模型会持续变化,价格会变化,能力边界也会变化。今天适合写代码的工具,明天可能更适合做审查;今天最强的闭源模型,未来也可能被更便宜的开源模型替代。

因此,真正值得长期建设的不是对某个 Agent 的依赖,而是自己的:

  • 任务协议
  • 上下文资产
  • 工具接口
  • 权限体系
  • 执行记录
  • 评测标准

把 Harness 当作可替换的执行引擎,而不是工作流本身。

当项目知识、任务状态和安全策略都掌握在自己手里时,从 Codex 切换到 Claude,或从 Claude 切换到 DeepSeek,就不再是一次迁移。

它只是一项配置。