资讯动态

Agent技能体系实战:从Prompt堆叠到可复用技能编排的工程化之路

发布时间:2026/10/9 19:29:25 来源:尧图企业网站定制
我最早注意到“agent-skills”——或者按我习惯的说法Agent技能体系——是在一个客服工单自动化项目里。当时我手头有一个表现还不错的Agent基于大模型做意图识别和话术生成demo时惊艳全场一上真实流量就露馅用户换一种说法它就懵遇到多步骤任务直接放弃最要命的是同类工单每次处理方式都不一样业务方根本不敢放手让它执行。折腾了大半个月我意识到问题不在模型而在Agent的能力组织方式上——我们把所有能力都堆在提示词里却没有把任务处理逻辑封装成独立、可复用、可评测的“技能”。后来我把整套方案重构成以skills为核心的架构情况才彻底改观。这篇文章就把我对agent-skills的完整理解、落地经验和踩坑记录写出来。具体会包括为什么Agent必须要技能化、技能系统的最小设计单元长什么样、多技能之间怎么编排协同、以及我在真实项目里遇到的那些坑和解决办法。如果你是做大模型应用开发的工程师或者正在把Agent往生产环境推这篇文章应该能让你少走不少弯路。1. 为什么Agent不能只靠Prompt必须要有技能体系先聊清楚一个基础问题Prompt和技能到底差在哪。大模型确实很强给它一段任务描述配上几个工具列表它往往就能干活。但这种模式撑死后端某个写死的场景一旦进入生产环境立刻暴露出一堆工程上的硬伤。我复盘那段时间踩的坑其实集中在三件事上问题单纯堆Prompt的表现技能化后的表现稳定性每次输出有微小漂移处理链路一长就失控流程固定模型只负责关键决策结果可复现可维护性提示词和业务逻辑混在一起改一处崩一片技能独立成模块改A不影响B可评测性只能人工看对话记录没法自动化回归每个技能有独立评测集改动后可批量验证这里的核心认知是技能不只是“更长的Prompt”而是把大模型的能力、外部工具、内部状态、决策规则和异常处理封装成一个完整任务单元。它像一个有明确输入输出和内部协议的微服务只是执行引擎里有一层大模型。我记得很清楚重构之后第一个受益的场景是退款处理。之前Prompt里的表述是“如果用户要求退款调用退款接口”看起来没什么问题对吧但实际业务里有十几种退款类型有的要审核、有的要原路退回、有的要扣手续费、有的账单已经封账还得走线下。业务方把这些规则一条条写进提示词模型根本记不住每次都得靠运气。技能化之后退款变成了一个独立技能输入是用户订单和退款诉求技能内部有标准评估流程模型只做“判断走哪条分支”这一件事其余步骤由确定性代码和子技能接管。结果就是处理成功率从靠Prompt时的不到60%提升到稳定在95%以上。这也是我一直主张的观点Agent的上限在模型也取决于模型的推理能力但Agent的下限也就是它能在生产环境跑多稳完全由技能体系的工程化程度决定。那项目名叫“agent-skills”到底想表达什么从我的角度理解它指向的是一套完整的技能工程方法论而不只是给模型塞几个工具描述。包含四层东西技能定义层标准化的技能描述、输入输出约束、触发条件技能实现层代码、Prompt模板、工具绑定、子技能编排技能调度层Agent如何从当前任务路由到正确技能技能治理层版本、评测、权限、审计。后面章节我会把这四层一层层掰开来讲。2. 技能的最小设计单元一份配置搞定定义、触发与执行很多团队做Agent功能时习惯直接写“一个函数就是一个技能”或者“一个Prompt就是一个技能”。这两种做法我都试过最后都不太理想。真正的技能单元应该是一份结构化的技能包它能在不依赖系统prompt的前提下向调度层传递所有必要信息。2.1 技能包的标准结构我在项目里最终沉淀出的技能包目录结构是这样的skills/ └── order_refund/ ├── SKILL.md # 技能声明名称、描述、触发条件、依赖 ├── runbook.md # 执行流程分步骤的决策指引和交接规则 ├── schemas.py # 输入输出Schema定义 ├── main.py # 技能主逻辑确定性部分模型决策点 └── tests/ # 该技能的独立评测用例关键在SKILL.md。它不是给模型看的长篇大论而是给两个读者看的一个是调度器可能是代码也可能是模型本身另一个是后续维护这个技能的工程师。一个典型的SKILL.md长这样--- name: order_refund description: 处理用户退款申请支持原路退回、重新支付、线下转账三种方式 version: 1.3.0 author: platform-team tags: [billing, order, refund] trigger: - 用户明确表达退款诉求 - 用户在售后工单中选择退款/退货分类 - 风控系统标记的争议订单【仅管理员可触发】 input: order_id: string # 必填订单ID reason_code: string # 必填退款原因编码 amount: float # 选填退款金额默认原订单金额 output: refund_id: string status: enum[submitted, approved, rejected, manual_review] dependencies: - order_query - user_identity_verify - payment_gateway_refund timeout_ms: 15000 fallback: manual_escalation你先别急着看语法里面有几个设计点我想单独强调第一trigger字段是给技能路由用的。Agent拿到用户消息后先做一次轻量分类判断命中了哪些技能的触发条件。我踩过的一个坑是有些技能描述写得太泛比如“处理订单相关问题”结果所有订单相关请求都路由进来技能内部再做二次判断导致大量无效调用和上下文浪费。触发条件写得越具体路由越精准。第二dependencies不是装饰用的它告诉调度层这个技能运行时依赖哪些其他技能或工具。这对后面做编排、做权限控制都有用。我在一次安全事故复盘时发现某个技能因为依赖列表没写全绕过了审计直接调用了高权限支付接口。自那以后依赖声明和权限绑定成了代码审查的强制项。第三timeout和fallback是生产环境必备字段。模型调用耗时不可控技能必须有超时上限并且明确超时后怎么办。我的默认策略是超时先重试一次仍失败就走fallback指定的技能或人工程序。2.2 技能和普通工具调用的本质区别很多人会问你的技能包不就是封装了一堆工具调用吗和直接给模型几个函数有什么区别区别非常大我用一个具体例子说明。假设你要做一个“差旅报销单审核”技能。普通工具调用的方式是工具A获取报销单 工具B获取差旅标准 工具C判断超支模型自己决定工具调用顺序凭推理能力把A、B、C串起来。这事looks简单但实际跑起来你会发现模型经常会在拿到报销单后直接下结论忘了查差旅标准或者查完标准算错了超支金额。为什么因为推理链路越长上下文干扰项越多模型的失误率指数级上升。技能化之后这条链路变成了# main.py 中简化后的确定性流程 def run(ctx: SkillContext): # 1. 固定顺序先取单再取标准两者无依赖关系但顺序固定 receipt ctx.call(order_query, idctx.input.order_id) standards ctx.call(travel_standard_query, employee_levelctx.input.employee_level, destinationreceipt.destination, date_range[receipt.start_date, receipt.end_date]) # 2. 把可计算的部分从模型推理中剥离 over_items [] for item in receipt.line_items: budget find_budget_rule(standards, item.category) if item.amount budget.ceiling: over_items.append({ category: item.category, amount: item.amount, budget: budget.ceiling, excess: item.amount - budget.ceiling }) # 3. 只有需要解释的异常判断才交给模型 if over_items: verdict ctx.llm_judge( prompt_templateOVER_BUDGET_REASONING, data{items: over_items, policy_notes: standards.policy_notes} ) return {verdict: needs_review, excess_items: over_items, reason: verdict} return {verdict: approved, excess_items: []}你有没有注意到这个技能里模型只被用在两个地方路由决策判断该走哪条分支和开放解释对超支情况的自然语言说明。其他所有环节都是确定性代码靠计算而不是靠感觉。这就是技能和工具的本质区别工具是单次动作技能是完整任务处理单元。工具回答“你能做什么”技能回答“这件事你怎么负责到底”。3. 多技能协同编排层的职责与边界单个技能解决单一任务Agent真正复杂的地方在于它需要面对的是一个完整用户请求里面可能包含了多步骤、多依赖、多条件分支。这部分承担编排责任的不应该是技能本身而应该是独立的编排层。3.1 编排器的职责路由而不是啥都管我先说我见过的一种普遍错误把编排器和技能混在一起在系统提示词里写“如果用户报告订单问题先执行A技能如果A技能返回x再执行B技能...”。这种硬编码的逻辑写进Prompt短期看能跑长期看就是灾难——每次改流程都动Prompt而Prompt一改所有关联技能全部受影响难以回归。更好的做法是编排器只负责路由和状态管理不负责具体执行。编排器需要回答以下几个问题用户当前请求应该交给哪个技能技能返回的状态是终态还是需要继续多个技能按什么顺序执行技能之间需要传递哪些上下文字段我用了一个很轻量但稳定的方案基于意图分类的路由器基于状态机的流程控制器。# 路由器把用户请求映射到技能名 ROUTER_PROMPT 你是技能路由引擎。根据用户请求和可用技能列表选出最合适的技能。 用户请求: {user_message} 可用技能只允许选一个: {skill_list} 输出JSON格式: {skill: 技能名, confidence: 0到1之间的小数, reason: 一句话理由} # 路由器解析结果后如果confidence低于0.7不直接执行技能 # 而是转向澄清话术让用户补充信息这个设计里有一个值得说的点confidence阈值。很多人做意图路由时模型说“我确定要调用退款技能”就真的调了。但实际场景里用户说“我不想要这个订单了”可能是退款也可能是取消订单或退货两者流程完全不同。我设了0.7这条线低于阈值就让用户先确认宁可多一次交互也不让路由错误导致后续流程全崩。3.2 子技能组合一个真实的多步流程是怎么串起来的我拿一个“企业客户合同续期”流程举例这个流程涉及5个技能看起来是这样的contract_renewal_flow: steps: - skill: contract_expiry_query input: customer_id output: current_contract - skill: credit_check input: customer_id output: credit_score - skill: pricing_eligibility input: - contract_id - credit_score output: eligible_plans - skill: renewal_negotiation input: - current_contract - eligible_plans output: negotiation_summary - skill: contract_signature_generation input: negotiation_summary output: contract_draft看起来只是顺序执行对不对但实际复杂不在于顺序而在于分支。我的流程里credit_check结果如果判定为低风险直接跳到renewal_negotiation如果判定为中风险需要额外走一个manual_approval技能如果高风险直接终止流程并通知销售人工介入。这些分支逻辑应该放在流程控制里由编排器判断前一步的技能输出值来决定下一步。总来说编排层的设计原则是流程用代码定决策用模型做异常走fallback。不要让模型记住整条流程也不要用超长Prompt把流程细节全部写进去更不要让每个技能自己去考虑“下一个技能是谁”。这是我在多次重构后得出的最稳的平衡点。4. 那些让人头疼的踩坑记录技能落地最容易出问题的五个环节技能化改造最大的挑战不是设计而是落地。下面这几个坑是我和团队在真实项目中踩过并最终解决的每一条都对应着实际代码层面的修复不是泛泛的经验之谈。4.1 坑一技能描述与触发条件的“虚假泛化”我最初写技能描述时非常有“复用意识”一个“订单处理”技能恨不得包揽查询、修改、取消、退款、催单。描述是“处理用户关于订单的所有问题”。结果路由器一上来就被带偏了。用户说“我的订单怎么还没有送到”路由器判定命中“订单处理”技能技能内部再判断意图再调用物流查询工具。绕了一大圈多消耗了大量tokens用户还觉得回复慢。解决方式是先聚焦再扩展每个技能只负责一类窄任务触发条件精确到动作和对象。比如技能名称从“订单处理”拆成“订单状态查询”“订单配送时间修改”“订单退款申请”“订单取消”四个独立技能。表面上看技能数量变多了但每个技能的命中率、执行成功率和评测得分都明显上升。我后来给团队定的规矩是如果技能描述里出现了“所有”“任何”“等”这类词基本可以判定命名粒度过大必须拆。触发条件宁可写得窄之后靠路由和技能内部再做子任务细分也不要一开始就写一个大而全的触发面。4.2 坑二上下文窗口和技能说明文档的冲突这个问题非常隐蔽。技能做得越完善说明文档就越长。我把一个“多平台商品比价”技能的runbook写到两万多字符包含平台对接说明、反爬策略、价格计算规则、异常处理表。结果每次技能被调用这堆文档全塞进上下文模型还没开始处理用户问题上下文就消耗了大半。代价是显著的响应变慢、成本上升、模型注意力被长文档里的细节带偏反而遗漏关键任务字段。我的修复方案是“分层说明书”SKILL.md只保留路由层需要的信息名称、触发条件、输入输出schema、前置依赖runbook.md细分为按需加载的片段技能执行时先加载第一个决策点所需的片段后续决策点遇到时再动态拼接参考文档单独存放不在技能执行时直接注入而是通过RAG方式在需要时检索相关片段。改造后同一技能的单次调用上下文消耗从原来的约1.2万token降到了约3500token。这个数字差异在生产环境里影响非常大既快又便宜。4.3 坑三模型的“自由发挥”与审批回退大模型天生爱自由发挥这在做创意写作时是优点可在处理财务、合同、医疗这类强约束场景时就非常危险。我遇到过的情况是模型在“报销单审核”技能里自行提高了餐饮报销标准理由是“用户出差地点属于一线城市认为合理”。我把“规则解读”和“规则执行”拆开了。规则执行全部落到确定性代码用Python字典和计算公式直接比对发票金额与标准上限模型唯一能做的是在异常情况下生成解释性文案但生成内容不允许包含规则外的金额建议。遇到模型自作主张最保险的方法是让它“没机会做决定”而不是“好言相劝别这么做”。事实证明不管你在提示词里写多少遍“不要超过标准”都挡不住模型的幻觉只有把决策从模型手里拿走才是真正的稳。4.4 坑四失败与重试机制的设计缺失技能执行中经常遇到外部API超时、返回格式异常、中间状态丢失等问题。早期我把所有失败都归结为“重试一次再不行就报错”结果经常出现重复扣款、重复创建工单这种更严重的二次事故。后来给每个技能加了两层防护幂等键每次技能执行带上单调递增的execution_id所有外部写入操作都校验这个ID重复调用时不重复执行状态机明确的失败分类把失败分成可重试、不可重试、需人工处理三类。比如支付网关返回“网络超时”属于可重试最多重试两次返回“余额不足”属于不可重试技能立刻终止并把用户转给话术处理返回“风控拦截”属于需人工处理技能自动创建工单并通知审核人员。这个机制上线后技能相关事故率下降了接近80%。技能化不是只让流程自动化更重要的是把不稳定因素纳入可控范围。4.5 坑五评测集到底覆盖什么很多团队做技能评测测的是“模型输出这句话对不对”。但技能在真实运行中是多步链路的组合输出只是一环光评输出没有意义。我的做法是给技能建立“场景级评测矩阵”每个技能至少覆盖四类场景场景类型评测内容典型用例数主路径按标准流程全流程执行成功20边缘条件输入为空、金额为负、客户等级为空等15异常路径外部API超时、返回格式错误、规则冲突15安全边界越权操作、非法参数注入、绕过审批10每个用例不只看终态输出还检查中间状态是否正确传递、调用了哪些外部工具、关键决策点是否落在预期分支。这套矩阵建好后每次技能改动都能跑一遍回归再也不怕“改A坏B”。5. 从技能到技能库沉淀可复用的Agent能力资产当你的项目里技能数量超过10个你会意识到“技能”这个层面已经不足以解决组织问题了。你会需要一套技能库的管理规范来支撑跨业务线的复用。5.1 分层设计通用技能、领域技能、场景技能我把技能库里的所有技能分成三层通用技能层与业务无关的基础能力比如”信息抽取““格式转换”“数据脱敏”“相似内容检索”。这类技能最容易被复用单独拉出来治理。领域技能层基于通用层组合起来的领域能力比如“报销合规检查”就是“数据脱敏”“规则引擎”“文本分类”的组合。场景技能层面向具体业务场景的端到端技能比如“销售差旅报销审核”直接面向最终用户。分层之后逻辑清晰很多上层技能的依赖只指向领域层领域层只依赖通用层通用层独立演进。避免最顶层技能直接调底层原子工具否则依赖关系会乱成一锅粥。5.2 版本演进与跨项目复用技能包本质上是代码所以它必须纳入版本管理。我用的规范是每个技能一个Git仓库目录单独的版本号和更新日志技能之间的依赖声明具体到版本号不允许“引用最新版”这种模糊依赖。跨项目复用最大的优势是可以让不同团队避免重复造轮子。例如一个“客户身份核验”技能在支付团队已经打磨过有完整的异常处理和评测集其他团队接入时只需要改几个业务参数几分钟就能完成适配。复用的前提是技能文档足够清晰尤其“边界行为”部分要说明哪些情况下它不会处理评测集对第三方开放接入方可以先跑测试判断是否满足自己的场景接口变更必须走兼容性评估每个发布周期先看有没有破坏下游调用方。5.3 技能治理权限、审计与淘汰技能越来越多了包括依赖关系、权限范围、生命周期管理。我把技能治理做成了每月一次的例行动作权限盘点核查每个技能实际调用的API权限和声明是否一致把闲置的高权限技能降权调用审计按技能维度统计调用量、成功率、平均耗时、失败分布全部落到面板上淘汰机制连续60天无调用的技能标记为”过时“连续90天仍无使用的移出主库。这个机制可能听起来很重但对一个中型团队来说它能让技能库保持干净减少维护负担。你也不想看到几十个无用技能躺在库里每次路由时都来干扰模型判断吧。6. 你接下来可以怎么开始落地听到这里你可能已经摩拳擦掌想知道从哪里入手。我的建议是不要一上来就建宏大的技能库而是从一个你手头最痛、最重复、最容易被老板催的那个Agent任务开始。具体步骤是基于我的经验总结选一个任务找一个当前Prompt处理得很费劲、错误率高的任务先不要选太复杂的流程中等复杂度最好。写技能包骨架按上面的结构初始化SKILL.md、main.py、schemas.py先不追求完美能跑通主路径就行。把可计算逻辑移到代码里检查技能执行链路凡是能用规则、公式、查表解决的判断一律从Prompt中移走。给技能加三大件幂等键、超时处理、回退策略。这一步不做好你后面会天天被on-call电话吵醒。搭评测集再上线至少把你的主路径用例和异常用例写出来再推进到生产。观察运行数据并迭代上线后持续关注调用成功率、失败类型分布按数据反馈修技能包。如果你手头有想尝试的Agent技能场景照着这个流程走一遍应该几天内就能看到明显变化。我在把这个架构推到三四个不同业务线之后最深的感受是技能化不是一个技术决策而是一个工程纪律。它逼着你把模型的自由度关进笼子里把决定权收回到确定性代码手里把Agent从“看起来很聪明”变成一个“行为可预期、结果可校验、质量可复盘”的生产工具。它确实是更麻烦一些但这些麻烦全部都是为了上线后的安稳觉。

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

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

免费获取报价 →
↑