a2a

a2a (Agent-to-Agent) — 跨模型对抗式 code review。Claude 写的代码让 Codex 审,Codex 写的让 Claude 审,互相找茬不留死角。

install
source · Clone the upstream repo
git clone https://github.com/CtriXin/agent-2-agent
Claude Code · Install into ~/.claude/skills/
git clone --depth=1 https://github.com/CtriXin/agent-2-agent ~/.claude/skills/ctrixin-agent-2-agent-a2a
manifest: SKILL.md
source content

a2a — 对抗式 Code Review

谁写的代码,就让对手来审。Self-review is self-deception.

核心机制

对抗原则:review 优先在对立模型上执行。Claude 产出的代码由 Codex 审查,Codex 产出的代码由 Claude 审查。

为什么有效:不同模型有不同的 blind spot。Claude 倾向 over-engineer,Codex 倾向跳过 boundary check。让它们互相找茬,bug 无处藏身。

运行模式

模式条件说明
adversarialClaude + Codex 双向均可用跨模型对抗审查,最高质量
single-model-multi-lens仅一侧可用同模型多视角审查,质量降低但仍有多视角覆盖
blocked无法执行无法执行 review,报告标注
mode: blocked
并中止

跨模型双向 dispatch

  • Claude 写的代码 → Codex 审
    codex exec
    (Codex 有自己的 API key)
  • Codex 写的代码 → Claude 审
    claude -p
    + token bridge(见下方说明)

Token Bridge 机制(解决 Codex sandbox 无法访问 macOS Keychain 的问题):

preflight 在有 Keychain 访问权限的环境中(如 Claude Code、正常终端)运行时,会自动提取 OAuth access token 并缓存到

~/.cache/a2a/.claude-token
(权限 600)。Codex sandbox 内调
claude -p
时,通过读取此文件设置
ANTHROPIC_API_KEY
环境变量,绕过 Keychain 限制。

# Codex 环境内调 Claude 的标准方式:
TOKEN=$(cat ~/.cache/a2a/.claude-token 2>/dev/null)
ANTHROPIC_API_KEY="$TOKEN" claude -p "review prompt..."

⚠️ 从 Claude Code 内部不要直接调

claude -p
CLAUDECODE=1
环境变量会触发 nested session 保护。如需从 Claude 侧 review,使用 Agent tool spawn sub-agent。

报告中

Mode
字段必须如实标注当前模式。

触发方式

  • 用户说 "review"、"审查"、"code review"、"帮我 review 一下"
  • 用户说 "a2a"、"a2a review"、"对抗审查"
  • plan-to-codex 的 Phase 3 收口环节
  • 手动指定:
    /a2a src/path/to/file.js

审查规模判定

先算变更量,再决定派几个 reviewer。必须严格遵守,不得跳级。

# 硬性检查(dispatch 前执行)
diff_lines=$(git diff --stat HEAD~1 | tail -1 | grep -oE '[0-9]+' | head -1)
new_lines=$(git diff HEAD~1 --diff-filter=A --stat | tail -1 | grep -oE '[0-9]+' | head -1)
dir_count=$(git diff --name-only HEAD~1 | xargs -I{} dirname {} | sort -u | wc -l)
规模条件Reviewer 配置预估耗时
Light< 50 行Challenger only~30s
Medium50–200 行Challenger + Architect~1min
Heavy200+ 行,新增 ≤ 100 行Challenger + Architect~1.5min
Heavy+200+ 行,新增 > 100 行三人全上~2min
Cross-module涉及 3+ 目录三人全上~2min

三大审查视角

详见

references/review-lenses.md

  • The Challenger — 质疑者:找 edge case、未处理的 error path、race condition
  • The Architect — 架构师:审视 coupling、职责边界、component 拆分合理性
  • The Subtractor — 删减者:找 over-engineering、premature abstraction、多余 config

Preflight — 环境检测

首次使用或分享给同事时,跑 preflight 确认环境就绪:

~/.claude/skills/a2a/scripts/preflight.sh
# JSON 格式(供脚本读取):
~/.claude/skills/a2a/scripts/preflight.sh --json
# 登录状态刚变化时强制刷新:
~/.claude/skills/a2a/scripts/preflight.sh --refresh

