一个 PR 审查 Agent 连续三次指出同一种无关紧要的问题,开发者大概率不会再认真读它的第四条评论。

这不是模型不够聪明。更麻烦的是,团队其实已经把正确答案写进了反馈里,可那段反馈跟着一次对话结束就蒸发了。下一个 PR 到来时,Agent 又从零开始犯错。

Warp 最近公开的做法给了我一个很工程化的提醒。不要指望 Agent 在对话里慢慢长记性。把人类反馈变成一个小的、可审查、可回滚的文件变更,再让它走 PR 流程。这样一来,Agent 的改进才不是玄学,而是一套能被版本控制的系统。

这篇不打算复述 Warp 的案例。我更关心一个落地问题。对正在做 Java、Spring、LangGraph 或内部研发平台的团队,怎样把那个听起来很轻的自我改进循环,做成不越权、不污染上下文、也不把坏习惯自动放大的工程能力。

先别急着让 Agent 学习,它连问题在哪都未必知道

Warp 的起点很真实。他们的内部代码审查 Agent 会给出无用评论,工程师抱怨输出质量低。团队试过手工改 prompt,也补过 AGENTS.md 一类的上下文文件。效果有,但不持久。

很多团队到这里会继续加规则。发现 Agent 漏了异常处理,就添一条。发现它喜欢挑变量名,就再添一条禁止规则。过一阵子,提示词长成了一面贴满便利贴的墙,谁也说不清其中哪条还有效。

我一直觉得这类修补有一个别扭的地方。它把两个完全不同的工作揉在一起了。

一部分是执行任务。比如读一个 PR,找出可能的并发问题,给出评论。

另一部分是从很多次任务里归纳规则。比如团队并不反对重命名,只反对 Agent 忽略项目里特定的全局变量命名约定。

前者需要贴近当前代码和当前上下文。后者需要跨任务观察、过滤噪声、做取舍。让同一个执行 Agent 一边审 PR 一边重写自己的行为准则,听着很酷,实际很容易失控。它既没有足够的样本,也没有距离感。

Warp 把它拆成了两个 Skill。内层的 base skill 负责具体任务和领域知识。外层的 improver skill 定时读取累积反馈,提出针对 base skill 的小修改。人类批准后,下一次任务才带着新版本规则运行。

这一步看起来只是多了一个文件,事实上是把学习从推理过程里搬进了工程系统。

真正的状态,不该藏在聊天记录里

有些 Agent 产品把每次对话摘要塞回 memory,试图解决遗忘问题。这条路并非完全不行,特别适合保存用户偏好、临时线索和正在进行的工作。

但把团队的操作规范也塞进去,就容易出事。

memory 通常自动写入,变化很快,还很难看清一条结论来自哪个反馈。Skill 则应该是稳定的程序性知识,也就是在什么场景做什么、为什么这样做。它应该被有意识地修改,并且可以被审阅。

你想想看,下面两种状态的风险完全不同。

  • 某位开发者今天在排查支付超时,Agent 记住了订单号和排查路径
  • 团队决定所有 WebFlux 链路上的超时评论都要附带 Netty event loop 的证据

前一个适合短期 memory。后一个更像代码规范,应该落在版本库里。混在一起,过几周以后你几乎无法追问某条行为从何而来,更别提撤销一条错误规则。

Anthropic 对 Agent Skills 的定义也很接地气。它是文件系统里的能力包,包含 metadata、指令和按需读取的资源或脚本。metadata 用于识别何时触发。主指令在任务命中后加载。更细的参考资料和脚本只在需要时读取。

这套 progressive disclosure 很重要。它不是为了让目录看起来漂亮,而是在给上下文做预算。把架构规范、历史事故和脚本全部塞进系统提示词,模型未必更懂,只会让真正与当前任务有关的信号更稀。

所以一个可维护的 Agent,不是有一个越来越大的 prompt。它更像一个小型代码库,有明确入口、受控依赖和版本历史。

Warp 的闭环,最值钱的不是自动改文件

Warp 的 issue triage Agent 很能说明问题。有人在 GitHub 提 issue 后,GitHub Action 触发 Agent。它判断复杂度和可行性,打标签,并给出修复方向。

在一个案例里,Agent 少打了 ready to spec 标签。维护者没有去某个独立的反馈后台填表,而是直接在 issue 中写下原因。这个问题已经描述了真实痛点,即使 UI 或 UX 还没定,也足够让贡献者开始做产品和技术规格。

