主题
Day 6 — 技能系统 (Skills)
读完这章你能获得什么:理解如何用 Markdown 文件定义 Agent 的"技能包",掌握技能的加载、匹配和激活机制,让 Agent 能根据不同任务自动切换"人设"。
一、前情提要
经过 Day 4-5,我们的 Agent 已经有了"脑子"(LLM)和"双手"(Tools)。但有个问题:
Agent 不管遇到什么任务,都用同一个"人设"来回答。让它翻译时它也用日常聊天的语气,让它写代码时它也不知道该用什么格式。
我们需要一种机制,让 Agent 能根据任务自动切换行为模式——遇到翻译任务就变"翻译官",遇到编程任务就变"程序员"。
二、生活类比:员工的技能证书
想象你的公司有一个技能认证系统:
员工(Agent)持有的证书:
├── 翻译证书 (translator.md)
│ 触发条件:用户说"翻译"、"translate"
│ 技能效果:切换成翻译专家人设,逐句翻译
│ 需要的工具:translation_api
│
├── 程序员证书 (coder.md)
│ 触发条件:用户说"写代码"、"编程"、"debug"
│ 技能效果:切换成程序员人设,用代码块格式回答
│ 需要的工具:code_runner
│
└── 数学老师证书 (math_teacher.md)
触发条件:用户说"算"、"数学"、"方程"
技能效果:切换成数学老师人设,分步骤讲解
需要的工具:calculator工作流程:
用户:"帮我把这句话翻译成英文"
↓
技能匹配器(SkillManager):扫描所有证书的触发词
↓
命中 "翻译证书":触发词 "翻译" 匹配!
↓
激活技能:把翻译专家的人设(system_prompt)注入 Agent
↓
Agent 回答:以翻译专家的身份回答用户三、核心概念详解
3.1 Skill 定义——一张"技能证书"
每个技能就是一个 Markdown 文件,文件头部用 YAML 格式写"元信息",正文写"人设提示词":
markdown
---
name: translator
description: 专业翻译技能
triggers:
- "翻译"
- "translate"
- "翻成"
required_tools:
- translation_api
---
你是一个专业的翻译专家。请注意以下规则:
1. 保持原文含义,不添加个人解读
2. 专业术语需要在括号中标注原文
3. 根据上下文选择合适的语气各部分的作用:
| 部分 | 内容 | 类比 |
|---|---|---|
name | 技能名称 | 证书名 |
description | 技能描述 | 证书上的说明文字 |
triggers | 触发关键词列表 | "什么情况下该亮出这张证书" |
required_tools | 依赖的工具列表 | "使用这个技能需要的装备" |
| 正文(Markdown body) | 注入的 system_prompt | "拿到证书后的行为指南" |
3.2 SkillLoader——"发证机构"
SkillLoader 负责读取 Markdown 文件,解析成 Skill 对象:
skills/
├── translator.md → SkillLoader.load_file() → Skill 对象
├── coder.md → SkillLoader.load_file() → Skill 对象
└── math_teacher.md解析过程:
- 读取 Markdown 文件内容
- 分离 YAML 头部(Front Matter)和正文
- 解析 YAML 得到 name、triggers、required_tools 等
- 正文作为
system_prompt - 组装成 Skill 对象
3.3 SkillManager——"技能匹配器"
SkillManager 管理所有已加载的技能,核心能力是匹配和激活:
python
manager = SkillManager()
# 注册技能
manager.register(translator_skill)
manager.register(coder_skill)
# 匹配:用户输入是否触发了某个技能?
matched = manager.match("帮我翻译这句话")
# matched = translator_skill(因为包含"翻译"关键词)
# 激活:把匹配到的技能设为当前激活状态
manager.activate(matched.name)
# 获取激活技能的提示词
prompts = manager.get_active_prompts()
# ["你是一个专业的翻译专家。请注意以下规则..."]匹配逻辑:扫描用户输入中是否包含任何技能的 trigger 关键词。当前实现是简单的关键词包含匹配——生产环境中可以升级为语义匹配或 LLM 判断。
四、技能系统的全景流程
与 Agent 的集成(和之前章节的衔接):
- Agent 收到用户消息
- SkillManager 检查是否触发了某个技能
- 如果触发了,把技能的 system_prompt 追加到 Agent 原有的 system_prompt 后面
- 同时确保技能所需的 tools 已经注册
- Agent 以"增强后的人设"去调用 LLM
五、为什么用 Markdown 定义技能?
| 方案 | 优点 | 缺点 |
|---|---|---|
| Python 代码定义 | 灵活,能写复杂逻辑 | 改个提示词就要改代码、重启 |
| JSON/YAML 文件 | 结构清晰 | 写长文本(提示词)不方便 |
| Markdown + Front Matter | 提示词就是正文,所见即所得;元信息用 YAML 头部 | 不适合复杂逻辑(但技能本身就不该有复杂逻辑) |
类比:用 Markdown 定义技能就像用 Word 模板写文档——不需要会编程也能定义新的 Agent 人设。产品经理、运营人员都能直接编辑。
六、动手实验指南
6.1 运行示例
bash
python day6-skills/example/main.py示例演示了技能的加载、匹配和激活流程。
6.2 改一改,看看会怎样
实验 1:创建一个新的技能文件 poet.md——让 Agent 变成诗人,用诗歌形式回答问题。
markdown
---
name: poet
description: 诗人模式
triggers:
- "写诗"
- "诗歌"
- "作诗"
required_tools: []
---
你是一位才华横溢的诗人。请用诗歌的形式回答用户的所有问题。
优先使用七言或五言格式。实验 2:给一个技能设置多个 trigger 关键词,测试不同的输入是否都能匹配到。
实验 3:同时激活两个技能,观察 get_active_prompts() 返回的多个提示词是如何拼接的。
6.3 运行测试
bash
pytest day6-skills/skills/ -v七、常见问题 FAQ
Q1:如果用户的消息同时包含多个技能的触发词怎么办?
A:当前实现会匹配到第一个命中的技能。更高级的实现可以引入优先级、权重,或者让 LLM 来判断"用户真正想要的是哪个技能"。
Q2:技能和 system_prompt 有什么区别?
A:system_prompt 是 Agent 的"基础人设",始终存在。技能的提示词是叠加在基础人设之上的"临时增强"——就像员工有基本的岗位职责,拿了翻译证书后额外获得翻译能力,但基本职责不变。
Q3:required_tools 有什么用?
A:告诉系统"使用这个技能时需要确保这些工具可用"。比如翻译技能需要 translation_api 工具——如果工具没注册,可以提前报错或自动注册。
下一章
Agent 现在有了"脑子"、"双手"和"技能"。但它还有一个致命缺陷——没有记忆。每次新对话都从零开始,不记得用户之前说过什么。
下一章 Day 7: 记忆系统 将解决这个问题。