agent-skills实践:打造可复用、可校验的Agent技能系统
开头这几年做大模型应用开发大家应该都感觉到了单纯的 Prompt 工程已经撑不起复杂业务真正难的是让 Agent 在真实环境里稳定地干活。“agent-skills”这个项目就是冲着这个痛点来的——它把 Agent 的能力拆解成一个个可复用、可管理、可验证的技能单元让大模型不再是“只会聊天”而是能按需调用一套经过设计的工具链。我接触这个方向是在开发一个内部文档处理助手的时候。当时最大的麻烦是模型经常在几个工具之间反复横跳参数传错一个类型就报错同一个功能写了两版但命名混乱。后来我把所有能力按技能的方式重构整理了描述规范、参数校验和执行流程问题一下子就清晰了。这篇文章就用我的实际经验拆解 agent-skills 这个项目的设计思路、核心实现和落地中容易踩的坑。适合正在做 Agent 开发、工具编排、或者想把模型能力产品化的朋友参考。1. 内容整体设计与思路拆解1.1 为什么 Agent 需要“技能”而不是一堆函数在没有技能系统的时候我们通常是把所有可调用函数直接丢给模型。函数列表一长模型就开始懵——它不知道什么场景该用哪个函数经常选错或者把参数拼得乱七八糟。agent-skills 的核心思路是把函数封装成“技能”每个技能自带描述、触发条件、参数 Schema 和执行策略。模型看到的不再是几百个扁平函数而是分好类的技能清单每个技能告诉它“我是什么、用来做什么、什么时候用我”。我打了这么个比方这就像你把所有电器插头都换成了统一的插座标准但每个插座上写了“这里插热水壶功率多大要等水开再断电”。模型不需要理解每个电器内部怎么工作只需要按标签选择即可。1.2 技能系统的三层抽象结构agent-skills 在架构上分了三层层级作用对应物描述层告诉模型技能是什么、何时用技能名称、描述、触发场景协议层定义输入输出格式与校验规则JSON Schema、参数类型、返回值执行层真正跑业务逻辑Python 函数、API 调用、子 Agent我在项目里最受益的就是这种分层。以前改一个工具函数可能会影响模型对它的理解分层之后描述层变化不影响执行逻辑参数改动也只动协议层代码维护成本大幅下降。三层结构中描述层决定了模型会不会选这个技能协议层决定了调用成不成功执行层决定了结果质量。这三者耦合越低整套系统越好维护。2. 核心细节解析与实操要点2.1 技能描述怎么写才能被模型准确识别这是整个技能系统里最微妙的部分。同样一个获取天气的功能用“获取指定城市的当前天气状况”和“查天气”模型在业务中的调用准确率完全不同。我的经验是三个原则动词开头明确动作。 “获取”、“创建”、“计算”、“比对”这类动词要让模型一看就知道该不该用。写清楚适用场景和限制。 比如“适用于查询结构化流程信息不适用于自由文本总结”这能显著降低乱调用概率。参数说明尽量给枚举值或格式示例。 模型对格式的感知远弱于人类给它一个 “2024-06-01” 这样的示例比写 “日期格式字符串” 有效得多。我在一个技能描述里加过一句“仅当用户明确提到导出需求时使用”结果误触发率下降了 30% 左右。描述语言的精准程度直接决定了模型在推理链路中的表现。2.2 参数校验不能只靠模型自觉让模型直接生成 JSON 参数并调用最稳的方法不是靠它“自觉”而是在协议层做强制校验。我用 JSON Schema 做参数校验。核心字段包括{ type: object, required: [city, unit], properties: { city: { type: string, description: 城市名称如 北京 }, unit: { type: string, enum: [celsius, fahrenheit] } } }这里有两个容易踩的坑必填参数没标 required模型漏传时技能直接报错而且报错信息可能很模糊调试半天。enum 没有仔细定义模型传了不在列表里的值又得走一遍兜底逻辑。我的做法是校验失败时不让模型无限重试而是把错误信息拼进下一轮 Prompt让模型自己修正。同时限制最多重试 2 次超过就返回明确错误避免 Agent 死循环烧 token。2.3 技能执行结果返回格式要统一老手不会忽略这一步执行结果返回格式如果不统一模型理解结果的能力会大打折扣。比如有的技能返回 “操作成功”有的返回一堆 JSON有的直接抛异常模型很难稳定地判断“任务是否真正完成”。我最终统一成了这样{ status: success, data: {}, message: 可选给模型的补充说明 }错误时统一为{ status: error, error_type: 参数错误/业务错误/网络错误, message: 面向模型的错误解释 }统一结构之后模型判断状态就变得非常可靠。这个细节在很多开源项目里不太被强调但实测对成功率影响非常明显。3. 实操过程与核心环节实现3.1 技能注册与动态加载机制在 agent-skills 项目里我实现了一套技能注册机制。新技能不需要改主流程代码只要按规范写成一个类放到指定目录即可自动加载。核心代码思路如下class BaseSkill: name description parameters_schema {} def execute(self, **kwargs): raise NotImplementedError class WeatherSkill(BaseSkill): name get_weather description 获取指定城市的当前天气 parameters_schema { type: object, required: [city], properties: { city: {type: string, description: 中文城市名} } } def execute(self, **kwargs): city kwargs[city] # 实际为调用第三方接口 return {status: success, data: {temperature: 26}}服务启动时自动扫描 skills 目录下的所有类收集 name、description、parameters_schema汇总成一个技能清单给模型。def load_skills(): skills [] for skill_class in discover_skill_classes(): skills.append({ name: skill_class.name, description: skill_class.description, parameters_schema: skill_class.parameters_schema, executor: skill_class() }) return skills这套机制的好处是新增能力只需要写一个类不污染主流程而且技能可用单独测试出问题可以快速回滚。3.2 模型调用的完整链路设计一个典型的调用链路是这样的用户输入任务描述系统将技能清单 用户任务组合成 System Prompt模型输出 ReAct 格式的思考链决定要不要调用技能从输出解析工具调用指令查找到对应技能类校验参数 Schema执行技能返回结构化结果结果回填进对话上下文模型生成最终答复这里的第 3 步我建议不要使用自由格式的输出而是用约束好的 JSON 格式或函数调用协议否则解析成本高且错误率大。{ thought: 用户需要查询北京的天气, tool_name: get_weather, tool_params: { city: 北京 } }解析类输出我写了一个简单的 Parserdef parse_tool_call(response_text): try: data json.loads(response_text) if tool_name in data and tool_params in data: return data[tool_name], data[tool_params] return None, None except json.JSONDecodeError: return None, None说句实话解析是这整个链路里最薄弱的一环。模型偶尔会输出多余的前缀或注释所以我推荐如果模型平台支持原生函数调用格式就直接用原生的如果只能走文本输出就需要做容错处理。3.3 技能编排单个技能不够用怎么办单个技能解决的是单个动作但真实业务往往是多步骤。比如“查天气然后决定适不适合跑户外运动”这就需要编排层。我的做法是引入子 Agent 模式。一个主 Agent 负责拆解任务把任务分发给多个子技能或子 Agent再把它们的结果汇总。def orchestrate_task(task_description, skills): steps planner_agent(task_description) results [] for step in steps: tool_name, params executor_agent(step) result execute_skill(tool_name, params) results.append(result) return summarizer_agent(results)这种编排方式的好处是每个环节职责清晰坏处是多层调用延迟明显token 消耗增加。小团队做项目的话我的建议是能用单技能解决的任务就不要编排编排越多越容易在长链路中出现上下文丢失或错误累积。3.4 内置的几个常用技能示例这个项目里还自带了几个高频技能对快速跑通流程很有帮助。class SearchSkill(BaseSkill): name web_search description 搜索引擎查询用于获取最新信息需要提供 query parameters_schema { type: object, required: [query], properties: { query: {type: string, description: 搜索关键词} } } def execute(self, **kwargs): query kwargs[query] # 实现为搜索接口回传 return {status: success, data: {results: []}} class SQLQuerySkill(BaseSkill): name sql_query description 执行只读 SQL 查询用于获取数据库内的信息 parameters_schema { type: object, required: [sql], properties: { sql: {type: string, description: 只读 SQL 语句} } } def execute(self, **kwargs): # 只允许 SELECT通过白名单校验 return execute_readonly_query(kwargs[sql])这里特别提醒SQL 技能必须做只读校验限制库名、表名白名单不然模型生成的语句可能引起数据风险。我在内部实现里对所有 SQL 加了正则校验不以 SELECT 开头的直接拒绝执行。4. 常见问题与排查技巧实录4.1 模型不调用技能一直在“瞎聊”这个是最常见的问题。模型不选技能通常是因为描述不够强它觉得“直接回答也能完成任务”。排查思路看技能描述是否包含明确的名词和动词比如“获取”、“查询”、“解析文件”等在 System Prompt 里加约束“需要查询实时数据时必须调用工具不得自行假设结果”调整技能名称不要用过于抽象的名称直接用动作对象我遇到最耐人寻味的一次是某个技能叫“信息抽取”模型始终不调用改成“从文档文本中抽取联系人姓名和电话”之后调用率一下就上来了。4.2 技能调用了但参数一直传错参数传错大部分时候是 Schema 不够具体。给模型一个字符串类型不如给它枚举和示例值。举个例子我自己写的“生成周报”技能里time_range 参数定义为 string模型经常传 “这周”后来我改成 enum{ time_range: { type: string, enum: [本周, 上周, 本月] } }改完之后参数生成正确率几乎从 60% 上到 95%。4.3 技能执行很慢拖垮整体响应这个问题主要是模型生成调用语句的时间 技能真实执行的时间叠加导致的。排查两手抓技能执行层面检查是否本来就是同步耗时操作能改成缓存结果或异步预取的就不要硬跑模型层面不要让模型做太多步推理简单任务用低温度复杂任务再让模型有计划地逐步执行我个人建议把技能类里加一个预估耗时的元字段class BaseSkill: estimated_ms 500编排层可以依据这个字段决定是同步等还是异步轮询。4.4 技能结果模型看不懂有一次我返回的是一个自定义格式的 dict模型愣是没理解里面的 status 字段导致它自己编了一个“失败”的结论。排查后发现是返回结构里嵌套太深、字段名太艺术。要不要用“状态码”、“消息内容”、“业务数据”这种最容易理解的字段名也是实战中总结出来的教训。不要为了省 token 把字段名压缩成单字母模型理解不了简洁只理解高频。下面是常见问题速查表问题现象可能原因快速解法模型不调用技能描述模糊、名称抽象重写技能描述加触发场景词参数频繁错误Schema 信息不足加 enum、格式示例、默认值调用成功但结果错误返回结构混乱统一 status/data/message链路太长、反应慢删掉不必要中间步骤单技能优先少编排模型反复调用同一技能没给终止条件在 Prompt 里限制调用次数4.5 调试技能系统的辅助手段调试这类系统最麻烦的就是看不到模型“为什么选了 A 不选 B”。我的做法是给所有技能调用加了日志在上下文中记录当时模型生成的完整 thought 字段。这样每次调用出错都能回溯到模型的那段推理文本。此外把所有技能清单打出来做一次自查也很有效。我曾经用一个脚本导出所有技能的描述文本让团队另一位同事只凭描述猜功能。猜不中的技能基本就是描述要重写了。4.6 一个容易忽略的边界问题技能冲突当两个技能的描述存在重叠时模型会随机选择。比如“获取天气”和“获取空气质量”看起来不同但在“今天适不适合跑步”这类任务里模型可能调用任意一个。这不算 bug但需要人工设计技能的边界。我的做法是在描述里各加一句使用条件天气技能用于温度、降水、风力等气象条件查询空气质量技能用于 PM2.5、AQI 等污染指标查询在描述中把边界写清楚模型基本上不会再出现随机选择的问题。结尾我在实际使用 agent-skills 这一套思路的时候最深的感受是技能系统的上限不在代码写得有多花哨而在是否把“描述—参数—执行—返回”这条链路都处理干净。一个看似微小的字段改动可能让模型调用成功率从 70% 跳到 90% 以上。但反过来一个模糊的技能描述也可能让你的 Agent 在关键时刻根本不知道该不该出手。最后再分享一个小技巧技能系统性能调优时先测单个技能的 P50 延迟和错误率再测整链路。因为大部分问题都出在个别技能上把响应最差的技能单独拿出来优化比盲目调整 Prompt 要高效得多。如果你也在做 Agent 开发建议从一个最小的技能集开始跑通一个真实业务闭环再逐步扩充技能库。这个成长曲线会非常平滑而且踩坑可控。

