AI Agent Skill(技能)开发全指南(3/5):从原理到搭建你的第一个 Skill
摘要:随着大模型(LLM)从“聊天机器人”向“智能体(Agent)”演进,Skill(技能)已经成为 AI 能够真正操作现实世界的核心载体。本文将系统讲解 Skill 的技术本质、架构设计、通信协议(Function Calling / MCP)、开发全流程,并手把手带你从零构建一个可运行的 “天气查询 Skill”,最后探讨企业级 Skill 生态的构建思路。
一、什么是 Skill?—— 重新定义 AI 的能力边界

1.1 从 Chatbot 到 Agent:为什么需要 Skill?
早期的 ChatGPT 类应用本质上是一个文本预测引擎。它拥有海量的世界知识,但它被囚禁在数字世界里。它无法告诉你现在的天气,无法帮你订外卖,也无法查询你的私人日程。
Skill 就是打破这层壁垒的钥匙。
-
没有 Skill 的 LLM:大脑发达,但手脚瘫痪。
-
拥有 Skill 的 LLM:拥有了眼睛(视觉识别)、耳朵(语音识别)、手(执行 API 调用)和脚(导航)。
定义:Skill 是一种封装了特定业务能力、可被 AI Agent 动态发现、理解并调用的标准化接口模块。它允许大模型将用户的自然语言意图转化为具体的程序指令,从而完成感知、决策和执行。

1.2 Skill vs Plugin vs Function Calling vs Tool
这几个术语经常混用,但它们处于不同的抽象层级:
|
术语 |
定位 |
关系 |
|---|---|---|
|
Tool (工具) |
最底层的具体实现。一段代码或一个 API 端点。 |
Skill 的组成部分。 |
|
Function Calling |
一种技术机制(由 OpenAI 定义)。告诉模型有哪些函数可用,让模型输出调用这些函数的 JSON 参数。 |
实现 Skill 调用的主流技术手段。 |
|
Plugin (插件) |
早期的概念(如 ChatGPT Plugins)。通常包含 API 描述文件和清单文件。 |
Skill 的早期形态,现多已被 Function Calling 和 MCP 取代。 |
|
Skill (技能) |
业务视角的封装。它不仅仅是一个函数,可能包含鉴权、缓存、错误处理、业务逻辑编排。 |
面向 Agent 的最终交付物。 |
一句话总结:我们使用 Function Calling(或 MCP)技术,将底层的 Tools 封装成业务级的 Skills,供 Agent 使用。
1.3 Skill 的核心特征
-
自描述性 (Self-Describing):Skill 必须包含一个清晰的 Schema(模式),告诉 AI 它是干什么的,需要什么参数,返回什么结果。
-
幂等性 (Idempotency):理想情况下,多次调用同一个 Skill 产生的副作用应该是相同的(例如,查询天气是只读的,天然幂等;转账则需要通过唯一 ID 防止重复扣款)。
-
安全性 (Security):Skill 往往涉及数据隐私和系统权限,必须有严格的沙箱机制和权限控制。
-
可组合性 (Composability):高级 Agent 可以将多个 Skill 串联起来(ReAct 模式),完成复杂任务。
二、Skill 的技术原理与架构
2.1 经典的交互流程 (ReAct + Function Calling)
一个典型的 Skill 调用流程如下:
-
用户输入:"北京今天适合穿什么衣服?"
-
意图识别:LLM 分析发现,要回答这个问题,需要先知道北京的天气。
-
工具选择:LLM 在系统提示词(System Prompt)提供的 Skill 列表中,找到了
get_weather这个 Skill。 -
参数提取:LLM 提取出参数:
location = "Beijing"。 -
输出指令:LLM 停止生成自然语言,转而输出一段结构化的 JSON:
{"name": "get_weather", "arguments": {"location": "Beijing"}}。 -
执行代码:后端程序解析这段 JSON,调用真实的
get_weather("Beijing")函数(可能是调用第三方天气 API)。 -
返回结果:函数返回
"Sunny, 25°C"。 -
二次推理:后端将结果塞回对话上下文,LLM 再次接管,结合天气数据生成最终回答:"北京今天晴天,25度,建议穿轻薄的长袖衬衫。"
2.2 Skill 的系统架构
一个生产级的 Skill 架构通常包含以下层次:
┌─────────────────────────────────────────────┐
│ AI Agent / Orchestrator │
│ (负责思考、规划、调用 Skill) │
└───────────────────────┬─────────────────────┘
│ JSON Instruction
┌───────────────────────▼─────────────────────┐
│ Skill Gateway / Proxy │
│ (鉴权、限流、日志、参数校验) │
└───────────────────────┬─────────────────────┘
│ Internal Call
┌───────────────────────▼─────────────────────┐
│ Skill Executor │
│ ┌─────────┐ ┌─────────┐ ┌─────────────────┐│
│ │ Weather │ │ Search │ │ Internal DB CRUD││
│ │ Skill │ │ Skill │ │ Skill ││
│ └─────────┘ └─────────┘ └─────────────────┘│
└───────────────────────┬─────────────────────┘
│ HTTP/gRPC
┌───────────────────────▼─────────────────────┐
│ External Services (APIs) │
│ (Weather.com, Google, Internal RPC) │
└─────────────────────────────────────────────┘
2.3 两种主流协议:OpenAI Function Calling vs MCP
2.3.1 OpenAI Function Calling
这是目前最普及的方案。开发者定义一个 JSON Schema 来描述函数。
优点:生态成熟,各大模型厂商(OpenAI, Anthropic, Gemini, 国产大模型)基本都兼容。
缺点:强依赖于 Prompt Engineering,缺乏标准化的生命周期管理。
2.3.2 MCP (Model Context Protocol)
由 Anthropic 提出的开放协议,旨在成为 AI 应用的“USB-C”接口。MCP 定义了一个标准的客户端-服务器架构。
-
MCP Host:Claude Desktop, IDE 等。
-
MCP Client:Host 内的连接器。
-
MCP Server:封装了具体 Skill 的服务端。
优点:解耦彻底,支持双向通信(Server 可以主动请求资源),更适合复杂的本地工具集成(如操作文件系统、数据库)。
缺点:相对较新,生态还在建设中。
本文后续示例将主要基于 OpenAI Function Calling 风格,因为这是目前 Web 服务开发中最通用的方式。
三、Skill 的设计哲学与最佳实践

