AgentScope Java新手村 Skills 技能系统详解
时间:2026-07-07 15:22
AgentScope2 0技能系统通过SKILL md文件协议定义技能,按需加载从而节省Token消耗。支持Workspace共五种仓库,按声明顺序进行查重与组合。加载分为路由和按需两阶段,Tool为原子操作,Skill为流程编排。该系统有效降低Token消耗并提升技能复用效率。
第十八章 Skills 技能系统:SKILL.md 文件协议与5层仓库,按需加载节省Token
先说一个判断——在AgentScope 1.x时代,“技能”这个概念其实有点模糊不清,业务方经常跑来问:“Skill和Tool到底有什么区别?”这回2.0版本算是给出了一个清晰干脆的定义,彻底把这件事理顺了。
18.1 什么是Skill?
想象一下,Skill可以理解为“操作手册+资料包”的组合体。主Agent会先读取SKILL.md文件里的description字段,判断这个技能是否适用于当前任务。如果决定要用,才会把SKILL.md的完整内容和相关附件加载到上下文中。这就像一个精明的项目经理,先看摘要决定要不要翻完整本手册。
18.2 第一个Skill:会议纪要
来看一个具体的例子,这个Skill专门用来整理会议纪要。首先在workspace下创建skills/meeting-minutes/目录,里面放两个文件:SKILL.md和template.md。
SKILL.md的内容是这样组织的:
```
---
name: meeting-minutes
description: |
把对话内容整理成结构化会议纪要。当用户说"总结这段对话" / "写成会议纪要" / "提取action item" 时使用。
allowed-tools: [read_file]
---
# Meeting Minutes Skill
你需要按下面的步骤把对话整理成会议纪要:
1. 提取每个 speaker 的关键发言
2. 提炼出 action item(谁 / 做什么 / 截止日期)
3. 用 `template.md` 的格式输出
4. 模板文件通过 `read_file` 读取
```
而template.md则定义了输出格式:
```
# 会议纪要
**时间**:
**参与方**:
## 关键结论
- ...
## Action Items
| 负责 | 事项 | 截止 |
|------|------|------|
| ... | ... | ... |
## 待讨论
- ...
```
关键点在于,当你用HarnessAgent.builder().workspace(...)启动时,框架会自动扫描workspace/skills//SKILL.md,并将其注册到WorkspaceSkillRepository中。完全不用手动注册,省心省力。
18.3 5层SkillRepository组合
2.0版本把Skill仓库做成了接口,支持五种实现自由组合,按需选用:
| 后端 | 适用 | 依赖 |
|------|------|------|
| WorkspaceSkillRepository | 本地workspace | 无(agentscope-harness自带) |
| ClasspathSkillRepository | 内置/三方库里的skill | 无(agentscope-harness自带) |
| GitSkillRepository | 团队Git仓库 | agentscope-extensions-skill-git-repository |
| NacosSkillRepository | Nacos配置中心 | agentscope-extensions-nacos-skill |
| MysqlSkillRepository | MySQL知识库 | agentscope-extensions-skill-mysql-repository |
| PostgresSkillRepository | PostgreSQL知识库 | agentscope-extensions-skill-postgresql-repository |
如果需要使用非本地仓库,按需引入对应的Ma ven依赖即可:
```xml
io.agentscope
agentscope-extensions-skill-git-repository
2.0.0-RC2
io.agentscope
agentscope-extensions-skill-mysql-repository
2.0.0-RC2
io.agentscope
agentscope-extensions-skill-postgresql-repository
2.0.0-RC2
io.agentscope
agentscope-extensions-nacos-skill
2.0.0-RC2
```
WorkspaceSkillRepository和ClasspathSkillRepository已经内置于agentscope-harness中,完全不需要额外引入。
在配置时,多个仓库可以组合使用,声明顺序决定了优先级:
```ja va
HarnessAgent agent = HarnessAgent.builder()
....
.skillRepository(
// 声明顺序 = 优先级:先本地 → 再 git → 再 nacos → 再 mysql → 再 postgres
// 同名 skill 以先声明为准,后面的被忽略
new WorkspaceSkillRepository(filesystem, "skills", contextSupplier), // 本地 SKILL.md(最高优先级)
new GitSkillRepository("https://github.com/your-org/team-skills.git"), // 团队公共 skill
new NacosSkillRepository(nacosClient, "agentscope-skills"), // Nacos 配置中心
new MysqlSkillRepository(dataSource, "skill"), // MySQL skill 表
new PostgresSkillRepository(dataSource, "skill") // Postgres skill 表
)
.build();
```
这4层仓库按声明顺序查重:先workspace,再git,再nacos,再mysql。相同id的skill,以先声明的为准,后面的被忽略。
18.4 Skill加载的两个阶段
主Agent使用Skill的方式是按需加载,分为两个阶段。
18.4.1 路由阶段:只读description
主Agent启动时,所有skill的description会被拼接到system prompt里。LLM看到用户说“总结会议”时,知道有meeting-minutes这个skill可用,但此时还没读取完整内容。这就好比先看一眼目录,确定这本书有没有自己需要的章节。
18.4.2 加载阶段:按需读SKILL.md全文
LLM决定使用meeting-minutes后,会调用内置的read_skill工具,读取完整的SKILL.md以及附件路径,然后才开始干活。只有到这一步,才会把完整内容加载到上下文。这种按需加载机制,能有效节省token消耗。
18.5 在subagent上挂Skill
subagent和主Agent一样,也能挂载Skill:
```ja va
SubagentDeclaration translator = SubagentDeclaration.builder()
.name("translator")
.description("中英互译") // 主 agent 通过 description 决定是否用这个 subagent
.inlineAgentsBody("...") // 省略号替换为 subagent 的完整系统提示词
.skillRepository(
new ClasspathSkillRepository("i18n"), // 来自 classpath:i18n/**/SKILL.md
new GitSkillRepository("workspace-skills") // 团队 skill 仓库
)
.build();
```
主Agent通过subagent的description决定是否使用它,然后subagent再在自己的技能仓库中查找相应技能。
18.6 内置Skill:来自classpath
如果你的Skill不需要运行时更改,可以打包成jar包。在src/main/resources/skills/下创建目录:
```
src/main/resources/skills/payment-check/
├── SKILL.md
└── checklist.md
```
然后通过ClasspathSkillRepository加载:
```ja va
new ClasspathSkillRepository("skills")
// "skills" 对应 classpath:skills/**/SKILL.md
// 适合把标准操作手册打成 jar,下游项目引依赖即用
```
启动时会自动扫描classpath:skills/**/SKILL.md。这种方式非常适合把标准操作手册做成共享库,下游项目引入依赖即可使用。
18.7 Skill与Tool的区别
| 维度 | Tool | Skill |
|------|------|-------|
| 形态 | Ja va 方法 | Markdown 文件 |
| 何时进入 prompt | 启动时全部注册 | 按 description 路由 + 按需加载 |
| 业务方改动 | 改 Ja va + 重新编译 | 改 .md 文件即可 |
| 适合 | 原子操作 | 流程、模板、领域知识 |
一个典型的组合方式是这样的:
- read_file / grep_files —— Tool(原子操作)
- meeting-minutes —— Skill(流程)
主Agent在meeting-minutes的allowed-tools里声明它需要read_file,这样LLM就知道“用这个skill时只能调用read_file这个工具”。
18.8 完整可运行示例
来看一个完整的项目结构:
```
workspace/
├── MEMORY.md
└── skills/
├── meeting-minutes/
│ ├── SKILL.md
│ └── template.md
└── invoice-parser/
├── SKILL.md
└── rules.md
```
每个SKILL.md的description就是主Agent看到的入口。以invoice-parser为例:
```yaml
---
name: invoice-parser
description: |
解析发片内容。当用户提供发片文本 / 提到"发片号 / 金额 / 税号"时使用。
allowed-tools: [read_file, parse_invoice]
---
# Invoice Parser
1. 用 `parse_invoice` 工具从文本提取结构化字段
2. 用 `read_file` 读 `rules.md` 校验字段格式
3. 返回结构化结果
```
rules.md定义了校验规则:
```
- 发片号:8 位数字
- 金额:保留 2 位小数
- 税号:18 位字母数字
```
主Agent的代码非常简单:
```ja va
HarnessAgent agent = HarnessAgent.builder()
.name("assistant")
.sysPrompt("你是助理,会用 skill 解决具体问题。")
.model(model())
.workspace(Path.of("./workspace"))
// 设置了 .workspace(),框架自动扫描 workspace/skills/ 加载 SKILL.md
// 无需手动注册 WorkspaceSkillRepository
.build();
```
运行host.call("帮我把这段对话整理成会议纪要")时,LLM会先通过description路由到meeting-minutes,然后加载SKILL.md的完整内容,按照模板输出结果。
18.9 最小迁移清单(1.x SkillsKit → 2.0 SkillRepository)
| 1.x 用法 | 2.0 等价 |
|----------|----------|
| SkillsKit.register(skill) | SkillRepository + workspace/skills//SKILL.md |
| agent.skills(kit) | HarnessAgent.builder().skillRepository(...) |
| 业务方实现 Skill 接口 | 写 SKILL.md |
| 技能库动态加载 | 多种 SkillRepository 后端 |
| 跨项目复用 | ClasspathSkillRepository 打 jar / GitSkillRepository / PostgresSkillRepository |
18.10 本章小结
2.0版本用SKILL.md协议加SkillRepository抽象,彻底替代了1.x的SkillsKit。这里有几个核心要点值得记住:
第一,5种仓库后端——Workspace、Classpath、Git、Nacos、MySQL、PostgreSQL,按声明顺序查重,灵活组合。
第二,路由靠description,加载靠on-demand,这种机制能有效节省token成本。
第三,Skill与Tool互补——Tool是原子操作,Skill是流程编排。两者各司其职,共同构建起一个清晰、可扩展的技能系统。