2026年9月27日 3 分钟阅读

让 AI Coding Agent 证明它的工作:Keel 门控框架完全指南

tinyash 0 条评论

AI Coding Agent 正在快速进化——Claude Code、Codex、Copilot 和 Kiro 都能独立完成从需求到代码的全流程。但一个核心问题始终悬而未决:如何确认 Agent 声称的”完成”是真的?

当 Agent 告诉你”测试全部通过,功能已实现”时,你要么信任它,要么自己跑一遍验证。对于生产级项目来说,这种”信任但需复核”的模式成本太高。

keel(GitHub: daneb/keel)是一个 Rust 编写的门控框架(gated harness),它的核心理念是:让 AI Coding Agent 证明它的工作。keel 不实现模型适配器、工具注册表或推理循环——这些留给 Claude Code、Codex 等工具去做。keel 站在它们之上,负责两件事:可审计的停止条件和跨工具的持久记忆。

安装与基本概念

keel 在 crates.io 上以 keel-harness 包名发布(因为 keel 和 keel-cli 已被其他无关项目占用),安装后二进制文件名为 keel:

cargo install keel-harness   # 安装后得到一个名为 keel 的二进制文件

当前版本为 v0.10.1,基于 Rust 编写,支持 macOS 和 Linux,采用 MIT OR Apache-2.0 双许可证。项目状态显示已完成所有五个阶段(PLAN.md),包含证据链、bundle 验证、PR 检查和 GitHub Actions runtime。

keel 的核心设计哲学可以概括为一句话:keel 是指挥者,不是 Agent 循环。 它不重复造轮子,而是站在现有 Agent 之上提供治理层。

核心概念:Gates 与证据链

Gates(门控)

keel 定义了六个门控阶段,每个阶段都有明确的通过/失败标准:

门控职责失败条件
G0Spec 校验:EARS 格式?有 oracle?无占位符?store 是否最新?任何标准不可证伪
G1Plan 校验:影响范围已追踪?预算合理?有回滚方案?影响集是否最新?未追踪、超预算、无回滚
G2执行校验:构建、测试、lint、所有 oracle、scope、budget、ratchet任何检查失败
G2.5质量审查:是否新增 mock?测试是否被篡改?findings 分级(HIGH 阻止)HIGH findings 存在
G3人工审批:前序门控全绿、diff 可审阅、人工判定人工否决
G4学习闭环:分类失败、提出 lessons—

关键设计细节:

  • blocked 是一个真实的判定结果,有自己的退出码(3)。它意味着检查无法运行(缺少工具、无索引、无凭据),永远不会静默通过,也不会归咎于 Agent。
  • Approvals 绑定到 hash:如果在签认后修改了 spec,G1 会以 spec changed after approval 失败。否则”approved”就成了一枚永远有效的印章。
  • Budgets 是不变式:每个生成物都拟合到硬行数预算内,截断通知消耗的是预算的一部分。被裁剪的内容不会删除,而是携带指向全文的指针。

证据链(Evidence Chain)

keel 将所有审批、门控判定和运行记录链接成一条 hash 链。每条记录引用前一条的 hash,形成防篡改结构。

keel chain verify          # 验证整条链
keel chain head            # 查看链头
keel chain verify --head   # 验证指定哈希之后的部分

如果有人在链中插入、删除或重排记录,keel chain verify 会精确指出哪一步出了问题。

完整工作流:从 Spec 到 Evidence Bundle

Step 1:初始化项目

keel init    # 脚手架、种子数据、构建第一个符号索引