3.1 单一职责原则 (SRP)
一个 Skill 只做一件事。
❌ 错误示例:handle_user_request(处理查询、修改、删除用户)。
✅ 正确示例:query_user_by_id, update_user_email。
3.2 良好的命名与描述 (Naming & Description)
LLM 不是编译器,它是通过语义来理解 Skill 的。命名和描述比代码本身更重要。
-
函数名:使用动词+名词,如
calculate_loan_interest。 -
描述:详细解释功能、适用场景和限制。
-
差:
Get weather. -
好:
Retrieves the current weather for a specified city. Use this when the user asks about temperature, humidity, or weather conditions. Note: Supports Chinese and English city names.
-
3.3 参数设计的艺术
-
枚举约束 (Enums):如果参数是固定的几个值,一定要用
enum,这能极大降低幻觉。-
例如:
unit参数只能是["celsius", "fahrenheit"]。
-
-
必填与选填:区分
required字段。对于非必填项,在描述中说明默认值。 -
自然语言兜底:有时候用户会说“明天”而不是日期。可以在 Skill 内部做一个日期解析层,或者让 LLM 调用一个专门的
parse_dateSkill。
3.4 防御性编程
永远不要相信 LLM 的输出。
-
类型校验:即使 Schema 定义了 Integer,也要在代码中验证。
-
范围校验:如果是查询分页,检查 page_size 是否超过上限。
-
注入防护:如果 Skill 涉及数据库查询,防止 SQL 注入(虽然 LLM 输出的是参数,但仍需警惕)。
四、动手实践:搭建你的第一个 Skill

