Skill 不是 Prompt 模板,而是 Code Agent 的领域知识接口

0 阅读13分钟

cover.png

很多人第一次把 Code Agent 接进老项目,都会经历一个落差:

Demo 里它能十分钟写完一个 CRUD;一进真实业务系统,它开始犯一些“刚入职新人”才会犯的错。

它能看懂 Controller,却不知道这个字段为什么不能改;它能补一个接口,却不知道下游有个定时任务依赖这个状态;它能生成 SQL,却不知道这个表的历史脏数据需要兼容;它能跑测试,却不知道真正危险的逻辑藏在一个没有测试覆盖的分支里。

这时候很多人的第一反应是:是不是模型还不够强?

模型当然重要,但在复杂项目里,另一个问题更致命:你的仓库没有给 Agent 暴露“领域知识接口”。

人类开发者可以靠老人带、会议纪要、群聊上下文、历史事故记忆来理解项目。Code Agent 没有这些。它能看到的,通常只有当前上下文窗口里的代码、文档、工具返回和你临时塞给它的 Prompt。

所以,今天这篇想讲清楚一个判断:

Skill 不是 Prompt 模板,而是把团队知识、业务约束、代码路径和验证动作,整理成 Agent 能按需加载、能执行、能校验的领域知识接口。


一、为什么复杂项目会让 Code Agent 变“笨”

layered-control-panel.png

Code Agent 写新项目往往很顺,因为新项目的信息密度低:

  • 目录结构简单;
  • 业务规则少;
  • 历史包袱少;
  • 改错成本低;
  • 代码和需求基本同频。

但老项目完全不同。真正影响 Agent 质量的,不是代码行数本身,而是代码背后的隐性知识。

比如一个女装电商项目里,“商品审核通过后是否自动上架”听起来只是一个字段,但它可能同时牵扯:

  • 平台审核状态;
  • 本地商品状态;
  • 库存是否可售;
  • 店铺是否授权;
  • 是否触发同步任务;
  • 是否允许人工覆盖;
  • 是否要兼容抖店、微信小店等不同平台语义。

如果这些知识只散落在口头经验、历史需求、接口文档、数据库字段备注、微信群截图里,Agent 就只能靠局部代码猜。

局部猜测的问题在于:它通常“看起来对”,但不一定“在这个项目里对”。

这也是为什么 OpenAI 在 Codex 的 Harness Engineering 文章里强调:不要把一个巨大的 AGENTS.md 当百科全书,而是把它当目录,用结构化的仓库知识作为系统事实来源。因为上下文是稀缺资源,巨大的说明书会挤占任务、代码和真正相关的资料。

Anthropic 的 Claude Code 文档也给了类似思路:CLAUDE.md、Skills、Rules、Memory 这些机制,本质上都在解决同一个问题:如何让模型在需要的时候拿到正确范围的项目知识,而不是每次都从零开始猜。


二、Prompt、Rules、Memory、Skill 到底有什么区别

很多团队把这些概念混在一起,最后变成一个超长 Prompt:

“你是资深 Java 架构师,请遵守我们的代码规范,请理解我们的订单系统,请不要改数据库,请注意幂等,请先看这些文件……”

这不是工程化,只是把口头交代换成了文本交代。

更好的做法是把不同类型的上下文分层。

类型适合放什么典型形式风险
Prompt当前这一次任务“帮我新增商品同步接口”一次性、不可复用
Rules / Instructions全仓库通用约束AGENTS.mdCLAUDE.md.github/copilot-instructions.md太长会稀释重点
Memory长期偏好和经验个人偏好、项目习惯、反复纠错记录可能过期或污染
RAG / Knowledge Base大体量外部知识文档库、规范、接口资料检索质量决定效果
Skill可触发的领域能力包SKILL.md + references + scripts需要维护和验证

progressive-disclosure-workbench.png

一句话区分:

  • Prompt 是“这次要做什么”;
  • Rules 是“在这个仓库里都要遵守什么”;
  • Memory 是“长期记住我和项目的偏好”;
  • RAG 是“需要时去外部查资料”;
  • Skill 是“遇到某类任务时,加载一套可执行的领域知识和工作方法”。

所以 Skill 不应该写成:

你是一个资深后端工程师,写代码要优雅。

它更应该像这样:

---
name: product-sync
description: 处理抖店/微信小店商品同步、审核状态、自动上架语义映射时使用
---

# 商品同步 Skill

## 什么时候使用
- 修改商品创建、更新、审核、上架、库存同步逻辑
- 对接抖店、微信小店等平台商品接口
- 处理本地商品状态与平台状态映射

## 关键业务约束
- 平台审核通过不等于本地立即可售,必须同时检查库存、店铺授权、上架策略
- 自动上架字段只表示“审核通过后的期望动作”,不是强制覆盖人工下架
- 跨平台字段语义不能直接复用,必须经过映射表

