Agent 的 App Store 来了:写一个 SKILL.md,Java Agent 立刻多一项新技能

本文基于 Agent Skills 开放规范(agentskills.iospring-ai-agent-utils 0.11.0Spring AI Alibaba 1.1.2.0编写,事实核对自 agentskills.io 规范页、anthropics/skills 仓库与两个框架的官方文档。该领域迭代极快,请以官方文档为准。

开篇:Agent 也该有个应用商店

2008 年 App Store 上线之前,手机出厂什么样就是什么样------电话、短信、浏览器,能力边界焊死在固件里。之后的故事我们都知道了:能力变成可以随时安装的东西

2026 年的 AI Agent 正站在同一个节点上。你精心装配了一个 Java Agent:它能读写文件、执行 Shell、调用 MCP 工具,骨架很完整。然后你让它干一件具体的事------比如"把这个库发到 Maven Central"------它开始胡言乱语:编造 Sonatype 的流程、忘记 GPG 签名、把 SNAPSHOT 版本直接 deploy 上去。

问题不是模型笨,是它缺经验。而你司那位每次发版都一次过的高级工程师,经验全在他的脑子里和一篇内部 Wiki 里。

Agent Skills 干的就是这件事:把领域经验打包成一个文件夹,Agent 需要时自动加载 。它由 Anthropic 在 2025 年底发布为开放标准,官方仓库 anthropics/skills 目前已有 171.9k stars,Claude Code、Cursor、Codex CLI、OpenCode 等约 30 款 Agent 产品都能读这个格式。

而它最反直觉的地方在于:给 Agent"装应用",不用编译、不用 API、不用重启进程------写一个 Markdown 文件就行

这篇文章把规范讲透,再给出 Java 侧的两条落地路径,最后手写一个能在你项目里直接用的技能。

一、先分清:MCP 管"接工具",Skills 管"装技能"

写过 MCP Server 的读者(上一篇【一个 @McpTool 注解,让 Claude 和 Cursor 直接调用你的 Spring 服务】我们刚写过)容易把 Skills 理解成又一个工具协议。它们解决的是两个维度的问题:

维度 MCP Agent Skills
扩展什么 Agent 的:能操作哪些外部系统 Agent 的:具备哪些领域经验
形态 运行中的服务(JSON-RPC over Streamable HTTP / STDIO) 一个静态文件夹(SKILL.md + 资源)
类比 USB-C 外设:接上就有新硬件 App:装上就有新软件
谁执行 Server 进程干活 Agent 用已有的工具照着说明干活
上下文成本 工具 schema 常驻上下文 元数据常驻,正文激活时才加载

还是拿"发布 Maven Central"举例,两者是互补而非竞争关系:

  • MCP 提供通道 :一个 mvn 执行工具让 Agent 能跑命令------但它不知道该跑什么命令、什么顺序;
  • Skill 提供剧本:先查 POM 必填字段、再确认非 SNAPSHOT、GPG 签名、deploy、close、release,以及每一步的经典翻车点。

Agent 拿着剧本(Skill),通过通道(MCP/Shell 工具)把活干了。这就是 2026 年 Agent 扩展的完整拼图。

二、技能包长什么样:一个带说明书的文件夹

规范定义的技能包结构,全部约定就这么多:

bash 复制代码
maven-central-release/
├── SKILL.md              # 必需:元数据 + 指令正文
├── scripts/              # 可选:可执行代码(Python/Bash/JS 均可)
│   └── verify-signature.sh
├── references/           # 可选:按需阅读的文档
│   └── GPG-TROUBLESHOOTING.md
└── assets/               # 可选:模板、数据文件

核心是 SKILL.md,格式为 YAML frontmatter + Markdown 正文

markdown 复制代码
---
name: maven-central-release
description: Guides through publishing Java artifacts to Maven Central via the Central Portal, including POM checks, GPG signing and staging release. Use when the user wants to release, publish or deploy a library to Maven Central.
license: Apache-2.0
metadata:
  author: lambert
  version: "1.0"
---

# Maven Central 发布流程

(正文:具体指令,见第七节完整示例)

frontmatter 字段全表:

字段 必需 约束 说明
name 1--64 字符,小写字母/数字/连字符,须与目录名一致 不能大写、不能 - 开头结尾、不能连续 --
description 1--1024 字符 整个技能的灵魂,Agent 靠它判断何时激活
license --- 许可证名或指向捆绑许可文件
compatibility ≤500 字符 环境要求,如 Requires git, jq and network access
metadata string→string 映射 任意扩展:author、version 等都放这里(没有顶层 version 字段
allowed-tools 空格分隔 预批准工具列表,实验性,各实现支持不一

两个容易被忽视的细节:

description 是给模型看的,不是给人看的。 规范的好例子/坏例子对比很直白------Helps with PDFs. 是坏例子;Extracts text and tables from PDF files... Use when working with PDF documents or when the user mentions PDFs, forms, or document extraction. 是好例子。后者把做什么何时用都写全了,还埋了触发关键词。写技能时在这上面花的时间,回报率最高。

没有编译,没有注册中心。 一个文件夹扔进约定目录(Claude Code 是 .claude/skills/),Agent 下次启动就能发现它。"技能即文件"和 T01 里"子 Agent 即 Markdown" 是同一套扩展哲学:声明式配置 + 运行时发现------Spring 开发者应该感到眼熟,这不就是 component scanning 吗。

三、最妙的设计:渐进式加载(Progressive Disclosure)

如果一百个技能的正文全部常驻上下文,Agent 还没干活 token 就烧完了。规范的解法是三层按需加载:

层级 加载内容 加载时机 Token 预算
第 1 层:元数据 name + description 启动时全部技能都加载 每技能约 100
第 2 层:指令 SKILL.md 完整正文 技能被激活时才加载 建议 < 5000
第 3 层:资源 scripts/ references/ assets/ 执行中按需读取 视需要而定

对应到 Agent 的运行时:

  1. 启动时,100 个技能只占用约 1 万 token 的"目录页";
  2. 用户说"帮我发个版",模型比对 description 判断 maven-central-release 相关,调用技能工具,正文(八步发布流程)这时才进入上下文;
  3. 执行到 GPG 签名报错,Agent 才去读 references/GPG-TROUBLESHOOTING.md,定位问题后继续。

配套的工程约束也清晰:SKILL.md 保持在 500 行以内 ,细节拆到 references/;文件引用一层深度、走相对路径,避免 A 引 B、B 引 C 的加载链。

这套设计值得每个做 Agent 应用的人细品------它本质上是一份上下文预算的分配方案:常驻的只留目录,重的内容全部惰性加载。同样的思路可以(也应该)用在你自己的系统提示词、工具描述、知识库注入上。此前业内把这叫 Context Engineering,Skills 规范给出了它的第一个大规模标准化实践。

四、生态现状:商店已经开业

一个"App Store"要成立,需要三样东西:标准、货架、装机的手机。Agent Skills 三样都有了。

标准 :规范独立维护在 agentskills.io,不绑定任何厂商。配套 skills-ref 参考实现(含 skills-ref validate 命令)可以校验技能包合规性。

货架 :官方仓库 anthropics/skills 按"创意与设计 / 开发与技术 / 企业与沟通 / 文档技能"分类陈列,其中 docx/pdf/pptx/xlsx 四个文档技能是 Claude 文档能力的底层实现(source-available),另有 Notion 等合作伙伴的官方技能。社区侧,GitHub 上的 Claude Code Skills 已超过 1400 个,官方 plugin marketplace 收录 650+。安装体验是真·App Store 式的:

bash 复制代码
/plugin marketplace add anthropics/skills
/plugin install document-skills@anthropic-agent-skills

装机的手机 :Claude Code(插件方式)、Claude.ai(付费计划内置全部示例技能)、Claude API(Skills API 上传自定义技能);规范侧则是约 30 款第三方 Agent 产品(Cursor、Codex CLI、OpenCode 等,见官方 Client Showcase 收录)都能直接读 SKILL.md------一次编写,处处运行,这就是开放标准该有的样子。

对 Java 开发者,真正的问题只剩一个:我的 Spring Agent 怎么"装机"? 两条路径。

五、路径一:spring-ai-agent-utils 的 SkillsTool

T01 介绍过这个"Java 版 Claude Code"工具库,其中 SkillsTool 就是 Agent Skills 规范的 Spring AI 原生实现。当前版本 0.11.0(SkillsTool 的装配 API 与 0.10.0 保持一致)。

最小装配:

java 复制代码
@Bean
CommandLineRunner runner(ChatClient.Builder chatClientBuilder,
        @Value("${agent.skills.paths}") List<Resource> skillPaths) {

    return args -> {
        ChatClient chatClient = chatClientBuilder
                .defaultTools(
                    // 技能系统:运行时扫描 SKILL.md
                    SkillsTool.builder()
                        .addSkillsResources(skillPaths)
                        .build(),
                    // 技能的"手脚":没有这些,技能只是纸上谈兵
                    FileSystemTools.builder().build(),
                    ShellTools.builder().build())
                .build();
        // ...
    };
}
properties 复制代码
# 支持通配符扫描,classpath 与文件系统均可
agent.skills.paths=classpath:/skills/*/SKILL.md,file:.claude/skills/*/SKILL.md

机制拆解------SkillsTool 与第 2、5 节的规范是如何对应的:

  • SkillsTool 实现的是 ToolCallbackProvider 接口:启动时扫描所有 SKILL.md 的 frontmatter,把每个技能动态注册成一个工具 ------工具名取 name,工具描述取 description。这就是第 1 层加载:约 100 token 的元数据常驻;
  • 模型判断某个技能与当前任务相关、发起工具调用,此时才读取 SKILL.md 正文------第 2 层;
  • 正文中引用的 references/scripts/,Agent 用 FileSystemToolsShellTools 按需读取执行------第 3 层。

也就是说,规范的"渐进式加载"在 Spring AI 里被映射成了"动态工具生成":技能的发现靠工具描述,技能的激活就是一次工具调用。很优雅------没有引入任何新抽象,全部建立在既有的 Tool 体系上。

两个进阶用法(0.x 版本 API 迭代较快,以 examples/skills-demo 与官方文档为准):

java 复制代码
// 1. 子 Agent 也能带技能:TaskTool 委派时共享技能目录
var taskTools = TaskToolCallbackProvider.builder()
        .chatClientBuilder(chatClientBuilder.clone())
        .skillsDirectories(".claude/skills")   // 方法名以官方示例为准
        .build()
        .getToolCallbacks();

// 2. ClaudeSubagentType 上按子 Agent 粒度注入
ClaudeSubagentType.builder()
        .chatClientBuilder("release-engineer", chatClientBuilder.clone())
        .skillsResources(skillPaths)
        .build();

设想一个组合:主 Agent 把"发版"任务委派给一个只挂了 maven-central-release 技能和 Shell 工具的子 Agent------技能限定 + 工具最小权限,发版这种高危操作就有了执行边界。

官方在 examples/skills-demo 提供了完整示例(含 ai-tuto 演示技能),cd examples/skills-demo && mvn spring-boot:run 即可体验。

六、路径二:Spring AI Alibaba 的 Skills 体系

如果你的技术栈是阿里系(DashScope / Qwen / Graph 编排),SAA 从 1.1.2.0(2026-02 发布)开始原生支持 Agent Skills,且集成面更广(从 ReAct 智能体到 Graph 工作流都有接入口):

  • ReactAgent 集成 :通过 SkillsAgentHook 把技能挂进 ReAct 循环,实现"技能发现 → 按需加载 → 工具执行"全流程自动化;
  • Graph / ChatClient 链路:不使用 ReactAgent 的 Graph 工作流或纯 ChatClient 应用同样可以接入技能(通过对应的 Hook / Advisor 机制);
  • 可扩展的注册中心 :内置 FileSystemSkillRegistry / ClasspathSkillRegistry 两种技能注册中心,并开放 SkillRegistry 扩展接口------实现该接口即可接入自建存储体系,社区已有 OSS 远端存储 + 多租户的实践案例(按团队、按组织集中管理技能库)。中心化能力是"可扩展"出来的,不是开箱即用的,选型时要算上这层自研成本。

具体 API 以 官方 Skills 教程 为准。一个务实的选型判断:Spring 原生技术栈 + 本地/仓库内技能管理 → agent-utils;阿里云生态 + 愿意基于 SkillRegistry 自建中心化技能库 → SAA。两者读的是同一份 SKILL.md,技能资产本身可迁移。

七、实战:写一个"Maven Central 发布"技能

现在把三层加载机制走成一遍真实流程。选"发布 Maven Central"这个场景是有讲究的:流程繁琐(POM 规范、GPG 签名、staging、同步等待)、经验密集(每一步都有经典翻车点)、且是 Java 开发者的高频痛点------这正是技能的甜区:知识在文档里躺着,但组合运用需要老手经验

第 1 步:创建技能包

sql 复制代码
.claude/skills/maven-central-release/
├── SKILL.md
└── references/
    └── GPG-TROUBLESHOOTING.md

第 2 步:写 SKILL.md

markdown 复制代码
---
name: maven-central-release
description: Guides through publishing Java artifacts to Maven Central, covering POM verification, GPG signing, staging deployment and release. Use when the user wants to release, publish, or deploy a library to Maven Central, or mentions Sonatype, OSSRH or the Central Portal.
license: Apache-2.0
metadata:
  author: lambert
  version: "1.0"
---

# Maven Central 发布流程

按以下步骤操作。任何一步失败,先读 references/GPG-TROUBLESHOOTING.md(仅签名问题)再重试。

## 发布前检查(不可跳过)

1. 确认版本号非 SNAPSHOT:`mvn help:evaluate -Dexpression=project.version`
2. 确认 POM 含全部必填字段:name、description、url、licenses、developers、scm
3. 确认 javadoc 与 sources jar 已配置(maven-javadoc-plugin / maven-source-plugin)
4. 确认 GPG 密钥未过期,且公钥已上传至 keyserver.ubuntu.com

## 发布

5. 先本地演练:`mvn clean package -P release`,并验证签名(逐一指定文件,勿用 `*.asc` 通配------glob 展开后第二个 .asc 会被当作被签数据):
   `gpg --verify target/mylib-2.1.0.jar.asc target/mylib-2.1.0.jar`
6. 确认无误后执行 `mvn clean deploy -P release`(release profile 含 GPG 签名配置)
7. 登录 Central Portal(central.sonatype.com),找到 staging 仓库,逐项检查:
   - POM 渲染正常、坐标正确
   - 三个 jar(main/sources/javadoc)与 .asc 签名文件齐全
8. 点击 Publish,记录发布坐标

## 发布后

9. 同步需要 30 分钟到 2 小时,用以下命令验证可拉取:
   `curl -sI https://repo1.maven.org/maven2/<group-as-path>/<artifact>/<version>/`

## 已知翻车点

- deploy 报 401:检查用户 token(不是账号密码),server id 必须与 POM 中 distributionManagement 的 id 一致
- 签名验证失败:见 references/GPG-TROUBLESHOOTING.md
- 404 但 Portal 显示已发布:同步延迟,等满 2 小时再排查

注意这个文件的写法处处体现第 2、3 节的规范:正文只放流程主干与高频翻车点(约 60 行,远低于 500 行红线);GPG 深度排查这种低频内容拆到 references;description 里埋足了触发关键词(release、publish、Sonatype、Central Portal)。

第 3 步:写按需加载的 references

markdown 复制代码
# GPG 签名问题排查

(GPG-TROUBLESHOOTING.md,仅在签名失败时被 Agent 读取)

## gpg: signing failed: No secret key
密钥不在当前 keyring。检查:`gpg --list-secret-keys`。
若为空,导入备份或重新生成:`gpg --full-generate-key`(选择 RSA 4096)。

## gpg: signing failed: Inappropriate ioctl for device
PIN 输入程序在无终端环境不可用。pom.xml 的 gpg 插件配置加:
<configuration><gpgArguments><arg>--pinentry-mode</arg><arg>loopback</arg></gpgArguments></configuration>

## keyserver 上传后仍提示找不到公钥
keyserver 同步有延迟(可达数小时)。可换用 keys.openpgp.org 的上传 API(注意是 POST,不是 `curl -T` 的 PUT):
`gpg --export -a <key-id> | curl -X POST -F 'key=@-' https://keys.openpgp.org/v1.0/upload`
上传后需按提示完成邮箱验证,公钥才可被检索。

第 4 步:校验并注册

bash 复制代码
# 规范校验(skills-ref 参考实现)
skills-ref validate .claude/skills/maven-central-release

然后按第五节的装配代码把 .claude/skills/*/SKILL.md 挂到 SkillsTool

第 5 步:验证

对 Agent 说:

"我要把项目发到 Maven Central,2.1.0 版本"

观察它的行为:模型比对 description 判断 maven-central-release 技能命中 → 调用技能工具加载正文 → 从第 1 步开始执行,检查版本号时发现你忘了去 SNAPSHOT 后缀,主动叫停并提示你 ------这就是"技能生效"的样子:它不只是会执行,还知道什么时候不该继续

八、Skill、MCP、子 Agent:什么时候用哪个

三者经常被混为一谈,用一张表收束:

扩展需求 用什么 例子
注入领域知识 / 操作流程 Skill 发布流程、公司规范、代码审查清单
接入外部系统 / 数据源 MCP 数据库查询、内部 API、SaaS
隔离执行环境 / 并行分工 子 Agent 大范围代码检索、独立评审任务
复杂能力 组合使用 Skill 提供剧本,MCP 提供通道,子 Agent 提供隔离舞台

判断口诀:知识用 Skill、通道用 MCP、隔离用子 Agent

小结

回到开篇的对照:手机的能力边界曾焊死在固件里,App Store 把它变成了可安装的。Agent Skills 对 AI Agent 做了同一件事------而且比 App Store 更彻底:装一个"应用"的成本低到了写一个 Markdown 文件

对 Java 开发者,这件事有三层价值:

  1. 直接可用:agent-utils 与 SAA 两条路径都已支持规范,你的 Spring Agent 今天就能"装机";
  2. 技能资产可沉淀:团队的老手经验(发版流程、联调排障、线上预案)第一次有了标准化的封装格式,写一次、所有 Agent 通用;
  3. 架构可借鉴:渐进式加载是一份生产级的上下文预算方案,即使不用 Skills,这套"目录常驻、正文惰性"的思路也适用于任何 Agent 的提示词工程。

下一步,我会继续沿着"Agent 的经验从哪来"这条线写下去------技能解决了经验的外置,记忆解决状态的持久,两者合起来就是长时程 Agent 的基础。系列后续见下方导航。

参考资料

相关推荐
Web3_Basketball15 分钟前
从0到1落地模型供应链审计RAG依赖来源校验:踩坑全记录
ai编程
用户75650617861117 分钟前
开发 Nemu 的第二天:从会说话,到受控地看懂钉钉
ai编程
小羊4318 分钟前
Agent的任务拆解艺术:从目标到可执行子任务
ai编程
桃西西呀2 小时前
模型都能自己写代码了,你的 Agent 为什么还接不进一个日历?——一篇讲透 MCP 这个 AI 世界「USB-C」
人工智能·ai编程·mcp
刘广睿2 小时前
AI 生图从玄学到工程:Stable Diffusion、ComfyUI 与 Midjourney 的原理与 Prompt 方法论
aigc·stablediffusion·comfyui·ai生图
Csvn2 小时前
第 7 章 MCP 标准化工具接入
人工智能·aigc·agent
zynio2 小时前
手写 RAG 知识库问答智能体:混合检索 + 查询改写 + 抗幻觉,黄金集实测全过
ai编程
心易行者3 小时前
html在线运行搭AI编程验证流水线:5步走完从生成到到上线全流程
人工智能·python·ai编程
xiezhr4 小时前
别把豆包当聊天用了,现在的豆包和以前不一样了
agent·ai编程·豆包marscode