news 2026/9/7 5:39:10

Agent Skills实战:用Python构建可复用的AI技能与API服务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills实战:用Python构建可复用的AI技能与API服务

2026年如果你还停留在“写Prompt调用大模型”的状态,那基本还停留在Agent浪潮的上一站。现在更值得学的是Agent Skills——把工具、提示词、执行流程打包成可复用的“技能”,让智能体自己决定什么时候调用、怎么调用、调用完之后怎么把结果接回主线任务。

这次我们直接聊实战:Agent Skills是什么、和普通Prompt模板有什么区别、如何用Python从零实现一个最小Skill,再把它封装成HTTP服务接入业务系统。这篇不是概念科普,而是带你跑通一条完整的代码路线。

文章内容会覆盖:

  • Agent Skills 的定义、结构和核心思路;
  • 一套最小可运行的项目代码(Skill定义 + LLM调用 + Agent循环);
  • 如何把它包装成API服务、处理批量任务;
  • 开发中的性能观察、常见排错和工程化建议。

整个教程的代码都以通用Python工程为模板,LLM调用走OpenAI兼容接口。你只需要准备好Python环境和一个可用的模型接口(云API或本地模型都行),就能跟着跑。

1. Agent Skills 核心能力速览

能力项说明
项目类型AI Agent 开发范式 / 工具封装方案
功能定位把提示词、工具函数、执行流程封装成可复用技能
开发语言Python 为主
运行环境CPU即可开发调试;若LLM本地部署需独立显卡
LLM 来源云API或本地OpenAI兼容服务
核心优势一次开发,多次复用;Agent 自主决策调用
扩展方式新增 Skill 定义 + 实现函数,无需改主循环
API 服务可基于 FastAPI / Flask 二次封装
批量任务通过目录扫描或队列消费实现
适合人群LLM 应用开发者、Agent 框架初学者、自动化流程开发者

从材料看,这个方向目前已经被多个大模型团队作为官方能力推进。吴恩达的Agent Skills教程发布后,相关讨论热度很高。2026年版的学习路径也不再是“看概念”,而是“跑代码”。下面我们直接进入开发。

2. Agent Skills 和普通提示词模板的本质区别

很多初学者会把Agent Skills理解成“一段写好的Prompt”,这是最大的误区。

普通提示词模板是一个静态文本,模型每次拿到它的行为都是一次性推理。比如你写一段“你是翻译助手,把用户输入翻译成英文”,它只是一个指令,没有工具调用能力,也没有状态管理。

Agent Skills 的差异在于它包含三种元素:

  • 描述(Description):告诉Agent“这个技能什么时候用、能做什么”。
  • 工具函数(Function):真正执行的代码,比如查数据库、计算文件大小、调用HTTP接口。
  • 参数Schema(Parameter Schema):LLM调工具时按什么样的结构传参。

Agent在执行用户任务时,会根据当前对话状态,从注册的多个Skill中自主选择是否调用某个技能。这才是“技能”的含义:它不是被用户直接触发,而是被Agent在推理过程中动态决策触发。

用一个例子说明:

类型做法
普通Prompt“你是一个文件整理助手,当用户输入文件目录时,请列出文件大小。”
Agent Skill定义一个list_files(path)函数,并写清描述“当需要查看目录文件、检查文件大小或整理文件时调用该技能”,Agent根据用户意图自己决定是否调用。

后者具备组合能力。你可以定义10个Skill,让Agent在对话中连续调用它们,完成“读取文件 -> 抽取关键信息 -> 生成摘要 -> 发送通知”这种多步骤任务。

这也是2026年版Agent开发最值得掌握的一点:** Skill 是可复用的原子能力,Agent 是编排执行的控制器。**

3. 适用场景与使用边界

3.1 适合解决什么问题

  • 企业内部知识库问答:把“文档检索”“数据库查询”“权限验证”分别做成Skill,Agent按需调用。
  • 自动化办公:生成周报、整理Excel、批量发邮件,每个能力封装成Skill。
  • 代码生成与代码执行:Skill调用代码解释器,Agent验证代码结果。
  • 内容生产流程:调用搜索、抓取网页、生成图片、排版发布。
  • 个人助理:把定时任务、天气查询、日程管理全部封装成稳定技能。

