一、前言
现在不管是做企业应用、内部效率工具还是对外AI产品,大家都越来越清楚一件事:单纯靠大模型聊天,根本解决不了真实业务问题。用户要的不是说得好听,而是能真正把事办成,比如自动查数据、生成报表、处理工单、对接业务系统,甚至完成一整串复杂流程。
但直接把一堆 API、工具塞给大模型去调用,很容易出现逻辑混乱、执行出错、不可控、不好维护的问题。业务一变,代码就要重写,模型也跟着乱决策。所以行业里慢慢形成了一种更稳定、更工程化的思路:把 、AI的能力拆成一个个标准化、可复用、可管理的技能单元,也就是我们常说的SKILL体系。
基于SKILL构建 AI 智能体,本质上就是让AI从即兴发挥变成按规办事,让每一项能力都可注册、可调度、可监控、可迭代。今天我们就从业务落地的实际应用视角,完整讲清楚:如何从零搭建一套可直接用在生产环境的SKILL驱动AI智能体,从架构设计、技能定义,到前后端实现、调度执行与部署,全部一次性说清道明,了解透彻。

二、核心概念
1. 什么是 SKILL
SKILL可以理解未智能体的"能力插件",是封装特定任务逻辑、输入输出、触发条件与执行流程的标准化单元,也是AI智能体能够落地业务、解决实际问题的核心基础。
区别于普通 Tool(工具):
SKILL不只是简单的调用接口,而是包含场景描述、任务目标、触发条件、执行步骤、输出规范、示例案例、依赖关系七大完整要素,是可独立开发、独立测试、独立部署、独立迭代的最小能力单元;
比如"查询天气"这个 SKILL,不只是调用天气API,还会明确适用场景、输入的城市格式、输出的天气字段、异常处理方式,甚至给出测试示例,方便开发和维护。
区别于子Agent(子智能体):
SKILL更轻量、更聚焦,只负责完成某一个单一的具体任务,没有独立的上下文管理和记忆能力,所有的调度、上下文衔接、记忆存储,都由主Agent统一管控;
比如"生成周报"和"发送邮件"是两个独立SKILL,主Agent会根据用户需求,调度这两个SKILL协同完成"生成周报并发送"的完整任务,而每个SKILL只专注自己的核心功能。

2. SKILL 架构的核心价值
2.1 模块化
- 将智能体的能力拆分为独立的SKILL单元,每个SKILL负责一项具体任务,开发时可分工协作,不同开发人员负责不同SKILL;
- 迭代时只需修改对应 SKILL,无需改动整个智能体代码,大幅降低系统耦合度,提升开发效率。
2.2 可扩展
- 支持SKILL的动态注册与卸载,新增业务能力时,只需按标准开发新的SKILL并放入指定目录,系统会自动加载,无需修改主 Agent 核心代码;
- 淘汰无用能力时,直接删除 SKILL 目录即可,灵活适配业务迭代需求。
2.3 可观测
- 每个SKILL的执行过程都有清晰的日志记录,从触发、参数校验、执行到输出,全链路可监控、可审计;
- 一旦出现问题,能快速定位到具体SKILL,无需排查整个系统,降低问题排查成本。
2.4 高可靠
- 单一SKILL出现故障(如 API 调用失败、代码报错)时,不会影响整个智能体的正常运行,系统会自动触发降级机制;
- 返回友好提示或调用备用 SKILL,保障业务流程不中断,提升系统稳定性。
2.5 易维护
- 所有SKILL按统一目录结构组织,每个SKILL都有标准化的元数据SKILL.md,清晰记录其功能、用法和依赖;
- 后续维护时,只需查看对应 SKILL 的文档和代码,无需梳理整个系统逻辑,降低维护成本,也便于新人快速上手。

