【AgentScope】08-技能(Skill)详解
技能(Skill)详解
一句话概括
技能系统就是给 Agent 装"插件"——你把写好的能力包放到指定位置,Agent 就能在需要的时候自动加载并使用。
你能学到什么
- 什么是 Skill,它和 Tool 有什么区别
- Skill 的两种安装来源:技能市场和本地工作区
- 四种 Repository 后端(Git、Nacos、MySQL、Classpath)各自的适用场景
- 四层优先级机制:同名 Skill 谁覆盖谁
- Builder API 的关键方法和使用时机
- 写好 Skill 描述的最佳实践
核心概念
Skill(技能)— 手机上的 App
想象你买了一部新手机。手机刚开机时,只能打电话和发短信——这是 Agent 的"基本能力"(比如对话、推理)。
现在你去应用商店下载了一个"翻译 App"、一个"计算器 App"、一个"天气预报 App"——这些 App 就是 Skill。每个 App 有自己的说明文档(SKILL.md),告诉手机什么场景下该启动它。你不需要手动打开,手机会在你说话时自动判断"哦,用户在问天气,我该启动天气 App"。
Skill 和 Tool 的区别在于:
| Tool(工具) | Skill(技能) | |
|---|---|---|
| 类比 | 螺丝刀、锤子这样的手动工具 | 一个装有工具和说明书的工具箱 |
| 内容 | 一个单独的函数/方法 | 一整个目录:包含 SKILL.md(说明文档)、references(参考资料)、scripts(脚本) |
| 获得方式 | 代码里直接注册 | 从市场下载或放到工作区 |
| 复杂度 | 通常只做一件事 | 可以组合多步操作、带参考资料 |
技能市场(Skill Repository)— 应用商店
你手机上的"应用商店"就是技能市场。在 HarnessAgent 里,技能市场有多种"商店"可选:
- Git 仓库:像团队的私有 GitHub 仓库,大家把技能放上去共享
- Nacos:像一个在线配置中心,技能可以实时更新推送
- MySQL:像一个企业内部管理系统,统一存储和分发技能
- Classpath:像手机出厂预装的 App,跟着程序一起打包
本地工作区(Workspace Skills)— 本地安装的 App
除了从商店下载,你也可以直接把技能文件放到工作区目录里,就像你把 APK 文件直接拷贝到手机上安装一样。不需要任何注册,放好就生效。
工作区又分两种:
- 共用技能(
workspace/skills/):所有用户都能看到,像公司公告栏上贴的规章制度 - 用户专属技能(
workspace/<userId>/skills/):只有特定用户能看到,像你抽屉里私人的笔记本
四层优先级 — 食堂打饭排队规则
想象你在公司食堂打饭,排了四个窗口。高优先级的窗口可以"盖过"低优先级窗口的菜品:
| 优先级 | 来源 | 生活类比 |
|---|---|---|
| 1(最低) | 项目全局目录 | 公司总部的统一菜单——所有分公司都有的基础菜品 |
| 2 | 技能市场 | 分公司自己加的菜品——可能覆盖总部菜单中的同名菜品 |
| 3 | 工作区共用 | 你所在部门的部门特色菜——覆盖分公司的同名菜品 |
| 4(最高) | 用户隔离目录 | 你个人定制的私房菜——最高优先级,覆盖前面所有的同名菜品 |
关键规则:下层独有的技能会保留,只在重名时才用高优先级的版本覆盖。就像总部菜单有 10 个菜,分公司加了 5 个(其中 2 个和总部重名),最终菜单是总部独有的 8 个 + 分公司独有的 3 个 + 分公司覆盖的 2 个 = 13 个菜。
关键代码解读
1. 最简示例:接入 Git 技能市场
HarnessAgent agent = HarnessAgent.builder()
.name("assistant") // 给 Agent 起个名字
.model(model) // 指定使用的大模型
.workspace(workspace) // 指定工作区(存放本地技能等)
// 核心一行:创建一个 Git 技能仓库,指向你团队的 Git 地址
.skillRepository(new GitSkillRepository("https://github.com/your-org/team-skills.git"))
.build(); // 构建 Agent
就这么简单。构建完成后,Agent 在推理时能看到这个仓库里所有技能的名称和描述,需要用哪个就调用 load_skill_through_path 加载详细内容。
2. Git Skill Repository — 最常用的技能来源
<!-- 第一步:在 pom.xml 里加 Maven 依赖 -->
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-extensions-skill-git-repository</artifactId>
<version>${agentscope.version}</version>
</dependency>
// 第二步:在 Builder 里注册 Git 仓库
.skillRepository(new GitSkillRepository("https://github.com/your-org/team-skills.git"))
Git 仓库的工作机制:
- Agent 每次需要读取技能时,会做一次轻量远端检查(不是每次都完整拉取)
- 只有远端 HEAD 发生变化时,才会真正 pull 新内容
- 如果仓库里有
skills/子目录,会优先读取它;否则读取根目录 - 如果你想自己控制同步节奏,可以关闭自动同步:
// false = 关闭自动同步
GitSkillRepository repo = new GitSkillRepository("https://github.com/your-org/team-skills.git", false);
// 在合适的时机手动调用 sync() 同步
repo.sync();
生活类比:Git 技能仓库就像一个共享网盘。你不用每次都重新下载整个网盘,而是先检查"有没有新文件"——有变化才下载,没变化就用本地缓存。
3. Nacos Skill Repository — 实时推送的技能中心
<!-- Maven 依赖 -->
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-extensions-nacos-skill</artifactId>
<version>${agentscope.version}</version>
</dependency>
// 创建 Nacos 技能仓库
// aiService: Nacos 的连接配置
// "namespace": Nacos 中的命名空间,用于隔离不同环境的技能
NacosSkillRepository market = new NacosSkillRepository(aiService, "namespace");
HarnessAgent.builder()
.skillRepository(market) // 注册到 Agent
.build();
// 注意:NacosSkillRepository 实现了 AutoCloseable
// 应用退出时需要关闭,释放订阅连接
// try-with-resources 或者手动 close() 都行
适用场景:需要在线下发技能、技能内容可能随时变更的场景。Nacos 是一个配置中心,技能更新后可以实时推送给所有 Agent。
生活类比:Nacos 像一个在线文档协作平台(比如飞书文档)。你在文档里改了内容,所有打开这个文档的人立刻就能看到最新版本,不需要手动刷新。
4. MySQL Skill Repository — 企业级统一管理
MysqlSkillRepository registry = MysqlSkillRepository.builder(dataSource)
.databaseName("agentscope") // 数据库名称
.skillsTableName("skills") // 存技能元信息的表名
.resourcesTableName("skill_resources") // 存技能资源文件的表名
.createIfNotExist(true) // 表不存在时自动建表
.writeable(true) // true = 允许从 Agent 侧写回技能
.build(); // 如果只读分发,传 false
HarnessAgent.builder()
.skillRepository(registry)
.build();
适用场景:平台侧统一管理技能时使用。比如你做了一个 AI 平台,管理员在后台页面上传和管理技能,所有 Agent 实例都从这个 MySQL 里读取。
writeable(true):Agent 可以往数据库里写回新的技能(适合用户自定义技能的场景)writeable(false):只读模式,Agent 只能读取,不能写入(适合集中分发的场景)
生活类比:MySQL 技能仓库像一个公司内部的知识库系统(比如 Confluence)。管理员在上面统一管理文档,普通员工只能看(writeable(false)),有权限的员工也可以编辑(writeable(true))。
5. Classpath Skill Repository — 打包随程序走
首先,在项目里放好技能文件:
src/main/resources/skills/
└── code-reviewer/
└── SKILL.md
然后在 Builder 里注册:
// "skills" 是 classpath 下的目录前缀
.skillRepository(new ClasspathSkillRepository("skills"))
适用场景:技能跟着 JAR 包一起发布。适合标准化、不会频繁变更的技能。
生活类比:Classpath 技能就像手机出厂时预装的 App——不用下载,开机就有。但它也不容易更新,要更新就得换手机(重新打包 JAR)。
6. 接入多个技能市场
// 方式一:链式调用,一个一个加
HarnessAgent.builder()
.skillRepository(communityMarket) // 先加社区市场
.skillRepository(internalRegistry) // 再加内部注册中心
.skillRepository(teamGitRepo) // 最后加团队 Git 仓库
.build();
// 方式二:一次性传入一组
.skillRepositories(List.of(communityMarket, internalRegistry, teamGitRepo))
重要细节:skillRepositories(list) 会清掉之前用 skillRepository(...) 添加的所有市场,然后用传入的列表替换。所以不要混用两种方式。
7. 工作区中的技能目录
所有人共用(优先级 3)
workspace/skills/
└── code-reviewer/
├── SKILL.md # 技能说明文档
├── references/
│ └── style-guide.md # 参考资料
└── scripts/
└── run-checks.sh # 配套脚本
放在 workspace/skills/ 下的技能,所有用户都能看到和使用。
单个用户专属(优先级 4,最高)
workspace/
├── skills/code-reviewer/SKILL.md ← 共用版(所有人可见)
└── alice/
└── skills/
└── code-reviewer/
└── SKILL.md ← Alice 的覆盖版(仅 Alice 可见)
- Alice 调用时:拿到她自己目录下的覆盖版
- Bob 调用时:拿到共用版,看不到 Alice 的那份
- Alice 如果在自己目录下放了一个新技能
notes-taker:只有她能用,Bob 看不到
前提条件:用户隔离依赖 RuntimeContext.userId,调用方必须把 userId 传入 RuntimeContext。
8. 四层优先级完整示例
假设有以下技能分布:
| 来源 | 技能列表 |
|---|---|
| 项目全局目录(优先级 1) | code-reviewer、data-analyzer |
| Git 市场(优先级 2) | code-reviewer、translator |
| 工作区共用(优先级 3) | code-reviewer、chart-maker |
| Alice 用户目录(优先级 4) | code-reviewer、notes-taker |
Alice 最终看到的技能列表:
| 技能名 | 实际使用版本 | 来源 |
|---|---|---|
code-reviewer |
Alice 的覆盖版 | 优先级 4(最高) |
notes-taker |
Alice 专属 | 优先级 4(只有 Alice 有) |
chart-maker |
共用版 | 优先级 3 |
translator |
市场版 | 优先级 2 |
data-analyzer |
全局版 | 优先级 1(只有全局有) |
总共 5 个技能,不重复计算同名覆盖。
整体流程图
┌──────────────────────────────────────────────────────────────┐
│ HarnessAgent 构建 │
│ │
│ Builder 配置: │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ skillRepository() │ │ skillRepository() │ ... 可以多个 │
│ │ (Git/Nacos/ │ │ (MySQL/ │ │
│ │ MySQL/Classpath)│ │ Classpath) │ │
│ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │
│ └──────────┬───────────┘ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ 合并为市场技能列表 │ 优先级 1-2 │
│ └──────────┬──────────┘ │
│ │ │
│ ┌───────────────────┼────────────────────┐ │
│ │ Workspace │ │ │
│ │ ┌──────────────┐ │ ┌──────────────┐ │ │
│ │ │ skills/ │ │ │ alice/skills/│ │ │
│ │ │ (共用技能) │ │ │ (用户专属) │ │ │
│ │ └──────┬───────┘ │ └──────┬───────┘ │ │
│ │ │优先级 3 │ │优先级 4 │ │
│ └─────────┼─────────┴─────────┼──────────┘ │
│ │ │ │
│ └────────┬──────────┘ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ 四层优先级合并 │ │
│ │ 4 > 3 > 2 > 1 │ │
│ │ 重名时高优先级覆盖 │ │
│ └──────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Agent 可用技能列表 │ │
│ │ │ │
│ │ 每个 skill 只暴露 name + description │ │
│ │ Agent 判断相关后才调用 load_skill_through_path │ │
│ │ 加载完整 SKILL.md + references + scripts │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
学习要点
1. 技能 = 目录 + SKILL.md
技能就是一个文件夹,里面至少要有 SKILL.md。可以额外带 references/(参考资料)和 scripts/(脚本)。Agent 先看 name 和 description,觉得相关才加载完整内容。
2. 两种安装来源互不冲突
- 技能市场:通过
skillRepository()注册,适合集中管理的通用技能 - 本地工作区:放到
workspace/skills/目录下,适合项目特有的定制技能
两种来源同时生效,不需要二选一。
3. 四层优先级是核心机制
项目全局(1) < 技能市场(2) < 工作区共用(3) < 用户隔离(4)
- 低优先级独有的技能会保留
- 只有同名时,高优先级才会覆盖低优先级
- 这是实现"通用 + 定制"的关键设计
4. 四种 Repository 各有适用场景
| Repository | 适用场景 | 特点 |
|---|---|---|
| Git | 团队共享技能 | 版本控制,轻量同步检查 |
| Nacos | 在线实时推送 | 订阅变更,需要关闭释放连接 |
| MySQL | 企业平台统一管理 | 可读写,适合后台管理界面 |
| Classpath | 随程序打包 | 标准化不常变,零配置 |
5. description 写得好不好决定了 Agent 用不用这个技能
Agent 最初只能看到每个技能的 name 和 description。如果 description 写得太笼统(“这是一个数据分析工具”),Agent 可能判断不准,错过使用时机。应该写具体的触发场景(“当用户要算统计、出报表、做趋势图时使用”)。
6. SKILL.md 控制在 2k tokens 左右
详细内容放 references/ 目录下,脚本放 scripts/ 目录下。Agent 需要时会自己读取这些附加文件。这样做的好处是避免一次性加载太多内容,浪费 Token 和推理时间。
7. 通用技能放市场,项目特有写工作区
代码评审、表格分析这类跨项目通用的技能,放到 Git 市场集中维护。公司内部 RPC 规范、项目命名约定这类跟着项目走的技能,写到 workspace/skills/ 里跟着代码走版本控制。
8. disableDynamicSkills() 的使用时机
默认情况下,Agent 每次推理前都会重新合并技能列表(支持热更新)。如果你的场景是单次任务跑完就退出,或者接的市场后端比较慢,可以调用 disableDynamicSkills() 在 build 时合并一次,运行期不再变化。平时不需要动这个开关。
更多推荐


所有评论(0)