从提示词玄学到技能化拆解:Agent工程化落地方案

发布时间:2026/10/13 5:51:21
从提示词玄学到技能化拆解:Agent工程化落地方案 上个月我把一个跑了两周的Agent项目推倒重来了一半原因很简单Agent看起来什么都会一点但真正做正经事的时候老是给我整出些“半吊子”结果。不是漏了关键步骤就是自己瞎编参数再不然就是同一个问题换个说法就不知道怎么处理了。后来我把所有能力项拆成了独立、可复用、可单独维护的“技能单元”——也就是这个agent-skills项目的由来。简单说就是不再让Agent靠一大段提示词“自由发挥”而是把它的能力拆成一个个有清晰名称、触发条件、参数约束和实现逻辑的技能块由调度层按需选择、组合、执行。这套思路极大改善了原来那种“一个提示词走天下”的不确定性也让我终于能跟别人讲清楚Agent到底会做什么、不会做什么。这篇内容我会从重构动机、技能库设计、实现方式、实测踩坑到最小落地清单完整讲一遍适合正在搭Agent系统、被“提示词玄学”折磨的开发者参考。1. 从“一个提示词走天下”到“技能化拆解”我的重构动机先说清楚我为什么要做这种拆解不然你直接看后面的实现会觉得多此一举。1.1 最初Agent为什么总是“半吊子”刚开始我搭Agent的方式和大家差不多一个系统提示词把角色、目标、约束、工具说明全塞进去然后把用户问题扔给模型。听起来很灵活实际用起来问题一堆。最典型的一个现象是任务稍微复杂一点模型就开始“丢步骤”。比如我让它做一份数据处理报告它前两步做得挺好到第三步“缺失值统计”就跳过了直接给了结论。你再追问它一脸无辜地说“抱歉我忽略了这一点”然后补上一段。这种体验在Demo里还能忍真正接到批量任务里没法用因为你永远要人工盯结果。另一个问题是改动成本极高。你想让Agent多掌握一种处理方式得改提示词提示词改长了原来的行为又变了这叫“牵一发动全身”。我试过把一份系统提示词从800字加到2000字效果反而更差模型开始抓不住重点。第三个问题是不可观测。Agent的每一步推理都在模型内部出了问题你只能看最终输出根本不知道它哪一步想岔了。出了问题排查成本特别高。1.2 对“技能”这个概念的重新理解市面上很多产品把Agent的能力封装成“工具”一个工具对应一个函数。但实际跑下来我觉得“工具”这个颗粒度太细了很多真实场景需要的是“一组连贯动作”。举一个例子如果我给Agent一个“查天气”的函数这是工具。但如果我让它“根据天气决定周末活动方案”它需要先查天气、再查周边地点、再查询餐厅排队情况、最后组合成方案。这串动作如果散落在多个工具调用里模型自己编排出错率就很高。所以我在agent-skills项目里定义的“技能”比“工具”高一层它是一个围绕某个明确目标的、有输入输出约束的、可独立执行的工作单元可以内部嵌套多个工具调用或模型推理但对外暴露的是稳定接口。1.3 技能化拆解后我拿到的实际收益重构后最直观的改变有三个链路可复现同一个技能处理同一类输入结果相对稳定。因为技能内部的步骤是固定的模型发挥的空间被限制在可控范围内。问题可定位Agent一旦结果不对我能明确知道是哪个技能出了问题直接修那个技能的内部逻辑不用把整段提示词翻出来改。能力可复用新项目接进来技能库直接继承。实际开发中我有一个“数据清洗技能”和“报告生成技能”换了个业务场景依然能用这是以前不敢想的。这三点加起来让我从“求模型给个正确答案”变成了“给模型搭好一条靠谱的生产线”。2. 技能库的骨架元信息、描述与参数Schema技能拆好了但怎么让Agent在正确的时候调用正确的技能这一层是整个agent-skills里最容易做又最容易做砸的部分。2.1 技能元信息名字、描述、参数Schema是命根子我一开始想得很简单给每个技能一个名字和一句话介绍模型不就能自己选了吗实际测试后才发现模型选技能的能力很大程度取决于你给它的“标签”写得清不清楚。一个标准的技能元信息我后来总结下来必须有四部分字段作用我的建议name技能的全局唯一标识用短横线分隔的小写英文例如fetch-weatherdescription模型判断何时调用该技能的依据写清楚“解决什么问题”“适合什么输入”“不适合什么场景”parameters入参的JSON Schema字段名、类型、必填项、枚举值、默认值都要写清楚returns出参结构说明模型拿到后知道下一步能拿什么去拼装其中最容易忽视的是description中的“不适合什么场景”。模型是文本匹配的思路你不告诉它这个技能不归它管它很容易拿着天气技能去回答“明天穿什么”这种问题。这里有一个我当时反复调的例子{ name: generate-meeting-minutes, description: 根据会议录音转写文本生成结构化会议纪要包含议题、结论、待办事项。适合输入为会议转写内容且用户要求记录会议信息。不适合用于总结普通文档、文章或网络资料。, parameters: { type: object, properties: { transcript: { type: string, description: 会议录音转写的纯文本内容 }, format: { type: string, enum: [simple, detailed], default: simple, description: 纪要格式simple为简易条目detailed为带发言人分段的详细纪要 } }, required: [transcript] }, returns: { type: object, properties: { summary: {type: string}, decisions: {type: array, items: {type: string}}, actionItems: {type: array, items: {type: string}} } } }提示description字段里优先写“用户问题里可能出现的关键词”和“技能结果会被用来干什么”而不是抽象的功能描述。模型很吃这一套。2.2 选择器是怎么从几十个技能里找到对的技能数量一多每次对话不可能把所有技能定义都塞给模型否则上下文要爆炸。后来我引入了一个“选择器”模块分两层跑召回层用关键词和向量相似度从技能库里筛出Top 5候选技能。精排层把候选技能的完整元信息name description parameters等交给模型让模型从中选出要调用的技能。精排这步看起来多余其实性价比极高。召回层可能根据“会议”两个字召回会议纪要和会议日程两个技能精排层根据完整描述就能把日程那个剔掉。既然是“模型选技能”就存在选错的可能。所以每个技能在执行前我还加了一个“输入校验器”用参数的JSON Schema做预检。如果入参明显不符合约束就拒绝执行并返回一个可读的错误状态而不是硬着头皮跑。2.3 技能粒度划分太粗等于没拆太细等于没写这是我在项目里反复纠结的问题。一开始恨不得把每个动作都做成技能结果技能库膨胀到几百个选择器天天选错。后来走回另一个极端只做了五个大技能每个技能内部逻辑复杂得像一锅粥一样不稳定。最后我总结了一个可操作的判断标准如果一个技能内部的模型推理步骤超过5步且逻辑分支很容易相互干扰那它就应该被拆分。如果两个技能经常被一起调用且调用顺序基本固定那它们可以考虑合并成一个复合技能。判断拆分是否合适的最直接方式是能不能给这个技能写出一句“清晰的触发条件”。写不出来说明边界模糊拆得不对。按这个标准我把闹钟相关的“设置闹钟、删除闹钟、查询闹钟”合并成一个“管理闹钟”技能内部通过动作参数区分把“生成周报”拆成“汇总数据”和“撰写周报”两个技能边界清晰了准确率上去了。3. 技能实现层的三种落地方式提示模板、工具函数与复合流程元信息和选择器管的是“什么时候用哪个技能”真正干活的还是技能内部。同样的技能根据任务性质不同我实现了三种类型。3.1 纯提示型技能把领域知识固化成模板有些技能本质上是“把特定领域的处理逻辑稳定输出”。比如代码审查、文案润色、摘要提取它们的核心价值在“知道该关注什么”而不是“调用什么工具”。这类技能我把它们做成提示模板配合少量示例few-shot而不是让模型自由发挥。比如我做“bad-case分析”技能时模板里固定了四个分析维度输入特征、错误模式、可能原因、修复建议。无论用户扔什么Case进来输出都保持同一结构后面做统计分析非常方便。一个重要的点这类技能虽然自由度高但必须设置“不允许输出主观评价”“不确定时明说不知道”等硬性约束。不然模型会在模板框架里继续自由发挥效果和没模板没区别。3.2 工具型技能Function Calling背后的JSON Schema工具型技能用于需要确定性计算的场景查数据库、调API、算指标。这部分的实现我用的是主流的Function Calling模式但有一个细节很容易被忽略JSON Schema的定义质量直接决定参数填充质量。我踩过的典型坑是某技能要求传入日期我Schema里只写了type: string结果模型传了“今天”“明天”“本周一”这种自然语言日期。后来我在description字段加了严格约束“必须是YYYY-MM-DD格式的日期字符串不得使用任何相对日期描述”问题立刻缓解了大半。另一个实用技巧是给数值参数设置合理范围。比如“查询近N天数据”的N我设置了minimum: 1, maximum: 90。模型如果在边界外取数预检阶段就会直接拦下来比到真正执行时报错友好得多。3.3 复合型技能多个原子技能的组合编排最复杂的技能是复合型技能内部会编排多个工具调用或子技能。比如“排查系统异常”这个技能内部先调日志查询工具、再调指标分析工具、最后让模型综合判断给出根因。我在实现时采用了一个很土但很有效的方法状态机。把复合技能拆成几步每步明确输入输出上一步的输出作为下一步的输入。每一步都记录执行状态中途失败就停在那里返回“哪个环节失败、失败原因是什么”而不是让模型继续硬撑。好处也很明显可定位性极强。比如某次复合技能失败我一看日志就知道是“指标分析”这步超时而不是整个大流程崩溃修起来很快。注意复合技能不宜过深。我踩过嵌套五层的坑模型推理链路一长错误率指数上升。一般建议嵌套不超过三层单层内的原子动作控制在五个以内。4. 实测中踩过的坑技能互斥、幻觉调用与退化问题这里分享几个我在agent-skills项目中真实遇到的坑每一个都花了我不少时间才定位到根因。4.1 技能描述写得太“漂亮”导致的误触发最开始我写技能描述时特别爱用“功能强大”“自动适配各种情况”“支持多种输入格式”这类词觉得这样模型能更灵活地调用。结果恰恰相反模型变得“太灵活了”经常把用户的一个普通请求硬套到某个描述看起来高大上的技能上。后来我专门做了一个“技能描述鲁棒性测试”挑100条典型用户问题逐个检查选择器选中的技能是否合理。测试结果直接暴露出5个技能描述过于宽泛把它们改成“仅当……时使用”“不适用于……”这种明确句式后误触发率从18%降到了4%左右。描述词这块与其给技能“贴金”不如老老实实划清楚边界。4.2 参数抽取的坑枚举值、必填项和类型转换工具型技能里模型填参数翻车的情况我见太多了。常见的有几种把“温度”填成了“湿度”因为两个字段没做枚举互斥。把“2025-01-01”填成了“20250101”因为Schema里没给format约束。该填数组的时候填了个字符串比如传入标签时传了“a,b,c”而不是[a, b, c]。这些问题大部分都能通过把JSON Schema写得更死来解决枚举值写全、类型写死、字符串约束加format、数组范围加minItems和maxItems。宁可多花点时间写Schema也别相信模型能靠自己“理解正确”这是铁律。还有一个实用做法参数抽取之后加一道二次归一化。比如所有日期字符串统一转成标准格式再往下游传所有枚举值转成小写再匹配。这一步成本很低但能显著降低下游工具报错的概率。4.3 Agent开始“偷懒”整体退化到默认技能这个坑特别诡异排查了很久。现象是一开始Agent技能切换得很正常跑了一百多轮对话后突然变得不爱调技能了所有问题都用默认回复兜底技能执行率直线下降。后来我看了中间日志发现问题的根源在“上下文污染”。之前执行过的技能描述和调用记录残留在上下文窗口里模型理解成“我要模仿最近的行为模式”于是变得保守不愿意尝试新技能。解决方案是在每次技能调用结束后对“模型推理摘要”做一次精简归档只保留本轮技能调用的关键信息不保留完整的历史工具报错、中间参数和长文本输出。这种做法本质上是缩小模型的“决策上下文”让它更关注当前任务。改造后技能执行率恢复了正常我再也没遇到那种“越跑越懒”的情况。5. 一套最小可用的agent-skills落地清单如果你也想在自己的项目里引入这套思路我建议不要一上来就铺开做几百个技能而是从一个窄业务场景开始。下面是我整理的最小落地清单。5.1 从业务流里圈出技能边界第一步不是写代码而是把业务流程画出来。我当时拿了一张白纸把用户请求、内部处理步骤、外部工具调用、最终输出全部写下来然后用一个标准问自己这一步是可复用的独立能力吗只有回答“是”的才做成技能。一个容易犯的错是把“用户意图”当技能边界。比如“用户想要一份周报”这不是技能这是一条流程“从数据库取出近7天指标并按周报模板生成文字”才是技能。技能要落在“怎样做”的层面而不是“为什么做”的层面。5.2 注册中心与技能自检我实现了一个非常简单的技能注册中心本质上就是一个目录里面登记了每个技能的实现文件路径、元信息、版本号、依赖工具列表。每次上线新技能都要跑一遍“自检脚本”用3条正例验证技能能否正常触发和返回。用3条负例验证技能不会误触发。用1条边界输入验证参数预检能力。这套自检逻辑帮我在迭代技能时避开了大量隐性回归问题。每次改完技能描述或参数Schema跑一遍脚本再上线稳重很多。5.3 可观测性每次技能调用的日志与评分最后一点心得是技能化的最大红利其实不是效果提升而是可观测性提升。每次技能调用我都会记录下来字段说明触发来源用户原始问题 / 上层Agent透传选择器输出的候选与最终选择方便追溯选择链路入参与出参快照只记录关键字段不上报全量执行耗时与状态success / failed / rejected用户反馈可选用户点了“不喜欢”就标记为负样本有了这些日志我每周都能做一次技能调用质量Review直接在表里看到哪个技能被调用最多、哪个技能经常失败、哪个技能被反复误触发。数据驱动的迭代方式比拍脑袋改提示词靠谱得多。最后再分享一个实操中的小经验技能库一定要做版本管理不要直接在线上改。我吃过一次亏匆匆改了一个技能描述上线结果影响了一整批会话的调用行为花了一晚上才定位到是描述词调整导致的。现在所有改动都走版本号递增线上环境永远指向稳定版本新技能先进灰度观察几天再放开全量。这套agent-skills的框架本质上不是用什么新奇的模型技术而是把Agent的能力组织方式工程化了。对我而言它解决了最核心的信任问题——我终于敢把Agent的任务结果直接交付给别人用而不需要每次都人工返工检查。如果你现在也在被“提示词玄学”折磨不妨从拆一个最常用的技能开始试试。