Skip to content

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

解析过程

  1. 读取 Markdown 文件内容
  2. 分离 YAML 头部(Front Matter)和正文
  3. 解析 YAML 得到 name、triggers、required_tools 等
  4. 正文作为 system_prompt
  5. 组装成 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 的集成(和之前章节的衔接):

  1. Agent 收到用户消息
  2. SkillManager 检查是否触发了某个技能
  3. 如果触发了,把技能的 system_prompt 追加到 Agent 原有的 system_prompt 后面
  4. 同时确保技能所需的 tools 已经注册
  5. 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: 记忆系统 将解决这个问题。