3.2 不适合什么场景

  • 单轮简单问答:直接调用模型接口就够了,不需要引入Agent和Skill。
  • 需要绝对确定性的流程:Agent的决策有随机性,如果是银行核心交易、医疗诊断等场景,建议用传统工作流做强制流程控制。
  • 超大上下文单次推理:Skill是为多步骤组合设计的,如果所有逻辑都在一次性Prompt内完成,就不需要它。

3.3 使用边界与合规提醒

开发Agent Skills时,有一点必须说在前面:

  • 如果Skill需要访问用户文件、数据库、私人信息,必须获得用户授权,并且设置最小权限。
  • 如果Skill用于生成人脸、声音、文案等,必须确保素材版权合规。
  • 对外提供API服务时,要加鉴权,避免被滥用。
  • 批量调用模型服务时,要注意模型服务的并发限制和内容安全政策。

4. 环境准备与前置条件

开发Agent Skills不需要很重的硬件。核心开发过程是写Python代码,调试时调用一个LLM服务即可。

4.1 推荐环境清单

环境项推荐配置说明
操作系统Windows 10/11、macOS、Linux均可
Python版本3.10+代码用到typingdataclass
包管理pip / uv / conda任意一种
LLM服务OpenAI兼容API也可以是本地vLLM / Ollama等
网络能访问LLM服务即可本地部署则无需公网
磁盘空间代码不到10MB若本地模型则需几十GB以上

如果你用本地大模型,建议显存至少覆盖你要加载的模型体积。7B量化模型大约需要6GB以上显存,实测必须以本机为准。如果只是学Skill机制,用云API最省事。

4.2 创建项目目录

mkdir agent-skills-demo cd agent-skills-demo mkdir skills mkdir data mkdir outputs

目录规划:

  • skills/:存放Skill定义和实现代码;
  • data/:放测试文件;
  • outputs/:放结果文件。

4.3 安装依赖

pip install openai python-dotenv fastapi uvicorn

我们使用:

  • openai:调用LLM接口;
  • python-dotenv:管理环境变量;
  • fastapi+uvicorn:把Agent封装成HTTP服务。

5. 从零实现一个最小 Agent Skills 系统

下面我们实现一套最精简但结构完整的系统,总共四个核心文件。

5.1 定义 Skill 数据结构

文件:skill_base.py

from dataclasses import dataclass, field from typing import Callable, Any @dataclass class Skill: name: str description: str parameters: dict func: Callable[..., Any] examples: list = field(default_factory=list) def to_tool_json(self) -> dict: """转换成LLM函数调用格式""" return { "type": "function", "function": { "name": self.name, "description": self.description, "parameters": self.parameters, } }

5.2 编写两个示例 Skill

文件:skills/basic_skills.py

import os import json import hashlib from typing import List def list_file_sizes(path: str = ".") -> str: """列出指定目录下所有文件的大小""" results = [] for name in os.listdir(path): full_path = os.path.join(path, name) if os.path.isfile(full_path): size = os.path.getsize(full_path) results.append({"file": name, "size_bytes": size}) return json.dumps(results, ensure_ascii=False, indent=2) def compute_text_hash(text: str) -> str: """计算文本的MD5哈希值""" return hashlib.md5(text.encode("utf-8")).hexdigest() def get_file_skills() -> List[Skill]: file_skill = Skill( name="list_file_sizes", description="当用户需要查看某个目录下的文件列表、检查文件大小、统计目录占用时需要调用这个技能。", parameters={ "type": "object", "properties": { "path": {"type": "string", "description": "要列出的目录路径"} }, "required": ["path"] }, func=list_file_sizes, examples=["帮我看看当前目录下有哪些文件,各占多少空间?"] ) hash_skill = Skill( name="compute_text_hash", description="当用户需要对一段文本计算MD5哈希值时调用这个技能。", parameters={ "type": "object", "properties": { "text": {"type": "string", "description": "要计算哈希的文本"} }, "required": ["text"] }, func=compute_text_hash, examples=["帮我给 'hello world' 算一下MD5。"] ) return [file_skill, hash_skill]