keel init 会扫描代码库,使用 tree-sitter 构建符号索引(支持 Rust、Python、JavaScript、TypeScript/TSX、Go、Java、C#),并生成 .keel/store 目录作为单一事实来源。

Step 2:创建 Spec(定义”完成”的含义)

keel spec new rate-limit   # 脚手架化 spec,然后自动运行 G0

Spec 是你对”完成”的精确定义,采用 EARS 格式(Every time / When / Then / And / So),每条标准必须附带一个可运行的 oracle(自动化检查)。G0 会拒绝任何包含占位符或不可证伪标准的 spec。

Step 3:审批 Spec

keel approve rate-limit --stage spec

审批会将你的签名绑定到当前 spec 的 hash。之后修改 spec 会导致后续 G1 失败。

Step 4:生成 Plan(计算影响范围)

keel plan rate-limit       # 计算 blast radius,生成 plan.md + tasks.md
keel tasks                 # 将 plan 按依赖波次展示

keel 利用符号索引计算影响范围(blast radius),生成按依赖关系分波次的任务列表。G1 会验证:影响集是否已追踪、预算是否合理、是否有回滚方案。

Step 5:驱动 Agent 执行

keel run rate-limit        # 驱动 Agent,捕获证据,进行门控
keel run rate-limit --waves  # 每个任务一个 worktree,逐波执行
keel run rate-limit --no-driver  # 不驱动 Agent,直接门控当前工作树

执行过程中,keel 会:

  1. 从 Store 组装上下文(约定、技术栈、地图、lessons、spec、task)
  2. 通过 keel.drivertask/1 JSON 协议向 Agent 发送任务
  3. Agent 返回 keel.driverresult/1 + diff
  4. keel 运行 G2/G2.5/G3 门控

Step 6:导出证据 Bundle

keel export rate-limit     # → keel-rate-limit.tar.gz
keel bundle verify keel-rate-limit.tar.gz   # 离线验证每条链接

Bundle 包含:轨迹(trajectory.jsonl)、门控判定、证据和 manifest。任何人可以在没有访问仓库的情况下离线验证整个运行过程。

Step 7:CI 集成

模式 A:PR 覆盖检查(keel-cover)

在 .github/workflows/keel-cover.yml 中添加一行,即可阻止没有任何 keel bundle 的 PR:

on: pull_request
jobs:
  keel-cover:
    runs-on: ubuntu-latest
    steps:
      - uses: daneb/keel@v0.10.1

只有携带了恰好匹配其内容的通过运行的 bundle 的 PR 才能通过。维护者可以通过添加 keel:exempt label 来豁免特定 PR。

模式 B:CI Runtime(keel-runtime)

在 GitHub Actions 中,keel 可以直接在 gVisor 容器内门控 PR,并将 bundle 提交回 PR:

      - uses: daneb/keel/runtime@v0.10.1
        with:
          spec: rate-limit
          image: rust:1-bookworm       # 你的工具链

此模式下,GitHub runner 持有证据链并从外部对容器进行 attestation,keel 在 gVisor 容器内门控 PR,最后将 bundle 提交回去。

检索命令:Retrieve, Don’t Read

keel 的核心理念之一是 “Retrieve, don’t read”——不要读整个文件,而是精准检索所需信息。以下命令都基于符号索引:

keel outline       # 文件的结构大纲
keel symbol        # 查找符号
keel source        # 获取源码片段
keel refs          # 查找引用
keel importers     # 查找谁导入了这个模块
keel blast 'src/api/**'    # 这个变更会影响什么?
keel slice T-1             # 获取一个任务所需的全部上下文(预算适配)
keel bench                 # 测量 token 节省量(vs 读取整个文件)
keel mcp                   # 通过 MCP 协议暴露相同查询(stdio)

关键设计:索引是加速器而非依赖项。如果索引缺失、过期或语法不支持,所有查询会自动降级到 ripgrep,并明确告知。这防止了 Agent 在降级时自信地给出错误答案。

证据与学习系统

重放与运行管理

keel replay           # 重放一次运行
keel runs                  # 列出所有运行
keel runs --prune          # 清理旧运行
keel report [slug]         # 查看一个 feature 的完整生命周期
keel serve                 # 浏览器只读视图(loopback)

学习闭环

keel learn                 # 从运行中学习
keel failures              # 查看失败分类
keel lessons               # 查看所有 lessons
keel lesson promote    # 提升 lesson
keel lesson reject     # 拒绝 lesson
keel lesson demote     # 降级 lesson

当同一个失败模式在不同运行中出现两次时,可以将其提升为一个 lesson。一旦 lesson 拥有 oracle,它会编译为 G2 检查(携带 from: L-nnnn),不再注入上下文——因为如果一个规则不能被违反,就不需要每次提醒。

指标与 Ratchet

keel metrics               # 通过率、失败分类、token 用量、gate theatre
keel ratchet               # 只能改善不能退化的指标

扩展机制

keel 通过三个 JSON 子进程契约扩展,所有语言无关:

扩展类型输入/输出添加方式
Gate Checkstdout 打印 Check[[gate.G2.check]] in keel.toml
Agent Driverkeel.drivertask/1 in → keel.driverresult/1 out~40 行适配器 + [[driver]]
Reviewerkeel.reviewrequest/1 in → keel.reviewresult/1 out[[review]] 条目
Shared Store另一个 repo 的 .keel/store[[shared]] 路径或 submodule

keel driver check 会在一个 scratch repository 中运行任意 driver 的 conformance probes,绝不在你的主工作树上执行。

keel 与 moor:协作关系

keel 有一个配套工具 moor,用于在本地机器上运行 Agent:

  • keel 决定什么被允许、检查工作、保持记录
  • moor 决定 Agent 在哪里运行:密封的 Docker 沙箱,无 host mounts,egress allowlist

moor 从沙箱外部写入 keel 的记录,因此 Agent 无法篡改记录。两者独立工作,但设计上为协作而构建。

适用场景与注意事项

适合的场景:

  • 生产级项目中需要严格的质量门控
  • 多 Agent 协作场景(不同 Agent 共享同一 store)
  • 需要审计跟踪的团队环境
  • 对 AI 生成的代码有合规要求的项目

注意事项:

  • keel 不替代 Agent,而是治理 Agent。你需要同时运行 Claude Code/Codex 等工具
  • 首次 keel init 需要几分钟构建索引(取决于代码库大小)
  • CI 集成需要配置 contents: write 权限(runtime 模式)
  • 当前仅支持 macOS 和 Linux,Windows 支持尚未实现

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。