接下来,我们将使用 Python + FastAPI 搭建一个简单的 Web 服务,并实现一个 “天气查询 Skill”。
4.1 环境准备
确保安装了 Python 3.9+。
mkdir my_first_skill && cd my_first_skill
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install fastapi uvicorn httpx openai python-dotenv
创建 .env 文件存放 API Key:
OPENAI_API_KEY="sk-your_key_here"
# 或者使用兼容 OpenAI 接口的国内模型
# OPENAI_BASE_URL="https://api.moonshot.cn/v1"
4.2 步骤一:编写 Skill 的核心逻辑(Tool)
我们先不关心 AI,直接写一个纯粹的天气查询函数。
创建 weather_tool.py:
import httpx
import os
from typing import Dict, Any
# 这里使用 Open-Meteo (免费,无需 API Key)
# 但为了演示,我们假设有一个需要 Key 的商业 API 逻辑
# 实际调用:https://api.weatherapi.com/v1/current.json?key=KEY&q=Beijing
class WeatherService:
def __init__(self):
# 为了演示,我们不真的调用收费 API,而是 Mock 数据
# self.api_key = os.getenv("WEATHER_API_KEY")
# self.base_url = "https://api.weatherapi.com/v1"
pass
async def get_current_weather(self, location: str, unit: str = "celsius") -> Dict[str, Any]:
"""
模拟获取当前天气。
在实际应用中,这里会调用 httpx 请求第三方 API。
"""
# Mock Data based on location
mock_db = {
"beijing": {"temp_c": 25, "condition": "Sunny", "humidity": 40},
"shanghai": {"temp_c": 28, "condition": "Cloudy", "humidity": 70},
"new york": {"temp_c": 15, "condition": "Rainy", "humidity": 90}
}
loc_key = location.lower()
if loc_key not in mock_db:
return {"error": f"Weather data for '{location}' not found."}
data = mock_db[loc_key]
# 单位转换
temp = data["temp_c"]
if unit == "fahrenheit":
temp = (temp * 9/5) + 32
return {
"location": location,
"temperature": round(temp, 1),
"unit": unit,
"condition": data["condition"],
"humidity": data["humidity"]
}
# 实例化服务
weather_service = WeatherService()
4.3 步骤二:定义 Skill 的 Schema(说明书)
这是最关键的一步。我们需要告诉 LLM 如何调用这个函数。
创建 skill_definition.py:
SKILL_SCHEMA = {
"name": "get_current_weather",
"description": "Get the current weather for a specific location. Use this whenever the user asks about the weather, temperature, or climate conditions in a city.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g., 'Beijing', 'London', 'New York'. Support both Chinese and English.",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The temperature unit. Defaults to celsius.",
},
},
"required": ["location"],
},
}
# 将所有 Skill 汇总
AVAILABLE_SKILLS = [SKILL_SCHEMA]
# 映射 Skill 名称到实际的执行函数
SKILL_EXECUTORS = {
"get_current_weather": weather_service.get_current_weather
}
4.4 步骤三:搭建 FastAPI 服务与 Agent 逻辑
现在,我们将 Skill 挂载到一个 Web 服务中,并处理与 LLM 的交互。
创建 main.py:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from openai import AsyncOpenAI
from dotenv import load_dotenv
import json
import traceback
from weather_tool import weather_service
from skill_definition import AVAILABLE_SKILLS, SKILL_EXECUTORS
load_dotenv()
app = FastAPI(title="My First AI Skill Server")
# 初始化 OpenAI Client
client = AsyncOpenAI()
class ChatRequest(BaseModel):
message: str
history: list[dict] = [] # 用于维护多轮对话
@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
try:
messages = request.history + [
{"role": "user", "content": request.message}
]
# 第一轮:让 LLM 决定是否需要调用 Skill
response = await client.chat.completions.create(
model="gpt-3.5-turbo", # 或者 "moonshot-v1-8k"
messages=messages,
tools=[{"type": "function", "function": s} for s in AVAILABLE_SKILLS],
tool_choice="auto", # 自动决定是否调用工具
)
response_message = response.choices[0].message
# 检查是否有工具调用请求
if response_message.tool_calls:
# 执行 Skill
tool_call = response_message.tool_calls[0]
function_name = tool_call.function.name
if function_name not in SKILL_EXECUTORS:
raise HTTPException(status_code=400, detail=f"Unknown skill: {function_name}")
# 解析参数
arguments = json.loads(tool_call.function.arguments)
# 执行对应的函数
function_response = await SKILL_EXECUTORS[function_name](**arguments)
# 将消息历史拼接起来
# 1. 用户的原始请求
# 2. LLM 返回的带有 tool_calls 的消息
# 3. 工具执行的结果
messages.append(response_message)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(function_response, ensure_ascii=False),
})
# 第二轮:将工具结果发回给 LLM,让它生成最终回复
final_response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages,
)
return {
"role": "assistant",
"content": final_response.choices[0].message.content,
"debug": {
"skill_called": function_name,
"arguments": arguments,
"raw_result": function_response
}
}
else:
# 如果不需要调用工具,直接返回 LLM 的回复
return {
"role": "assistant",
"content": response_message.content
}
except Exception as e:
print(traceback.format_exc())
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
4.5 步骤四:运行与测试
-
启动服务:
python main.py -
使用 curl 或 Postman 测试:
curl -X POST "http://localhost:8000/chat" \ -H "Content-Type: application/json" \ -d '{ "message": "北京今天多少度?", "history": [] }'
预期返回结果:
{
"role": "assistant",
"content": "北京今天的气温是25°C,天气晴朗。",
"debug": {
"skill_called": "get_current_weather",
"arguments": {
"location": "北京",
"unit": "celsius"
},
"raw_result": {
"location": "北京",
"temperature": 25.0,
"unit": "celsius",
"condition": "Sunny",
"humidity": 40
}
}
}
🎉 恭喜!你已经成功构建了第一个 AI Skill。
五、进阶:构建企业级 Skill 生态