3. SKILL 的能力分类
| 类别 | 核心功能 | 典型示例 | 实现方式 |
|---|---|---|---|
| 基础交互 | 对话理解、意图识别 | 问候、澄清、结束 | 大模型 Prompt |
| 信息获取 | 数据查询、API 调用 | 天气、新闻、数据库查询 | 代码 + API |
| 内容生成 | 文案、报告、代码 | 写邮件、生成周报 | 大模型 + 模板 |
| 工具操作 | 文件、系统、第三方工具 | 读写文件、发送邮件 | 代码执行 |
| 流程编排 | 多技能组合、任务规划 | 差旅预订、报告生成 | 工作流引擎 |
| 领域专业 | 垂直行业能力 | 医疗问诊、金融分析 | 领域知识 + 技能 |
4. SKILL 的标准结构
skill-name/
├── SKILL.md # 技能元数据(核心)
├── init.py # 技能入口
├── impl.py # 技能实现逻辑
├── examples/ # 输入输出示例
├── tests/ # 单元测试
└── resources/ # 配置/依赖资源
三、SKILL.md 详细说明
SKILL.md是SKILL体系最核心的文件,相当于每个技能的身份证 + 说明书 + 接口文档 + 运行手册,系统、开发者、大模型都靠它工作;
1. SKILL.md 是什么
SKILL.md 是技能的标准化元数据文件,采用YAML + Markdown 混合格式。它的作用:
- 让系统自动识别技能
- 让调度引擎知道何时触发
- 让执行器知道入参和出参
- 让大模型知道如何调用
- 让开发者知道功能、边界、示例
- 让运维知道依赖、权限、版本
总结来说:没有SKILL.md,SKILL就无法被智能体识别与使用。
2. SKILL.md 固定标准格式
XML
---
# YAML 格式:机器可解析字段(核心!系统读取这里)
name: 技能唯一标识
description: 技能一句话功能描述
version: 版本号
author: 开发者
category: 技能分类
priority: 执行优先级
trigger:
keywords: []
intent: []
context: []
confidence: 0.8
input_schema:
type: object
properties: {}
required: []
output_schema:
type: object
properties: {}
examples:
- input: ""
output: {}
- input: ""
output: {}
dependencies:
api: []
skills: []
permissions: []
limits:
max_retries: 2
timeout: 5
rate_limit: "10/min"
---
# Markdown 格式:注释文档(系统不解析)
## 功能说明
...
## 执行流程
1. ...
2. ...
## 异常处理
...
## 使用注意事项
...

3. 格式内容详解
3.1 基础信息段
XML
name: weather_query # 唯一标识(英文、下划线,不能重复)
description: 查询城市天气 # 功能描述(给大模型+人看)
version: 1.0.0 # 版本(方便升级/回滚)
author: AI-Team # 开发者
category: info_query # 分类:info_query / operate / generate / workflow
priority: 5 # 优先级1-10,数字越高越先匹配
用途:
- 系统唯一识别技能
- 展示在管理后台
- 做版本控制
- 做技能分类检索
3.2 触发规则 trigger
XML
trigger:
keywords: ["天气", "温度", "下雨", "预报"] # 关键词匹配
intent: ["查询天气", "获取气象"] # 意图名称
context: ["出行", "旅游", "日常"] # 场景上下文
confidence: 0.8 # 触发置信度阈值
作用:让智能体知道什么时候用这个技能
- keywords:用户输入包含这些词,优先匹配
- intent:意图标识,大模型可直接选择
- context:场景过滤,避免乱触发
- confidence:高于 0.8 才触发,避免误调用
业务意义:精准触发,不幻觉、不错误调用、不乱执行。
3.3 输入规范 input_schema
XML
input_schema:
type: object
properties:
city:
type: string
description: 城市名称
days:
type: integer
default: 1
minimum: 1
maximum: 7
required: ["city"]
作用:
- 告诉大模型必须提取什么参数
- 告诉执行器接收什么格式
- 自动做参数校验
- 缺失参数时自动反问用户
3.4 输出规范 output_schema
XML
output_schema:
type: object
properties:
success: {type: boolean}
message: {type: string}
data: {type: object}
作用:
- 统一所有技能输出格式
- 主 Agent 可以稳定解析结果
- 前端可以统一渲染
- 异常统一返回格式
3.5 示例 examples
XML
examples:
- input: "杭州明天天气"
output: {"success":true,"data":{"city":"杭州",...}}
- input: "上海未来3天天气"
output: {"success":true,...}
- input: "查询火星天气"
output: {"success":false,"message":"不支持该城市"}
作用:
- 给大模型做小样本学习
- 给测试做自动化用例
- 给开发者理解输入输出
- 提升意图识别准确率
3.6 依赖 dependencies
XML
dependencies:
api: ["weather_api"]
skills: []
permissions: ["user:normal"]
作用:
- 系统启动时检查依赖是否就绪
- 权限控制
- 技能之间的依赖编排
- API 密钥检查
3.7 限制 limits
XML
limits:
max_retries: 2
timeout: 5
rate_limit: "10/min"
作用:
- 失败自动重试
- 超时强制结束
- 防刷限流
- 保证系统稳定
3.8 注释说明文档
bash
## 功能说明
用于查询国内城市实时天气与预报。
## 执行流程
1. 解析用户输入,提取城市、天数
2. 校验城市是否支持
3. 调用天气API
4. 返回格式化结果
## 异常处理
- API 失败:返回友好提示
- 城市不支持:明确提示
## 注意事项
仅支持国内一线/新一线城市
作用:
- 团队协作文档
- 维护手册
- 上线说明
- 业务边界说明
4. SKILL.md 必不可少
- 系统自动加载技能
- 大模型知道如何调用
- 调度引擎知道如何触发
- 执行器知道参数格式
- 开发者知道功能边界
- 测试知道用例标准
- 运维知道依赖与权限
- 业务能做到可管控、可审计、可迭代
它是SKILL体系的"契约文件",没有它,模块化、工程化都无法实现。
四、SKILL 智能体整体架构
1. 分层架构图
- 用户交互层与前端/API网关作为入口,将请求汇聚至 Agent核心层。
- Agent核心层依次调用 技能注册中心 → 技能调度引擎 → 技能执行层 → 基础设施层,完成从意图理解到技能执行的全链路。
- 各层职责清晰,便于扩展与维护。