相关新闻

Spring AI接入大模型:从yml配置到ChatClient四步调用实战

Spring AI接入大模型:从yml配置到ChatClient四步调用实战

Spring AI 出来以后我一直想找个最轻量的方式试一下,毕竟后端项目里已经全是 Spring 那一套了,如果接入大模型还要写一堆 HTTP 轮子,那体验确实说不过去。直到我配好 yml、把 ChatClient 直接注入到项目里,发现整个调用过程干净得…

2026/10/12 4:47:50 阅读更多 →
深入理解 ABAP CDS User-Defined Functions,从标量函数到 AMDP 与 SQLScript 的完整运行链路

深入理解 ABAP CDS User-Defined Functions,从标量函数到 AMDP 与 SQLScript 的完整运行链路

在日常的 ABAP CDS 开发里,我们很容易碰到这样一类需求。某个字段并不是数据库表里原封不动存储的数据,也不是简单的加减乘除,更不是 CASE、CAST、字符串处理或者日期函数几句话就能表达清楚的计算。业务规则可能涉及多层判断、多个输入参数、较复杂的数学公式,甚至希望把同…

2026/10/12 4:47:50 阅读更多 →
Linux系统篇48——线程(十三) 线程安全、重入与死锁,可重入为什么是线程安全的子集