## 代码入口
- 商品同步服务:`xxxProductSyncService`
- 状态映射:`ProductStatusMapping`
- 平台适配器:`DouyinProductAdapter``WxShopProductAdapter`

## 验证动作
- 修改状态映射后运行 `scripts/agent-checks/verify-product-status.ps1`
- 新增平台字段时补充接口字段审计文档

这就不是“提示词模板”了,而是一个能被触发、能导航代码、能携带约束、能调用验证脚本的知识接口。


三、一个可用的 Skill,应该长什么样

Anthropic 的 Claude Code Skills 文档里有一个很关键的设计:每个 Skill 至少有一个 SKILL.md,里面包含 YAML frontmatter 和正文说明;复杂 Skill 可以把模板、示例、脚本、参考文档放到同一目录下,并在需要时再加载。文档还特别提醒,SKILL.md 本体要保持聚焦,详细资料放到 supporting files 里。

这背后的工程思想叫“渐进披露”:先让 Agent 看到索引和使用条件,只有任务真的需要时,再加载更深的材料。

agent-friendly-repo-blueprint.png

一个实用 Skill 通常由四层组成:

1. Metadata:让 Agent 知道什么时候该用

最重要的是 description,它不是给人看的广告语,而是给模型做路由判断的触发条件。

坏例子:

description: 商品相关开发

好例子:

description: 修改商品同步、审核状态、自动上架、平台字段映射、库存可售状态时使用

越贴近真实任务语言,越容易被正确触发。

2. Main Instructions:只放高频、稳定、关键的规则

SKILL.md 不是仓库百科。它应该回答:

  • 这个领域的核心概念是什么;
  • 最容易改错的地方是什么;
  • 代码入口在哪里;
  • 修改前必须检查什么;
  • 修改后必须验证什么。

不要把几十页接口文档全部塞进去。那会让 Skill 退化成新的“巨型 Prompt”。

3. References:把低频细节放到可按需读取的文档里

例如:

.claude/skills/product-sync/
  SKILL.md
  references/
    douyin-product-fields.md
    wxshop-product-fields.md
    status-mapping.md
    historical-incidents.md

这样 Agent 处理抖店字段时读抖店资料,处理微信小店字段时读微信资料,不必每次把所有平台细节都塞进上下文。

4. Scripts:把“应该检查”变成“可以执行”

文档是软约束,脚本是硬反馈。

比如:

scripts/agent-checks/
  verify-product-status.ps1
  verify-platform-field-map.ps1
  verify-db-migration.ps1

当 Skill 告诉 Agent “修改字段映射后必须跑验证脚本”,这件事就从一句建议变成了可执行流程。OpenAI 在 Harness Engineering 里也提到,文档本身不够,架构约束、结构化测试、自定义 lint 才能持续防止系统漂移。


四、知识接口不是文档搬家,而是把知识变成可操作结构

很多团队做 Agent 知识库时会犯一个错误:把现有文档直接丢给模型。

这当然比没有强,但还不够。因为人类文档通常按“给人阅读”的方式组织,而 Agent 更需要“为任务决策”组织。

人类文档常见写法:

商品状态包括待审核、审核中、审核通过、审核拒绝、已上架、已下架……

Agent 需要的写法:

## 状态修改决策表

| 当前任务 | 必看文件 | 禁止行为 | 验证动作 |
|---|---|---|---|
| 新增平台审核字段 | `platform-field-map.md` | 不允许直接复用其他平台字段语义 | 跑字段映射校验 |
| 修改自动上架逻辑 | `auto-listing-policy.md` | 不允许覆盖人工下架状态 | 跑商品状态回归用例 |
| 调整库存可售判断 | `stock-policy.md` | 不允许只看平台库存字段 | 跑库存边界用例 |

区别在于:前者是资料,后者是接口。

资料告诉你“有什么”;接口告诉 Agent “遇到什么任务、去哪里看、不能做什么、做完怎么验”。

knowledge-quality-gate.png

我建议把团队知识拆成 6 类:

知识类型应该记录什么适合位置
领域词典业务名词、状态、枚举、平台语义差异docs/knowledge/domain/*.md
代码锚点领域概念对应哪些服务、表、接口、任务Skill / catalog
不变量绝对不能破坏的规则AGENTS.md / Skill
决策记录为什么当初这么设计ADR / design docs
事故经验哪些地方曾经踩坑references / incidents
验证动作改完如何证明没坏scripts / tests

这才是 Code Agent 能消费的知识。


五、比“没有知识”更危险的是“过期知识”

如果一个 Skill 写完就没人维护,它很快会变成风险源。

因为 Agent 会认真执行它。

一个过期的状态映射文档,可能比没有文档更危险;一个已经失效的架构规则,可能让 Agent 把正确的新代码改回错误旧模式;一个没人更新的历史说明,会让模型对当前业务做出错误判断。

所以 Skill 必须带反腐机制。

可以从四件事做起:

1. 给知识标注来源和成熟度

不要只写结论,至少记录:

  • 来源:官方文档、代码反推、需求评审、线上事故、人工确认;
  • 更新时间;
  • 负责人;
  • 成熟度:draft、verified、proven。

这和腾讯技术文章里提到的知识分层、成熟度、来源追踪思路是一致的:知识不是一次性文档,而是需要生命周期治理的资产。

2. 定期做“反向校验”

不是只检查代码是否符合文档,也要检查文档是否还符合代码。

例如:

  • 文档里写的入口类是否仍存在;
  • 决策表里的字段是否仍在数据库;
  • 状态枚举是否新增但文档未更新;
  • Skill 引用的脚本是否还能跑。

3. 把 Review 意见沉淀回知识接口

如果一次 PR 里人类 reviewer 反复指出“这个字段不能这么映射”,不要只改代码。

应该把这条经验写进对应 Skill,并补一个验证动作。否则下一次 Agent 还会犯同样的错。

4. 能用测试表达的规则,不要只写在文档里

文档适合表达语义,测试适合表达边界。

如果一个规则足够重要,就应该变成:

  • 单元测试;
  • 集成测试;
  • schema 校验;
  • lint;
  • migration check;
  • CI gate。

Agent 最适合在明确反馈里迭代。模糊的“注意一下”很难稳定生效。


六、一个 Java 后端项目怎么最小落地

你不需要一开始就搭一个“知识平台”。对大多数团队来说,先从仓库本地结构开始就够了。

your-project/
  AGENTS.md
  docs/
    knowledge/
      catalog.md
      domain/
        product.md
        order.md
        inventory.md
      decisions/
        2026-05-商品自动上架策略.md
      incidents/
        product-status-regression.md
  .claude/
    skills/
      product-sync/
        SKILL.md
        references/
          douyin-product-fields.md
          wxshop-product-fields.md
          status-mapping.md
  scripts/
    agent-checks/
      verify-product-status.ps1
      verify-platform-field-map.ps1

这里的分工很清楚:

  • AGENTS.md:只放仓库地图、通用约束、测试命令、禁区;
  • docs/knowledge/catalog.md:告诉 Agent 有哪些知识,分别解决什么问题;
  • docs/knowledge/domain/*.md:沉淀稳定业务概念;
  • .claude/skills/*/SKILL.md:面向具体任务触发;
  • references/:放平台字段、历史细节、长文档;
  • scripts/agent-checks/:放可执行验证。

一个好的 AGENTS.md 不应该超过几百行。它的角色不是“把所有知识说完”,而是导航:

# Agent Guide

## 仓库结构
- `metast-modules/product`: 商品域
- `metast-modules/order`: 订单域
- `docs/knowledge/catalog.md`: 领域知识索引

## 修改商品同步时
- 先阅读 `.claude/skills/product-sync/SKILL.md`
- 平台字段以 `docs/knowledge/domain/product.md` 和 Skill references 为准
- 禁止直接把一个平台字段语义套到另一个平台

## 验证
- 后端基础测试:`mvn test`
- 商品状态校验:`powershell scripts/agent-checks/verify-product-status.ps1`

这类结构的价值在于:它不会假设模型一次性记住所有东西,而是把仓库变成一张可导航的知识地图。

skill-eval-dashboard.png


七、怎么判断你的 Skill 真的有用

不要靠感觉判断。

可以用几个很朴素的指标:

指标问题
触发准确率Agent 遇到相关任务时会不会主动加载 Skill
导航准确率Agent 能否找到正确代码入口
约束命中率是否避免了已知禁区
首轮通过率第一次实现后测试/脚本通过多少
人工纠错数Reviewer 还需要指出多少领域性错误
知识回流率PR 里的新经验有没有沉淀回 Skill

如果一个 Skill 写完后,只是让回答看起来更专业,但不能减少返工、减少猜测、减少重复纠错,那它还不是工程资产。

真正有价值的 Skill,应该让 Agent 从“会写代码”变成“知道在这个仓库里怎样写才对”。


结尾:Prompt 是沟通,Skill 是接口

Prompt 解决的是“这次任务怎么说清楚”。

Skill 解决的是“同一类任务以后怎么稳定做对”。

这两者不是一个层级。

当项目很小、任务很新、上下文很少时,一个好 Prompt 就够了。但当项目变复杂,业务规则开始累积,团队经验开始沉淀,Agent 真正缺的不是更长的提示词,而是一个能访问、能导航、能验证、能演化的知识接口。

对开发者来说,这件事的意义也很直接:

以后写代码不只是“让人看得懂”,还要“让 Agent 能正确接手”。

代码结构、文档索引、测试反馈、领域知识、历史决策,都会变成 Agent 时代的软件工程基础设施。

也许几年后,一个成熟项目的标配不只是 README.mddocs/tests/,还会包括:

AGENTS.md
.claude/skills/
docs/knowledge/
scripts/agent-checks/

不是为了追新概念,而是因为复杂系统从来不缺代码,缺的是能被正确消费的知识。


参考资料