图片

让Java开发者像写Spring Boot一样开发AI应用——第二阶段第七篇

写在前面

前六天,我们解决了Agent的“动手”(工具调用)、“记忆”(短时+长时+画像)和“输出工程化”(结构化输出)问题。Agent已经能思考、能行动、能记住你、能按格式输出。

但还有一个更根本的工程问题没有解决:能力太多,塞不下。

一个企业级Agent可能需要几十种能力——PDF解析、Excel处理、代码审查、邮件发送、数据库查询……如果把这些能力的说明全部塞进System Prompt,Token会爆炸、模型会“选择困难”、能力难以复用和维护。

这就像让一个员工把所有岗位的操作手册都背下来——他记不住、容易搞混、新增一个岗位就得重新背一遍。

今天,我们给Agent装上一座“技能图书馆”——Agent Skills可扩展技能体系。

📌 本文是第二阶段“核心能力实战篇”的第七篇。Skills解决的是更上层的问题:如何把大量业务能力组织成可按需发现、按需加载、按需执行的模块化能力系统。今天是“核心能力实战篇”的收官之篇——Skills让Agent从“全能但臃肿”进化为“按需学习、精准调用”。

一、为什么需要Agent Skills?

传统方式的“三重困境”

在Skills出现之前,给Agent扩展能力的传统方式是:把所有工具的说明、使用场景、调用方法全部塞进System Prompt。

困境一:Token爆炸

一个企业级Agent可能需要几十种能力。如果把每个能力的说明都写进System Prompt,Token消耗会急剧膨胀,响应变慢、成本飙升。

困境二:模型“选择困难”

当一个Agent拥有几十个工具时,模型很难在每次对话中做出正确的工具选择决策。工具越多,模型选择越不稳定。

困境三:能力难以复用和维护

每次新增能力都要修改System Prompt,能力之间相互耦合,改一个可能影响全部。不同项目想复用同一个能力,只能复制粘贴。

💡 传统方式就像让一个员工把所有岗位的操作手册都背下来——他记不住、容易搞混、新增一个岗位就得重新背一遍。Skills则像给员工一个书架——需要做哪件事,就去翻对应的那本手册。

Skills的设计理念:渐进式披露

Spring AI Alibaba Skill采用渐进式披露(Progressive Disclosure)机制。

核心理念:先给“菜单”,再按需上“菜”。

| 步骤

|

做什么

|

类比

第1步

系统初始仅注入技能元数据(名称、描述、路径)

|

服务员给你看菜单

| | 第2步 |

模型判断需要使用某技能时,调用read_skill(skill_name)加载完整的SKILL.md

|

你点菜,厨师看菜谱

| | 第3步 |

按需访问技能资源、执行绑定工具

|

厨师按菜谱做菜

|

渐进式披露的核心价值:

| 价值

|

说明

省Token

不用一次性加载所有技能内容

| | 好维护 |

技能独立成目录,改一个不影响其他

| | 可复用 |

写好的技能可以在多个项目间共享

| | 易扩展 |

新增技能只需新建一个目录

|

二、Skills的目录结构与SKILL.md规范

标准目录结构

每个技能独立为一个子目录,SKILL.md为强制必需文件:

<span leaf="">skills/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span># 技能根目录</span></span>

各目录的职责:

| 目录/文件

|

必需性

|

职责

SKILL.md 必需

技能的核心描述文件,包含元数据和操作指南

| | references/ |

可选

|

存放参考文档、API说明、格式规范等

| | examples/ |

可选

|

存放使用示例代码或演示数据

| | scripts/ |

可选

|

存放可执行的Python/Shell脚本

|

💡 SKILL.md是唯一必需的文件——没有它,这个目录就不算一个Skill。

SKILL.md格式规范

SKILL.md采用YAML头(frontmatter)+ Markdown正文的格式。

基础格式:

  • <span leaf=""><span>---</span></span>
    
<span leaf=""><span>**必需字段说明**</span>[reference:21]:</span>

💡 同名技能在“项目级别”会覆盖“用户级别” 。projectSkillsDirectory指向项目目录下的skills文件夹,userSkillsDirectory指向用户目录下的~/saa/skills。

SkillsAgentHook——技能钩子

SkillsAgentHook负责两件事:

  1. 注入技能列表:将所有技能的元数据(name、description、skillPath)注入到系统提示中

  2. 注册read_skill工具:让模型可以通过调用read_skill(skill_name)加载完整的SKILL.md

<span leaf=""><span>SkillsAgentHook</span>&nbsp;<span>hook</span>&nbsp;<span>=</span>&nbsp;SkillsAgentHook.builder()</span>

💡 SkillRegistry是“书架”,SkillsAgentHook是“图书管理员”——书架负责存放所有书(技能),管理员负责把书名目录告诉读者(模型),并在读者需要时把具体的书拿给他。

四、技能发现→按需加载→工具执行全流程

完整工作流程

<span leaf="">用户:”帮我从这份PDF中提取表格数据”</span>

渐进式工具披露

Skills的一个精妙设计是渐进式工具披露——工具不是一开始就全部暴露给模型,而是跟随Skill按需加载。

传统方式:所有工具一次性注册 → 模型面对几十个工具,选择困难

Skills方式:

<span leaf="">第1步:系统提示中只有技能列表(没有工具)</span>

💡 传统方式像把所有工具都摆在桌面上——找起来费劲、容易拿错。Skills像工具墙——你需要什么工具,才从墙上取下来用。

