AI Agent技能化开发:从对话到可复用、可组合的技能体系

发布时间:2026/8/27 5:38:52
AI Agent技能化开发:从对话到可复用、可组合的技能体系 这次我们来看一个 GitHub 仓库addyosmani / agent-skills。先说结论从项目名看这不是一个传统意义上的“模型权重仓库”也不是一个需要下载大模型才能跑的一键包而是一个围绕AI Agent 技能体系的仓库。它讨论的核心问题很明确当 Agent 不再只是“聊几句就结束”的对话机器人而是需要自主完成多步任务时怎么把能力拆成可复用、可组合、可维护的“技能”单元。如果你正在做 Agent 开发、工作流编排、或者是把 AI 接入到实际业务系统里这个问题比选哪个大模型更值得先想清楚。这篇文章会从 Agent Skills 的定义、技能分类、设计原则、本地开发环境、最小代码实现、接口与批量任务、性能观察、异常排查和最佳实践几个方向展开帮助你建立一套可以落地的 Agent 技能化开发框架。由于目前能获取到的仓库具体描述有限文章中涉及具体文件结构和精确功能的部分会以通用技术方案的方式给出并明确标注哪些是推测、哪些是通用实践。1. 核心能力速览能力项说明项目类型Agent 技能库 / Agent 技能设计参考核心问题如何把 Agent 的能力拆成可复用、可组合、可维护的“技能”主要功能技能定义、技能组织、技能调用、技能编排、技能复用适用人群AI 应用开发者、Agent 框架使用者、工作流设计者运行环境不依赖特定 GPU可在纯开发机上设计是否需要大模型需要但只作为 Agent 的推理内核仓库本身不是模型仓库启动方式取决于具体 Agent 框架通常是代码引入或技能目录加载是否支持 API通用设计上支持技能层可封装为接口是否支持批量任务通用设计上支持技能可编排为批量执行硬件要求很低文本规划和接口调试为主适合场景Agent 产品设计、企业内部自动化、多智能体协作需要强调一点目前公开材料里关于这个仓库的代码细节很少所以上面表格里“是否支持 API”“是否支持批量任务”这类字段是基于 Agent 技能化开发的通用设计推导出来的不是仓库文档里的原文结论。实际使用前要以仓库 README 和源码为准。2. Agent Skills 是什么从“对话”到“技能”现在很多团队做 AI 应用思路还停留在“大模型 聊天机器人”。但真正要把 AI 用进生产流程只靠对话是不够的。一个合格的 AI Agent 需要能调用工具、读取数据、生成文档、执行代码、做判断、在多个步骤之间传递状态。这些能力如果全部写在一个main.py里很快就会失控。更合理的方式是把 Agent 的能力拆成一个个“技能”。所谓 Agent Skill就是一个带有明确输入、明确输出、明确执行逻辑的能力单元。它可以是一个函数比如search_web(query) - results一个服务比如image_generate(prompt, size) - image_url一个工作流比如写周报 - 汇总本周 commit - 生成 Markdown - 发送到钉钉一个知识模块比如法律条款检索 - 结合用户问题做摘要从命名agent-skills来看仓库的内容大概率是围绕“如何整理和定义这些技能”展开的。它可能包含技能目录结构、技能描述规范、技能调用示例甚至是一套可复用的技能模板。2.1 为什么技能化比“提示词堆叠”更可靠很多开发者已经发现单个提示词解决问题的能力很有限。模型容易遗漏条件多步任务容易中断上下文一长就忘记前面的约束。技能化的核心优势就是把这些不稳定的“语义能力”变成稳定的“程序能力”。举一个典型例子提示词方案请帮我从这份 PDF 里提取所有发票抬头、金额和日期然后生成一个 Excel 表格。技能方案调用一个pdf_invoice_extractor技能输入 PDF 路径输出结构化 JSON再调用一个json_to_excel技能把 JSON 转成 xlsx 文件。第二种方式的每一步都可验证、可测试、可重跑。即使中间某一步失败也可以单独重试而不用把整段对话重新执行一遍。这正是 Agent Skills 对开发者的价值它不是给模型加一层提示词而是把 Agent 从“随机应变”变成“有章可循”。3. Agent 技能分类四类常见的技能模型从目前 Agent 开发的主流实践看Agent Skills 大体可以分成四类技能类型作用典型例子感知型技能从外部世界获取信息网页搜索、PDF 解析、数据库查询、摄像头读取执行型技能对系统或数据执行操作发送邮件、写文件、调用 API、执行 shell 命令推理型技能对信息进行加工和判断摘要生成、代码审查、风险评分、路由决策协作型技能与其他 Agent 或角色交互任务分发、结果汇总、多 Agent 辩论这四类技能不是互斥的。一个复杂的 Agent 任务往往是由多个类型的技能组合完成的。3.1 感知型技能感知型技能是 Agent 的信息入口。没有感知能力Agent 就只能依赖用户输入的那点上下文很难处理真实业务。设计感知型技能时要考虑三个问题输入是什么格式文件名、URL、数据库连接串、工单 ID输出是什么格式原始文本、结构化 JSON、图像路径容错怎么处理找不到文件、网络超时、数据为空时应该返回什么3.2 执行型技能执行型技能是 Agent 的手和脚。它们会产生真实的外部影响所以设计时要格外谨慎。推荐统一封装成函数并且所有关键操作都要记录日志。比如一个“发送邮件”技能至少应该记录收件人、主题、发送结果、失败原因。3.3 推理型技能推理型技能是 Agent 的“大脑功能区”。它不是简单调用一次大模型而是把推理过程封装成可重复使用的逻辑比如从一段长文本中抽取关键字段。判断一个用户请求是否合规。把用户意图路由到不同的下游技能。推理型技能要特别注意“输出格式稳定”。因为后面的流程可能依赖这个输出所以最好强制模型输出 JSON并用代码做字段校验。3.4 协作型技能当单个 Agent 无法完成复杂任务时可以把任务拆给多个 Agent。协作型技能负责管理它们之间的关系包括任务分发、进度同步、结果汇总。协作型技能的设计误区是“过度复杂”。对于大多数团队先从一个“主导 Agent 多个工具型 Agent”的简单结构开始比直接上多智能体辩论更可控。4. Agent 技能设计原则可复用、可组合、可观测不管你用什么框架实现 Agent Skills设计原则基本是通用的。4.1 单一职责一个技能只做一件事。不要把“读取 PDF、提取发票、写 Excel”塞进一个技能里而是要拆成三个。这样每个技能都可以单独维护和复用。4.2 输入输出可序列化技能最好是“输入是 JSON输出是 JSON”。这样技能与技能之间可以通过标准数据结构传递数据调试时也能直接查看中间结果。# 不好的设计输入输出依赖全局状态 def parse_pdf(): global pdf_path global result_list # ... return # 好的设计输入输出干净清晰 def parse_pdf(pdf_path: str, max_pages: int 10) - list[dict]: # 返回页面文本列表 return []4.3 可观测性每个技能都要有日志、耗时记录和错误上下文。线上跑批量任务时你不可能靠肉眼观察每一步。可观测性是排障的基础。建议每个技能至少输出开始时间、结束时间输入摘要不要打全量数据输出摘要异常堆栈4.4 可降级技能要有失败降级策略。比如搜索技能超时是直接失败还是返回空结果并让用户知晓发送邮件技能失败是重试两次还是进入人工审核队列这些策略应该在技能设计阶段就定下来而不是等运行时再拍脑袋。5. 适用场景与使用边界Agent 技能化的思路适合以下场景企业内部知识库问答需要读取文档并引用出处。自动化运营需要定时抓取数据、生成报告并发送。代码生成与审查需要读取仓库、调用编译、运行测试。客服工单处理需要查询订单、判断语义、回复模板。但不适合的场景也很明确纯闲聊对话不需要复杂技能反而会增加延迟。需要强实时交互的 UI 操作技能调用是接口级的很难完全模拟鼠标键盘。对错误零容忍的金融交易场景技能自动化必须叠加人工审批。5.1 合规与安全边界涉及 Agent 技能开发时有一个绕不开的问题权限边界。技能会操作真实系统所以必须做好权限最小化设计。文件技能只允许读写指定目录。网络技能只在白名单域内发起请求。数据库技能只使用只读账号除非明确需要写操作。人脸、声纹、版权素材等敏感能力必须确认已获得合法授权并且只在受控环境中测试。输出内容对外发布或商用前必须做人工复核。这些不是可选项。技能化开发越深入接触的系统和数据越多安全设计就必须越严格。6. 环境准备与前置条件由于agent-skills的具体实现方式尚不明确这里给出通用的 Agent 技能开发环境准备清单。无论最终使用什么框架下面的工具链基本都逃不掉。6.1 系统与语言建议在 Linux 或 macOS 上开发Windows 也可以但要注意几个点使用 Python 3.10 或更高版本当前主流 Agent 框架普遍支持。如果技能里包含异步任务建议使用Python 3.11异步语法体验更好。确保安装git因为技能仓库大概率通过 git 分发。6.2 依赖管理推荐使用uv或poetry管理依赖而不是裸用pip。尤其是技能库会牵扯到多个子包容易出现依赖冲突。# 使用 uv 创建虚拟环境并安装依赖 uv venv .venv source .venv/bin/activate uv pip install -e .[dev]6.3 Agent 框架选型如果你还没有选定 Agent 框架可以从以下维度考虑框架定位适合人群LangGraph图结构编排状态管理强需要复杂流程控制的团队LlamaIndex知识库和文档能力强以文档问答为核心的产品AutoGen多 Agent 对话协作多智能体协作研究自研框架高度可控技能数量固定、流程明确不管选哪个框架核心思路一样技能要独立于框架存在最好只是一个普通函数或类再由框架负责调度。6.4 模型服务Agent 技能库本身不包含大模型但运行时需要一个推理服务。可以是本地 Ollama 服务vLLM 部署的开源模型云端模型 API建议开发阶段先用一个小模型跑通链路再切到强模型做效果验证。这样可以降低排队时间和调用成本。7. 一个最小可用的 Agent Skills 实现为了说清楚技能化开发怎么落地这里提供一个最小实现。它不是agent-skills仓库的代码而是一个符合通用技能设计思路的示例。7.1 技能基类用 Python 定义一个基础技能类。# skills/base.py 技能基类。 所有 Agent 技能都应该继承 BaseSkill 并实现 execute 方法。 from abc import ABC, abstractmethod from dataclasses import dataclass from datetime import datetime dataclass class SkillResult: success: bool data: dict error: str def to_json(self) - dict: return { success: self.success, data: self.data, error: self.error, } class BaseSkill(ABC): name: str base_skill description: str Base skill. def __init__(self): self.start_time None self.end_time None abstractmethod def execute(self, **kwargs) - SkillResult: 执行技能逻辑。 pass def timed_execute(self, **kwargs) - SkillResult: self.start_time datetime.now() try: result self.execute(**kwargs) except Exception as exc: result SkillResult(successFalse, data{}, errorstr(exc)) self.end_time datetime.now() duration (self.end_time - self.start_time).total_seconds() print(f[skill] {self.name} finished in {duration:.2f}s) return result这个基类做的事情很简单定义技能的统一入口execute自动记录耗时和异常。技能的实现者只需要关心核心逻辑。7.2 一个实际的技能示例下面实现一个“从文本中抽取关键词”的推理型技能。它适合作为第一个练手技能因为不涉及外部服务只需要调用大模型接口。# skills/keyword_extractor.py 关键词抽取技能。 输入一段文本输出关键词列表。 from typing import List from openai import OpenAI from skills.base import BaseSkill, SkillResult class KeywordExtractorSkill(BaseSkill): name keyword_extractor description 从一段文本中抽取关键词返回 JSON 数组。 def __init__(self, model: str gpt-4o-mini, base_url: str None, api_key: str None): super().__init__() self.client OpenAI(base_urlbase_url, api_keyapi_key) self.model model def execute(self, text: str, max_keywords: int 10) - SkillResult: prompt f 请从下面的文本中抽取 {max_keywords} 个关键词只返回 JSON 数组。 不要输出其他任何内容。 文本 {text} response self.client.chat.completions.create( modelself.model, messages[ {role: system, content: 你是一个关键词抽取器只输出 JSON。}, {role: user, content: prompt}, ], temperature0.2, ) content response.choices[0].message.content.strip() return SkillResult(successTrue, data{keywords: content})注意这里把模型输出原样塞进了data。更严格的做法是先用json.loads解析并校验失败了再重试一次或返回错误。这个“输出校验”步骤在技能化开发中非常重要。7.3 技能注册与路由技能多了以后Agent 需要知道“某个请求该调用哪个技能”。这就需要一个注册表。# skills/registry.py 技能注册表。 支持按名称注册和查询技能。 from typing import Dict, Type from skills.base import BaseSkill class SkillRegistry: def __init__(self): self._skills: Dict[str, BaseSkill] {} def register(self, skill: BaseSkill): if skill.name in self._skills: raise ValueError(fSkill {skill.name} already registered.) self._skills[skill.name] skill print(f[registry] register skill: {skill.name}) def get(self, name: str) - BaseSkill: if name not in self._skills: raise KeyError(fSkill {name} not found.) return self._skills[name] def list_skills(self) - list[str]: return list(self._skills.keys()) def register_default_skills(): 初始化时注册所有内置技能。 registry SkillRegistry() # 示例注册关键词抽取技能 # registry.register(KeywordExtractorSkill(model..., base_url..., api_key...)) return registry有了注册表Agent 主流程就变得很简单根据用户意图找到技能名调用对应技能把结果返回给模型生成最终答复。7.4 Agent 主循环下面是一个极简 Agent 主循环它只做三件事接收用户输入。用模型判断调用哪个技能。执行技能并返回结果。# agent.py 极简 Agent 主循环。 真实项目中建议用 LangGraph 或自研状态机替换这里的手写逻辑。 import json from openai import OpenAI from skills.registry import SkillRegistry class SimpleAgent: def __init__( self, registry: SkillRegistry, client: OpenAI, model: str gpt-4o-mini, ): self.registry registry self.client client self.model model def decide_skill(self, user_input: str) - str: # 让模型从技能列表中选择一个 skills self.registry.list_skills() prompt f 用户输入{user_input} 可选技能{json.dumps(skills, ensure_asciiFalse)} 请只返回技能名不要输出其他内容。 response self.client.chat.completions.create( modelself.model, messages[ {role: system, content: 你是技能路由助手。}, {role: user, content: prompt}, ], temperature0, ) skill_name response.choices[0].message.content.strip() return skill_name def run(self, user_input: str): skill_name self.decide_skill(user_input) skill self.registry.get(skill_name) result skill.timed_execute(textuser_input) return result.to_json() if __name__ __main__: registry register_default_skills() # 这里需要替换为你实际使用的模型服务配置 client OpenAI( base_urlhttp://127.0.0.1:8000/v1, api_keyEMPTY, ) agent SimpleAgent(registryregistry, clientclient) output agent.run(帮我提取下面这段文字的关键词......) print(output)这个示例虽然简单但已经体现出了 Agent Skills 的核心结构技能注册表、技能调度、统一执行入口。后续扩展时你可以给 Agent 增加“多轮对话记忆”“技能参数提取”“失败自动重试”等能力。8. 接口 API 与批量任务技能化开发的另一个好处是很容易暴露成接口服务并支持批量任务。8.1 把技能封装成 API 服务如果你希望把技能库变成独立的服务推荐使用 FastAPI。下面是一个通用示例# api_server.py 技能 API 服务。 启动后可以通过 HTTP 请求调用技能。 from fastapi import FastAPI, HTTPException from pydantic import BaseModel from skills.registry import register_default_skills app FastAPI(titleAgent Skills API) registry register_default_skills() class SkillRequest(BaseModel): skill: str params: dict {} class SkillResponse(BaseModel): success: bool data: dict error: str app.post(/skill/run, response_modelSkillResponse) def run_skill(req: SkillRequest): try: skill registry.get(req.skill) except KeyError: raise HTTPException(status_code404, detailfSkill {req.skill} not found.) result skill.timed_execute(**req.params) return SkillResponse(successresult.success, dataresult.data, errorresult.error) app.get(/skills, response_modellist[str]) def list_skills(): return registry.list_skills()启动命令# 启动技能 API 服务 uvicorn api_server:app --host 127.0.0.1 --port 80808.2 Python 调用示例服务启动后可以用下面的方式调用import requests url http://127.0.0.1:8080/skill/run payload { skill: keyword_extractor, params: { text: Agent Skills 可以显著提高 AI 应用的稳定性和可维护性。, max_keywords: 5, }, } response requests.post(url, jsonpayload, timeout60) print(response.status_code) print(response.json())如果返回值里的success字段为false就说明技能执行失败需要结合error字段排查。8.3 批量任务设计当你要处理上百个文件或上百条文本时不应该逐个调用接口而应该设计批处理流程。推荐做法输入目录放待处理文件。输出目录放结果文件。每次调用技能前用任务 ID 生成独立输出文件。记录每个任务的状态pending、running、success、failed。失败任务保留错误日志支持重跑。# batch_runner.py 简单批量任务执行器。 读取 inputs 目录下的 json 文件执行技能后写入 outputs 目录。 import json from pathlib import Path from skills.registry import register_default_skills INPUT_DIR Path(./inputs) OUTPUT_DIR Path(./outputs) STATE_FILE Path(./task_state.json) def load_tasks(): tasks [] for file_path in sorted(INPUT_DIR.glob(*.json)): with open(file_path, r, encodingutf-8) as f: task json.load(f) task[_source_file] file_path.name tasks.append(task) return tasks def run_batch(skill_name: str): registry register_default_skills() skill registry.get(skill_name) tasks load_tasks() OUTPUT_DIR.mkdir(exist_okTrue) state {} for task in tasks: task_id task[_source_file] print(f[batch] start task {task_id}) try: result skill.timed_execute(**task[params]) state[task_id] success if result.success else failed output_path OUTPUT_DIR / task_id.replace(.json, _result.json) output_path.write_text( json.dumps(result.to_json(), ensure_asciiFalse, indent2), encodingutf-8, ) except Exception as exc: state[task_id] failed print(f[batch] task {task_id} error: {exc}) STATE_FILE.write_text( json.dumps(state, ensure_asciiFalse, indent2), encodingutf-8, ) print(f[batch] finished. state {state}) if __name__ __main__: run_batch(keyword_extractor)批量任务的核心不是“并发跑多快”而是“失败后能不能恢复”。所以状态记录比并发更重要。先把状态管理做好再考虑用ThreadPoolExecutor或asyncio提高吞吐。9. 资源占用与性能观察Agent 技能库本身几乎不消耗 GPU资源占用主要来自两个部分大模型推理服务。技能里调用的外部工具比如 OCR、语音识别、浏览器渲染。9.1 观察什么指标建议重点观察四个指标指标意义观察方式模型推理时延单个技能调用的瓶颈在技能timed_execute里打印耗时Token 消耗成本控制记录每次调用的输入输出 token内存占用长文本处理时容易上涨观察 Python 进程 RSS外部接口时延PDF、OCR 这类依赖外部服务的技能单独打点统计9.2 如何降低时延技能内部不要重复初始化模型客户端建议在构造函数里只初始化一次。多个独立技能可以并行执行但要控制并发数避免打爆外部服务。对不变化的输入做缓存比如同一天内同一份文档的解析结果。使用流式输出时减少不必要的中间结果落盘。9.3 显存和 CPU 的关系如果你的 Agent 技能里包含本地推理模型比如本地 OCR 或本地向量化模型那么显存占用取决于推理模型的大小而不是技能库本身。更稳妥的判断是Agent 技能库的职责是“编排”不是“推理”。把重计算模型单独部署成 HTTP 服务技能层通过调用来使用这个架构在资源利用和组织协作上都更合理。10. 常见问题与排查方法问题现象可能原因排查方式解决方案技能返回successfalse技能内部抛异常查看error字段和日志堆栈先复现单条输入逐步定位模型路由选错技能技能描述不够清晰检查提示词里的“可选技能”列表给每个技能补充更明确的描述批量任务全部失败输入数据格式不匹配查看第一条任务的日志用最小样本跑通后再放大API 调用超时技能执行时间过长查看服务端日志耗时上调 timeout或把任务改为异步端口冲突8080 被占用检查端口占用换端口启动或杀掉旧进程技能重复执行导致副作用没有做幂等设计检查“发送邮件”这类技能的执行记录增加任务 ID 去重模型输出格式不稳定没用 JSON Mode 或输出校验查看原始输出强制 JSON 输出并在代码里解析校验依赖版本冲突技能库与框架版本不兼容查看 pip 依赖树锁定版本隔离虚拟环境中文乱码编码问题检查文件读写编码统一使用 UTF-8 编码10.1 排查顺序建议当一套技能链路出问题时不要先怀疑大模型。按这个顺序排查输入数据对不对。技能参数对不对。技能内部有没有异常。中间结果是否符合预期。模型推理是否正常。最终输出是否被正确组装。大部分问题出在前三步属于工程问题不是模型问题。11. 最佳实践与使用建议11.1 第一次先做最小闭环不要一上来就设计二十个技能。先做一个“输入文本 - 提取关键词 - 返回 JSON”的最小闭环把注册、路由、调用、结果返回整条链路跑通。跑通之后再扩展其他技能。11.2 每个技能都要有独立测试用例技能一旦多了以后改动一个基础方法可能会影响多个技能。建议至少给每个核心技能写一组输入输出用例用 pytest 做回归测试。# tests/test_keyword_extractor.py 关键词抽取技能测试示例。 实际使用时需要 mock 模型接口避免真实调用。 from skills.keyword_extractor import KeywordExtractorSkill def test_keyword_extractor_returns_list(): skill KeywordExtractorSkill(modelfake, base_urlhttp://127.0.0.1:8000/v1, api_keyEMPTY) result skill.timed_execute(text人工智能正在改变软件开发方式。, max_keywords3) assert result.success is False # 因为 fake 模型不可用先验证错误分支11.3 技能参数要收敛给技能传入的参数越少越好。比如关键词抽取技能只需要text和max_keywords不要传整个用户对象。参数少了Agent 路由时更好生成参数也更容易测试。11.4 日志要结构化生产环境不要用杂乱无章的print。建议输出 JSON 日志{ event: skill_execute, skill: keyword_extractor, status: success, duration_ms: 320, input_tokens: 120, output_tokens: 35 }结构化日志后续可以接入 ELK 或 Loki排查问题时效率会高很多。11.5 权限和授权检查清单如果你的技能接触真实业务数据上线前请确认数据来源是否合法。数据处理是否脱敏。技能执行的写操作是否有审批。涉及人脸、声音、版权素材时是否已获得授权。对外输出是否经过人工复核。Agent 技能化让自动化变得更容易也让错误和越权变得更隐蔽所以合规检查必须前置。12. 从agent-skills出发下一步怎么走回到addyosmani / agent-skills这个仓库。虽然目前公开资料有限但它的命名本身就说明了一个趋势Agent 开发正在从“提示词工程”转向“技能工程”。接下来你可以做三件事先去仓库里看 README 和文件结构确认它是否提供了技能目录模板或调用示例。不要停留在概念直接看代码。根据本文第 7 节的最小实现搭建一个本地技能库骨架先跑通注册、调用、返回结果。把你自己项目里经常出现的“一次性脚本”改造成标准化技能观察可维护性是否提升。最容易踩的坑有两个一是把技能库做成一个大杂烩什么能力都往里塞二是忽略输出格式校验导致 Agent 拿到错误格式后产生幻觉式推理。技能化不是银弹但它确实是当前让 AI Agent 进入生产环境最稳定的路径之一。先用一个小技能跑起来再逐步扩展这是目前最值得尝试的方式。建议收藏备用后面做 Agent 设计时可以直接对照。