Linux系统篇48——线程(十三) 线程安全、重入与死锁,可重入为什么是线程安全的子集

📚 本文收录于「流浪」的系列专栏 🐧 Linux系统⚙️ C📊 数据结构与算法🐍 Python🔗 LangChain & LangGraph🗄️ MySQL 数据库🌿 Git 工具🌐 计算机网络🤖 LLM&…

2026/10/12 4:47:50 阅读更多 →

最新新闻

【xilem0.4基础语法学与练】第33课 text_input 文本输入框

【xilem0.4基础语法学与练】第33课 text_input 文本输入框

前言 参考官方文档:https://docs.rs/xilem/latest/xilem/view/fn.text_input.html 版本:Xilem 0.4 一、text_input基础概念 text_input 是可编辑文本输入框组件,接收用户键盘输入字符串。 区分三个文本组件: label :只…

2026/10/12 5:30:14 阅读更多 →
Maven 配置全流程详解:从 JDK、环境变量到 IDEA 关联

Maven 配置全流程详解:从 JDK、环境变量到 IDEA 关联

不夸张地说,Maven 配置是 Java 开发路上第一个让新手挠头、让老手也偶尔翻车的环节。IDEA 自带的 Maven 能建项目,换个电脑就跑不动;命令行输入 mvn -v 有输出,一拉依赖却卡在原地;明明照着教程写了 mirror 镜像&#…