检测项:Claude CLI、Codex CLI、本地登录态。默认缓存 900 秒,只做本地检查,不会发起 review 请求。

前置校验(Gate)

a2a 支持审查代码变更Plan / 设计方案,自动判定模式:

  1. Code Review 模式
    git diff --stat
    或用户指定的文件有实际代码修改 → 进入代码审查
  2. Plan Review 模式:无 diff,但用户明确指定了 plan / 设计文档 → 进入 Plan 审查
  3. 无审查对象:无 diff 也无用户指定 → 提示:
    "未检测到审查对象。请指定代码变更范围或要审查的 plan 文件。"

执行流程

Step 1: 环境检测 + 确定变更范围

🔍 运行 preflight,确认模式,确定审查范围。Token bridge 会自动维护,无需手动操作。

~/.claude/skills/a2a/scripts/preflight.sh --json

如果刚执行过

codex login
/
claude auth login
,用
--json --refresh
跳过缓存。

Token bridge 自动补全:preflight 完成后,检查 token 文件是否存在。如果缺失,立即自动补全:

TOKEN_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/a2a/.claude-token"
if [[ ! -s "$TOKEN_FILE" && "$(uname)" == "Darwin" ]]; then
  security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null \
    | python3 -c "import json,sys; t=json.load(sys.stdin).get('claudeAiOauth',{}).get('accessToken',''); print(t) if t else None" \
    > "$TOKEN_FILE" 2>/dev/null && chmod 600 "$TOKEN_FILE"
fi

这段在每次

/a2a
启动时自动执行,用户完全无感。

确定变更范围:

# 自动检测
git diff --stat HEAD~1
# 指定范围
git diff --stat main...HEAD
# 指定文件
cat src/pages/target.vue

根据 Gate 规则判定模式:有 diff → Code Review;无 diff 但有 plan → Plan Review;否则拒绝。

Step 2: 加载审查基准

📋 读取视角定义(red-line 扫描延迟到 Step 5 统一执行)

  1. references/review-lenses.md
    — 三大视角定义
  2. 目标项目的
    AGENT.md
    /
    AGENTS.md
    (如存在)— 仅用于理解项目 context,不传给 reviewer
  3. 目标项目的
    .ai/constraints.json
    (如存在)— 同上,留给 Step 5 统一扫描

Step 3: 明确变更意图

必须在 review 前声明:这次改动要解决什么问题?

Intent:     {一句话描述这次改动的目的}
Constraint: {这次改动不能碰的东西}

Step 4: 派遣 Reviewer(并行)

🤖 Claude 始终是 orchestrator,双向跨模型通过不同 dispatch 通道实现

非 git 目录检测(dispatch 前必须执行):

if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  SKIP_GIT_FLAG=""
else
  SKIP_GIT_FLAG="--skip-git-repo-check"
fi

Step 4a: 判定代码作者

根据以下信号判定变更代码的作者模型:

  1. 用户明确告知("这是 Codex 写的"、"刚用 Codex 生成的")
  2. Git commit message 含
    codex
    openai
    等关键词
  3. 默认:假定为 Claude 产出(因为 a2a 从 Claude Code 发起,大多数场景是 Claude 刚写完代码后 review)

Step 4b: 按作者 + 当前环境选择 dispatch 通道

路径 A: Claude 产出 → Codex 审查(从 Claude Code 发起)

codex exec --cd "$(pwd)" $SKIP_GIT_FLAG --full-auto -- "按照以下审查清单 review 代码变更..."
  • --cd
    确保 Codex 在正确的项目目录下执行
  • --skip-git-repo-check
    用于非 git 目录(自动检测,按需添加)
  • --
    separator 防止 prompt 内容被误解析为 flag
  • 禁止传
    --model
    参数
    ——让 Codex 使用用户自己在
    ~/.codex/config.toml
    配置的模型

路径 B: Codex 产出 → Claude 审查(从 Claude Code 发起)

通过 Agent tool spawn 隔离 sub-agent 执行 review(in-process,天然有 auth):

使用 Agent tool,为每个 lens 分别 spawn 一个独立 agent:
- agent 1: Challenger lens + 完整 diff
- agent 2: Architect lens + 文件列表/签名/摘要
- agent 3: Subtractor lens + 完整 diff + 新增文件