5.3 实现 Agent 主循环

这是核心部分。Agent做的事情是:

  1. 接收用户消息;
  2. 把所有Skill描述发给LLM;
  3. LLM决定是否调用Skill,并返回结构化参数;
  4. 我们执行Skill函数,把结果返回给LLM;
  5. LLM根据执行结果生成最终回复。

文件:agent.py

import json from typing import List, Optional from openai import OpenAI from skill_base import Skill from skills.basic_skills import get_file_skills class SimpleAgent: def __init__(self, model: str = "gpt-4o-mini", base_url: Optional[str] = None): self.client = OpenAI(base_url=base_url) if base_url else OpenAI() self.model = model self.skills: dict[str, Skill] = {} def register_skill(self, skill: Skill): self.skills[skill.name] = skill def register_skills(self, skill_list: List[Skill]): for skill in skill_list: self.register_skill(skill) def _build_tools(self) -> list: return [skill.to_tool_json() for skill in self.skills.values()] def run(self, user_message: str, max_steps: int = 5, verbose: bool = True) -> str: messages = [ { "role": "system", "content": "你是一个智能助手。你可以使用工具来完成任务。" "如果你需要调用工具,请按函数调用格式返回。" }, {"role": "user", "content": user_message} ] for step in range(max_steps): response = self.client.chat.completions.create( model=self.model, messages=messages, tools=self._build_tools(), tool_choice="auto" ) message = response.choices[0].message if verbose: print(f"[Step {step + 1}] 模型回复: {message.content}") if message.tool_calls: for tool_call in message.tool_calls: print(f" 调用技能: {tool_call.function.name}") if not message.tool_calls: return message.content or "" messages.append(message) for tool_call in message.tool_calls: skill_name = tool_call.function.name arguments = json.loads(tool_call.function.arguments) skill = self.skills.get(skill_name) if not skill: result = f"错误: 技能 {skill_name} 不存在" else: try: result = skill.func(**arguments) except Exception as e: result = f"技能执行出错: {str(e)}" messages.append({ "role": "tool", "tool_call_id": tool_call.id, "content": str(result) }) return "已达到最大执行步数,任务未完成。" if __name__ == "__main__": agent = SimpleAgent() agent.register_skills(get_file_skills()) response = agent.run("帮我看看当前目录下有哪些文件,各占多少空间?") print("\n最终回复:") print(response)

5.4 运行测试

python agent.py

如果一切正常,你会看到类似这样的流程输出:

[Step 1] 模型回复: None 调用技能: list_file_sizes [Step 2] 模型回复: 当前目录下的文件如下: - skill_base.py: 2215 字节 - agent.py: 3451 字节 ...

这里你可以非常直观地看到Agent的决策路径:LLM判断“用户想了解文件大小”,于是调用list_file_sizes技能,拿到结果后组织成自然语言回答。

如果模型输出不稳定,可以在消息中加入Skill的examples作为少样本示例,提高调用准确率。

6. 扩展更多技能:让 Agent 处理复合任务

上面的两个技能都偏向“查询型”。在实际开发中,Agent Skills 更常见的用法是组合型任务。

举例:我们增加一个write_file技能,让Agent具备“查看文件 -> 提取信息 -> 写入汇总文件”的能力。

新增代码到skills/basic_skills.py

def write_text_file(filename: str, content: str) -> str: """把内容写入指定文件""" if not filename.endswith(".txt"): filename += ".txt" with open(filename, "w", encoding="utf-8") as f: f.write(content) return f"文件已写入: {filename}" write_skill = Skill( name="write_text_file", description="当用户需要把文本内容保存为一个文件时调用这个技能。", parameters={ "type": "object", "properties": { "filename": {"type": "string", "description": "目标文件名"}, "content": {"type": "string", "description": "要保存的文本内容"} }, "required": ["filename", "content"] }, func=write_text_file, )

然后注册进Agent:

agent.register_skill(write_skill)

测试输入:

帮我统计一下当前目录里所有Python文件的大小,然后把统计结果写入 output.txt。

Agent 会先调用list_file_sizes,再调用write_text_file。两个技能之间不需要你写任何额外代码,LLM会自动完成参数传递。这正是Agent Skills最核心的价值。

7. 将 Agent Skills 封装为 API 服务

在真实项目中,Agent不会只在命令行里运行,而是要给其他系统调用。

我们使用 FastAPI 封装一个标准接口。

文件:api_server.py

from fastapi import FastAPI from pydantic import BaseModel from agent import SimpleAgent from skills.basic_skills import get_file_skills app = FastAPI(title="Agent Skills Demo API") agent = SimpleAgent() agent.register_skills(get_file_skills()) session_memory = {} class ChatRequest(BaseModel): message: str session_id: str = "default" @app.post("/chat") def chat(req: ChatRequest): if req.session_id not in session_memory: session_memory[req.session_id] = [] session_memory[req.session_id].append({"role": "user", "content": req.message}) reply = agent.run(req.message) session_memory[req.session_id].append({"role": "assistant", "content": reply}) return { "session_id": req.session_id, "reply": reply } @app.get("/skills") def list_skills(): return {"skills": list(agent.skills.keys())} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)

启动API服务:

python api_server.py

然后另开一个终端测试:

curl -X POST http://127.0.0.1:8000/chat \ -H "Content-Type: application/json" \ -d '{"message": "帮我看看当前目录下有哪些文件", "session_id": "test1"}'

返回结果:

{ "session_id": "test1", "reply": "当前目录下的文件包括:agent.py、skill_base.py、api_server.py ..." }

这个接口可以轻松接进企业微信机器人、Web应用、自动化脚本等。

如果要做批量任务,只需循环调用/chat接口。比如:

import requests tasks = [ "统计data目录下所有文件大小", "计算文本 'Hello' 的MD5", ] for task in tasks: resp = requests.post("http://127.0.0.1:8000/chat", json={ "message": task, "session_id": f"batch-{task[:5]}" }) print(resp.json()["reply"])

8. 资源占用与性能观察

8.1 观察哪些指标

Agent Skills 系统的性能瓶颈通常不在代码本身,而在:

  • LLM推理延迟:每轮对话至少一次模型请求,多技能组合需要两到三次请求。
  • Token消耗:工具描述和工具返回结果都会占用上下文。
  • 状态大小:对话历史越长,Token成本越高。

8.2 如何设计实验观察

  1. 先用简单任务记录一次调用的总耗时和Token消耗。
  2. 增加一个需要两次技能调用的复合任务,对比耗时和Token增长。
  3. 检查工具返回内容是否过大,比如list_file_sizes返回所有文件信息,在大目录下会产生大量Token。

8.3 优化手段

  • 给Tool返回结果做截断,超过一定长度只保留摘要。
  • 对话历史做滑动窗口,只保留最近若干轮。
  • 技能描述写精简,减少每轮请求的固定Token开销。
  • 多次技能调用之间使用tool_choice: "none"强制结束,避免Agent反复调用。

9. 常见问题与排查方法

问题现象可能原因排查方式解决方案
模型不调用任何技能Skill描述不够具体,或参数Schema错误对比当前模型支持的tool格式优化description,补全examples
技能调用时参数缺失LLM没有按Schema生成参数查看完整LLM返回简化参数数量,必填参数写清楚
技能执行报错函数内部没有做类型校验在func内打印传入参数增加try/except和参数默认值
上下文越来越大工具返回值太大或历史未裁剪打印messages长度和Token数对工具返回做截断;裁剪历史
API调用超时模型响应慢或网络问题设置timeout参数调大timeout;增加重试
并发请求互相干扰全局Agent实例共享状态检查是否有共享变量每次请求创建Agent,或用session隔离
批量任务卡住部分任务触发死循环设置max_steps上限增加step超时和条件判断

一个大坑是:很多模型对工具描述非常敏感。如果你写的描述是“列出文件大小”,模型可能不知道该在什么场景调用;如果写成“当用户询问任何与文件信息、目录内容、磁盘占用有关的问题时调用”,调用准确率会明显提升。