当你有了 10 个、100 个 Skill 时,上述简单的架构将面临挑战。企业级落地需要考虑更多维度。
5.1 Skill 注册中心 (Registry)
不能把所有的 Skill Schema 都硬编码在代码里。需要一个中心化的注册表(可以是数据库或配置文件)。
# skills/weather.yaml
name: get_current_weather
version: 1.0.0
description: ...
endpoint: http://internal-api/weather
auth: api_key
schema:
type: object
properties: ...
服务启动时,自动扫描并加载这些配置。
5.2 权限与隔离 (Auth & Isolation)
-
用户级权限:用户 A 不能调用用户 B 的私有 Skill(如查询私人日历)。
-
租户隔离:SaaS 环境下,Tenant A 的 Skill 不能被 Tenant B 看到。
-
沙箱机制:如果 Skill 允许用户上传代码执行(极端危险),必须使用 Docker 或 WASM 进行强隔离。
5.3 异步 Skill (Async Skills)
有些任务耗时很长,比如“生成一张复杂的海报”或“训练一个模型”。
此时不能让 LLM 等待 HTTP 响应。
解决方案:异步回调机制。
-
LLM 调用
create_poster_taskSkill。 -
Skill 立即返回一个
task_id:“任务已提交,ID 为 xxx”。 -
后台 Worker 执行任务。
-
任务完成后,通过 WebSocket 或 Webhook 通知 Agent,Agent 再告知用户。
5.4 RAG + Skill 的结合
很多时候,用户的问题既需要知识检索,又需要工具调用。
例如:“帮我总结一下昨天关于 Q3 财报的邮件,并对比去年同期数据。”
-
RAG:检索昨天关于 Q3 财报的邮件内容。
-
Skill:调用
query_database获取去年同期的财务数据。 -
LLM:融合两者生成总结。
这需要在 Prompt 层面进行精细编排,或者使用 LangChain/LlamaIndex 等框架的 Agent 模块。
5.5 监控与可观测性 (Observability)
你需要知道:
-
哪个 Skill 调用最多?(热门功能)
-
哪个 Skill 经常失败?(稳定性问题)
-
Token 消耗在哪里?(成本控制)
-
LLM 是否产生了幻觉参数?(质量评估)
建议使用 OpenTelemetry 或类似工具,为每个 Skill 调用生成 Trace ID。
六、常见陷阱与避坑指南

