30. AI Skills技能系统,让 Agent 自动变强

在构建 AI Agent 的过程中,如何让 Agent 具备特定领域的专业能力是一个核心问题。传统的做法是将所有功能硬编码到 Agent 中,但这种方式缺乏灵活性和可复用性。Skills 技能系统的出现,为这个问题提供了一种优雅的解决方案。

动画视频在《30. AI Skills 技能系统,让 Agent 自动变强》

什么是 Skill

Skill(技能)是一种可复用的功能单元,用于扩展 Agent 的任务执行能力。每个 Skill 封装了特定领域的指令、脚本和参考资料,使 Agent 能够胜任各类专业任务。

这种设计的核心思想是模块化。就像给手机安装 App 一样,我们可以为 Agent 动态加载不同的技能,让它具备代码审查、文档生成、数据分析等能力。每个技能都是独立的,可以单独开发、测试和复用。

|-------------|---------------------------------|
| 文件/目录 | 说明 |
| SKILL.md | 必需。包含技能指令和元数据(name、description) |
| scripts/ | 可选。存放可执行脚本(Python、Shell 等) |
| references/ | 可选。存放参考文档、示例数据等辅助资料 |

SKILL.md 文件结构

每个 Skill 的核心是一个名为 SKILL.md 的文件。这个文件由两部分组成:Frontmatter 元数据和 Markdown 指令。

Frontmatter 元数据位于文件开头,采用 YAML 格式,定义了技能的名称、描述等关键信息。其中,description 字段尤为重要,它直接决定了 Agent 能否在正确的时机找到并使用该技能。一个好的描述应该简洁明确,并包含触发条件,让 Agent 一看就知道"什么场景下该用我"。

Markdown 指令部分则是技能的具体内容,告诉 Agent 拿到这个技能之后该怎么做、按什么步骤执行、有哪些注意事项。这部分内容会被注入到 Agent 的上下文中,指导它完成任务。

复制代码
---
name: code-review
description: 审查代码质量、检查常见问题。当用户要求代码审查时使用。
---
 
# 代码审查
 
审查代码文件,检查以下问题:
- 语法错误和潜在 Bug
- 代码风格和规范
- 性能问题
- 安全漏洞
 
## 使用方法
 
当用户要求审查代码时,执行:
 
```bash
python /skills/code-review/scripts/review.py <file_path>
```
 
## 输出格式
 
按严重程度分类:
- 🔴 严重问题(必须修复)
- 🟡 警告(建议改进)
- 🟢 提示(可选优化)

Skills 的执行流程

理解了文件结构,再来看 Skill 是如何运作的。整个执行流程可以分为三个阶段:扫描匹配、加载注入、执行反馈。

当用户输入一个请求时,Agent 首先扫描 skills 目录下所有 SKILL.md 的前置元数据,提取各技能的名称与描述,生成可用技能清单。然后,Agent 将用户请求与清单中的描述进行语义匹配。一旦找到合适的技能,就调用 load_skill 方法将该技能的完整提示指令加载到对话上下文中。最后,Agent 按照加载的指令执行任务,并将结果返回给用户。

这个过程对用户来说是透明的。用户只需要表达意图,Agent 会自动找到并使用合适的技能完成任务。

实践:集成代码审查 Skill

理论讲完了,接下来通过一个完整的示例来演示如何将 Skill 集成到 Agent 中。我们已经创建好了一个代码审查 Skill,现在要让它工作起来。

首先需要安装 deepagents 开发包。

复制代码
pip install deepagents

需要注意的是,deepagents 目前不支持通过 init_chat_model 构造的模型 对象,因此需要调整模型的初始化方式。

最关键的是 create_deep_agent 的调用,其中 skills 参数指定了技能目录。

create_deep_agent 默认使用内存后端 StateBackend,无法读取本地文件系统。如果要加载磁盘上的 Skill 文件,必须显式传入 FilesystemBackend。这是一个容易忽略的配置点。

复制代码
import os
from dotenv import load_dotenv
from deepagents import create_deep_agent
from langchain.chat_models import init_chat_model
from langchain_core.tools import BaseTool
from langchain_community.tools import WriteFileTool, ReadFileTool, ListDirectoryTool
from deepagents.backends import FilesystemBackend
 
load_dotenv()
 
# 使用 configurable_fields 创建可配置模型
# model = init_chat_model(
#     model_provider="openai",
#     configurable_fields=["model", "api_key", "base_url"],
#     config_prefix="QWEN"
# ).with_config({
#     "configurable": {
#         "QWEN_model": os.getenv("QWEN_MODEL"),
#         "QWEN_api_key": os.getenv("QWEN_API_KEY"),
#         "QWEN_base_url": os.getenv("QWEN_BASE_URL")
#     }
# })
 
os.environ["OPENAI_API_KEY"] = os.getenv("QWEN_API_KEY")
os.environ["OPENAI_BASE_URL"] = os.getenv("QWEN_BASE_URL")
model = f"openai:{os.getenv('QWEN_MODEL')}"
 
 
class CalculateTool(BaseTool):
    name: str = "calculate"
    description: str = "计算数学表达式的值"
 
    def _run(self, expression: str) -> str:
        try:
            return f"计算结果: {eval(expression)}"
        except Exception as e:
            return f"计算错误: {str(e)}"
 
    async def _arun(self, expression: str) -> str:
        return self._run(expression)
 
 
# ========== 初始化工具 ==========
 
calculate = CalculateTool()
write_file = WriteFileTool()
read_file = ReadFileTool()
list_dir = ListDirectoryTool()
 
 
 
# ========== 创建 Deep Agent ==========
agent = create_deep_agent(
    model=model,
    tools=[calculate, write_file, read_file, list_dir],
    system_prompt="你是一个助手,会用工具计算、读写文件、列出目录。",
    skills=["skills"],
    backend=FilesystemBackend(root_dir=os.getcwd()),
    debug=True
)
 
queries = [
    "审查 mcp_weather.py 代码",
    "计算 2024*12+500,然后把结果保存到 result.txt",
    "读取 result.txt 的内容",
    "列出当前目录文件"
]
 
for q in queries:
    print(f"\n问:{q}")
    result = agent.invoke({"messages": [{"role": "user", "content": q}]})
    print(f"答:{result['messages'][-1].content}")
 

Skill 系统让 Agent 的能力扩展变得模块化和可插拔。通过编写清晰的 SKILL.md 文件,定义准确的描述和完整的执行指令,Agent 就能在合适的时机自动找到并使用相应的技能。

这种"按需加载、即插即用"的设计思路,不仅提高了代码的可复用性,也让 Agent 的能力边界可以不断扩展。随着更多 Skill 的积累,Agent 将能够胜任越来越复杂的任务场景。