每个 agent 独立执行,互不可见(满足隔离要求)。

路径 C: Codex 产出 → Claude 审查(从 Codex 发起,token bridge)

当 a2a 从 Codex 环境发起时,通过 token bridge 调用

claude -p

# 读取 preflight 缓存的 OAuth token
TOKEN=$(cat ~/.cache/a2a/.claude-token 2>/dev/null)
if [[ -z "$TOKEN" ]]; then
  echo "错误:未找到 Claude token 缓存。请先在 Claude Code 或终端中运行:"
  echo "  ~/.claude/skills/a2a/scripts/preflight.sh --refresh"
  exit 1
fi

# 通过环境变量传递 token,绕过 Keychain 限制
ANTHROPIC_API_KEY="$TOKEN" claude -p "按照以下审查清单 review 代码变更..."

前提:必须至少运行过一次

preflight.sh
(从 Claude Code 或正常终端,非 Codex sandbox),以便将 OAuth token 从 macOS Keychain 缓存到文件。

路径 D: Codex 不可用 → Claude 单模型多视角(降级)

同路径 B 的 Agent tool 方式,但报告标注

mode: single-model-multi-lens

每个 reviewer 收到专属 review packet(按 lens 裁剪,严格精简):

通用字段(所有 reviewer 共享):

  • 变更 intent:1-2 句话概括目的,不传原始 plan 全文
  • 审查视角定义:只给自己那个 lens(从 review-lenses.md 摘取对应段落)

Lens 专属 diff 裁剪

Lens收到的 diff 内容
Challenger完整 diff(需要看具体代码找 bug)
Architect文件列表 + 函数签名 + 变更摘要(审结构不需要逐行)
Subtractor完整 diff + 新增文件列表(找多余代码)

不传给 reviewer 的内容

  • 项目 red-line 约束 → 移到 Step 5 由 Claude 统一扫描
  • CLAUDE.md / AGENT.md → 不传给 reviewer
  • Plan / 设计文档 → 提炼为 1-2 句 intent,不传原文

Reviewer 输出限制(必须附加到每个 reviewer 的 prompt 末尾):

输出限制:
- 每条 finding ≤ 3 行(trigger + impact + fix)
- 总 findings ≤ 10 条
- 无 finding 时只输出 "LGTM",不要写分析过程

所有 reviewer 并行执行,互不可见对方结果(防止从众效应)。

Step 5: 汇总 Findings + Red-Line Scan

📊 收集所有 reviewer 发现,然后 Claude 统一执行一次 red-line scan

Red-Line Scan(仅在此步骤执行一次):

  1. 读取项目的
    AGENT.md
    CLAUDE.md
    .ai/constraints.json
  2. 提取 red-line 约束条目
  3. 对完整 diff 扫描一次,违规项作为 🔴 High finding 加入汇总

通用 red line(项目无配置时的兜底):

eval() / new Function() / innerHTML =   → security risk
未经封装的 process.env 直接读取          → environment leak
硬编码 secret / token                   → credential exposure

汇总规则:保留 reviewer provenance,按 severity 分级

Severity定义示例
🔴 High会导致线上问题或数据丢失未处理的 null、XSS injection、state race
🟡 Medium不影响当前功能但埋坑coupling 过紧、缺少 error boundary、hardcode
🟢 Low风格或可维护性建议命名不清、注释缺失、可简化

主审裁定每条 finding:

  • Accept — 确实是问题,需要修
  • Dismiss — reviewer 过度解读或不适用当前场景
  • Flag — 有道理但 non-blocking,记录为 TODO

Step 6: 输出 Verdict Report

表格自适应规则:根据 findings 数量和内容长度选择宽/窄模式。

固定 5 列

#
,
Sev
,
Lens
,
问题
,
裁定

字段规则
Sev只写 emoji:🔴🟡🟢,不加文字
Lens缩写:
Ch
= Challenger,
Ar
= Architect,
Su
= Subtractor;多人
Ch+Ar
问题
`file:line`
嵌在开头,后接完整问题描述,不省略内容
裁定自适应(见下方宽窄规则)

