资讯动态

Agent技能体系设计:从提示词到可复用技能,提升大模型任务执行力

发布时间:2026/10/21 15:11:22 来源:尧图企业网站定制
“agent-skills”这个标题第一次看到时我以为是个开源仓库的名字后来仔细琢磨下来它更像一套方法论把智能体Agent从“能聊天”推向“能干活”的过程中真正值得沉淀的不是某个模型参数而是一份份可以被命名、调用、组合和迭代的“技能”。我做过好几个智能体项目早期习惯把所有能力和约束写进一条超长提示词结果模型一遇到多步骤任务就开始“耍滑头”要么跳过关键环节要么把工具参数编错要么在同一个错误上反复打转。后来我花了两周时间把整个系统重构引入了“技能”这个概念把所有能力按统一的格式抽出来再搭配调度、上下文管理、失败重试和评估机制效果立刻不一样了。这篇文章就把我这段时间的思路、落地过程和踩过的坑完整地梳理一遍给正在设计Agent能力模块的人做个参考。1. 为什么我把Agent的能力重心从提示词迁到“技能”1.1 提示词工程解决的只是“一次表达”技能解决的是“可复用的行动”很多人觉得Agent就是把提示词写完、把工具接上然后等模型自己发挥。早期我也是这么干的。但真实场景里Agent要干的活往往不是单轮问答而是一串连续动作读文档、拆任务、调接口、做判断、写结果、汇报进度。这时候如果把所有指令揉进一段提示词会出现一个很尴尬的局面——模型确实能理解你的话但它没办法把这段话变成“稳定执行的动作单元”。技能这个概念本质上是在提示词和工具之间加了一层“能力封装”。一个技能拥有固定的名字、清晰的输入输出、明确的触发时机和可测试的执行逻辑。模型不再需要从一大段文字里猜“现在该做什么”它只需要对照技能注册表找到匹配的技能并调用即可。这就像教一个新同事做事你不会一次性把公司所有规章丢给他而是会先给他一份岗位手册上面写着每条任务的适用条件和操作流程。这种设计带来三个直接好处第一技能可以被单独测试第二技能可以被重复组合第三技能的执行过程可以用日志记录出了问题能定位到具体环节。这些优势是单纯提示词给不了的。1.2 我习惯把技能分成三类工具型、认知型、协作型在设计技能体系的时候我没急着写代码而是先把要做的能力分成三类这对我后续的架构影响很大。第一类是工具型技能。这类技能负责调用外部系统比如查数据库、调接口、发消息、读写文件。它们的特征是“动作明确、结果可校验”重点在于参数规范化和异常处理。我遇到最多的问题是模型生成参数时自由发挥经常把字段名写错或者把必填参数漏掉。所以这类技能必须在参数层做强制校验不能完全信任模型输出。第二类是认知型技能。这类技能负责信息处理比如总结、翻译、分类、拆解、推理。它们不产生物理世界的变化只改变信息的形态。认知型技能的核心是输出格式的稳定性。同一个任务模型今天给我JSON格式明天给我Markdown格式后天的结果里多了一段“小贴士”这会让下游流程非常难受。我会在技能描述里把输出结构钉死必要时用后置解析器修正格式。第三类是协作型技能。这类技能管的是Agent之间的分工和交接比如“请求其他Agent处理”“将任务归档到队列”“向用户确认信息”。当系统里有多个Agent各司其职时协作型技能就是它们之间的通信协议必须定义清楚消息格式、超时时间和失败处理方式。这三类技能混在一起使用时最忌讳的是把它们的描述写成一锅粥。工具型技能要突出“做什么、动什么系统”认知型技能要突出“输入长什么样、输出长什么样”协作型技能要突出“什么时候该把任务交给别人”。模型判断技能的触发条件时靠的就是这些差异化的描述。1.3 一次失败复盘超长提示词是怎么击穿Agent的说一个我真实经历过的事项目代号就叫“模拟项目X”。当时要做一个内部需求管理Agent功能很明确用户扔进来一段产品需求文本Agent自动生成任务清单、风险评估和排期建议。第一版我自认为很“大模型原生”把全部业务流程写进一条提示词一共两千多字里面包含了角色设定、业务规则、输出格式、示例、负面声明甚至还有“不要输出多余内容”这种警告。结果一实测就露馅了。模型在简单需求上表现良好但只要需求文本超过两千字它就开始忘事先忽略风险分析再把输出格式改得面目全非偶尔还会在回答里把用户输入原样抄一遍当成自己生成的任务。复盘时我发现问题不在模型能力而在于“责任不清”。两千多字的提示词相当于所有职责摊在一张纸上模型既要做阅读理解又要做任务规划和格式化成文根本没有机制保证每一步都被执行。我后来把这张纸撕了改成六个独立技能每个技能只负责一件事文档解析、需求分类、任务拆解、工作量估算、风险识别、报告生成。模型在每一轮只被调用一次只做一件小事成功率一下就上来了。这件事让我彻底确信Agent的能力应该被拆成技能而不是被堆在提示词里。2. 落地技能体系时我优先做的四件事确定“技能优先”的方向后我重新设计了整个Agent骨架。很多人问我要从哪一步开始我的经验是先做四件事技能注册表、任务规划器、工具调用层、上下文管理器。这四样构成了技能体系的地基缺一不可。2.1 技能注册表给每个技能一个身份证技能注册表是整套体系的“索引”。它告诉模型系统里有哪些能力每个能力叫什么名字什么时候能用需要什么参数会返回什么结果。我会给每个技能建一条结构化记录类似这样{ skill_id: req_split, name: 需求拆分, description: 将一段自然语言需求文本拆分为可执行的子任务清单, trigger_example: [ 用户提交了一段产品需求描述且未指定处理方式, 上层规划器输出了需要进一步拆分的任务节点 ], not_trigger_example: [ 用户只是询问流程说明没有提交具体需求, 需求文本已被拆分为任务清单要求直接展示结果 ], parameters: { raw_text: string, 需求原文, constraints: array, 拆分的硬性约束例如必须包含验收标准 }, output_schema: { task_list: array, 每个元素包含 title/owner/acceptance_criteria, depends_on: object, 任务依赖关系 }, max_tokens: 1200 }这条记录不要太长但触发条件一定要写清楚。我早期吃亏就吃在描述太抽象模型把“可以处理需求”理解成“所有文字都归它管”结果用户随便说句话它都去触发需求拆分。后来我加了trigger_example和not_trigger_example两个字段用正反例子帮助模型理解边界误触发的情况少了很多。技能注册表还有一个作用它天然变成了一个“可检索目录”。当Agent只有两三个技能时把所有描述全塞进上下文还能接受当技能超过二十个后就不能全量塞入了。我会给技能做摘要索引每次只把跟当前任务相关的五到八个技能完整描述加载进来其余只保留标题和一句话简介。这个设计在后面上下文小节里会详细说。2.2 任务规划器拆步骤而不是让模型一口气走完有了技能还得知道按什么顺序用它们。我最初犯过一个错让模型自己在一次回答里规划并执行所有步骤。结果它往往“规划得很完整执行得很稀碎”——计划列了八步实际只做了三步还把第三步和第四步合并了。后来我加入了一个独立的任务规划器。任务规划器的核心循环是“规划-执行-观察-调整”我把它做成一个显式的状态机接收用户目标结合技能注册表生成候选执行方案。把方案拆成有序步骤每个步骤绑定一个技能。每一步只执行一个技能执行完把结果写回“工作记忆”。每执行完一步检查结果是否满足预期不满足则回到第2步调整后续方案。所有步骤完成后汇总输出最终结果。这里的关键是“每一步只执行一个技能”。模型不是不能多步处理而是多步处理时容易丢失中间状态。拆成单步之后每一步的上下文都是上一步的产物信息链路是清晰的模型不需要在脑子里同时维护十个中间变量。我在规划器里还加了一个“步骤上限”参数默认是10步超过上限就自动停止并向用户求助。这是为了防止模型在复杂任务里无限扩张计划把简单事做成大型项目。很多Agent框架都有类似“最大迭代次数”的概念我强烈建议这个参数不要调太大否则查一个数据的任务会演变成模型自己给自己安排二十个子任务。2.3 工具调用层让Agent的动作变得规范可观测技能和外部工具是两回事。技能是逻辑单元工具是物理接口。一个技能可能内部调用了两个工具也可能完全不依赖工具。为了让技能跑得稳我单独设计了一层“工具调用层”所有外部操作都走这一层不允许技能直接裸调外部接口。工具调用层最重要的规范是“动词化”。每个工具都是一句话能说清的动词比如query_order、update_task_status、send_email、fetch_page。动词的好处是天然告诉模型这是动作不是数据。我在早期把工具命名为order_data、task_info这类名词模型经常把它们当成“要查询的内容”而不是“可执行的函数”后来全部改成动词之后问题基本消失。工具调用层还必须强制结构化返回。我在代理层定义了一个统一返回格式{ status: success, data: {}, error: null, trace_id: xxx }不管工具内部发生什么成功也好、失败也好、超时也好统一是这三件套。失败时data为空error里写清楚原因。不要把这个细节当作小事模型一旦看到五花八门的返回结构下一步就开始犯迷糊。统一返回结构相当于给模型铺了一条永远不变的路它只需要看status就能决定下一步是继续还是换策略不需要对每个工具做特判。2.4 上下文管理器控制输入才能控制行为技能体系设计得再漂亮上下文管理没做好照样会变成一场灾难。我的粗测结论是当上下文里无关内容占比超过30%时模型的任务完成率会明显下降。这不是模型能力不行而是注意力被稀释了。上下文管理器要解决三件事工作记忆多长、长期记忆怎么存、技能描述加载多少。工作记忆我设置成一个“短期缓冲区”只保存当前任务相关的中间结果。每执行完一个步骤工作记忆里只追加该步骤的结构化摘要不追加原始回复全文。比如需求拆分技能跑完后我存的是“已将需求拆分为6个子任务包含2个前置依赖”而不是把那6个子任务的完整原始文本原封不动塞回去。长期记忆放在外部存储里比如用户偏好、历史处理过的类似任务、被纠正过的错误。技能在需要时主动读取长期记忆而不是把所有历史记录一股脑放进上下文。这就像你说“这个用户喜欢简短的回复”那就在相关技能执行时把这条偏好注入进去其余时候它是安静的。技能描述的加载策略我前面提过这里再强调一遍注册表里的完整描述平均每条约200到400字二十条就是八千字如果每轮对话都全量加载上下文成本高还不说模型还会被多余的技能描述干扰。所以我给每个技能设置了“相关度”标签规划器负责根据标签筛选没被选中的技能只在注册表摘要里出现一行让模型知道“有这个东西但不展开”。3. 用一个需求管理Demo演示“技能化”的完整动作纸上谈兵没意思我拿“模拟项目X”这个需求管理Agent当例子把技能化的过程完整走一遍。这个Demo我后来重构了两次当前这版逻辑比较顺读者可以直接拿来套用到自己的项目里。3.1 先定义目标和边界重构第一步不是写代码而是画边界。我给这个Agent定的目标是用户提供一段自然语言的需求描述Agent输出任务清单、依赖关系、风险点和粗略工作量。边界则画得很清楚有三件事它不做不做代码生成和自动修改代码。不做完整的项目管理排期只给出粗略的工作量估算。不直接创建工单只输出结构化结果由用户确认后再写入系统。这个边界很关键。没有边界的Agent会在“帮忙”的路上越走越远用户问一句“这个需求要多久”它可能顺手把项目排期表都给你排了。有了边界规划器生成方案时就有了硬约束不会跑偏。3.2 技能拆解六个技能各管一摊在边界之内我把整个流程拆成六个技能。每个技能都很小单个技能的逻辑复杂度接近“一道流程题”而不是“一个业务系统”。技能输入输出依赖文档解析原始需求文本、格式声明结构化需求对象无需求分类结构化需求对象需求类型、对应处理模板文档解析任务拆解需求对象、分类结果任务清单和依赖关系需求分类工作量估算任务清单每项任务的估算区间和总人工日任务拆解风险识别任务清单、需求对象风险项列表及缓解建议任务拆解报告生成全部中间结果最终交付文档所有前置技能这个表格看起来平淡无奇但它帮我解决了一个大问题每个技能的输入都来自上一个技能的结构化输出链路是单向前进的没有交叉依赖。这大大降低了模型的“想做太多事”的冲动。3.3 一个执行流程示例从需求文本到任务列表假设用户扔进来一段文本“我们希望把登录模块升级成支持扫二维码方式保留原有账密登录同时增加一个找回密码的入口后端要支持会话过期时间配置前端需要适配深色模式。”任务规划器会这样走调用“文档解析”技能。这一步只做格式清理把文本变成{title, requirement_text, keywords, original_links}对象。调用“需求分类”技能。它根据解析结果判断这是“登录模块改造”类别并套用该类别的处理模板。进入一个“子任务循环”。每个子任务调用一次“任务拆解”技能。模型先拆出“扫码登录”再拆出“找回密码”再拆出“会话过期配置”每拆一个就写回工作记忆免得一次拆太多把自己绕晕。所有任务拆完后调用“工作量估算”技能按任务清单逐项给出区间比如“扫码登录2到3人日”。调用“风险识别”技能把登录方式从账密扩展到扫码带来的兼容性风险、安全风险、旧版本客户端不兼容风险等检出来。最后调用“报告生成”技能把前面五步的结构化数据缝合成长文报告。整个流程看起来步骤很多但每一步都短小清晰。实测下来用户投喂同样一段需求第一版“超长提示词方案”的task清单经常缺项第二版“技能化方案”的缺项率低了很多。代价是流程多跑了几次模型调用但换来的是可控性对我来说非常值。3.4 技能化版本与“一条提示词版本”的真实差异我把两版方案做了对比差异最明显的不只是成功率还有排查问题的速度。维度一条提示词版本技能化版本新增一种需求类型修改一处两千字的提示词副作用难预估新增一个技能或调整一个技能描述某个步骤执行失败模型可能在后续步骤中带病执行失败在步骤层暴露可停止、可重试、可降级输出格式变化寄希望于“请严格按照格式”这种申明每个技能的输出结构单独校验模型升级后的影响面整个提示词全部需要重新验证逐技能验证影响面粒度小单位任务Token成本低一次调用完成高多次调用完成但浪费减少必须诚实说技能化不是免费的。它会把一次模型调用变成三到五次Token成本会上升。但我的观点是Token成本一次性上升换来的是“可维护性”的指数级提升。在真实业务里后期维护成本往往压过推理成本。只要不做那种每分钟调用百万次的高频场景技能化带来的额外开销完全可接受。4. 接入大模型之后我踩过的四个真实坑技能体系理论归理论接上大模型以后一堆毛病才冒出来。我在调试“模拟项目X”时踩过不少坑挑四个最典型的说说每个都是教训。4.1 技能描述写得越全模型越不知道何时触发第一次写技能描述时我像写产品手册一样把背景、步骤、注意事项、业界最佳实践全写进去了。结果模型反而触发得乱七八糟。问题出在一句话上模型的技能触发判断靠的是“快速匹配”不是“深度阅读”。它拿到一段用户输入第一时间想到的是“这段话和哪个技能描述的开头几句最像”。如果技能描述开头全是“本技能用于在深入理解需求并综合考量项目背景与用户意图的基础上……”这类套话模型的注意力就被带跑了。后来我调整了写法技能描述的câu结构是“触发条件优先操作指令次之补充细节最后”。一段描述通常压到200字以内开头第一句一定是“当满足以下条件时使用本技能”。同时把正反例塞进描述模型看到“用户提供需求原文”就触发看到“用户仅咨询流程”就不触发。效果立竿见影。4.2 上下文被技能说明撑爆模型反而“忘”了正事技能数量一多我遇到一个新问题为了确保模型知晓所有能力我把全部技能描述都塞进系统提示词。结果模型调用“报告生成”技能时居然把“文档解析”技能的例子段抄进了最终答案。原因不复杂上下文里跟当前任务无关的技能说明太多了模型在做生成时更容易“跑题式联想”。这就好比让一个员工在堆满杂物的办公桌上写报告他写着写着瞟到旁边的旧图纸不自觉就把它当成参考资料了。解决方法是分级加载我在2.1和2.4里提到的技能注册表摘要索引就是为此设计的。当前任务相关技能加载全量描述非相关技能只保留一行。底线是上下文里每一行文本都要有“当前步骤的价值”没有价值就宁可删掉。4.3 多个技能都能匹配时模型经常选错有一段时间我总是看到模型在应该调用“需求分类”时却去调用“任务拆解”。两个技能对同一段输入都算“相关”模型选择时就像抛硬币。这个坑的根源是技能职责边界没有写清楚。我的修法是在调度层加“硬规则”而不是继续优化提示词。比如在调度逻辑里明确写“如果需求已经通过解析技能产出结构化对象则后续只能调用分类技能不再允许重复调用解析技能。”这种规则可以在规划器里用一段轻量级代码实现不依赖模型的临场判断。硬规则虽然牺牲了一点灵活性但在关键路径上能显著减少误触发。为了避免误触发我还在技能注册表里增加了一个conflict_with字段。当两个技能同时匹配时调度器优先检查冲突表按预设优先级做唯一选择。比如任务拆解和需求分类冲突时明确“先分类、后拆解”模型不需要自己背这个规则。4.4 执行失败后模型陷入“重试-失败-重试”的死循环这是最让人血压升高的问题一个工具调用失败了错误信息是“参数xx格式不正确”。模型看到status: error后转头就用一模一样的参数重新调一次连错误都没变然后它再来一次第三次还是一样。它仿佛觉得每次调用都是独立事件不会从错误信息里学习。我在工具调用层加了“失败计数器”和“变化规则”。具体做法是同一个技能连续失败2次强制切换策略。切换策略至少有三种改写参数格式、更换技能、放弃当前步骤并返回给用户。失败3次以上直接停止当前任务链把错误日志汇总后交给用户处理。这个规则听起来很简单但真的能救很多次。我见过模型在某个接口前重试7次的情况如果按我的规则第三次就已经停下来给用户交代问题了。你设计技能体系时一定要记住模型在失败时倾向于“再试一次”你的代码要把这个倾向拦截住。5. 技能体系如何与记忆、学习、模型升级配合技能不是孤立存在的。它要和记忆配合要和模型版本配合还要靠使用日志持续迭代。这节说说我在这三个方面的实践。5.1 技能是招式记忆是内功心法技能相当于一套招式模型知道“怎么打”但不知道“什么时候用哪一招最合适”。记忆弥补的正是这一层判断力。我在系统里维护了两类记忆。第一类是用户偏好记忆比如某个用户长期要求报告里包含“风险缓解时限”那“报告生成”技能执行时就会自动追加这个约束第二类是业务经验记忆比如过去一百次需求处理中“登录模块”相关的任务经常出现“兼容性”风险那“风险识别”技能在遇到登录需求时就会优先检查兼容性项。这里有个容易走偏的地方不要把记忆原始文本堆进技能提示应该把记忆加工成“规则片段”。比如长期记忆里存了100条历史风险记录我不会全塞给模型而是用统计脚本提炼成“登录类需求风险top3兼容性、安全、旧版本迁移”。模型拿到的是精炼后的经验不是原始语料。5.2 大模型一升级技能描述就要重新过一遍模型升级看起来是纯利好但对技能体系来说是“变更风险”。同一个技能描述旧版模型理解得很好新版模型可能因为训练数据不同反而产生不同的理解。我之前在某个业务项目里换过模型版本升级后“需求分类”技能突然不触发了日志显示模型把分类任务当成了普通的文本摘要任务。解决方法是在每次模型升级前跑一遍“技能回归集”。我维护了大约一百条典型输入覆盖每个技能的触发条件、边界情况和异常输入。升级后先用回归集快速扫描看技能触发率有没有明显变化。如果某个技能的触发率跌了就重新改写它的描述用新模型的“语言习惯”重新表达。这是模型升级时最不该跳过的步骤。5.3 用调用日志反推技能拆分与触发阈值形成热更新闭环技能体系设计得再好也不可能一次到位。我依赖日志做持续迭代。每一条技能调用记录我都存下来关键字段包括触发技能名、输入摘要、输出摘要、是否成功、后续是否被用户修改、Token消耗、耗时。每隔一段时间我会对日志做几个统计某个技能被调了多少次成功率多少。哪些技能经常被一起调用说明它们可以合并或存在隐藏依赖。哪些技能调用少但每次调用都绕了远路说明触发条件太隐蔽或描述不对。用户修改输出的频率高说明某个技能的输出不符合预期。基于这些统计我会调整技能描述、触发条件、拆分粒度。比如“工作量估算”和“风险识别”原本是两个独立技能日志显示几乎总是在“任务拆解”后被顺序调用且结果互相影响我后来就把它们合并成“任务评估”技能减少了调度开销。这个“日志反推技能设计”的循环是我最推荐大家坚持做的事。6. 我评估一套技能体系好不好的三个标准聊完设计和实战最后说说怎么评价技能体系。我的评估标准只有三条但每一条都能拆成可执行的检查项。6.1 技能调用准确率与任务成功率这是第一层指标也是最容易量化的。我会跑固定测试集记录每个技能“该触发时是否触发”“不该触发时是否误触发”。理想状态下准确率应该大于90%。任务成功率看的是端到端效果比如需求管理Demo中用户输入一段需求后生成的最终报告是否满足基本要求比如不缺失必要模块、风险点不少于预期。这一层指标出现问题时先看是技能描述问题还是规划器问题。如果某个技能经常不触发改描述优先如果规划顺序混乱优先调整规划器逻辑。6.2 可扩展性和可维护性一个技能体系好不好加一个新技能需要多少成本这是一个很现实的评判维度。在我的框架里新加技能只需要三步写一条注册记录定义输入输出结构写一个执行函数。如果加一个技能需要动到其他技能的逻辑那就说明技能边界设计有问题。可维护性还有一个隐藏指标出问题时定位速度。我更看重失败日志能不能告诉你“错在第几步、哪个技能、什么错误”。如果你的Agent失败后只有一个“处理失败”的笼统信息技能体系就是不达标的。6.3 安全护栏与降级恢复能力最后一条标准很容易被忽略。技能体系越强大Agent的“行动能力”越强就越需要安全护栏。我至少会做四层护栏第一层所有危险操作删除、修改、对外发送都要用户确认这个确认动作本身做成一个“确认技能”不让模型直接执行第二层权限隔离技能调用底层接口时使用最小权限账号第三层降级策略核心技能挂了之后Agent自动切换到“只读模式”或者“咨询模式”不让用户面临一个半残的系统第四层完整追踪每个技能调用都有trace_id能把动作还原成时间线。这些护栏写进技能体系里不是限制Agent能力而是保证你敢于放开能力。我见过很多团队因为害怕模型乱来把技能集合设计得极其保守这其实是另一种损失。合理的做法是让技能开放但让护栏敏感。我在实际项目里最深的体会是Agent的“技能”设计本质上是一个软件工程问题而不是一个运气问题。只要把每个技能当成一个可以单测的模块把调度逻辑写成显式流程把模型当作一个“偶尔犯错但高效”的执行者整个系统就能稳步向前。如果你只记住一句话那就是技能描述里最值钱的内容不是“你能干什么”而是“什么时候别用我”。这句话帮我避开了绝大多数误触发问题也送给正在打磨Agent的你。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