2026/10/12 5:30:14 阅读更多 →
【xilem0.4基础语法学与练】第32课 prose 可选择文本

【xilem0.4基础语法学与练】第32课 prose 可选择文本

前言 参考官方文档:https://docs.rs/xilem/latest/xilem/view/fn.prose.html 版本:Xilem 0.4 一、prose基础概念 prose 是可鼠标选中复制的段落文本组件。 label 文本不可选中复制;prose支持鼠标拖拽选中文本、CtrlC复制,适合日志…

2026/10/12 5:30:14 阅读更多 →
软件测试基础全解析:从用例设计到缺陷管理的完整路径

软件测试基础全解析:从用例设计到缺陷管理的完整路径

干这行这么多年,经常被问到一句话:"软件测试基础篇这东西,是不是就学学怎么点点点?" 说实话,我入行前也是这么以为的,以为测试就是照着用例点按钮、提bug、催开发修。真正在项目里滚过几轮之后才…

2026/10/12 5:30:14 阅读更多 →
Paperclip 与 OpenClaw 互相成就:智能体「运行时 + 编排」生态成型记

Paperclip 与 OpenClaw 互相成就:智能体「运行时 + 编排」生态成型记

Paperclip 与 OpenClaw 互相成就:智能体「运行时 编排」生态成型记 【免费下载链接】paperclip The open-source app everyone uses to manage agents at work 项目地址: https://gitcode.com/GitHub_Trending/papercl/paperclip 2026 年,开源智…

2026/10/12 5:30:14 阅读更多 →
Adobe认证报考全流程指南:从报名到拿证一次讲透

Adobe认证报考全流程指南:从报名到拿证一次讲透

做设计这行,Adobe认证是常被问起的一个东西。不管是刚毕业的学生、想转行的职场新人,还是已经在接私活的自由设计师,总会有人来问:这套认证到底怎么考、怎么报名、多久能拿证、证书有没有用。我前前后后帮团队里几个新人梳理过整套…

2026/10/12 5:29:14 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/11 14:36:54 阅读更多 →