
做Agent项目有一阵子了从最早靠“写一个大大的System Prompt”硬撑到后来被多轮对话折腾得怀疑人生再到现在完全依赖技能库来组织Agent的行为——这条路走下来最大的感受就是没有技能体系Agent项目做到后面必崩。不管你是刚接触agent-skills这个概念还是已经在自己的项目里塞了几个粗糙的“伪技能”这篇内容都值得你花十分钟读完。我会把技能设计、拆解、落地、测试、迭代这条链路完整讲一遍包括踩过的坑和现在正在用的模板。1. 先搞清楚Agent技能到底是什么为什么不能靠提示词硬顶1.1 技能不是工具不是提示词而是一套完整的能力封装很多人在Agent开发里会把“技能”和“工具”混为一谈这是第一个认知误区。工具是Agent可以调用的外部函数比如get_weather(city)、send_email(to, content)它本身没有“判断能力”只是机械化执行的接口。而技能是更高一层的抽象——技能定义了“在什么场景下、按照什么思路、用什么工具、以什么格式输出”这一整套可复用的行为模板。举个例子。做客服Agent你给模型暴露了一个refund_order(order_id)工具这不算技能。真正的问题是模型什么时候该调退款接口退款前需不需要检查订单状态需要校验什么条件超时怎么办拒绝退款的话怎么跟用户解释这些决策逻辑、约束规则、边界处理才是技能的核心。技能打包的是“决策脚本工具调用话术规范”工具只是它手里的螺丝刀。用生活化的类比来说工具是超市货架上的原材料技能是一道菜的完整菜谱。光有面粉、鸡蛋、黄油模型能做一百种不同的东西但每次发挥都不稳定有了“戚风蛋糕技能”“曲奇饼干技能”它就知道该预热烤箱多少度、搅拌到什么状态、烤多久出品就稳定了。1.2 技能体系要解决的四个真实痛点为什么说靠“一个大System Prompt 一堆工具定义”的方案必然出问题因为在实际项目中这套方案会撞上四堵墙上下文失控把大量规则塞进System Prompt意味着每次对话都要重复消耗token规则越多留给实际对话和推理的空间越小。更麻烦的是长上下文中模型对顺序靠后的规则关注度会显著下降你辛辛苦苦写的规则根本进不了注意力窗口的核心区域。行为不可预期同一类任务模型这次这么做下次那么做。没有固定的行为模板约束输出格式、处理流程、兜底逻辑全凭模型当时的“心情”线上问题排查起来极其痛苦。无法测试回归没有技能边界就没有明确的测试单元。你想验证“退款拒绝场景是否稳定”“多轮追问是否跑偏”都不知道从哪里下手。复用几乎为零每个Agent项目从零开始堆提示词上一个项目的经验完全没法迁移。换个场景全重来团队积累沉淀不下来。技能库的存在就是为了把这些问题从“运行时”前置到“设计时”。规则写死在技能文件里Agent只在特定的技能触发点加载对应的指令块上下文干净了行为稳定了测试有边界了项目之间的复用也成了可能。1.3 技能与工作流、子Agent的边界还有必要厘清另外两个容易混淆的概念工作流和子Agent。工作流Workflow是技能的“编排层”它描述多个技能以什么顺序、在什么条件下被调用。技能本身是单点的能力单元工作流是把这些单元串起来的剧本。一个技能可以被多个工作流引用一个好的技能设计一定跟具体工作流解耦。子Agent则是一个独立的、持久的Agent实例有自己的角色设定和上下文窗口。子Agent内部也可以挂载技能。区别在于技能是“挂在Agent身上的能力模块”而子Agent是“独立的执行主体”。设计时优先考虑技能只有当某个任务需要独立的对话历史、独立的记忆状态、或者需要不同的人格设定时才考虑拆子Agent。2. 技能库规划怎么把模糊需求拆成一张技能清单2.1 从业务场景反推技能边界我见过很多人一上来就拍脑袋列技能比如“做个数据分析技能”“写个客服技能”这种粒度完全没法用。正确的做法是从业务场景反推先把高频的、重复出现的任务类型列出来再逐一判断边界。拿一个企业级知识库问答Agent举例。表面需求是“回答员工关于公司制度的问题”但这个需求背后至少能拆出制度查询技能回答考勤、报销、差旅等标准化制度问题答案需引用制度原文章节。流程引导技能当用户问“怎么请假”“怎么报销”时输出分步骤操作指引而不是罗列制度条文。表单填写辅助技能用户问到具体表单字段含义时结合表单结构逐字段解释。异常上报技能当用户在制度里找不到答案或者发现制度矛盾时引导用户提交人工工单。多轮追问技能用户描述不满时通过结构化追问缩小信息范围而不是一次性给一堆无关内容。这样拆下来每个技能的边界都是清晰的任务类型而不是宽泛的能力域。判断技能边界是否合理的三个标准一技能描述能否用一句话说清“在什么情况下做什么事”二技能内部是否有固定的处理流程三技能是否具备可验证的输入输出。三条都满足才值得做成独立技能。2.2 技能粒度拆大不拆小拆重不拆轻技能粒度是个典型的trade-off。拆得太粗比如“全能助手技能”等于没拆跟拿System Prompt硬顶没有区别拆得太细比如把“获取用户名”都做成技能库会爆炸Agent在触发路由时也会混乱。我自己的标准是“任务粒度优先”一个技能对应一个用户可见的任务类型而不是多个同类任务合成一个。比如“合同审核技能”可以是一个技能但技能内部通过子步骤处理“金额校验”“条款缺失检测”“风险等级判定”等环节而“发送邮件”“创建日历事件”这种单步操作一般不单独成技能直接作为工具挂在Agent的基础工具集里就行。还要遵循“拆重不拆轻”原则一个任务出现频率越高、出错代价越大、处理逻辑越复杂越值得独立成技能偶尔出现一次、处理逻辑简单的任务可以在工作流里内联处理别为了凑数硬造技能。2.3 命名规范与技能注册表技能命名不是小事它直接决定Agent的路由准确率。我的建议是采用“动词短语场景限定”的统一格式动词在前名词在后必要时加限定词。比如query_leave_policy查询请假制度submit_expense_workflow引导差旅报销流程validate_reimbursement_form校验报销单填写escalate_to_human_agent升级人工客服这种命名有两个好处第一语义清晰路由模型一看就懂第二动词开头让相似技能之间的区分度更高避免路由混淆。同时给每个技能维护一个注册表Registry记录技能ID、名称、版本号、一句话描述、触发场景关键词、依赖工具、负责人、最近更新时间。注册表是技能库的“索引”既方便人查阅也是后面做路由路由优化和效果评估的基础数据。3. 核心实操一个技能文件从0到1的完整写法3.1 技能文件的标准结构我现在用的技能模板是JSON格式原因很简单结构化字段方便程序读取instructions字段里面的自然语言也是人能直接读懂的。一个完整的技能文件长这样{ skill_id: query_leave_policy, name: 查询请假制度, version: 1.3.0, description: 在用户询问请假规则、请假天数、请假流程时触发。回答需引用公司《考勤管理制度》具体条款。, trigger_keywords: [请假, 年假, 病假, 事假, 调休], input_schema: { type: object, properties: { leave_type: { type: string, enum: [annual, sick, personal, compensatory], description: 请假类型 }, question_focus: { type: string, description: 用户关心的具体角度如天数上限、审批流程、所需材料 } }, required: [leave_type] }, output_schema: { type: object, properties: { answer: { type: string, description: 面向用户的完整回答必须标注引用条款编号 }, source_refs: { type: array, items: {type: string}, description: 引用的制度条款编号列表 }, needs_human: { type: boolean, description: 是否建议转人工制度未覆盖或信息不足时为true } }, required: [answer, source_refs, needs_human] }, tools: [search_policy_doc, get_employee_profile], instructions: ...此处放详细提示词见下节..., error_strategies: { no_result_found: 提示用户换个关键词查询并询问是否需要转人工, doc_access_failed: 先降级使用内置制度摘要再提示用户稍后重试, ambiguous_leave_type: 向用户确认具体请假类型再回答不要自行假设 } }这里面的每一项都有讲究。description是Agent路由判断是否触发该技能的关键依据一定要写清楚“什么场景下用、解决什么问题”千万不能写成产品宣传稿比如“本技能为公司员工提供全面、高效的请假制度查询服务助力员工清晰了解公司政策”——这玩意儿路由模型看到就头晕根本不知道什么时候该触发。input_schema和output_schema是结构化约束的骨架作用有两个一是告诉模型“进入这个技能后应该收集什么信息”二是强制输出格式稳定方便下游逻辑继续处理。3.2 技能内部提示词instructions的写法这套模板值得抄instructions字段是技能的灵魂也是最见功力的地方。我不建议写一大段杂乱的指令而是按固定章节组织让模型知道每一部分在说什么。模板如下# 角色定位 你是公司考勤制度查询专员。你的职责是基于《考勤管理制度》回答员工关于请假规则的询问不回答与请假无关的问题。 # 知识来源 - 优先使用search_policy_doc工具检索制度原文引用时标注条款编号。 - 不得根据个人经验推测制度内容不得编造条款。 # 执行步骤 1. 解析用户意图从用户输入中提取请假类型年假/病假/事假/调休。 2. 如果请假类型不明确先向用户确认不要自作主张。 3. 调用search_policy_doc检索对应条款。 4. 根据检索结果组织回答回答格式固定为「根据《考勤管理制度》第X条你询问的Y情况是Z。具体说明...」 5. 如果检索无结果或制度未覆盖将needs_human设为true并引导用户提交工单。 # 输出规范 - 回答必须包含条款编号引用。 - 以下情况必须转人工制度明确写“以HR解释为准”的、用户遭遇特殊情况如长期病假、用户两次以上追问未获满意答案。 - 禁止直接输出“我不知道”必须给出替代方案。这个模板的妙处在于先把模型的身份钉死角色定位再把它的信息来源锁死知识来源然后用“执行步骤”限制推理路径最后用“输出规范”兜住边界。四个章节各有分工覆盖了“我是谁、我知道什么、我怎么做、我如何停”的完整闭环。写技能提示词时有几个细节容易踩坑。第一个坑允许模型自由发挥的内容给太多。“你可以根据实际情况灵活回答”这种说法越少越好灵活性应该靠分情况的条件分支给出而不是靠模型的临场判断。第二个坑输出规范只写了“应该”没写“禁止”。大模型对“不能做什么”的服从度往往高于“要做什么”每条关键边界都要显式写出禁止项。第三个坑转人工的条件不够具体。“觉得不确定就转人工”等于没说要写清楚“两次追问未获满意答案”“用户明确表达不满”“制度无覆盖”这类可观测的条件。3.3 触发条件与输入整理的工程细节技能文件里的trigger_keywords只是辅助信号真正的主力是description 用户当前意图的语义匹配。在工程实现上常见做法是给每个技能计算一个“触发评分”评分由三部分构成描述与当前对话语义相似度用向量嵌入算权重最高关键词命中数量权重中等上下文连续性比如用户上一轮就在问请假那么本轮优先触发请假相关技能权重低但能兜底这个评分逻辑要放在Agent的主循环里在每次收到用户消息后执行。另外注意技能触发锁定在单轮还是多轮需要显式设计。我的经验是一旦某个技能触发至少在后续两轮内保持“技能状态激活”防止用户追问一句“那如果我想请三天呢”就直接跳回通用对话导致上下文断裂。输入整理也值得提一句。input_schema定义的字段必须由调度器或模型在触发技能时从对话中抽取这个抽取过程本身不要交给技能内部处理而是在技能触发前完成。触发后技能专注于“基于给定输入进行处理”不要指望它自己从客气的闲聊里提取结构化参数。4. 技能库落地目录组织、版本管理、测试与迭代4.1 技能库目录结构与注册表设计技能库的目录组织直接影响团队协作和维护成本。我个人首选这种按领域分层的结构skills/ ├── registry.json # 技能注册表全库索引 ├── hr/ │ ├── query_leave_policy/ # 每个技能一个独立目录 │ │ ├── SKILL.json # 技能定义主体 │ │ ├── test_cases.json # 测试用例集 │ │ └── CHANGELOG.md # 版本变更记录 │ ├── submit_expense_workflow/ │ └── validate_reimbursement_form/ ├── finance/ │ ├── invoice_query/ │ └── budget_forecast/ └── common/ ├── escalate_to_human_agent/ └── clarify_user_intent/按领域分目录按技能分文件夹每个技能自带测试用例和变更日志。registry.json是全局索引记录所有技能的元信息运行时服务启动时加载它来构建技能路由表。技能的版本号我遵循主.次.修订的格式修订号变化表示修正措辞、修补边界条件次版本号变化表示行为逻辑有调整、输出规范有变化主版本号变化表示技能触发场景或核心流程重设计。版本变更记录必须写清“改了什么、为什么改、影响哪些场景”否则技能库迭代两三轮之后就会变成一团糊涂账。4.2 测试集设计黄金数据、场景覆盖、回归机制测试是技能库区别于普通提示词工程的关键。没有测试你不知道一次改动是改好了还是改坏了。我目前实践下来比较有效的测试体系分三层黄金用例集Golden Set每个技能准备10-30个标注好的输入-期望输出对。输入是真实的用户说法输出是专家人工标注的理想回答。跑回归时用技能跑一遍这些用例比对关键字段答案是否包含条款引用、是否触发转人工、输出是否合规。场景维度覆盖黄金用例要覆盖“主流程”、“边界情况”、“异常情况”三个维度。主流程是正常询问边界情况是模糊请假类型、制度未覆盖、用户一次问多个问题异常情况是工具检索失败、用户情绪化表达、连续追问。光有主流程用例不行技能出问题基本都在边界和异常场景。回归机制任何技能修改触发全库回归测试。跑完后关注两个指标一是本技能的黄金用例通过率二是非目标技能的用例通过率有没有下降防“技能间串味”。自动化跑测试的时候我习惯把LLM输出抓进JSONL日志比对时不看生成文本的完全相等而是看结构化字段是否符合断言外加用一个大模型判官模型对回答质量做打分。这样既有客观指标又能捕获逻辑层面的劣化。4.3 全库联动技能间冲突检测与编排技能多了之后最要命的不是单个技能写不好而是技能之间互相咬合出问题。两个常见场景一是触发冲突用户说“我想请假”但“请假制度查询”和“请假流程引导”两个技能都有可能触发。解决办法除了细化各自描述外还有一个实用技巧在技能描述里显式声明“不做什么”。比如流程引导技能写“不回答具体天数上限天数问题交给制度查询”描述里的互斥声明能让路由准确率显著提升。二是编排时序多个技能应该按什么顺序串行执行这需要工作流定义。工作流文件里以节点方式声明技能调用顺序、条件分支和结果传递。比如{ workflow_id: leave_request_full_process, steps: [ {step: 1, skill: query_leave_policy, when: user asks about policy}, {step: 2, skill: validate_reimbursement_form, when: user asks about materials}, {step: 3, skill: escalate_to_human_agent, when: policy not found or user unhappy} ] }技能是积木工作流是图纸。把技能设计得足够原子、可组合工作流层才能灵活编排。如果技能之间隐式耦合比如技能A内部偷偷调用了技能B的逻辑编排层就完全失控了。5. 避坑指南技能库开发中我踩过的那些坑5.1 技能描述写成“能力简介”导致路由失灵最早期我写技能描述特别“正规”每个都是“本技能为企业高效地提供xx服务助力xx目标”结果实测触发准确率惨不忍睹。后来改成直接描述“该技能在什么时候被触发、做什么事情、不做什么事情”触发准确率立竿见影地上来了。核心思路是描述是给路由模型看的说明书不是给领导看的汇报材料。较好的描述对比失败本技能为员工提供全面、便捷的请假制度查询服务帮助员工快速了解公司考勤政策提升人事服务体验。成功当用户问到请假规则、请假天数上限、请假审批流程时触发此技能。它检索制度原文并回答引用条款编号。不回答请假之外的问题不处理请假审批单的实际提交。5.2 技能内部指令过于宽松回答千奇百怪另一个让我痛苦了很久的问题是技能写好了但执行质量还是飘。后来细查发现问题出在instructions里大量出现“根据实际情况灵活处理”“如果合适的话可以适当补充”这类模糊指令。模型每次都会“灵活”出不同的花样来。解决办法就是前面说的把灵活性拆成显式条件分支。比如“如果用户请假类型不明确使用预设话术追问选项为年假/病假/事假/调休”远比“必要时可以询问用户”稳定得多。指令越像决策树输出越像流水线指令越像散文输出越像散文。5.3 工具调用异常未捕获技能直接崩技能依赖的工具不可能100%可用搜索结果为空、外部API超时、权限校验失败都是家常便饭。最开始我只在工具调用成功时定义了行为失败时模型要么硬编答案要么直接死机。现在的做法是在技能文件里显式定义error_strategies为关键失败场景逐个写明降级策略。比如制度检索失败时降级到内置摘要数据源同时告诉用户“全文检索暂时不可用当前回答基于摘要如需细节点这里转人工”。这个设计逻辑有点像代码里的try-catch但比异常捕获更高一层——它连降级后的话术都替你写好了。5.4 上下文污染问题技能结束后未清理技能状态技能执行完成并不等于事件结束。如果不显式清理“当前处于哪个技能上下文”的状态两个技能执行后状态会混在一起。最典型的翻车现场用户先问休假政策技能结束后追问“那我如果因为做手术要请两周呢”触发了一个全新的medical_leave_policy技能但上一技能的历史记录还滞留在上下文里模型开始用休假制度回答医疗期问题。解决思路有两条一是技能框架层在每次技能开始前做一次上下文裁剪只保留对当前技能有用的对话摘要二是在技能切换时做一个显式的“意图重定位”把上一技能的历史压缩成一句摘要而不是原样堆在上下文里。5.5 版本漂移技能没变模型升级后行为变了这个坑最隐蔽。技能文件一字未改但底层模型从A版本升级到B版本后同一批测试用例的通过率掉了15%。原因很简单技能指令是在特定模型能力前提下调出来的模型换了隐含的行为模式也跟着变。应对策略有两个层面第一任何底层模型升级前必须跑全量技能回归测试不允许跳过第二写技能指令时尽量降低对模型“悟性”的依赖需要几步就说几步把推理路径显式化这样模型换血时的行为偏移会小很多。技能文件写得越“手把手”模型升级带来的风险越低。6. 几个进阶思考多模态技能、技能市场与成长型技能库技能体系做到后期可以往三个方向延伸。第一个方向是多模态技能。现在很多Agent已经不满足于纯文本交互视觉技能开始冒头比如截图理解、图片生成、图表解读。这类技能的难度在于input_schema和output_schema要扩展出图像字段而且模型对视觉输入的推理路径要比纯文本更不确定测试集需要额外准备视觉样本。第二个方向是技能市场的思路。团队内部积累了一套技能库完全可以沉淀出通用技能包在多个项目之间复用更大的想象空间是跨组织的技能交易生态好技能像插件一样被更多人安装使用。当然这要求在技能设计上有更强的规范性和文档文化否则技能质量参差会让整个市场体验崩掉。第三个方向是成长型技能库。传统技能是静态的而现在开始有团队在做自演化技能——根据线上失败案例自动生成补充规则由人工审核后合入技能文件。这个方向现在还比较早期但我觉得是重要趋势因为技能库想要持续有价值就必须形成“跑线上→发现问题→改技能→回归测试→再上线”的闭环把这个闭环从手工操作逐步半自动化是值得投入的方向。我个人在实际操作中最大的体会是Agent技能库的搭建本质上是把“跟模型对话”变成“给模型编手册”的过程。每一次把模糊需求变成结构化技能文件都是在给Agent的行为确定性加一分。这活儿枯燥但扎实。如果你正在做Agent项目无论规模大小尽早建立技能库意识、哪怕是先写两三个核心技能后面你会发现整体系统的稳定性和迭代效率都会有质的提升。最后分享一个小技巧给每个技能写一条“信号钩子”也就是一句话讲清“用户在什么语境下最可能触发你”。这一句话记在description最前面。我试过把钩子写在末尾路由准确率明显下降。别让你的技能在关键时刻找不到主场这也算是我用一次次踩坑换来的经验了。