2. 核心组件详解
2.1 Agent Core(智能体核心)
- **接收用户请求:**作为入口,统一处理用户输入,完成初步清洗与格式归一化。
- **意图理解与任务拆解:**调用大模型进行语义解析,识别用户意图,将复杂任务拆解为可执行的子任务。
- **调用 SkillRegistry 匹配技能:**根据解析结果,查询 SkillRegistry 获取可用的技能列表。
- **调度执行引擎,编排技能流程:**将技能组合成工作流(DAG),并交由调度引擎执行,支持串行、并行、条件分支。
- **管理对话记忆与上下文:**维护当前会话的短期记忆(历史轮次、关键实体),必要时从长期向量库中召回相关记忆。
- **合成最终响应:**整合技能执行结果,利用大模型生成自然语言回复,返回给用户。
2.2 SkillRegistry(技能注册中心)
- **扫描技能目录,加载 SKILL.md 元数据:**自动发现技能模块,解析其元数据(名称、描述、输入输出、依赖、版本)。
- **提供技能查询、匹配、发现能力:**支持按名称、标签、语义相似度进行技能检索,为 Agent Core 提供候选技能列表。
- **管理技能版本、依赖、权限:**维护技能升级策略,确保依赖版本兼容,控制技能调用权限(如仅管理员可用)。
- **支持动态注册/卸载:**允许运行时添加新技能或停用过时技能,无需重启服务,实现热插拔。
2.3 Skill Scheduler(技能调度引擎)
- **根据任务规划,选择最优技能组合:**基于成本、耗时、成功率等指标,从候选技能中选出最优执行路径。
- **处理技能依赖、并行/串行执行:**解析技能间的输入输出依赖,自动并行无依赖的技能,提升执行效率。
- **异常处理、重试、降级:**对执行失败的技能进行重试,如可重试错误,若仍失败则执行降级方案,如使用备选技能或返回友好提示。
- **执行状态跟踪与日志记录:**实时记录每个技能的执行状态、耗时、输入输出,便于监控和问题排查。
2.4 Skill Executor(技能执行器)
- **加载技能实现(代码/Prompt):**根据技能类型(函数式、API、Prompt 模板),加载对应的实现逻辑。
- **解析输入,校验参数:**将 Agent Core 传递的上下文参数与技能要求的输入进行匹配,校验必填字段与数据类型。
- **执行技能逻辑,调用外部工具:**实际运行技能,可能调用本地函数、远程 API、数据库查询或大模型推理。
- **格式化输出,返回结果:**将执行结果按统一格式返回给调度引擎,便于后续技能使用或最终响应合成。
2.5 Infrastructure(基础设施)
- **大模型API、第三方服务、数据库:**提供底层能力支撑,如LLM推理、知识库检索、业务系统对接。
- **向量库、文件存储、消息队列:**存储非结构化数据(文档、图片)、管理异步任务、实现服务解耦。
- **认证、监控、日志系统:**保障服务安全,实时观测性能指标,记录全链路日志用于审计与优化。
五、SKILL 智能体完整实现
1. 技术选型
- 框架:FastAPI(API+WebSocket)
- 技能管理:自定义 SkillRegistry + 目录扫描
- 大模型:本地大模型或在线api调用
- 数据校验:Pydantic
- 技能发现:文件系统监听 + 动态加载
- 部署:Docker + 云服务器
2. 步骤 1:设计 SKILL
2.1 SKILL 设计五步法
- 场景定义:明确技能适用场景、用户画像、业务目标
- 触发设计:关键词、意图、上下文触发条件
- IO 规范:输入输出 Schema(JSON Schema)
- 执行逻辑:步骤化流程、工具调用、异常处理
- 示例与测试:3 + 输入输出示例,覆盖正常、边界、异常
2.2 实战:天气查询 SKILL设计
2.2.1 目录结构
skill_agent_project/
├── .env # 环境变量(API KEY、配置)
├── main.py # 后端入口:FastAPI + WebSocket + Agent调度
├── skill_registry.py # 技能注册中心 + 动态加载 + 文件监听├── requirements.txt # 所有依赖清单
├── Dockerfile # 生产部署(可选)
├── static/ # 前端静态资源
│ └── index.html # 实时对话前端界面
└── skills/ # 所有技能统一存放目录(核心)
└── weather_query/ # 示例技能:天气查询
├── SKILL.md # 技能元数据(Schema、触发、描述)
├── impl.py # 技能真正执行逻辑├── examples/ # 示例输入输出(可选)
└── tests/ # 技能单元测试(可选)
注意加粗的部分,完整的一个SKILL所包含的完整文件以及文章种提供的完整示例代码,实际目录结构可参考下图:

2.2.2 完整SKILL.md
XML
---
name: weather_query
description: 查询指定城市实时天气与未来N天预报,支持国内主要城市
version: 1.0.0
author: DevTeam
trigger:
keywords: ["天气", "温度", "下雨", "晴天", "预报", "穿衣"]
intent: ["查询天气", "获取气象信息", "天气建议"]
context: ["出行", "旅游", "日常"]
input_schema:
type: object
properties:
city:
type: string
description: 城市名称(如:杭州、北京)
days:
type: integer
default: 1
minimum: 1
maximum: 7
description: 预报天数(1-7天)
required: ["city"]
output_schema:
type: object
properties:
success: {type: boolean}
message: {type: string}
data:
type: object
properties:
current: {type: object}
forecast: {type: array}
examples:
- input: "杭州明天天气怎么样?"
output:
success: true
message: "查询成功"
data: {"current": {...}, "forecast": [...]}
- input: "查询上海未来3天天气"
output: {"success": true, ...}
- input: "查询火星天气"
output: {"success": false, "message": "不支持该城市"}
dependencies:
api: ["open-weather-map"]
skills: []
---
# 执行流程
1. 解析用户输入,提取city和days参数
2. 校验城市有效性,仅支持国内城市
3. 调用OpenWeatherMap API获取天气数据
4. 格式化数据为标准输出结构
5. 处理API异常,返回友好提示
# 边界限制
- 仅支持中国内地城市
- 预报天数范围:1-7天
- API调用频率限制:10次/分钟
2.2.3 技能实现:impl.py
python
import requests
import os
from pydantic import BaseModel, ValidationError
from typing import Optional, Dict, Any
# 输入输出模型
class WeatherInput(BaseModel):
city: str
days: int = 1
class WeatherOutput(BaseModel):
success: bool
message: str
data: Optional[Dict[str, Any]] = None
# 技能实现
class WeatherQuerySkill:
def __init__(self):
self.api_key = os.getenv("WEATHER_API_KEY")
self.base_url = "https://api.openweathermap.org/data/2.5"
self.supported_cities = ["杭州", "北京", "上海", "广州", "深圳"]
# 城市中文名到拼音的映射
self.city_name_map = {
"杭州": "Hangzhou",
"北京": "Beijing",
"上海": "Shanghai",
"广州": "Guangzhou",
"深圳": "Shenzhen"
}
def execute(self, input_data: dict) -> dict:
"""执行天气查询技能"""
try:
# 1. 校验输入
validated = WeatherInput(**input_data)
if validated.city not in self.supported_cities:
return WeatherOutput(
success=False,
message=f"不支持城市:{validated.city},仅支持:{', '.join(self.supported_cities)}"
).dict()
# 2. 调用API(将城市名转换为拼音)
city_pinyin = self.city_name_map.get(validated.city, validated.city)
params = {
"q": city_pinyin,
"appid": self.api_key,
"units": "metric",
"lang": "zh_cn"
}
response = requests.get(f"{self.base_url}/weather", params=params)
response.raise_for_status()
current = response.json()
# 3. 获取预报
forecast_params = params.copy()
forecast_params["cnt"] = validated.days
forecast_resp = requests.get(f"{self.base_url}/forecast", params=forecast_params)
forecast_resp.raise_for_status()
forecast = forecast_resp.json()
# 4. 格式化结果
result = {
"current": {
"temp": current["main"]["temp"],
"desc": current["weather"][0]["description"],
"humidity": current["main"]["humidity"]
},
"forecast": [
{
"date": item["dt_txt"],
"temp": item["main"]["temp"],
"desc": item["weather"][0]["description"]
} for item in forecast["list"]
]
}
return WeatherOutput(
success=True,
message="查询成功",
data=result
).dict()
except ValidationError as e:
return WeatherOutput(success=False, message=f"参数错误:{str(e)}").dict()
except Exception as e:
return WeatherOutput(success=False, message=f"服务异常:{str(e)}").dict()
# 技能入口
def get_skill():
return WeatherQuerySkill()
3. 步骤 2:实现技能注册中心:SkillRegistry
核心功能:扫描技能目录、加载元数据、提供查询匹配,对应文件:skill_registry.py
python
import os
import yaml
import importlib
from typing import Dict, List, Any
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class SkillRegistry:
def __init__(self, skill_dir: str = "skills"):
self.skill_dir = skill_dir
self.skills: Dict[str, Dict[str, Any]] = {} # name: skill_data
self._load_all_skills()
self._start_watcher()
def _load_skill(self, skill_path: str):
"""加载单个技能"""
skill_name = os.path.basename(skill_path)
skill_md = os.path.join(skill_path, "SKILL.md")
if not os.path.exists(skill_md):
return
# 解析SKILL.md
with open(skill_md, 'r', encoding='utf-8') as f:
content = f.read()
if '---' in content:
yaml_part = content.split('---')[1]
meta = yaml.safe_load(yaml_part)
meta["path"] = skill_path
meta["module"] = f"skills.{skill_name}.impl"
self.skills[meta["name"]] = meta
def _load_all_skills(self):
"""加载所有技能"""
self.skills.clear()
for item in os.listdir(self.skill_dir):
skill_path = os.path.join(self.skill_dir, item)
if os.path.isdir(skill_path):
self._load_skill(skill_path)
print(f"已加载 {len(self.skills)} 个技能: {', '.join(self.skills.keys())}")
def match_skills(self, query: str) -> List[Dict[str, Any]]:
"""根据用户查询匹配技能"""
matched = []
query_lower = query.lower()
for skill in self.skills.values():
# 关键词匹配
for kw in skill["trigger"]["keywords"]:
if kw.lower() in query_lower:
matched.append(skill)
break
return matched
def get_skill_instance(self, skill_name: str):
"""获取技能实例"""
if skill_name not in self.skills:
raise ValueError(f"技能不存在:{skill_name}")
skill_meta = self.skills[skill_name]
module = importlib.import_module(skill_meta["module"])
return module.get_skill()
# 文件监听:技能变更自动重载
class SkillChangeHandler(FileSystemEventHandler):
def __init__(self, registry):
self.registry = registry
def on_modified(self, event):
if event.is_directory:
return
if "SKILL.md" in event.src_path:
print("技能文件变更,重新加载...")
self.registry._load_all_skills()
def _start_watcher(self):
"""启动文件监听"""
event_handler = self.SkillChangeHandler(self)
observer = Observer()
observer.schedule(event_handler, self.skill_dir, recursive=True)
observer.start()
4. 步骤 3:实现Agent Core + 调度执行引擎
这里我们构建了一个基于SKILL的 AI 智能体后端服务,主要用于演示如何通过意图识别来调用特定功能。
- 核心用途:接收用户的自然语言输入,分析意图,匹配并执行相应的技能(如计算、翻译、查询天气等),并通过 WebSocket 实现实时对话交互。
- 核心逻辑:接收请求 → 意图理解 → 匹配技能 → 执行 → 返回结果
文件名称:main.py
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
import os
from dotenv import load_dotenv
from skill_registry import SkillRegistry
load_dotenv()
app = FastAPI(title="SKILL-Based AI Agent")
# 确保使用绝对路径
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, "static")
# 挂载静态文件
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
registry = SkillRegistry()
# 模拟LLM类
class MockLLM:
def __init__(self, **kwargs):
pass
def run(self, **kwargs):
# 模拟意图识别逻辑
query = kwargs.get("query", "")
skills = kwargs.get("skills", "")
# 简单的基于规则的匹配 - 返回实际的技能名称
if "天气" in query:
return "weather_query"
elif "旅游" in query or "景点" in query:
return "travel_guide"
elif "翻译" in query:
return "translate"
elif "计算" in query or "加" in query or "乘" in query:
return "calculator"
else:
# 返回第一个技能
skill_list = skills.split(", ")
return skill_list[0] if skill_list else "unknown"
llm = MockLLM()
# 模拟意图识别链
class MockIntentChain:
def __init__(self, llm, prompt):
self.llm = llm
def run(self, **kwargs):
return self.llm.run(**kwargs)
intent_chain = MockIntentChain(llm=llm, prompt=None)
# 对话记忆(模拟版本)
class MockMemory:
def __init__(self, **kwargs):
self.chat_history = []
memory = MockMemory()
# 连接管理
class ConnectionManager:
def __init__(self):
self.active_connections = []
async def connect(self, ws):
await ws.accept()
self.active_connections.append(ws)
def disconnect(self, ws):
self.active_connections.remove(ws)
async def send(self, msg, ws):
await ws.send_text(msg)
manager = ConnectionManager()
# 技能执行逻辑
async def execute_skill_flow(query: str) -> str:
"""执行技能流程"""
# 1. 匹配技能
matched = registry.match_skills(query)
if not matched:
return "暂不支持该功能,请尝试其他问题"
# 2. 意图识别选择最优技能
skill_names = [s["name"] for s in matched]
selected_skill_name = intent_chain.run(query=query, skills=", ".join(skill_names)).strip()
# 3. 获取技能实例
try:
skill = registry.get_skill_instance(selected_skill_name)
except:
return f"技能 {selected_skill_name} 加载失败"
# 4. 解析输入(简化版,实际需用大模型提取参数)
input_data = _extract_params_from_query(selected_skill_name, query)
# 5. 执行技能
result = skill.execute(input_data)
return f"【{selected_skill_name}】结果:{result}"
def _extract_params_from_query(skill_name: str, query: str) -> dict:
"""从用户查询中提取技能参数"""
query = query.strip()
# 计算器技能参数提取
if skill_name == "calculator":
# 提取数字和运算符
import re
# 匹配表达式(数字、运算符、括号)
expr_match = re.search(r'[\d\+\-\*\/\^\%\(\)\. ]+', query)
if expr_match:
expression = expr_match.group(0).strip()
return {"expression": expression}
else:
# 查找 "计算xxx" 或 "xxx等于多少" 模式
if "计算" in query:
expr = query.replace("计算", "").replace("等于多少", "").replace("等于", "").strip()
return {"expression": expr}
return {"expression": "0"}
# 翻译技能参数提取
elif skill_name == "translate":
import re
result = {"target_lang": "en", "text": "你好"}
# 提取目标语言
if "中文" in query:
result["target_lang"] = "zh"
elif "英文" in query or "英语" in query:
result["target_lang"] = "en"
elif "日语" in query:
result["target_lang"] = "ja"
elif "韩语" in query:
result["target_lang"] = "ko"
elif "德语" in query:
result["target_lang"] = "de"
elif "法语" in query:
result["target_lang"] = "fr"
# 提取待翻译文本(引号内的内容)
quote_match = re.search(r'["\'<<「『](.+?)["\'」』]', query)
if quote_match:
result["text"] = quote_match.group(1)
else:
# 简单提取:"把xxx翻译成..."
if "把" in query and "翻译成" in query:
text_part = query.split("翻译成")[0].replace("把", "").strip()
result["text"] = text_part
elif "将" in query and "翻译成" in query:
text_part = query.split("翻译成")[0].replace("将", "").strip()
result["text"] = text_part
return result
# 旅游指南技能参数提取
elif skill_name == "travel_guide":
input_data = {"city": "杭州", "days": 1}
if "上海" in query:
input_data["city"] = "上海"
elif "北京" in query:
input_data["city"] = "北京"
if "3天" in query:
input_data["days"] = 3
return input_data
# 天气查询技能参数提取
elif skill_name == "weather_query":
input_data = {"city": "杭州", "days": 1}
if "上海" in query:
input_data["city"] = "上海"
elif "北京" in query:
input_data["city"] = "北京"
elif "广州" in query:
input_data["city"] = "广州"
elif "深圳" in query:
input_data["city"] = "深圳"
if "3天" in query:
input_data["days"] = 3
return input_data
# 默认返回空字典
return {}
# WebSocket实时对话
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
while True:
user_msg = await websocket.receive_text()
await manager.send(f"[你] {user_msg}", websocket)
await manager.send("[AI处理中...]", websocket)
# 执行技能流程
response = await execute_skill_flow(user_msg)
await manager.send(f"[AI] {response}", websocket)
except WebSocketDisconnect:
manager.disconnect(websocket)
@app.get("/")
async def root():
return FileResponse(os.path.join(BASE_DIR, "static", "index.html"))
@app.get("/api/skills")
async def get_skills():
return {"message": "SKILL-Based AI Agent", "skills": list(registry.skills.keys())}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8002)
重点功能:
- 技能注册与匹配:利用 SkillRegistry 管理可用技能,根据用户输入匹配候选技能列表。
- 意图识别:通过 MockLLM模拟大语言模型从候选技能中确定用户的具体意图,例如区分"计算"和"翻译"。
- 参数提取:内置 _extract_params_from_query 函数,使用正则表达式从自然语言中提取关键参数,如提取算式、目标语言、城市名。
- 实时通信:基于 FastAPI 的 WebSocket 实现全双工通信,支持流式或即时响应的聊天界面。
- 静态服务:挂载静态文件目录,直接提供前端HTML页面index.html以便用户访问交互。
5. 步骤 4:前端实时交互界面
前端提供了一个可以满足交互的页面,样式可以根据我们的要求让AI替我们美化即可;
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SKILL AI Agent 实时对话</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:Arial}
.container{max-width:900px;margin:20px auto;height:90vh;display:flex;flex-direction:column}
.chat{flex:1;border:1px solid #ddd;border-radius:10px;padding:20px;overflow-y:auto;background:#f9f9f9}
.input{display:flex;margin-top:15px}
#msg{flex:1;padding:15px;border:1px solid #ddd;border-radius:8px;font-size:16px}
button{padding:15px 25px;background:#007bff;color:white;border:none;border-radius:8px;margin-left:10px;cursor:pointer}
button:hover{background:#0056b3}
.msg{margin:10px 0;padding:12px 16px;border-radius:8px;max-width:80%}
.user{background:#d3eafd;align-self:flex-end;margin-left:auto}
.ai{background:#fff;align-self:flex-start;border:1px solid #eee}
.log{color:#666;font-size:14px;padding:5px}
</style>
</head>
<body>
<div class="container">
<h2 style="text-align:center">SKILL AI 智能体</h2>
<div class="chat" id="chat"></div>
<div class="input">
<input id="msg" placeholder="输入问题...">
<button onclick="send()">发送</button>
</div>
</div>
<script>
const chat = document.getElementById('chat');
const msgInput = document.getElementById('msg');
// 获取WebSocket地址,处理不同端口
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsHost = window.location.host || 'localhost:8002';
const wsUrl = `${wsProtocol}//${wsHost}/ws`;
console.log('Connecting to WebSocket:', wsUrl);
let ws = null;
let isConnected = false;
function connect() {
ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('WebSocket connected');
isConnected = true;
addLog('已连接到服务器');
};
ws.onclose = () => {
console.log('WebSocket closed');
isConnected = false;
addLog('连接已断开');
// 3秒后尝试重连
setTimeout(connect, 3000);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
addLog('连接错误');
};
ws.onmessage = (e) => {
console.log('Received message:', e.data);
const div = document.createElement('div');
div.className = e.data.includes('[你]') ? 'msg user' :
e.data.includes('[AI]') ? 'msg ai' : 'log';
div.textContent = e.data;
chat.appendChild(div);
chat.scrollTop = chat.scrollHeight;
};
}
// 初始连接
connect();
function addLog(msg) {
const div = document.createElement('div');
div.className = 'log';
div.textContent = msg;
chat.appendChild(div);
chat.scrollTop = chat.scrollHeight;
}
function send() {
const msg = msgInput.value.trim();
if(!msg) return;
if (!isConnected) {
addLog('等待连接中...');
return;
}
console.log('Sending message:', msg);
try {
ws.send(msg);
msgInput.value = '';
} catch (error) {
console.error('Send error:', error);
addLog('发送失败');
}
}
msgInput.addEventListener('keypress', e => {
if (e.key === 'Enter') {
send();
}
});
</script>
</body>
</html>
六、运行与测试
1. 启动服务
1. 创建.env文件
echo "WEATHER_API_KEY=你的天气API密钥" >> .env
2. 启动后端
python main.py
3. 访问前端

注意: app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static") 静态文件挂载,由于我们已经挂载静态文件,启动后直接运行http://localhost:8002/即可运行文件
2. 测试用例
输入:查询北京的天气? → 调用 weather_query,返回':{temp': 12.94, 'desc': '阴,多云', 'humidity': 23}
输入:推荐杭州的旅游景点 → 调用travel_guide,返回:杭州1天旅游推荐:西湖, 雷峰塔

输入:将"你好"翻译成英文 → 调用translate,返回:{'original_text': '你好', 'translated_text': 'Hello', 'source_lang': 'auto', 'target_lang': 'en'}
输入:计算 123 + 456 → 调用calculator,返回:{'expression': '123 + 456', 'result': 579, 'steps': ['123+456 = 579']}
输入:自定义无主题内容 → 无匹配技能,返回提示

七、总结
整体来看,基于 SKILL 构建 AI 智能体,本质上是把一套杂乱、松散的 AI 能力,整理成标准化、可管理、可落地的工程化体系。SKILL 作为智能体的最小能力单元,不只是简单的工具调用,而是自带完整描述、触发规则、输入输出规范、示例与边界约束的标准化插件,既比普通 Tool 更严谨,又比子 Agent 更轻量、更易调度。
而 SKILL.md 作为整个体系的核心契约文件,承担了机器可读、人类可懂的双重角色,从基础信息、触发条件、参数规范到依赖限制一应俱全,让系统能自动识别、调度引擎能精准匹配、大模型能规范调用、开发者能快速维护,真正实现技能的可插拔、可扩展、可管控。对于想要把大模型真正落地到业务、从对话交互走向流程执行的场景来说,SKILL 体系是一条非常成熟、可直接量产的技术路线,也是 AI 智能体从 Demo 走向生产环境的关键一步。