10. 工程化最佳实践

开发Agent Skills不能只停留在Demo阶段,真正接入业务系统需要注意以下几点。

10.1 Skill 目录设计

建议每个Skill保持单一职责:

skills/ file_operations/ __init__.py list_files.py write_files.py move_files.py text_processing/ __init__.py summarize.py translate.py web_tools/ __init__.py fetch_url.py

10.2 增加执行日志

每个Skill调用都应该记录:

  • 调用时间;
  • 输入参数;
  • 返回结果长度;
  • 是否成功。

这样能快速定位是LLM决策错误还是Skill代码错误。

10.3 设置权限边界

如果Skill要执行系统命令或写文件,务必限定可操作目录,避免Agent因为误导性Prompt产生危险操作。例如:

allowed_root = "/path/to/sandbox" def safe_path(path): real_path = os.path.realpath(path) if not real_path.startswith(allowed_root): raise PermissionError("路径越界") return real_path

10.4 成本控制

为每轮对话设置Token预算,超过预算自动终止。调用LLM前,先过滤掉当前任务用不到的Skill,减少上下文负载。

10.5 数据合规

如果用Agent Skills处理用户上传的文件、图片或音视频,要明确告知用户用途,并在任务结束后按策略删除临时数据。批量生成、批量处理的内容,发布前必须人工复核。

11. 总结与下一步

Agent Skills值得最先验证的功能是“多技能组合调用”。先做一个包含文件操作和文本处理的最小系统,让Agent自动完成“读取文件-抽取内容-保存结果”的全流程。跑通之后,你就能体会到它和普通Prompt模板的本质区别:你不再写死执行步骤,而是交给Agent动态编排。

最容易踩的坑有两个:一个是Skill描述写得含糊,导致模型不调用或乱调用;另一个是忘记裁剪上下文,导致长会话后Token成本飙升。开发阶段就先把日志和控制参数加上,能省掉大量排查时间。

下一步你可以尝试的方向:

  • 接入更多数据源:数据库查询、对象存储、HTTP API。
  • 增加多轮记忆:用向量库保存历史任务状态。
  • 把Skill发布成独立微服务:多个Agent共享同一组技能。
  • 引入人工审核机制:Agent执行关键操作前需要审批确认。

这篇的代码已经能构成一个最小可运行框架,直接拿去做二次开发也够用。建议先跑通单技能,再加组合任务,最后再考虑接入业务系统。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 5:37:57

FPGA计数器的Verilog陷阱:阻塞赋值与非阻塞赋值深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 5:33:42

C#用DocX库处理Word文档:轻量高效的开源方案实战解析

简介:C#DocX 源码与 Demo 资源包,面向需要在 .NET 环境中操作 Word 文档的开发者,解决不安装 Microsoft Office 也能完成 Word 创建、编辑与 PDF 转换的需求。压缩包内含 244 个文件,以 83 个 C# 源码文件、86 个 Word 示例文档、…

作者头像 李华
网站建设 2026/9/7 5:33:35

韩顺平Java笔记完整版:从基础语法到面试高频考点解析

简介:韩顺平Java笔记完整版是一份面向Java初学者的系统学习资料包,聚焦从零到入门所需的核心知识体系,适合自学编程的学生、准备转行的职场新人以及希望巩固基础的在职开发者。压缩包采用RAR格式,整体大小约10.45MB,内…

作者头像 李华
网站建设 2026/9/7 5:31:21

USDS 2.0:从外部经验裁判到公理自我定义的科学验证范式跃迁——四维解耦审查体系的构建、旧范式非真理验证的系统性批判与真理不可取消性的本体论证明

USDS 2.0:从外部经验裁判到公理自我定义的科学验证范式跃迁——四维解耦审查体系的构建、旧范式非真理验证的系统性批判与真理不可取消性的本体论证明摘要自科学革命以来,人类始终面临一个根本性的元问题:如何判定一个知识主张是否具有科学合…

作者头像 李华
网站建设 2026/9/7 5:29:18

生产前清场检查表:从风险确认到落地执行的实用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华