-
过度依赖 LLM 的推理能力:不要把复杂的业务逻辑完全交给 LLM 去判断。Skill 内部要有完整的校验和兜底逻辑。
-
忽略负面反馈:当 Skill 执行失败时,返回给 LLM 的错误信息要友好且具有指导性。例如,不要只返回
404,而是返回{"error": "City not found, please check spelling or suggest nearby cities."}。这样 LLM 才能修正后重试。 -
上下文窗口溢出:Skill 返回的数据可能很大(例如长文档)。需要对返回内容进行截断、压缩或摘要,防止超出模型的上下文限制。
-
循环调用:Agent 可能会陷入死循环(调用 A -> 调用 B -> 发现需要 A -> 调用 A...)。需要设置最大调用步数(Max Steps),例如 ReAct 循环最多 10 次。
七、未来展望:Skill 将走向何方?

-
标准化 (Standardization):MCP 等协议的成熟将使得 Skill 像 NPM 包一样流通。你将不再需要从头写天气 Skill,而是直接
pip install mcp-weather-server。 -
GUI 自动化:Skill 不再局限于 API 调用。结合 Computer Use 模型(如 Claude 3.5 Sonnet),Skill 可以直接操作图形界面,点击按钮、填写表单,从而控制那些没有开放 API 的老旧软件。
-
自主进化:未来的 Agent 或许能够根据用户的需求,自动编写新的 Skill 代码并进行测试部署(Code -> Test -> Deploy),实现真正的自我进化。
-
去中心化市场:开发者可以将自己编写的优质 Skill 放到区块链上进行确权、交易和分发,形成一个繁荣的 AI 技能经济生态。
八、总结

Skill 是 AI Agent 的基石。它将大模型从“纸上谈兵”的理论家,变成了能够“撸起袖子加油干”的实干家。
构建 Skill 的过程,本质上是将人类的业务逻辑翻译成机器可执行、AI 可理解的接口。这要求我们不仅要懂后端开发,还要懂 Prompt Engineering,更要懂 AI 的行为模式。
回顾我们的第一个 Skill:
-
定义逻辑:编写了
get_current_weather函数。 -
定义接口:创建了 JSON Schema,作为 AI 的“说明书”。
-
编排流程:实现了 ReAct 循环(思考 -> 调用 -> 观察 -> 回答)。
这看似简单的三步,正是通往通用人工智能应用的第一步。希望这篇长文能为你打开 AI Skill 开发的大门,期待你构建出改变世界的智能应用!
附录:推荐阅读与工具
-
OpenAI Function Calling Docs: 官方文档永远是最好的起点。
-
Model Context Protocol (MCP): Anthropic 的最新协议,值得关注。
-
LangChain Tools: 提供了大量开箱即用的 Tool 封装。
-
FastAPI: 构建 Skill 后端服务的首选框架。
-
Pydantic: 数据验证的利器,非常适合定义 Skill 参数模型。
📚 附录链接补全
-
OpenAI Function Calling Docs
https://platform.openai.com/docs/guides/function-calling
官方指南,含 Schema 定义、多工具调用、stream 模式等最新写法。
-
Model Context Protocol (MCP)
https://modelcontextprotocol.io
Anthropic 主导的开放协议,SDK(Python / TypeScript)和 Server 样例都在这里。
-
LangChain Tools
https://python.langchain.com/docs/concepts/tools/
LangChain 的 Tool / ToolCall / Agent 编排文档,开箱即用的 Tool 封装大全。
-
FastAPI
官方文档,含依赖注入、Pydantic 集成、异步路径,搭 Skill 后端首选。
-
Pydantic
V2 文档,重点看
BaseModel、Field、model_validator——Skill 参数校验的核心。
本文涵盖了从原理到实战的内容。如果需要我针对特定场景(如企业内部系统、电商客服)为你设计一个更复杂的进阶版 Skill,请评论区留言!
更多推荐



所有评论(0)