代码示例:工具与技能绑定:

<span leaf=""><span>// 通过groupedTools将工具与技能名绑定</span></span>

Skill激活后的会话持久性

关键机制:一旦某个Skill被激活(即模型调用了read_skill),该技能在当前会话的后续轮次中仍然可用。

这意味着:

  • 用户说“帮我提取PDF数据” → 模型加载pdf-extractor技能

  • 用户接着说“再把提取的数据整理成表格” → 模型不需要重新加载该技能,直接使用

  • 同一个会话中,Skill只加载一次,但全程可用

五、实战代码

实战一:创建“PDF提取”Skill

Step 1:创建技能目录结构

<span leaf="">skills/</span>

Step 2:编写SKILL.md

<span leaf="">---</span>

3. 处理结果

  • 解析脚本输出的JSON

  • 将数据整理为易读的格式

输出格式

脚本返回JSON:

<span leaf="">{</span>
<span leaf="">**Step&nbsp;<span>3</span>:编写模拟执行脚本**</span>

实战二:实现技能自动发现与注册

Step 1:配置SkillRegistry和SkillsAgentHook

<span leaf="">package com.<span>example</span>.<span>skills</span>.<span>config</span>;</span>

实战三:让Agent根据任务自动加载对应Skill

<span leaf=""><span>@RestController</span></span>

课堂演示:运行并观察

| 用户输入

|

Agent行为

|

观察点

“请介绍你有些技能?”

|

从系统提示中读取技能列表

|

看到技能名称和描述

| |

“帮我从这份PDF中提取数据”

|

调用read_skill("pdf-extractor")

|

加载完整SKILL.md

| |

“再帮我整理成表格”

|

直接使用已加载的技能

|

技能在会话中持续可用

|

六、技能复用与插拔式架构设计

技能的可复用性

Skills的最大优势之一是可复用性:

  • 跨项目复用:写好的技能目录可以复制到任何Spring AI Alibaba项目中

  • 社区共享:技能可以打包成独立的模块,供团队或社区共享

  • 版本管理:每个技能独立版本,互不影响

💡 Skill就像乐高积木——你可以把一块积木用在任何项目中,也可以随时替换成另一块积木,而不影响整体结构。

插拔式架构设计

Skills支持插拔式架构——新增、删除、修改技能都不需要修改Agent的核心代码:

| 操作

|

方式

|

影响范围

新增技能

skills/目录下新建文件夹 + SKILL.md

|

只影响新技能本身

| | 删除技能 |

删除对应的技能文件夹

|

只影响被删除的技能

| | 修改技能 |

修改SKILL.md或脚本

|

只影响被修改的技能

|

生产环境注意事项

| 注意事项

|

说明

JAR包中的技能加载

Spring Boot打包成JAR后,FileSystemSkillRegistry可能无法正常加载。生产环境建议使用ClasspathSkillRegistry

| | 技能热加载 |

生产环境可配置技能自动重载,修改SKILL.md后无需重启应用

|

七、课后挑战

任务:创建3个不同领域的Skill

要求:

  1. Excel处理Skillexcel-processor
  • 功能:读取Excel文件、提取数据、生成报表

  • 触发词:Excel、.xlsx、表格处理、数据导出

  1. 网页爬取Skillweb-scraper
  • 功能:爬取网页内容、提取结构化信息

  • 触发词:网页、爬取、抓取、URL、链接

  1. 邮件发送Skillemail-sender
  • 功能:发送邮件、批量通知

  • 触发词:邮件、发送、通知、提醒

每个Skill需要包含:

  • 完整的目录结构(SKILL.md + 可选scripts/)

  • 清晰的YAML元数据(name + description)

  • 详细的Markdown正文(功能说明、使用方法、输入输出格式)

  • description中包含明确的触发关键词

验收标准:

  • 3个Skill的目录结构完整

  • 每个SKILL.md都包含正确的YAML头(name + description)

  • 每个SKILL.md的正文包含清晰的分步指令

  • Agent能通过read_skill成功加载每个Skill

  • Agent能根据用户问题自动选择正确的Skill

八、本日核心收获

  1. 传统方式有“三重困境” ——Token爆炸、模型选择困难、能力难以复用维护

  2. 渐进式披露是核心设计思想——先给“菜单”(技能列表),再按需上“菜”(加载完整SKILL.md)

  3. 标准目录结构——每个技能一个子目录,SKILL.md是唯一必需文件

  4. 四大核心组件——ChatModel(大脑)、SkillRegistry(书架)、SkillsAgentHook(图书管理员)、ReactAgent(智能体)

  5. 完整工作流程——发现(扫描技能列表)→ 加载(调用read_skill)→ 执行(按SKILL.md步骤操作)

  6. 渐进式工具披露——工具跟随Skill按需加载,避免模型“选择困难”

📌 本文是第二阶段“核心能力实战篇”的第七篇,也是收官之篇。七天时间,我们完整走过了Agent四大核心能力——工具调用(第7-8天)、记忆系统(第9-11天)、结构化输出(第12天)、Skills可扩展技能体系(第13天)。至此,Agent不仅会思考、会动手、会记忆、会按格式输出,还能按需加载海量能力而不臃肿。下一篇,我们将进入第三阶段“工程化与生产部署篇”,让Agent从“能跑”走向“能上线”。

有任何问题,欢迎在评论区留言交流!


作者:Java老兵搞AI,专注Java生态下的AI应用开发

如果觉得有用,点个「在看」支持一下吧,下期见!