在 AI Agent 的世界里,大语言模型是大脑,而 Skill 是双手。没有 Skill 的 Agent 只能”纸上谈兵”,而拥有丰富 Skill 的 Agent 才能真正改变世界。今天,我们来深入探讨 Agent Skill——智能体的核心执行能力。
什么是 Agent Skill?
Agent Skill(智能体技能)是指 AI Agent 能够执行的特定能力或功能。它是连接 LLM(大语言模型)与现实世界的桥梁,让智能体从”会说”变成”会做”。
简单来说:
Skill = 让 Agent 真正能够完成任务的能力单元
一个 Skill 通常包含三个核心要素:
- 输入(Input):技能执行所需的参数
- 逻辑(Logic):技能的具体实现
- 输出(Output):技能执行后的返回结果
Skill 的核心结构:Reference 与 Script
一个完整的 Agent Skill 不仅仅是一个函数定义,它还包含两个关键组成部分:Reference 和 Script。这两者共同构成了技能的第三层结构,使 Agent 能够处理更复杂的任务。
📚 Reference(参考)
Reference 允许技能引用同一目录下的其他文件,如脚本、配置文件或参考文档。智能体仅在需要时才加载这些资源,从而优化资源管理。
Reference 解决的核心问题是:让技能携带超出上下文限制的知识。
1 2 3 4 5 6 7 8 9
| skills/ ├── data_analysis/ │ ├── skill.yaml # 技能定义 │ ├── references/ │ │ ├── pandas_guide.md # Pandas 使用指南 │ │ ├── sql_syntax.md # SQL 语法参考 │ │ └── chart_types.json # 图表类型配置 │ └── scripts/ │ └── analyze.py
|
在技能定义中引用这些资源:
1 2 3 4 5 6 7 8 9 10
| name: data_analysis description: 分析数据并生成可视化报告
references: - path: references/pandas_guide.md description: Pandas 数据处理指南,包含常用操作示例 - path: references/sql_syntax.md description: SQL 查询语法参考 - path: references/chart_types.json description: 支持的图表类型及其配置参数
|
Reference 的优势:
- 按需加载:只有当 Agent 需要时才读取,节省 token
- 知识外置:复杂的领域知识可以独立维护和更新
- 上下文扩展:突破 LLM 上下文长度限制
📜 Script(脚本)
Script 是技能目录中的可执行代码文件,用于执行特定的任务或操作。这些脚本在需要时由智能体调用,以实现确定性的执行,避免大语言模型生成过程中的不确定性和幻觉问题。
Script 解决的核心问题是:用代码保证执行的准确性和可靠性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import pandas as pd import json
def analyze_csv(file_path: str, analysis_type: str) -> dict: """ 对 CSV 文件进行数据分析 Args: file_path: CSV 文件路径 analysis_type: 分析类型 (summary/correlation/distribution) Returns: 分析结果字典 """ df = pd.read_csv(file_path) if analysis_type == "summary": return { "rows": len(df), "columns": list(df.columns), "stats": df.describe().to_dict() } elif analysis_type == "correlation": return { "correlation_matrix": df.corr().to_dict() } elif analysis_type == "distribution": return { col: df[col].value_counts().to_dict() for col in df.select_dtypes(include=['object']).columns } return {"error": "Unknown analysis type"}
|
在技能定义中声明脚本:
1 2 3 4 5 6 7
| name: data_analysis description: 分析数据并生成可视化报告
scripts: - path: scripts/analyze.py function: analyze_csv description: 执行 CSV 数据分析,支持摘要、相关性和分布分析
|
Script 的优势:
- 确定性执行:复杂计算由代码完成,结果准确可靠
- 避免幻觉:数据处理、格式解析等任务不依赖 LLM 生成
- 性能优化:计算密集型任务用代码执行更高效
- 可测试性:脚本可以独立进行单元测试
Reference + Script 的协作
Reference 和 Script 结合使用,能让 Agent 处理非常复杂的任务:
1 2 3 4 5 6 7
| 用户请求 → Agent 理解意图 ↓ 加载相关 Reference(获取领域知识) ↓ 调用 Script(执行确定性操作) ↓ LLM 整合结果 → 返回给用户
|
例如,一个”财务报表分析”技能:
- Reference 提供:会计准则、财务指标定义、行业基准数据
- Script 执行:解析 Excel、计算财务比率、生成图表
- LLM 负责:理解用户问题、解读分析结果、生成自然语言报告
这种分工让每个组件发挥所长,构建出真正可靠的智能体技能。
在 Agent 开发中,Skill 和 Tool 这两个概念经常被混用,但它们有着微妙的区别:
| 维度 |
Tool(工具) |
Skill(技能) |
| 粒度 |
单一功能 |
可组合多个 Tool |
| 抽象层次 |
底层执行 |
高层能力 |
| 复杂度 |
通常较简单 |
可包含复杂逻辑 |
| 示例 |
发送 HTTP 请求 |
完成一次网络搜索并总结 |
你可以这样理解:Tool 是原子操作,Skill 是能力组合。
Skill 的分类
根据功能和应用场景,Agent Skill 可以分为以下几类:
🔍 信息获取类
负责从外部世界获取信息:
- 网络搜索:Google、Bing、DuckDuckGo 搜索
- 知识检索:RAG、向量数据库查询
- API 调用:天气、股票、新闻等 API
- 网页爬取:提取网页内容和结构化数据
📝 内容生成类
负责创建各种形式的内容:
- 文本生成:文章、邮件、报告
- 代码生成:各种编程语言的代码
- 图像生成:调用 DALL-E、Midjourney 等
- 文档生成:PDF、PPT、Excel
⚡ 操作执行类
负责执行具体的操作:
- 文件操作:读取、写入、删除文件
- 代码执行:运行 Python、JavaScript 代码
- 数据库操作:CRUD 操作
- 系统命令:执行 Shell 命令
🔗 集成交互类
负责与外部系统交互:
- 邮件发送:SMTP、Gmail API
- 消息推送:Slack、Discord、微信
- 日历管理:Google Calendar、Outlook
- 项目管理:Jira、Notion、Trello
🧠 认知推理类
负责复杂的思维和推理:
- 数学计算:符号计算、数值计算
- 逻辑推理:规则引擎、约束求解
- 规划决策:任务分解、路径规划
设计优秀 Skill 的原则
设计一个好用的 Skill,需要遵循以下原则:
1. 单一职责原则
每个 Skill 应该只做一件事,并把它做好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| def do_everything(query): ...
def search_web(query: str) -> list: """搜索网页""" ...
def analyze_content(content: str) -> dict: """分析内容""" ...
def summarize(text: str) -> str: """生成摘要""" ...
|
2. 清晰的接口定义
Skill 的输入输出要清晰明确,便于 LLM 理解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from typing import TypedDict
class SearchResult(TypedDict): title: str url: str snippet: str def web_search( query: str, num_results: int = 10, language: str = "zh-CN" ) -> list[SearchResult]: """ 搜索网页内容 Args: query: 搜索关键词 num_results: 返回结果数量,默认10条 language: 搜索语言,默认中文 Returns: 搜索结果列表,包含标题、链接和摘要 """ ...
|
3. 优雅的错误处理
Skill 应该能够优雅地处理各种异常情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class SkillResult: success: bool data: any error: str | None def safe_api_call(url: str) -> SkillResult: try: response = requests.get(url, timeout=10) response.raise_for_status() return SkillResult(success=True, data=response.json(), error=None) except requests.Timeout: return SkillResult(success=False, data=None, error="请求超时,请稍后重试") except requests.HTTPError as e: return SkillResult(success=False, data=None, error=f"HTTP错误: {e}") except Exception as e: return SkillResult(success=False, data=None, error=f"未知错误: {e}")
|
4. 可观测性
Skill 的执行过程应该可追踪、可调试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import logging from functools import wraps import time
def with_logging(func): @wraps(func) def wrapper(*args, **kwargs): start = time.time() logging.info(f"Skill [{func.__name__}] 开始执行,参数: {args}, {kwargs}") try: result = func(*args, **kwargs) elapsed = time.time() - start logging.info(f"Skill [{func.__name__}] 执行成功,耗时: {elapsed:.2f}s") return result except Exception as e: logging.error(f"Skill [{func.__name__}] 执行失败: {e}") raise return wrapper
@with_logging def my_skill(param: str) -> str: ...
|
实现 Skill 的常见模式
模式一:Function Calling
这是最常见的 Skill 实现方式,通过函数调用让 LLM 使用工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| from openai import OpenAI
client = OpenAI()
tools = [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的天气信息", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,如:北京、上海" } }, "required": ["city"] } } } ]
response = client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": "北京今天天气怎么样?"}], tools=tools, tool_choice="auto" )
|
模式二:MCP(Model Context Protocol)
MCP 是一种开放协议,让 Skill 可以跨模型、跨平台使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from mcp import Server, Tool
server = Server("my-skills")
@server.tool() def calculate(expression: str) -> str: """计算数学表达式""" try: result = eval(expression) return f"结果是:{result}" except: return "计算出错,请检查表达式"
@server.tool() def translate(text: str, target_lang: str = "en") -> str: """翻译文本""" ...
server.run()
|
模式三:插件系统
构建可扩展的插件架构,动态加载 Skill:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| from abc import ABC, abstractmethod import importlib import os
class BaseSkill(ABC): @property @abstractmethod def name(self) -> str: """技能名称""" pass @property @abstractmethod def description(self) -> str: """技能描述""" pass @abstractmethod def execute(self, **kwargs) -> any: """执行技能""" pass
class SkillRegistry: def __init__(self): self.skills: dict[str, BaseSkill] = {} def register(self, skill: BaseSkill): self.skills[skill.name] = skill def load_from_directory(self, path: str): """从目录加载所有 Skill""" for file in os.listdir(path): if file.endswith("_skill.py"): module = importlib.import_module(f"skills.{file[:-3]}") if hasattr(module, "skill"): self.register(module.skill) def get(self, name: str) -> BaseSkill: return self.skills.get(name) def list_all(self) -> list[dict]: return [ {"name": s.name, "description": s.description} for s in self.skills.values() ]
|
Skill 组合与编排
单个 Skill 的能力是有限的,真正强大的 Agent 需要组合多个 Skill:
顺序执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| async def research_and_write(topic: str) -> str: search_results = await web_search(topic) contents = await extract_contents(search_results) summary = await summarize(contents) article = await generate_article(topic, summary) return article
|
并行执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import asyncio
async def gather_info(topic: str) -> dict: results = await asyncio.gather( web_search(topic), search_academic_papers(topic), search_news(topic), get_social_trends(topic) ) return { "web": results[0], "academic": results[1], "news": results[2], "social": results[3] }
|
条件执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| async def smart_answer(question: str) -> str: question_type = await classify_question(question) if question_type == "factual": return await search_knowledge_base(question) elif question_type == "calculation": return await calculate(question) elif question_type == "creative": return await generate_creative_response(question) else: return await general_answer(question)
|
构建 Skill 生态
一个成熟的 Agent 平台需要建立完善的 Skill 生态:
🏪 Skill 市场
- 提供丰富的官方 Skill
- 支持第三方开发者贡献
- 完善的审核和评分机制
📦 Skill 包管理
1 2 3 4 5 6 7 8 9
| agent-cli skill install weather-skill agent-cli skill install translator-skill
agent-cli skill list
agent-cli skill update --all
|
🔐 安全与权限
1 2 3 4 5 6 7 8 9 10
| class SkillPermission: NETWORK = "network" FILE_READ = "file:read" FILE_WRITE = "file:write" EXECUTE = "execute" @skill(permissions=[SkillPermission.NETWORK]) def fetch_url(url: str) -> str: """需要网络权限的 Skill""" ...
|
最佳实践
基于实践经验,这里总结几条 Skill 开发的最佳实践:
✅ DO
- 保持 Skill 小而专注:一个 Skill 只解决一个问题
- 提供详细的描述:帮助 LLM 正确选择和使用 Skill
- 设置合理的超时:避免 Skill 执行时间过长
- 实现幂等性:同样的输入应产生同样的输出
- 添加使用示例:在文档中提供典型用例
❌ DON’T
- 不要在 Skill 中硬编码密钥:使用环境变量或密钥管理服务
- 不要忽略错误处理:所有异常都应该被正确捕获
- 不要返回过大的数据:限制返回数据的大小
- 不要阻塞主线程:耗时操作使用异步执行
未来展望
Agent Skill 的发展正在朝着以下方向演进:
🌐 标准化
- MCP、A2A 等开放协议的普及
- 跨平台、跨模型的 Skill 复用
- 统一的 Skill 描述规范
🤖 自动化
- Agent 自动发现和学习新 Skill
- 根据任务自动组合 Skill
- Skill 的自我优化和进化
🔒 安全化
- 更细粒度的权限控制
- Skill 执行的沙箱隔离
- 完善的审计和监控
总结
Agent Skill 是让 AI 智能体从”能说”到”能做”的关键。设计好的 Skill 系统需要:
- 清晰的职责划分:每个 Skill 专注做一件事
- 标准的接口定义:让 LLM 能正确理解和使用
- 健壮的错误处理:优雅应对各种异常
- 灵活的组合能力:支持复杂任务的编排
随着 AI Agent 技术的发展,Skill 生态将变得越来越丰富。掌握 Skill 的设计与开发,是构建强大 AI Agent 的必备能力。
现在就开始构建你的第一个 Agent Skill 吧!🚀