Skip to content

5.2 技能(Skills)与插件目录

本节你会学到

  • 技能目录布局(SKILL.md + 可选 references/*.md
  • 三层目录搜索顺序(用户 / 项目配置 / 项目仓库)和覆盖语义
  • 怎样写出 LLM 在恰当时机激活、其他时候不打扰的技能

技能不是代码,是给 LLM 看的 Markdown 指令。当"让 Agent 按你们公司的规范做事"不需要新工具、只需要新约束/新流程时,写一个技能比写代码高效 10 倍。

技能的形态

每个技能是一个目录:

my-skill/
├── SKILL.md              # 必需:入口文件
└── references/            # 可选:按需加载的辅助文档
    ├── conventions.md
    └── templates.md

SKILL.md 格式

markdown
---
name: customer-ticket-handler
description: 处理客户工单时使用——遵循公司退款规范、用固定措辞、先查订单再给答复。
---

# 客户工单处理技能

当用户在工单里询问退款/投诉/发货问题时,按本指南执行:

## 步骤

1. 先用 `get_customer_orders` 工具查订单
2. 如果订单状态是 "delivered" 超过 30 天 → 礼貌拒绝
3. 如果是物流问题 → 模板回复 + 转物流部
4. ...

## 口径约束

- 不承诺具体赔偿金额
- 不透露内部系统名
- 签名统一:"客户服务团队"

## 复杂情况

需要例外处理时,参考 `references/conventions.md` 中的边界情况清单。

YAML Frontmatter

只有两个字段:

字段必填用途
name唯一 id;不能含空格,建议 kebab-case
description触发描述——告诉 LLM 什么时候激活这个技能

description 被注入到系统提示的"可用技能清单"里。LLM 看到用户请求匹配 description 时,会主动调用 activate_skill 工具激活它。

三层目录搜索顺序

1. ~/.agentao/skills/            ← 全局(所有项目共享)
2. <cwd>/.agentao/skills/        ← 项目配置目录
3. <cwd>/skills/                 ← 项目仓库目录

同名冲突时,后加载的覆盖先加载的(也就是 .agentao/skills/ 覆盖全局,skills/ 覆盖前两层)。所以:

  • 嵌入你的产品时:把技能放在项目 repo 根的 skills/,用户拉代码即有
  • 用户自定义:留出 ~/.agentao/skills/ 让用户自己写个人技能
  • 临时/试验.agentao/skills/ 适合本项目专属但不想污染 git

远程安装

CLI 可以从 GitHub 安装受管理的技能:

bash
agentao skill install owner/repo[:path][@ref]

如果带 :path,Agentao 会把仓库里的这个子目录当作单个技能包安装。比如 Anthropic 官方 PDF 技能位于一个更大的仓库中:

bash
agentao skill install anthropics/skills:skills/pdf

项目级安装写入 <project-root>/.agentao/skills/;全局安装写入 ~/.agentao/skills/。仓库根目录的 skills/ 仍然优先级最高,所以产品随 repo 分发的技能可以覆盖受管理安装。

多租户场景的隔离

ACP 或多实例 Python 嵌入时,每个 Agent 构造时传的 working_directory 决定它看到的项目级技能目录——两个租户互不干扰。

python
# tenant-a 只能看到 /data/tenant-a 下的技能
agent_a = Agentao(working_directory=Path("/data/tenant-a"))
# tenant-b 只能看到 /data/tenant-b 下的技能
agent_b = Agentao(working_directory=Path("/data/tenant-b"))

~/.agentao/skills/ 是全局共享的(进程级用户 HOME),如果你不希望它被加载,在构造 Agent 之前用环境变量改 HOME 或者设计成 SkillManager(skills_dir=...) 的私有目录。

激活机制

技能不是被动加载的 —— 它们默认不在系统提示里。只有当 LLM 通过 activate_skill 工具主动激活时,技能的 SKILL.md 全文才会被注入。

┌─────────────────┐
│ available_skills │  ← 全部技能(只看到 name + description)
└─────────────────┘
         │ LLM 决定:"这次需要 customer-ticket-handler"

   activate_skill("customer-ticket-handler")


┌─────────────────┐
│  active_skills   │  ← 激活的技能(全文注入系统提示)
└─────────────────┘

这个设计让你可以堆很多技能而不污染上下文:只有真正用到的才占 token。

按需参考目录

references/*.md 不会自动加载。技能正文里可以告诉 LLM:"如果你遇到特殊情况,用 read_fileskills/my-skill/references/edge-cases.md"。

这样做的好处:

  • 技能主文件保持 < 2KB,容易被 LLM 吸收
  • 附属文档只在真正需要时才加载,节省 token
  • 复杂知识可以按主题拆分

写一个好技能的 3 条原则

1. 触发描述必须具体

description: "Handles customer issues" — 太宽,LLM 会在一切场景激活 ✅ description: "Activate when user asks about refunds, returns, or delivery issues. Not for sales questions." — 明确何时用、何时不用

2. 用祈使句和具体步骤

"We generally prefer JSON responses..." — LLM 不知道"generally"是啥 ✅ "When using get_customer_orders, always filter by customer_id. Never include internal tenant_id in user-facing replies." — 确切、可验证

3. 失败场景优先

写技能时先列不该做的再列该做的

markdown
## 绝对禁止
- 不得跨客户查询数据
- 不得承诺具体退款时效
- 不得暴露内部 API endpoint

## 正确做法
- ...

LLM 更擅长遵守"禁止"比学会"应该",这个顺序能提高合规率。

示例:给工程团队的"代码审查"技能

skills/code-review/
├── SKILL.md
└── references/
    ├── security-checklist.md
    └── performance-patterns.md

SKILL.md:

markdown
---
name: code-review
description: Activate before reviewing any pull request or diff. Enforces our team's review standards for Python / TypeScript code.
---

# Code Review Standards

## Your role

You are a principal engineer doing a pre-merge review. Be direct, be specific, cite line numbers.

## Review order

1. **Security first**: check `references/security-checklist.md` for the full list
2. **Correctness**: edge cases, error paths, async correctness
3. **Performance**: N+1 queries, unbounded loops, memory leaks
4. **Style**: conforms to existing patterns in the same file — do not impose
   new abstractions unless justified

## Output format

For each finding, produce exactly:

- **Severity** (Blocker / Major / Minor / Nit)
- **File:line**
- **The issue** (one sentence)
- **Suggested fix** (code or concrete action)

End with one paragraph summarizing the overall quality and whether it's
ready to merge.

## Strong rules

- Never say "looks good to me" without reading every changed file
- Never suggest refactors outside the diff scope unless they are Blockers
- Never be vague ("consider refactoring") — always name the concrete issue

调试技能:看它到底进没进系统提示

python
# 构造后检查
agent = Agentao(working_directory=Path.cwd())
print(list(agent.skill_manager.available_skills.keys()))   # 都发现了吗?
print(list(agent.skill_manager.active_skills.keys()))       # 当前激活了哪些?

# 手动激活(通常 LLM 自己激活)
agent.skill_manager.activate_skill("customer-ticket-handler")

# 查看激活后的注入内容
print(agent.skill_manager.get_skills_context())

技能 vs 工具:何时加工具、何时加技能?

场景选哪个
"每次写代码都要用 Python 3.12 类型注解"技能(约束风格)
"查询数据库"工具(实现能力)
"回答退款问题用固定模板"技能
"发 Slack 消息"工具
"先问澄清再做,不要贸然动手"技能
"上传文件到 S3"工具

口诀:需要新能力 → 工具;需要新约束 → 技能。

TL;DR

  • 技能是一个目录SKILL.md(YAML frontmatter + 正文)+ 可选 references/*.md(激活时按需加载)。
  • description 决定 LLM 何时激活——按 LLM 第一视角写("用户问到 X 时激活我")。
  • 三层搜索顺序:~/.agentao/skills/(全局)→ <wd>/.agentao/skills/<wd>/skills/项目内的优先级最高
  • 多个小而具体的技能 > 一个大杂烩。激活会消耗上下文 token,技能小才不肉疼。

→ 下一节:5.3 MCP 服务器接入