之后定时运行的 improver Agent 认证到 GitHub,通过 Skill 自带的 Python 脚本拉取最近带反馈的 issue,整理为 JSON,再据此提出最小改动。它开了一个 PR,让 base skill 学会在满足相应条件时打上 ready to spec。

这里至少有四个很容易被忽视的设计。

第一,反馈发生在原工作流里。开发者本来就要评审 PR、维护 issue,不必再做一次反馈提交。低摩擦不是体验优化,而是数据管道能不能活下去的前提。

第二,反馈里要有理由。一个 👎 只能告诉你结果不好,无法告诉 Agent 下次怎么做。相比之下,指出规则、边界和反例的两三句话,哪怕数量少,也可能非常有价值。

第三,improver 追求最小变更。它不是根据十条抱怨重写整个 Skill,而是把一个可验证的缺口补上。这让 diff 可读,也让回滚有抓手。

第四,人没有被踢出循环。自动化负责收集、归纳和起草。是否把规则写进团队的长期行为,仍由人通过 PR 决定。

最后这一点尤其关键。很多人把人审当成自动化不彻底,其实它恰好是系统的安全阀。Agent 改生产代码要 review,Agent 改自己的行为契约更应该 review,因为后者会影响之后所有任务。

别把原则写成 if else 的墓地

Warp 的建议里,有一句我很认同。写原则,不要写穷举规则。

比如代码审查 Skill 中写「寻找重复代码,并结合现有抽象判断它是否值得收敛」,通常比列出二十种变量名模式更靠谱。模型需要的是判断空间,而不是一部永远写不完的交通法规。

但这并不等于规则越少越好。涉及安全、权限、资金和发布的约束,应该明确且可执行。比如禁止把密钥写入日志,禁止未经批准调用生产环境写接口。这些不能靠模型领会氛围。

我自己的划分是这样的。

  • 原则,适合表达代码质量、沟通方式、审查取向,以及为什么这样做
  • 规则,适合表达权限边界、合规要求、确定的输入输出格式
  • 脚本,适合表达可重复校验,例如运行测试、扫描依赖、检查 YAML
  • memory,适合表达任务中暂时有用但不该成为组织制度的事实

这不是文字洁癖。把可确定的事情交给脚本,能让模型少背一点锅。把需要权衡的事情写成原则,能避免 Skill 退化成脆弱的关键词匹配器。

很多团队的失败尝试,恰好是反过来的。让模型猜一条硬边界,又用几千字规则约束它如何表达一个审美判断。前者危险,后者低效。

在 Java 和 Spring 团队里,闭环应该长什么样

假设你有一个 Spring Boot 代码审查 Agent。它会读取 PR diff、模块依赖和关键测试,输出建议。一个稳妥的目录可以从非常小的结构开始。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
skills/
spring-review/
SKILL.md
references/
reactor-webflux.md
persistence.md
scripts/
collect_feedback.py
run_checks.sh
improve-spring-review/
SKILL.md
scripts/
summarize_feedback.py
propose_patch.py

spring-review 的 SKILL.md 只放任务入口、审查原则和资源索引。关于 Reactor 上下文丢失、阻塞调用、事务边界这类细节,放在 references 中按需加载。能通过 Maven、ArchUnit、SpotBugs 或自定义脚本确定的问题,先让脚本跑出来,再让 Agent 解释优先级。

improve-spring-review 不应该直接改 main 分支。它做三件事就够了。

  • 收集有明确人类反馈的评论、issue 或评审线程
  • 过滤掉没有理由的情绪表达,并按主题聚类
  • 针对一个主题生成小 diff、证据链接和建议测试

然后它创建一个普通 PR。PR 描述至少要回答三件事。哪几条反馈触发了改动。Skill 原来在什么场景失效。新规则会不会误伤另一个场景。

这其实很像 Spring 团队熟悉的配置变更流程。你不会因为某次线上告警就让服务运行时随手改 application.yml。你会记录现象、复现、提交变更、跑测试、灰度观察。Agent 的行为配置也该有同样的纪律。

再往前一步,LangGraph 一类框架可以把这条链画成两个图。执行图只处理用户任务。改进图以低频定时任务运行,输入是已经标注来源的反馈集合,输出是候选规则补丁。二者共享 Git,却不共享执行时的任意状态。

