ADR-0001: Reverse-Thinking Gate — Engine-Level Enforcement vs Hook-Layer Opt-In¶
- Status: Accepted (缩水方案 Option 2-Plus 落地)
- Date: 2026-04-25
- Deciders: PM (产品经理) + Flyto Agent core team
- Related code:
core/pkg/counterfactual/,core/pkg/skills/reverse_think/,core/pkg/tools/tool.go(RequiresReverseThinking field),platform/common/safetychain/reverse_thinking_hook.go - Related TODO:
core/TODO.mdL569 (登记 2026-04-16, 缩水落地 2026-04-25) - Commit chain:
248253e(C1) →0385efd(C2) →c4b755f(C3) →4618b79(C4) →40aae31(C5) → C6 (本 ADR)
1. 背景 / Context¶
CLAUDE.md 宪法原则 1-5 规定 AI Agent 在做非平凡设计决策前应走五步: 读早期方案代码 → 标 CLEVER/UGLY → 升华思考 (CLI/SDK/API/跨行业) → 反向思考 → 等待确认. 当前实现:
- 软性 skill:
~/.claude/skills/reverse-think/SKILL.md使用 MiniMax-M2.7-highspeed 跑反向思维, JSON 输出 (hidden_assumptions/failure_scenarios/verdict/verdict_reason) - 强制确认协议 ⛔:
CLAUDE.md顶段, 写.go/ 启动 Agent 子进程 /git commit前必须 "⏸️ 等待确认" - 现有引擎级 gate:
core/pkg/hooks/PreToolUse(12 hook 类型) +core/pkg/permission/(32 文件 AI classifier + 规则) +core/pkg/validator/(可插拔审批契约) +core/pkg/circuitbreaker/+core/pkg/staging/+tools.Metadata.RequiresCheckpoint+engine.CheckpointHandlerFn
核心问题: 上述五步靠人/Agent 自觉遵守, 一致性差. TODO L569 提议升级为引擎级强制 gate, 引入 8 个新模块 (~1500-2500 行 Go).
2. 决策 / Decision¶
采纳 Option 2-Plus 缩水方案 (4 件套 + reference hook + ADR), 拒绝原方案 A 完整版 (引擎级 8 模块).
实施范围 (Option 2-Plus)¶
| 件 | 内容 | 路径 | 行数 |
|---|---|---|---|
| 1 | Deliverable schema | core/pkg/counterfactual/ |
~440 |
| 2 | MiniMax Go client | core/pkg/skills/reverse_think/ |
~790 |
| 3 | Tool metadata flag | core/pkg/tools/tool.go (新字段) |
~100 |
| 4 | Evolve sink adapter | core/pkg/counterfactual/replay_event.go |
~270 |
| 5 | Reference hook | platform/common/safetychain/reverse_thinking_hook.go |
~530 |
总计 ~2,131 行 (含双语 godoc + 测试).
拒绝范围 (方案 A 完整版)¶
| 模块 | 拒绝理由 |
|---|---|
(a) engine.ReverseThinkingGate 接口 |
与 hooks.PreToolUse 同时机同语义重叠 |
(e) engine.TriggerClassifier |
与 permission.Classifier 同语义; 业界惯例消费层自决白名单, 不在 engine |
(f) engine.DiscussPhaseGuard + ImplementPhaseExecutor + ConfirmationGate |
与 RequiresCheckpoint + permission.Handler 同语义已实装 |
(g) engine.AlternativePreserver |
在 runtime 层无合理语义; 源代码层是 git diff + CONTRIBUTING.md 注释规范 (0 行 Go); 业界零先例 |
(h) CrossDomainExtensions |
YAGNI, 零消费者 (rule of two: 没有第二个消费者前不抽象) |
3. 评估流程 / Evaluation Process¶
3-agent 并行 review (memory feedback_agent_teams_review_mode.md 模式), 三方独立产出报告后主线程 reconcile, PM 拍板.
调研 agent (业界先例)¶
调研 8 个主流 Agent 框架的"决策前 gate"机制:
| 框架 | 有无前置 gate | 触发粒度 | 形式 | 持久化结构 | 强制 vs 可选 |
|---|---|---|---|---|---|
| Claude Agent SDK | 是 | per-tool (matcher) | PreToolUse hook callback |
tool_input + session_id 输入, decision/reason 输出 | callback 由开发者注册 |
| OpenAI Responses API | 否 | per-message | reasoning_effort + reasoning items |
跨 function call 持久化但不可拦截 | engine 自管 |
| Vertex AI ADK | 是 | per-tool / per-model-call | before_tool_callback + before_model_callback |
callback 接 agent state | engine 提供 hook, 策略由开发者写 |
| LangGraph | 是 (interrupt) | per-node | interrupt() + Command resume; Agent Inbox UX |
富 payload + checkpoint 持久化 | 完全 developer-defined |
| AutoGen | 是 (HITL) | per-message | UserProxyAgent.human_input_mode |
仅 human input string | mode 配置 |
| CrewAI | 弱 | per-task | hierarchical process; verbose log | log only | 进程模式选择 |
| Semantic Kernel | 是 | per-function-invocation | Filter 链式 next() 中间件 | 可读 args + override result | engine 装载, filter 由开发者写 |
| Cline | 是 (Plan/Act) | per-session-mode | system prompt + READ_ONLY_TOOLS 白名单切换 | plan 自由文本 | mode 切换 + YOLO bypass |
业界共识: engine 提供 hook primitive, 策略由开发者写. 零框架在引擎里 hardcode "决策前必须填五步 deliverable 才能调 tool" 的强制规则.
业界没做的反向论证: 1. 吞吐量与 autonomous use case 冲突 (batch / 后台 agent / scheduled run / CI/CD 集成必须高吞吐) 2. 反思质量是 prompt 工程问题不是 enforcement 问题 (Reflexion 2023 论文 91% 的提升来自模型主动反思, 非 framework 强制结构) 3. 范畴错位: engine 不知道哪些工具值得反思 — 把判断推给开发者是把 domain knowledge 留在 domain 层的工程惯性
质疑 agent (5 道硬质疑)¶
-
范畴错位指控成立: CLAUDE.md 五步是给写代码的 dev 设的协议, runtime 工具调用没有"早期方案代码可读" / "改动后注释" 的对应物. 类比: 把 "TDD 红绿重构" enforce 到生产服务请求路径上, 显然荒谬.
-
吞吐数学不成立: logistics wave-decision 1000/s × 即使 TriggerClassifier 收敛到 10% 触发 → 100 reverse-think/s × 5-15s 延迟串行 → 需 500 并发 LLM call 在飞才能维持稳态; MiniMax token plan call 数 (calls/5h) 被打爆.
-
RequiresCheckpoint已实装 (主线程 anchor 漏掉的关键):core/pkg/tools/tool.go:142-157已有RequiresCheckpoint bool字段 +engine.CheckpointHandlerFn完整实装 (engine/checkpoint_test.go:11-69全分支测试). 这就是方案 A (d)+(f) 的已有版, 名字叫 RequiresCheckpoint. L569 增量价值 ≤ "改名 + 调 reverse-think skill 而非 generic handler" — 5 行 wiring 不是 1500-2500 行新模块. -
prompt-level 已是业界共识: 所有主流框架靠 system prompt + tool description 引导 reasoning. 0 行 Go / 0 维护 / 0 延迟 / 跨 provider 一致.
-
9 天前登记后 4 个新子包已消化: validator (4-23) + staging (4-24) + shadowdb (4-25) + reflector (4-24) 四个子包覆盖了 L569 当时担忧的 95% 价值. L569 是过期需求, 不重新评估就执行 = 沉没成本陷阱.
设计 agent (4 备选)¶
| 方案 | 范围 | 行数 | 优点 | 代价 |
|---|---|---|---|---|
| A 完整版 | 全 8 模块上引擎级 (TODO 原方案) | 1500-2500 | 北极星完整兑现 | 与 5 套现有 gate 重叠, 5-15s/tool call 延迟, 违反 CLAUDE.md 原则 10 "叠加而非替换" |
| B 缩水接口版 | (a)+(b)+(d), TriggerClassifier 走消费层 | ~600 | core schema-agnostic, "rule of two" 满足 | 接口空挂短期没消费者 |
| C 软性化 | 仅把 skill Go 化, 不动 engine / Tool metadata | ~300 | 0 延迟侵蚀, 0 引擎耦合, 1 commit | 没 CHANGELOG 突出特性, 跨行业扩展点缺失 |
| D hook 路径 | 走现成 PreToolUse, 0 新 gate 概念 | ~400 | 0 引擎核心改动, CLAUDE.md 原则 10 满分 | hook ergonomics 跨场景一致性靠 "约定俗成" |
设计 agent 推荐 D > C > B > A. 但 D + C 的组合 (skill Go 化作 hook backend) 是更完整的形态.
PM 反问与最终拍板¶
PM 提两次精准反问:
- "反向模式作为可选字段, 激活后按设计方案生效, 这个不算侵袭业务层吧?"
-
答: 运行时不侵袭确实成立 (默认关 = 0 延迟). 但 codebase 维护负担 + 与现有 5 套 gate 语义重叠 + (g)/(h) 范畴错位三件 opt-in 解决不了. 砍到 (b)+(c)+(d) 是合理形态.
-
"听上去确实应该消费层做, 甚至消费层使用者自己写 skill / 提示词. 但这样进化能力不存在, 进化结果停在哪里?"
- 答: 触发可以各行业自决, 格式和学习池要在 core 统一. 类比: 连锁医院各家自己决定哪些病人问诊 (触发), 但电子病历格式 + 病例学习数据库总部一份 (格式 + 学习). 加 1 件 evolve 接线 (Deliverable.AsReplayEvent → evolve.LogReplayer) 解决.
PM 最终拍板 Option 2-Plus = 4 件套 + ADR:
1. Tool 自描述标签 RequiresReverseThinking (core 共享 opt-in)
2. Deliverable 五步结构 (core 共享格式)
3. reverse_think Go 函数 (core 共享 backend)
4. AsReplayEvent 接进 evolve 学习池 (core 共享进化沉淀)
5. platform reference hook (Go 行业一行启用入口)
4. 后果 / Consequences¶
正面¶
- 与业界 8 框架共识对齐 (hook 路径 + tool metadata + 开发者自填策略)
- 0 延迟侵蚀业务路径 (默认关闭, opt-in 才触发)
- 0 引擎核心改动 (没在
core/pkg/engine/加新接口或字段) - 跨行业灵活性最大 (各行业自定义 PromptBuilder + Sink + 触发策略)
- 进化沉淀路径完整 (各行业产出经 AsReplayEvent 汇总到 core 的 evolve.LogReplayer)
- CLAUDE.md 原则 10 "叠加而非替换" 满分 (复用 hooks.PreToolUse 不引入新 gate 概念)
负面¶
- 没有 CHANGELOG 突出可见特性 (4 个新包 / 字段 / adapter, 不是一个大模块)
- 强制语义靠现有 RequiresCheckpoint + 强制确认协议 + permission Handler 组合, 不是单一引擎 gate
- 行业 platform 写自己的 hook backend 时可能走捷径 (传
validator.AlwaysApprove{}同形态 bypass), 但这是产品决策不是设计缺陷
中性¶
- 反向思维质量仍取决于 LLM (MiniMax) 输出质量, 任何方案 (含 A) 都改善不了模型主动反思的水平
- 跨行业一致性靠
MetadataKey = "flyto.counterfactual.deliverable"字符串字面量 + Deliverable schema 锁定; 升级时跨包协调
5. 替代方案保留 / Alternatives Preserved (CLAUDE.md 原则 5)¶
方案 A 完整版 (TODO L569 原方案)¶
如果未来 logistics platform 上量后, 反向思维数据驱动证明 "engine-level 强制 gate 真有 10x 决策质量提升", 可以从 Option 2-Plus 升级到方案 A. 升级路径:
core/pkg/counterfactual/Deliverable已是方案 A (b)CounterfactualDeliverable的实装, 直接复用core/pkg/skills/reverse_think/已是方案 A (c)core/pkg/skills/reverse_think/的实装, 直接复用tools.Metadata.RequiresReverseThinking已是方案 A (d) 同名字段的实装, 直接复用- 新增方案 A (a)
engine.ReverseThinkingGate接口 + (e)TriggerClassifier+ (f)DiscussPhaseGuard三件, 在core/pkg/engine/落 ~800-1000 行 - 方案 A (g)
AlternativePreserver与 (h)CrossDomainExtensions仍建议不上 (范畴错位 + YAGNI)
预期升级成本: ~1000 行 Go (从 Option 2-Plus 基础上). 触发条件: 数据证明 + 至少 2 个行业明确要求 (rule of two 满足).
方案 B 缩水接口版¶
Option 2-Plus 已部分包含 B 的接口形态 (counterfactual 子包 + Tool metadata). 与 B 的差异: B 想把 ReverseThinkingGate 做成接口空挂等消费者, Option 2-Plus 直接走 hooks.PreToolUse 不另起接口.
方案 C 完全软性化¶
Option 2-Plus 包含 C 的 skill Go 化部分 (core/pkg/skills/reverse_think/), 但比 C 多 4 件 (Deliverable + Metadata flag + AsReplayEvent + reference hook). 如果 PM 后续认为 4 件中任一过度设计, 可逐件拆除回退到 C.
方案 D hook 路径 (单纯版)¶
Option 2-Plus 包含 D 的 hook 路径 (ReverseThinkingHook 走 hooks.PreToolUse), 但比 D 多 3 件 (Deliverable + Metadata flag + AsReplayEvent). 这 3 件提供了 D 单纯版没有的"跨行业 schema 统一 + 进化沉淀"价值.
6. 触发重新评估的条件¶
未来出现以下任一情况, 应重新评估 ADR-0001 的决定:
- 数据驱动证据: logistics / finance / decision platform 任一上量后, 出现反向思维 hook 漏触发 (RequiresReverseThinking 标签覆盖率不足) 导致 5+ 真实事故, 且 prompt-level 增强补不上
- 业界先例改变: Anthropic / OpenAI / Google 任一在自家 Agent 框架引入 engine-level 强制 reasoning gate 并公开背书 (不是实验功能)
- 吞吐量假设破产: logistics batch decision 实测延迟容忍度 ≥ 30s (如 platform 决定走 nightly batch 而非实时 wave decision), 方案 A 的吞吐代价不再 disqualifying
- 第二个消费方需求: 至少 2 个行业 platform 明确写出 "需要 engine-level 强制反向思维, 不是 hook opt-in" 的需求文档 (rule of two)
满足任一即可重新走 3-agent review 评估升级到方案 A.
7. 参考链接¶
业界 Agent 框架文档¶
- Claude Agent SDK Hooks
- Anthropic Extended Thinking
- LangGraph Interrupts
- Semantic Kernel Filters
- Vertex AI ADK Safety
- Cline Plan/Act Modes
- Reflexion Paper (Shinn 2023)
项目内部参考¶
~/.claude/skills/reverse-think/SKILL.md— 软性 markdown skill (MiniMax 调用模板)core/CLAUDE.md— "强制确认协议 ⛔" 段 + 我的工作原则段 (五步)core/TODO.mdL569 — 原方案登记core/pkg/tools/tool.go:142-157—RequiresCheckpoint同源字段范本core/pkg/hooks/types.go+handler.go— hooks.PreToolUse + HookHandler 接口core/pkg/evolve/interfaces.go—Reflector+ReplayEvent+LogEntry进化循环接口core/pkg/staging/record.go—Record.Metadata字段 (Deliverable 落点)
8. 修订记录¶
| 日期 | 版本 | 变更 |
|---|---|---|
| 2026-04-25 | v1.0 | 初稿. 缩水方案 4 件套 + reference hook 落地 6 commit, ADR 起草 |