Skip to content

传感器 — Feedback 控制

传感器验证智能体做了什么。它们闭合使自纠正成为可能的环路:配备良好传感器的智能体,会在你看见之前修复自己的错误;没有传感器的智能体,则会带着自信的摘要交付错误。

传感器栈

按速度与成本排序,最快者优先 — 此顺序「质量左移」原则:

传感器延迟运行位置
类型检查器毫秒–秒编辑时(hook)、pre-commit、CI
Linter / 格式化器毫秒–秒编辑时(hook)、pre-commit、CI
单元测试智能体调用、pre-commit、CI
集成/E2E 测试分钟CI
架构适切性检查秒–分钟CI
AI 代码审查(推理型)分钟,$PR
人工审查小时PR

目标不是处处运行一切;而是让每个错误被能检测它的最便宜传感器尽可能早地捕获。上面两行昂贵的传感器,留给更便宜层无法发现的问题。

类型检查:免费传感器

严格的类型检查器对智能体工作价值最高,因为它在每次编辑时以零边际成本运行、完全确定性,且错误信息足够精确,智能体可自主据此行动。

  • TypeScript:"strict": true — 非 strict 的 TS 会静默放弃大部分价值。
  • Python:mypy 或 pyright,放在 CI 中,而非仅在 IDE。
  • Go、Rust、Java、C#:编译器已承担此职责;确保智能体宣布完成前先完成构建。

这也是语言策略上的论据:类型化代码库在度量上更易于 harness 化 — 编译器免费监督每一次智能体编辑。

测试:智能体用于自纠正的传感器

对智能体而言,测试套件不(仅)是安全网 — 它还是任务中途验证自身工作的工具。这改变了「好测试」的含义:

  1. 快。 智能体能在几秒内跑完的套件,会在每次改动后运行;需要 20 分钟的套件则几乎不会跑。即使完整套件较慢,也应保留快速子集(npm test)。
  2. 一条清晰命令即可运行,并在 AGENTS.md 中写清。若测试需要三个环境变量和数据库,请用脚本封装初始化。
  3. 确定性。 不稳定的测试会教智能体(像人类一样)忽略红灯。
  4. 行为导向。 锁定实现细节的测试会阻碍合法重构;锁定行为的测试能捕获真实回归。Fowler 的「经核准 fixtures」模式 — 经人工审查的黄金基准文件、由机器检查 — 对智能体密集型代码库很有效。

值得写入 rule 的约定:新行为应伴随测试落地,且为变绿而删除失败测试绝不可接受。 若允许,智能体两者都会做。

Linters:将约定编码为代码

每个能表达为 lint rule 的约定,都可以从 rules 文件中删除 — linter 以确定性强制执行,反馈环路优于说明文字。现代技术栈使自定义 rule 成本很低(ESLint flat config、Biome、Ruff、golangci-lint 自定义 linter)。

智能体工作的优先级:

  • 捕获语义失误的规则(未使用变量、悬空 Promise、未处理错误)优先于纯风格规则。
  • 可自动修复的规则 — 与格式化器配对,使 diff 只保留有效信号。
  • 针对项目中反复出现的「智能体总在做 X」的自定义 rule。

架构适切性:结构的传感器

Fowler 的第二项调节维度是架构适切性 — 验证结构、而非仅语法的传感器:

  • 依赖规则:「core 永不从 api import」— ArchUnit(JVM)、dependency-cruiser(JS/TS)、import-linter(Python)。
  • Monorepo 中的模块边界:Nx/Turborepo 边界检查。
  • 性能预算:打包体积上限、查询次数、p95 断言。

有智能体时重要:优化局部任务的智能体,会轻易违反局部文件未提及的全局约束。适切性检查使全局约束在局部立即可见。

Hooks 作为编辑时传感器

Cursor hooks 将传感器从「智能体记得时才跑」变为「始终跑」:

json
{
  "version": 1,
  "hooks": {
    "afterFileEdit": [
      { "command": "node ./.cursor/hooks/format-on-edit.js", "timeout": 30 }
    ]
  }
}

良好的 afterFileEdit 实践:格式化文件、对其运行 linter、对其包运行类型检查 — 并将失败反馈给智能体,使其此刻、在上下文中修复,而非一小时后在 CI 中才发现。保持快速(尽可能亚秒级);慢 hook 会拖累每一次编辑。

CI:正式记录的传感器

本地传感器是建议性的 — 没有任何机制强制智能体(或合并其工作的人类)已运行它们。CI 是传感器成为事实之处:

  • 每次 push 与 PR 运行测试、lint、类型检查。
  • 设为必需检查;CI 报红的智能体 PR 是未审查的工作,而非草稿。
  • 添加 harness-score --min-level N 作业,阻止 harness 回归 — 即有人删除 hooks 文件却无人察觉的配置漂移失败(第 7 章详情)。

Pre-commit 工具(husky + lint-staged、pre-commit、lefthook)填补编辑时 hooks 与 CI 之间的空隙:提交存在前的最后一道确定性 check。

推理型传感器:AI 审查 AI

基于 LLM 的审查(Cursor Bugbot、裁判智能体、审查插件)在计算无法检查之处才值得成本:此变更是否意味着正确的事?此抽象是否合理?两条规则保持诚实:

  1. 它补充计算栈,永不替代。批准无法编译代码的 AI 审查者是做戏。
  2. 其发现应可抽查 — 优先选择引用 file:line 并陈述失败场景的审查者,而非输出模糊感受者。

自纠正环路,组装完毕

栈就位后,LangChain 显式构建的环路自然涌现:智能体编辑 → hooks 格式化与 lint → 运行快速测试 → CI 重新验证一切 → 推理型审查者审阅通过前几层检查的变更。每一层捕获上一层遗漏的内容,且每次捕获发生在尽可能便宜的节点。仍缺的是使危险行动无法执行,而非仅能检测 — 那是 guardrails