# Dual Model Answer

> 由 Claude Code 调度本地 Codex CLI，完成用户要求的两模型同题独立作答、互审与双稿交付。需要可用的独立 Agent 和 Codex 认证；既有文档互审用 cross-review。

- Skill: `horacelubfa/dual-model-answer` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add horacelubfa/dual-model-answer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/horacelubfa/dual-model-answer/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: HoraceLuBFA (https://skillmd.com/u/horacelubfa)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/horacelubfa/dual-model-answer

---


# 双模型同题对拍（dual-model-answer）

把「同一个问题分别丢给 Claude 和 Codex、人肉搬运互相挑错、自己合并版本」收进一条命令。优化目标是答案的事实置信度与可追溯，不是让两个模型达成一致——分歧靠证据裁决，一致也不等于正确。

与手工做法的关键差别：**审阅意见真的送达对方**。手工时代你是人肉集成层，两个窗口都看，对方挑出的错你替它转达了；自动化之后这个人不在了，通道会断。文末「已知坑」记着实测后果。因此两条通道同时开——对方的审阅意见修我方的短，对方的答案原文补我方的长，少任何一条都是残的。

## Harness 与模型身份

文中的 Claude 与 Codex 是调度、文件命名及 transport 的角色标签，不保证分别使用 Anthropic 与 OpenAI 原厂模型。开局依据可见配置、认证方式与调用元数据记录两侧实际 Harness、Provider、发送模型及已知后端；模型自报身份不构成证据。不能确认最终权重时明确标记，不猜测。已有的 Cl/Cx finding 编号与文件名保留，避免破坏恢复和解析协议。

本流程的 Claude Code 调度端须具备独立 Agent 与 Bash，Codex 端须能真实执行调用。其他 Harness 收到该请求时先检查可用 transport；没有等价入口则准备最小交接包并说明需在 Claude Code 续接，不能在同一会话伪装双方完成。同后端跨 Harness 检查只能标为同模型审阅；用户明确要求不同模型时，该要求仍是验收项。

## 适用 / 不适用

任何想要高置信、经对抗核查答案的 Prompt 都适用：问题分析、文章、代码解读、技术选型、调研结论。不适用的三种情形与各自的替代技能见 description。

前置两条，分工不同：

- **调度方只能是 Claude Code。** 流程依赖 `Agent`（派发独立 subagent）与 `Bash`（后台起 `codex exec`）两项能力，`scripts/dma-lib.sh` 也只封装了 Codex 一侧的运输通道，Claude 一侧没有等价的 CLI 调用。其他宿主可以发现该入口并准备交接材料，但不能据此声称已有完整调度能力。
- **Codex CLI 是被调用的第二模型，不需要安装本 skill**，只要本地可用并已认证：`codex --version` 验安装，`codex login status` 验认证方式（该结果同时决定计费口径，开局播报要照它说）。不可用就如实报告并停，**绝不用单模型伪装双答**。

## 配套文件

| 文件 | 内容 | 何时用 |
|---|---|---|
| `references/templates.md` | frontmatter 字段、五种文档骨架、成稿规范块、四个 prompt 模板 | 每次拼 prompt、每次写盘前 |
| `scripts/dma-lib.sh` | 正文提取、diff、codex 调用、subagent 回收验收、冒烟核验、写盘、结构校验、留痕配额 | 开工时 source 一次 |

```bash
source ~/.agents/skills/dual-model-answer/scripts/dma-lib.sh
```

这些函数封装的都是抄错了不报错、只会悄悄给出坏结果的操作——三层嵌套的正文提取、需核对真实退出码和新产物的 codex 调用、日志会缺尾的联网核验。一律调用，不要复制片段自己拼。

规则文本按执行者归属：调度员要用的（处置词表、finding 编号、文档分区）写在本文件；只有 agent 要遵守的（成稿四条、核查着力点、修订四规则）住在 templates.md 的 prompt 模板里，那是唯一权威副本，改规则改那里。

## 输入参数

| 参数 | 默认 | 说明 |
|---|---|---|
| Prompt | 必填 | 任意任务 |
| 轮数 N（互审轮） | 2 | 终版为 v(N+1)，默认 v3；终审恒在最后 |
| 输出目录 | 当前工作目录下新建 `dual-model-answer/` | 用户可指定父目录 |
| 事项名 | 从 Prompt 概括 2~8 字，跟随 Prompt 语言 | 用户可指定 |
| Codex 模型 / effort | 跟随 `~/.codex/config.toml` | 用户点名时传 `-m <模型>` / `-c model_reasoning_effort=<级别>` |
| Claude 侧 subagent 模型 | 跟随会话模型 | 用户点名时给 `Agent` 工具传 `model`（`opus` / `sonnet` / `haiku` / `fable`）。它优先于 agent 定义的 frontmatter，且**与调度员自己的模型无关**——调度员跑低配、subagent 跑高配是支持的组合，见下节末段 |
| 成稿档位 | 依 Prompt 性质自动判定 | 研究档（信息查阅/综述/调研/事实密集型）强制引证与 GB/T 7714 参考文献；通用档（代码解读、方案权衡、创作类）不强制编号引证，但事实性断言仍须给可核查依据。判不准就按研究档，并在开局播报里说明 |

## 对等架构

主会话只当调度员：控步骤、发起调用、跑 diff、统一写盘、生成 frontmatter、与用户交互。**自己不作答、不审阅、不润色任何一方内容。**

每一步双方各派一个全新 agent——Claude 侧派新 subagent，Codex 侧开新 `codex exec` 会话。不用持久会话：`codex exec resume` 虽然可用，但 gpt-5.6-sol 的窗口是 258,400 token，超出后自动压缩是静默有损的（`replacement_history` 直接把历史换成摘要），而被换掉的正好是本 skill 唯一在乎的那层细节——某条引证的核对结果、某个页码的原文、某条被驳回意见的证据链。持久会话还会引入隐藏状态，中断即失。

持久会话唯一真正独有的资产是作者意图，它被外置成文档：每版答案尾部的取舍备忘，记着为什么选这条引证、放弃了哪些候选、哪些限定语是刻意的。写下来的意图可审计、可传递、不吃压缩。

全部状态存于文件，中断后看缺哪一对文件即知走到哪步。同一步内双方并行：Codex 后台跑，同时派 Claude subagent，两边都回收后再进下一步。

**两侧回收对称，一律走文件。** Codex 侧靠 `dma_codex` 的 `-o`；Claude 侧在 prompt 末尾附 templates.md 第 5 节的收尾指令，让 subagent 自己把正文 Write 到 scratchpad 的约定路径，回来跑 `dma_collect` 验收。不要从 subagent 的最终回复里提正文——那要经 transcript 提取，杂质形态每次不同（HTML 转义、对话性开场白、尾部残留围栏），混进交付文档不报错，只会让 `dma_body` 提不出正文、`dma_diff` 整份判为改动。走文件还有第二个好处：正文不再经通知灌进调度员上下文，调度员只看见字节数，这是调度员侧最大的一笔可省开销。

**调度员可以跑低配模型，subagent 跑高配。** 调度员的活本就是机械的——拼 prompt、发起调用、跑 diff、生成 frontmatter、机械抽取共识表。前提是别把判断留在调度员身上：正文回收已由 `dma_collect` 兜住，异常处置照「异常处理」表走，剩下唯一需要判断的是 `07 共识与分歧.md` 里跨轮次的状态演化（某条先保留分歧、后被提出方自行撤回改判采纳，或驳回后被对方终审确认成立）——这一步拿不准就照实列两行并注明演化过程，不要合并成一个结论。

## 文件与命名

输出目录 `<父目录>/dual-model-answer/`，内部平铺，文件名带执行步号，`ls` 的字典序即流程顺序。

```
dual-model-answer/
  00 index.md              链路总览 + 状态（中断恢复看它）
  01 Claude answer v1.md   01 Codex answer v1.md
  02 Claude review-1.md    02 Codex review-1.md
  03 Claude answer v2.md   03 Codex answer v2.md
  04 Claude review-2.md    04 Codex review-2.md
  05 Claude answer v3.md   05 Codex answer v3.md      ← 交付
  06 Claude 终审意见.md     06 Codex 终审意见.md        ← 附件
  07 共识与分歧.md                                     ← 附件
```

步号公式：`answer v(k)` = `2k-1`；`review-k` = `2k`；终审 = `2N+2`；共识与分歧 = `2N+3`。N=2 时共 14 份文件、12 次 agent 调用。

目标目录已存在时核对任务身份和已有状态；用户已要求续跑或新开时直接按该选择执行，只有目标仍有歧义才询问，不覆盖已有成果。调度员生成的中间物（diff、prompt、回收文件、日志）一律落 scratchpad，不进交付目录。

写盘由调度员统一做，frontmatter 由调度员生成而非 agent 自报。两个理由：Codex 在 `-s read-only` 下不能写文件，放开写权限会破掉只读红线；更要紧的是「读了哪份、针对哪份」一旦让 agent 自己填就成了自我报告，而调度员是唯一真正知道自己传了什么进去的角色。agent 只产出正文，调度员原文照录。

## 流程

### ⓪ 开局

确定参数 → 建目录、检查已有文件 → 涉及外部事实时用新的 scratchpad 执行 `dma_smoke` 验联网，已有本轮真实工具证据可复用 → 向用户播报一句配置：成稿档位、轮数、本次约 12 次模型调用、以及 Codex 侧的计费口径（用户已明示则不提）→ 开工。

计费口径不要硬编码：`codex login status` 显示 ChatGPT 登录就说「走你的 ChatGPT 套餐用量」，显示 API Key 就说「按 API 用量计费」。写死其中一种会让另一种用户收到错误的成本预期。

涉及外部事实时核验双方的联网能力。先检查当前 CLI 帮助和适用配置，必要的临时参数传给 `dma_codex` / `dma_smoke`；工具库不再硬编码历史联网旗标。纯本地材料推理不要求新闻检索。不能联网时标明缺口；用户要求外部事实核验或能力对称的部分不得默默降级。

### ① 独立作答（步 01）

双方仅凭原始 Prompt 作答，互不见面——任一方的 prompt 不得含对方答案或任何方向性暗示。**反锚定只约束这一步**，此后交叉阅读正是目的所在。产出正文 + 取舍备忘。

回收后跑 `dma_collect <回收文件>`（Claude 侧）与 `dma_check_ratio <写盘后的 answer>` 验留痕配额。

### ② 互审（步 2k）

每方派新 agent，读四样：对方 answer v(k) 全文（含其修订说明与取舍备忘——前者让我看见我上轮的意见被怎么处理，后者让我避开对方自己都标了存疑的材料）、对方 v(k-1)→v(k) 的正文 diff（k≥2，`dma_diff` 生成）、我方 answer v(k)（知道我方有什么才写得出「对方有而我方缺」）、我方 review-(k-1)（k≥2，闭环核对用）。

产出三节。**三个标题的字面与节数在所有轮次恒定**——调度员按标题机械定位，缺一节就错位：

- **一、闭环核对**：逐 ID 判断我上轮的发现对方是否处理，并核 diff——删除与弱化之处若未在对方修订说明里交代，逐一追问。无声的回归是实测出现过的失效模式。k=1 时本节保留，写「首轮互审，无上轮发现可核对」。
- **二、核查发现**：逐条标题式，送达对方。找不到问题必须明说「未发现」，不许编造弱问题凑数。
- **三、可吸收之处**：对方有而我方缺的实质内容，留给我方修订 agent，必须写实内容。实测中同一份核查被双方各做了一遍，就是缺这一节。

回收后跑 `dma_check_review <文件>` 验结构。

### ③ 修订（步 2k+1）

每方派新 agent，读五样：原始 Prompt、我方 answer v(k)、对方 review-k（评我，补短）、对方 answer v(k) 全文（补长）、我方 review-k（含吸收清单）。产出正文 + 修订说明 + 取舍备忘。

回收后跑 `dma_collect`（Claude 侧）与 `dma_check_ratio`。**留痕区超过正文 1/4 就退回该方压缩重出**，不由调度员代删——删哪一句是作者意图的取舍。压缩只压单条长度，不许减少回应条数。

### ④ 终审（步 2N+2）

跑满 N 轮后双方各再审一次对方的终版，读对方 v(N+1)、其正文 diff、我方 review-N。**只审不改**，产出闭环核对与新发现两节作为交付附件；不写吸收清单，没有下一版消费它。校验用 `dma_check_review <文件> final`。

这一步补的是结构性缺口：末轮审阅若既没有下一版承载、也没有独立附件收纳，它的发现就没有任何进入交付链路的通道。旧流程的那次实测里，终轮 5 条发现有 4 条「重要」级原样留在交付稿。

### ⑤ 共识与分歧（步 2N+3）

调度员用 `dma_findings` 抽出全部 finding，配合两份修订说明的处置字段，机械拼装四节：双方均采纳（已收敛）、一方驳回且对方接受、保留分歧（列双方立场与性质）、终审指出但未修正。纯提取不创作，每行可回溯到源文档——这是调度员唯一允许生成内容的地方，因为它不含任何判断。

### ⑥ 收敛判定与收尾

默认完成约定 N 轮与终审，不因局部无发现再次询问。用户明确选择“收敛即止”时，双方均无关键/重要新发现且既有发现闭合后进入终审；仅一方无发现则继续。不得将上限时的未决问题称为已解决。

收尾更新 `00 index.md` 状态，交付两份终版 + 两份终审意见 + 共识与分歧表，附两三句简报（轮次、收敛情况、主要分歧及裁决）。

## 调度员要用到的约定

**finding 编号** `{提出方}R{轮}-{两位序号}`，如 `CxR1-03` 是 Codex review-1 的第 3 条，Claude 侧前缀用 `Cl`，终审用 `{前缀}F-{序号}`。已发编号永不重排复用，后续轮次引用原 ID 追加状态。`dma_check_review` 会校验这个格式。

**处置封闭词表** 每条收到的发现必须标 采纳 / 驳回 / 保留分歧 之一。驳回须给证据，保留分歧须写明是事实层还是框架层。只有这套词表封闭，`07 共识与分歧.md` 才能机械抽取，所以不可临时扩充。

**文档分区** 答案文档是「正文 / `---` / 修订说明 / `---` / 取舍备忘」。分隔线以上严格无过程痕迹，以下才是留痕区。`dma_body` 靠这个结构提正文，写法跑偏会让 diff 整体失效。

agent 侧的规则（成稿四条、核查六个着力点、修订四规则）不在这里，见 templates.md 的 prompt 模板。

## Codex 调用

一律经 `dma_codex <工作目录> <prompt文件> <回收文件> <日志文件> [额外参数]`，用 Bash 工具的 `run_in_background` 发起，命令里不要再加 `&`（否则双重后台，harness 拿到的是包装进程的状态而非 codex 的）。函数里已经封好三件容易出事的：stdin 传参、只读沙箱、回收文件非空判定。

- **prompt 必须走 stdin**，不要用 `"$(cat 文件)"` 内联。实测内联会让长中文 prompt 被截断，到达模型的只剩一部分，而退出码、回收文件大小、产出结构全都正常，从外部完全看不出来。走了 stdin 就不要再加 `< /dev/null`，两者互斥。
- **完成判定包括实际调用已结束、真实退出状态、非空回收文件及文档协议检查**。包装层 exit 0 不能代替模型执行成功；每次调用隔离临时文件，禁止用旧产物通过检查。
- **联网参数**以当前 CLI 和配置为准，不将旧版本的 `tools.web_search=true` 或 `--search` 当作恒定接口。`dma_codex` 同步等待真实进程，拒绝复用已有回收路径，并检查退出码和非空新产物；之后仍须按文档协议验证结构。
- **日志不可全信**：实测 `run.log` 会缺尾，工具调用、最终答案、token 计数全都可能没记，而同一次运行的会话 rollout 里工具其实调了很多次。要判断工具有没有真的动过，读 `~/.codex/sessions/YYYY/MM/DD/rollout-*-<session id>.jsonl`，`dma_smoke` 就是这么验的。
- 材料一律给文件路径（Codex 经 `-C` 自行读取），不把全文塞 prompt。每份文档单一用途，指路只需写文件名。
- **Codex 会自动加载并通读本 skill**：实测它派活后的第一个动作就是通读 SKILL.md。好处是它免费拿到了规范；风险是本文件里的任何具体举例都会变成它的「标准答案」。因此**本 skill 与 templates.md 正文一律不得出现具体的事实性错例**（某本书某个页码、某条法规某个条款），只描述失效模式的形态——否则审阅方会照着例子去「找」，而不是照着待审文档去查。review prompt 里也写明了这一条。

## 安全红线

1. 事实核查只许只读操作；任何有副作用的命令一律不执行。唯一例外是为核对页码下载文献 PDF，且只许落在临时目录，不得改动任何既有文件。
2. Codex 失败/超时/输出为空：重试一次；仍失败就如实暂停报告用户，**绝不伪造内容顶替**。Claude subagent 同理。
3. 双方一致不等于正确；驳回对方发现必须给证据。
4. 只写本次对拍目录与临时回收文件，不动用户其他文件。

## 异常处理

| 异常 | 处理 |
|---|---|
| codex CLI 不可用 / 认证或配额错误 | 停下如实报告（可能需 `codex login` 或等配额），不自行改配置 |
| codex 报 unknown argument | 按上节查当前旗标形态，改用等价参数并回写进 skill；改动后必须重跑 `dma_smoke` 确认能力未降级 |
| `dma_codex` 报回收文件为空 | 视为失败（多半是参数错误秒退），读日志定位后重发 |
| `dma_smoke` 计数为 0 | 联网没挂上，停下报告用户，不要降级开跑 |
| `dma_check_review` 报警 | 退回该方按模板重出该文档，不由调度员代改 |
| `dma_collect` 报文件为空 | subagent 没按约定 Write 或路径写错；重发该步，别改从最终回复里提正文 |
| `dma_collect` 报首行非二级标题 | 混进了开场白或 frontmatter，退回该方重出，不由调度员代删 |
| `dma_check_ratio` 超配额 | 退回该方压缩留痕区重出；压单条长度，不许减少回应条数 |
| `dma_diff` 空或整份被判改动 | 分隔线/标题写法不符规范，同上退回重出 |
| 正文里混进过程性表述 | 退回该方重写正文 |
| 修订说明缺 ID（漏回应） | 退回该方补齐；下一轮闭环核对也会兜住 |
| 答案超长 | 材料继续走文件路径，不截断 |
| 中断恢复 | 看目录缺哪一对文件，从该步续跑；`00 index.md` 记着已完成步骤 |

## 已知坑（实测记录）

出自对一次真实对拍产出的逐条复核，以及本 skill 改版时的实测。异常处理表讲「出事了怎么办」，这张表讲「为什么这些规则长这样」。此处只记失效模式、不记具体错例——原因见上节末条。

| 现象 | 原因与对策 |
|---|---|
| 终轮审阅发现全数丢失 | 末轮审阅既无下一版承载、也无独立附件收纳，发现就没有进入交付链路的通道。那次实测终轮 5 条发现有 4 条「重要」级原样留在交付稿，其余 1 条亦未进入交付物。对策：终审步骤 + 共识与分歧表 |
| 意见滞后整整一轮才生效 | 旧设计里审阅意见不送达，只能经由审阅者自己下一版的正文间接传递。实测首轮 16 条发现有 10 条在对方次版里原样存活。对策：意见直送 |
| 同一份核查被双方各做一遍 | 写不进自己正文的纯证据质疑没有传递载体，对方只能重做一遍。对策：review 的「可吸收之处」一节 |
| 以删代改 / 内容净减少 | 实测六次订正有三次是删掉争议材料了事，已核实的正确引证反而没能进入交付物。对策：修订规则里的禁止条款 + 下一轮回归检查 |
| 无声回归 | 实测出现过：上一版正确的多项枚举，下一版悄悄少一项，修订说明里毫无记录。作者自己都不知道漏了，声明式约束抓不住。对策：`dma_diff` 递给审阅方 |
| 反锚定泄漏 | 旧设计两份文档是堆叠结构，指路靠「读到下一个 `##` 为止」，实测已发生泄漏（一方引用了只存在于对方审阅章节里的内容）。对策：一步一档，文件级隔离，这条切片路径随之取消。但它是投递边界而非沙箱：首轮的互不见面仍依赖调度员只投递原始 Prompt、agent 守住材料边界 |
| 长 prompt 被静默截断 | 内联传 prompt 时到达模型的只剩一部分，而退出码、文件大小、产出结构全都正常。对策：`dma_codex` 走 stdin |
| 日志的沉默不是证据 | 实测 `run.log` 会丢掉工具调用、最终答案与 token 计数，而同次运行的 rollout 显示工具实调了 9 次。对策：`dma_smoke` 只认 rollout 里的计数 |