分开之后,排查会轻松很多。某次审查跑偏,是 execution graph 的检索和上下文出了问题。某条长期行为变坏,则去查 improvement graph 的数据过滤、提示词或审批记录。别把它们都叫 Agent memory,然后对着一团黑箱发愁。

反馈不是越多越好,错误反馈会被复利放大

一旦听到「自我改进」,有些人自然会想到把点赞、踩和所有评论一股脑喂给 Agent。这是最需要克制的地方。

Warp 也明确提到,详细的领域反馈比大量粗糙信号更有用。而且反馈可能就是错的。谁的反馈能进入训练材料,Agent 是否能结合上下文做 sanity check,最终是否有人批准,都要预先设计。

一个现实例子是,资深开发者对某个 PR 评论「这里别上缓存」。如果 improver 只看这句话,它可能把「禁止缓存」写进全局 Skill。可原评论真正针对的是支付状态这种强一致数据,换到商品详情接口反而会误伤性能。

所以反馈记录至少要有这些字段。

  • 原始任务和相关代码版本
  • Agent 的原始输出
  • 人类反馈原文和反馈者角色
  • 反馈所处模块、风险级别和适用范围
  • improver 的归纳结果
  • 拟修改的 Skill 版本和最终审批结果

有了这些字段,你才有能力追溯。没有它们,所谓持续学习只是持续污染。

这块需要注意一下,安全类 Agent 更不能只看正反馈。攻击者、误操作用户,甚至一个图省事的同事,都可能给出诱导性反馈。对于安全审计、权限申请和运维执行,应该限制可采信的反馈者,保留人工终审,并把高风险规则绑定到可执行测试。不能验证的地方,就把自动更新的权限降下来。

衡量改进,别只盯着模型分数

一个 Skill 合并后,怎样知道它真的变好了。

只看 Agent 自己的自评没什么用。只看用户点了多少赞也不够,因为用户可能懒得反馈。Warp 建议观察团队原本就在看的全局指标,例如合并时间、贡献者数量和成本。

对研发 Agent,我会再加几项。

  • 被采纳的评论比例,但要区分不同风险等级
  • 人工撤回或标记为噪声的比例
  • 同类错误在后续任务中的复发率
  • 从触发到给出可用结果的耗时
  • 单个任务的 token、工具调用和人工复核成本

别只追求采纳率。一个只报绝对确定问题的 Agent 可能采纳率很高,却错过了真正棘手的设计风险。评估要回到 Agent 的职责。安全审计看漏报代价,代码 review 看信噪比,客服流程看解决率和升级率。

Anthropic 在 3 月更新 skill-creator 时,把这个方向说得更具体。它支持为 Skill 写 eval,追踪通过率、耗时和 token 消耗,还能让独立 Agent 并行跑测试,避免不同样本之间的上下文串味。也支持把两个版本盲测对比。

这里有个很有用的反直觉。一个 capability uplift Skill 的评估,不只是证明它有效,也可能证明它已经不必要了。若基础模型不加载该 Skill 也能稳定通过 eval,保留它只会增加上下文和维护成本。该删就删,别把 Skill 数量当成团队资产规模。

从一个窄场景开始,别一上来造自我进化平台

把这套方法搬进组织时,我建议选一个可验证、反馈密度高、影响范围小的场景。issue triage、依赖风险初筛、PR 标签分类,都比直接让 Agent 改业务逻辑合适。

第一周先不做自动更新。只收集反馈,建立几个 golden cases,并手工把两三个高质量反馈转成 Skill diff。你会很快看清团队的反馈是否足够具体,现有 Skill 是否过大,哪些问题其实该交给确定性脚本。

第二周才让 improver 自动起草 PR,但不自动合并。每一个补丁都要跑现有 eval,并且做一次 skill vs no-skill 对比。这里没有捷径,先把验证 harness 建起来,再谈让 Agent 调参。

等到连续几个周期都能看到可解释的提升,再扩到第二个 Agent。到那时,improver 可以共享一个模板,领域 Skill 仍然各自维护。共享的是收集、过滤、评估和 PR 协议,不是把所有业务知识搅成一锅。

这条路不如「Agent 自动从每次交互学习」听起来性感。但它有一个优势,出了问题你知道去哪里找,想停下来也有一个清晰的开关。

Agent 不会因为多跑几次就变成团队成员。

它会变好,是因为团队把经验留下来,把经验的来源保留下来,并且愿意像审代码一样审它将来的行为。

资料出处