宽模式(≤ 5 条 findings 或问题描述普遍短):

  • 裁定列写完整:
    Accept — 理由说明
    Dismiss — 为什么不适用
    Flag — 记 TODO 的原因

窄模式(≥ 6 条 findings 或问题描述普遍长):

  • 裁定列只写结果:
    Accept
    Dismiss
    Flag
  • 原因移到表格下方的 裁定说明 区(仅列出需要解释的条目):
    **裁定说明**
    - #2 Dismiss: reviewer 过度解读,当前 scope 只服务 content agent
    - #6 Flag: non-blocking,记 TODO,后续按 attempt 编号落盘
    
## a2a Review — {PACK_ID}

**变更**: {简述}
**规模**: {Light / Medium / Heavy / Heavy+}
**Reviewers**: Challenger + Architect + Subtractor
**Mode**: {adversarial / single-model-multi-lens / blocked}

### Verdict: {PASS / CONTESTED / REJECT / BLOCKED}

### Findings

| # | Sev | Lens | 问题 | 裁定 |
|---|-----|------|------|------|
| 1 | 🔴 | Ch | `src/x.vue:42` 删除"敏感操作确认"不安全 — 权限可被放宽,删了没第二道门 | Accept — 保留最小版 |
| 2 | 🟡 | Ar | `src/y.js:18` TODO 放在 wiki 目录语义不对 — wiki 是知识沉淀不是看板 | Accept — 移到根目录 |
| 3 | 🟢 | Su | `lib/z.ts:5` 单文件 Markdown 不支持并发检索 | Dismiss |

**裁定说明**
- #3 Dismiss: 当前 <15 条 TODO,过早优化

### 总结
{一段话总结 review 结论和 next step}

底线:问题列永远不省略。裁定列可以压缩但原因不能丢(移到下方)。

Verdict 标准

Verdict条件
PASS无 🔴 High finding
CONTESTED有 🔴 但 reviewer 之间存在分歧
REJECT多个 reviewer 共识性 🔴 finding
BLOCKED环境检测失败,无可用 CLI,review 无法执行

与 plan-to-codex 集成

本 skill 可以作为 plan-to-codex Phase 3 的增强版收口 review

原 Phase 3 流程:
  Claude 首审 → seal_review.sh → Codex 收口

增强流程:
  Claude 首审 → a2a review(多视角对抗) → verdict → review.md

当 a2a verdict 为 PASS 时,可以跳过

seal_review.sh

项目规范自动适配

审查时自动检测目标项目根目录的以下文件(任一存在即读取),仅在 Step 5 统一扫描时使用

  • AGENT.md
    /
    AGENTS.md
    — 编码规范与 red line
  • CLAUDE.md
    — Claude 专属约束
  • .ai/constraints.json
    — 硬约束

无需 hardcode 项目规则——每个项目自带自己的标准,Step 5 统一检查。

Dispatch 通道总结

发起环境代码作者ReviewerDispatch 通道模式
Claude CodeClaudeCodex
codex exec
adversarial
Claude CodeCodexClaudeAgent tool (sub-agent)adversarial
CodexCodexClaude
claude -p
+ token bridge
adversarial
任意任意同模型Agent tool 或 Codex 自审single-model-multi-lens

Token Bridge:preflight 从 macOS Keychain 提取 OAuth token → 缓存到

~/.cache/a2a/.claude-token
(权限 600) → Codex sandbox 内通过
ANTHROPIC_API_KEY
环境变量传递给
claude -p

Fallback: Single-Model-Multi-Lens 模式

当 Codex CLI 不可用时(没装或 auth 失败):

  • 所有 reviewer 通过 Agent tool spawn 独立 sub-agent 执行(每个 agent 独立运行,不共享上下文)
  • 报告标注
    mode: single-model-multi-lens
  • 质量低于跨模型对抗,但仍提供多视角覆盖

注意事项

  • 本 skill 只产出 verdict report,不自动改代码
  • Reviewer 不能看到彼此的输出(防止 conformity bias)
  • 每条 finding 必须引用具体文件和行号,不接受泛泛而谈
  • 禁止使用
    claude -p
    做 reviewer dispatch
    (见运行模式部分说明)