首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
Agent技能体系实战:从提示词堆砌到可测试的智能体能力分层
📅 2026/10/8 11:01:36
✍️ 爱科研究院
👁 阅读 3,247
接手这个项目之前我先说清楚一件事agent-skills 不是某个开源框架的名字而是我们内部给一套“智能体技能体系”起的项目代号。做这套东西的起因很直接——当时我们已经有一堆带大模型能力的 Agent 在跑但每个 Agent 的“本事”都写在提示词里提示词越堆越长逻辑越来越糊换一个场景就要复制一大段 prompt改一处行为要通读全文出问题根本定位不到是哪句话导致的。后来我带着团队把每个 Agent 的能力按“技能”拆开独立定义、独立注册、独立测试再让模型按需组合调用这套体系就是 agent-skills。这篇内容不是讲概念是讲我们在真实项目里怎么把技能层落地包括踩过的坑、改过的设计、实测下来的失败模式和最终的调优手段。如果你也在给 Agent 做能力分层、想让智能体行为更可控这篇文章应该能帮你少走不少弯路。1. 为什么要给 Agent 单独建一套技能层先说一个反直觉的现象很多人以为 Agent 的能力上限取决于模型本身的智力但实际项目里卡住我们的不是模型不够聪明而是模型根本不知道“自己有什么本事、什么时候该用哪个本事”。你给模型一段很长的提示词它确实能照着做但提示词里的行为边界是模糊的模型经常在边缘情况自己发挥导致同一个功能在不同场景下表现不一致。agent-skills 的核心思路很简单把智能体的能力从“提示词里的描述”变成“外部注册的、可调用的、可验证的功能单元”。类比一下提示词方式像是在跟一个人口头交代“你帮我处理文件如果有图片就压缩如果有 PDF 就转文本注意别把文件名搞乱。” 技能方式则是给这个人一本操作手册每个操作有编号、有输入输出说明、有适用条件他接到任务后自己查手册选操作选完按手册执行。后者明显更容易保证稳定性和可排查性。1.1 技能和“工具调用”有什么区别可能有人会说这不就是 function calling 吗确实有关系但不完全一样。工具调用通常解决的是“模型需要访问外部 API”的问题重点在参数映射和结果返回技能体系解决的是“模型面对复杂任务时如何组织自己的能力”的问题。我之前维护过一个小助手它集成了天气查询、日历管理、邮件发送三个工具当时以为把工具注册好就完事了。结果用户说“帮我安排明天下午的会议顺便看看天气”模型一口气把三个工具都调了一遍然后输出了一段“明天下午有雨所以会议建议改到室内”的建议。功能上没问题但这里模型其实是把三个独立工具组合成了一个隐性的技能。问题是这个隐性的组合没法复用下一次用户换个说法模型又要重新组合一遍偶尔还会组合错。真正的技能应该是把“查询天气 判断会议场地适宜性 生成提醒”打包成一个技能叫“评估会议安排建议”模型只需要做一次决策这个请求是否匹配该技能。所以技能是比工具更高一层的抽象它面向任务目标而不是面向单一 API。1.2 技能、工具、工作流三者怎么分工在 agent-skills 的设计里我们把能力分成三层层级作用例子维护频率工具层执行具体的外部操作发送 HTTP 请求、读写文件、查询数据库低技能层组合工具和逻辑完成一类任务文档格式转换、日程冲突检测、代码审查中工作流层定义任务阶段的顺序与分支新用户引导流程、工单处理流水线高技能层的价值在于工具是原子的工作流是定制的而技能恰好介于两者之间它既不会细到每次改动都要重写又不会大到难以测试。我们当时重构的第一件事就是把原来提示词里的“行为段落”全部拿出来识别其中哪些是原子操作、哪些是固定组合、哪些是流程控制然后按这个三层模型重新安置。纯粹的操作下沉到工具层有确定输入输出和边界条件的能力块进入技能层需要多步骤、多状态的编排留在工作流层。2. 技能怎么分类从认知层级到应用场景很多团队抄 openai 的 plugin 或者 langchain 的工具就开始写技能结果写出来一堆“通用技能”比如“网络请求技能”“文本处理技能”最后模型根本不知道该选哪个。技能分类的粒度直接决定了 Agent 调用的准确率。我们实践下来按认知操作的类型来分最清晰而不是按业务领域分。2.1 按认知层级拆技能我把技能分成四类感知类技能负责理解输入、抽取信息。比如“意图识别”“命名实体抽取”“文档结构解析”。这类技能通常不改变外部状态只加工信息。推理类技能负责逻辑推断、决策建议。比如“冲突检测”“风险评分”“方案比较”。这类技能内部可能有规则也可能有大模型推理但输出是结论性的。行动类技能负责执行外部动作。比如“发送通知”“创建工单”“修改配置文件”。这类技能直接产生副作用必须严格校验参数并留审计日志。记忆类技能负责读写长期状态。比如“用户偏好记录”“项目状态查询”“历史决策回顾”。这类技能是 Agent 跨会话保持一致性的关键。这个分类的一个直接好处是定义技能时能清楚地知道它应该具备什么属性。感知类技能要声明输出格式行动类技能要声明权限级别和可逆性记忆类技能要声明保留策略。如果这些属性混在一个技能里后续做权限控制和安全审计会非常痛苦。2.2 技能粒度的判断标准粒度判断是我踩过最多坑的地方。最初我们追求“一个技能解决一类问题”把“文档处理”做成了一个巨型技能内部有十几个分支。结果模型每次调用它都要传一大堆参数还经常漏掉某些分支需要的参数成功率低得离谱。后面我们改成了“一个技能只承担一种认知操作 少量辅助动作”的粒度。判断标准就三个技能的职责描述是否能在一句话内说清如果说需要三句话还带转折那就说明粒度大了。技能的输入输出是否足够收敛如果输入参数超过 5 个说明它可能隐藏了多个操作。技能的失败方式是否可归类如果一个技能报错时你会想加十几个异常处理分支那就应该拆开。2.3 一个真实场景的技能清单以我们当时做的“会议纪要助手”为例最终拆出的技能如下技能名类型输入输出extract_actions感知会议转录文本行动项列表detect_conflicts推理行动项 日历冲突警告schedule_meeting行动参会人、时间窗会议邀请链接update_project_memory记忆项目编号、关键结论存储确认你看没有一个技能叫“处理会议”。每个技能职责单一模型在调用时只需要回答两个问题当前任务属于哪类认知操作哪个技能匹配当前上下文这两个问题都比“哪个技能能处理整个会议流程”好回答得多。3. 技能定义与注册让模型准确理解能力边界技能定义的质量决定了模型能不能正确调用。我们早期用很简短的描述比如“该技能用于提取行动项”结果模型经常误调。后来我们花了大量时间打磨技能的元数据和描述模板准确率大幅提升。3.1 技能元数据 schema 的最终形态以下是我们稳定运行了三个月以上的技能定义结构简化版name: extract_actions version: 1.2.0 description: | 从会议转录文本中提取明确的行动项。行动项必须包含负责人、截止时间和可验证的动作描述。 如果原文没有明确负责人或截止时间应标记为待确认而不要编造默认值。 input_schema: transcript: type: string description: 会议录音转录的纯文本保留说话人前缀 output_schema: action_items: type: array items: owner: string deadline: string action: string status: enum[pending, confirmed] trigger_examples: - 整理一下会上说的待办 - 有哪些需要我们跟进的事情 - 提取行动项 - 把讨论结论落到任务清单 non_trigger_examples: - 会议时间改到三点 # 这是日程调整不是行动项提取 - 写一份会议纪要摘要 # 这是摘要生成不是行动项提取 required_context: - 会议上下文对象 - 当前项目编号你可能已经发现我们加了两个关键字段trigger_examples和non_trigger_examples。这是提升调用准确率最重要的手段。因为大模型的语义匹配需要正例和反例共同约束只给正例会扩大边界把不属于这个技能的内容也匹配进来。3.2 描述里容易忽略的三个细节第一描述里要写清楚“什么情况下不该用这个技能”。我们最初的技能描述全是正向说明模型会倾向于过度使用。比如给 extract_actions 加了non_trigger_examples之后误调率从原来的 18% 降到了 4%。第二必须指定输出规范并且说明如何处理“不确定信息”。大模型最擅长编造你没告诉它原文没有负责人时怎么办它就给你编一个。明确写“应标记为待确认”之后输出质量显著提升。第三要声明技能依赖的上下文。有些技能不是凭空运行的它需要访问当前会话的某些状态。如果不声明依赖模型可能在没有上下文的场景下强行调用导致运行时错误一堆。3.3 注册中心与版本管理技能表多了之后必须有一个注册中心来统一管理。我们一开始把技能定义直接写死在代码里后来发现每次迭代技能都要重新发版代价太高。改成注册表模式后整个技能库变成了一个 Json 文件 目录结构技能可以独立发布、回滚、灰度。目录结构长这样skills/ extract_actions/ skill.yaml validator.py tests/ detect_conflicts/ skill.yaml validator.py tests/ schedule_meeting/ skill.yaml call.py tests/发布流程也简单修改 skill.yaml 和对应实现代码跑本目录测试通过后合并主分支注册中心扫描到新版本就自动更新能力列表。模型在每次会话开始时会拉一次最新技能清单所以技能更新后最多过一轮会话就会生效。这个目录结构有个好处技能自带测试。每个技能目录下都有tests/里面放的是一些“输入 - 期望输出”的样本。任何技能升级必须保证这些测试用例仍然通过。这解决了我们长期头疼的“改了 A 技能结果 B 场景行为变了”的问题。4. 技能编排与执行引擎调用流程背后那些容易翻车的细节技能定义好了接下来是运行时怎么调用。我们自研了一个非常轻量的执行引擎核心流程只有四步意图匹配、参数解析、执行、观察反馈。但每一步都有大量容易翻车的地方。4.1 意图匹配与参数解析的拆解意图匹配用到的不是单纯的字符串匹配而是让模型根据用户的输入从技能清单里选。这里有个细节我们不是把所有技能都丢给模型选而是先用一个简单的 embedding 相似度做候选召回只把 Top 5 技能的定义传给模型做精确匹配。这么做有两个原因一是技能数量多了以后全量技能描述塞给模型会占用大量上下文窗口而且会让模型注意力分散二是 Top 5 召回后用模型做筛选准确率高很多。实测中候选召回 模型精确筛选的组合调用准确率比直接全量匹配高出约 12 个百分点。参数解析是更麻烦的一步。模型从用户原话里提取参数时经常出现三种错误参数名称对不上技能 schema、时间日期格式不标准、缺参数时直接编造。针对这三个错误我们在执行引擎里加了“参数校验器”先按 schema 强校验类型再针对日期类字段做归一化最后一旦检测到必填参数缺失不自动补值而是向用户反问确认。4.2 超时、并发与副作用保护技能一旦开始执行运行时环境就得有兜底机制。我们的执行引擎对每一项技能都设置了默认超时感知和推理类 10 秒行动类 20 秒记忆类 5 秒。超时之后不是简单报错而是把半成品状态写进调试日志这样排查问题时能看到卡在哪一步。行动类技能必须经过双重确认。比如 schedule_meeting 真正发出会议邀请前引擎会要求模型输出一个“预执行摘要”里面包含执行目标、影响范围、涉及的对象、失败后果评估。只有预执行摘要通过了才会发起实际调用。这一步看起来多此一举但救过我很多次——模型在参数有误时依然会自信地继续双重确认能拦截掉至少三成误操作。另外行动类技能我们还做了“同技能并发限制”。同一个用户会话中同类型的行动技能不允许并发执行必须排队。原因很实际两个并发任务同时读写同一份配置文件时产生了严重的竞态问题。限制并发之后这类问题基本消失了。4.3 上下文传递与状态隔离每个技能的输入输出怎么传递到下一个技能我们的做法是每个技能运行结束后将输出写入一个“会话状态桶”下一个技能可以从状态桶里按 key 读取所需的上下文。状态桶按会话隔离保证同一技能同时被两个不同会话调用时互不干扰。这个设计带来的一个好处是技能的输入输出可以不显式声明全部依赖而是通过状态桶读取。比如 detect_conflicts 依赖 extract_actions 的输出它只需要在 skill.yaml 里声明required_context: [action_items]即可。运行时引擎会自动检查状态桶里是否有这个 key如果没有就自动暂停并请求前置技能执行。状态桶还承担了审计日志的功能。每次状态桶被写入会记录写入技能、写入时间、写入内容摘要。这样一旦出现“用户消息被错误转交”之类的问题能很快定位是哪一步把错误信息放进了状态桶。5. 实测中常见的失败模式技能系统真正跑起来后才看到的坑如果只看理想流程一切都很顺。但把 agent-skills 放到真实流量里跑我们很快就遇到了各种各样的失败模式。这一节挑四个最典型的讲每个都附上我们最终的修复方案。5.1 技能选择错误相关性幻觉模型最容易犯的错误不是选错技能而是在几个高度相似的技能之间选了最不应该选的那个。比如 extract_actions 和 summarize_minutes两者都处理会议转录但一个是提取行动项一个是生成摘要。我们在测试阶段就发现模型在用户说“帮我看看会上说了什么”时经常跳到 extract_actions而实际上用户只是想要摘要。修复方案有两个层面。第一层是增强non_trigger_examples把这种容易混淆的输入明确标注出来。第二层是在技能描述里加一句“如果用户只需要了解会议内容而非跟进事项应该使用 summarize_minutes”。这两个措施叠加后这类混淆错误基本清零。经验就是技能定义的维护不是写一次就完了每一次发现误调都要回去更新技能描述里的正反例。5.2 技能循环调用模型在死胡同里打转另一个严重问题是循环调用。模型在完成一个任务后会检查状态桶里的数据发现还需要补充信息于是再次调用同一个技能。理论上这是正常的链式推理但偶尔模型会陷入“补信息 - 检查 - 还是缺 - 再补”的循环导致 API 费用飙升。我们在执行引擎里加了一个“技能调用次数上限”的护栏单个会话内同一技能最多连续执行三次。超过三次后引擎会打断循环把当前的中间状态返回给用户说明“这个任务需要更多外部输入”。这个护栏的另一个作用是迫使我们在技能设计时考虑更完整的参数收集不能依赖运行时反复修正。5.3 参数幻觉模型篡改用户输入参数幻觉是最隐蔽的坑。当技能要求的必填参数缺失时模型有时候不会向用户确认而是直接从历史上下文里“推测”出一个值填进去。我们遇到过最离谱的一次用户说“明天下午三点开会”说这句话的时候根本没提到会议室模型调用 schedule_meeting 时擅自填了“默认会议室”结果会议被安排到了错误的房间。针对参数幻觉我们的解决方案是“缺失必填参数禁止执行”并且强制模型输出“缺失参数说明”。如果模型无法从用户原话中提取到某个必填参数它必须在输出中明确列出缺什么。这个约束写进了 system prompt也在引擎层做了拦截。从工程上看宁可多问用户一步也不要让模型替用户做决定。5.4 错误反馈被模型忽略技能执行失败后会返回错误信息给模型让模型调整策略。但实测发现模型经常无视错误信息用同样的参数重试同一个技能直到超时。比如 schedule_meeting 返回“会议室时间冲突”模型居然带着同样的参数又试了一遍当然再次冲突。修复这个问题的关键是在错误信息里加上“建议调整方式”。也就是说执行器返回错误时不只是简单说“失败”而是给出结构化的错误码和可操作建议。调度冲突时建议会列出附近的空闲会议室权限不足时建议会指出缺少哪个权限项。把错误信息变成可供模型推理的结构化数据之后重试逻辑明显聪明了很多。6. 评估与迭代怎么证明技能变好了而不是变糟了最后说评估。技能体系做得好不好不能凭感觉得有一组可反复跑的测试集。6.1 小规模评估集的设计方法我们维护了一套“技能调用评估集”大概有几百条样本每条样本是一个用户输入 期望调用的技能 期望参数。跑评估的时候把样本喂给引擎比对实际调用结果和期望结果。评估集分三个维度意图匹配准确率、参数提取完整率、执行成功率。三个指标分开看否则无法定位问题。如果意图匹配准确率低优先改技能描述和正反例如果参数提取完整率低优先改输入 schema 的字段说明如果执行成功率低优先排查技能实现代码。每次技能定义做修改都先跑这个评估集把三个指标的变化记下来。我们有一个简单的表格记录版本变化版本意图匹配准确率参数提取完整率执行成功率备注v1.0.082%76%88%初始版本v1.1.086%81%89%增加反例v1.2.088%84%92%拆分粒度如果某个指标下降了要么回滚要么针对性修改不会盲目继续叠功能。6.2 失败用例进评估集的机制线上跑的过程中每个失败的调用都会被记录下来。每周我们抽一批失败样本人工看一遍把其中有共性的失败案例补充进评估集。这样评估集不是静止的而是跟着线上问题一起迭代。这个机制启动后技能系统的稳定性提升非常明显。原因也好理解大部分失败的根因都可以归结为“输入没在评估集里出现过”。把新输入纳入评估集后技能描述和执行逻辑的修改方向就有据可循了。6.3 技能的热度统计与淘汰最后我们给每个技能加了调用次数统计。运行一段时间后发现有些技能几乎天天被调用有些技能一个月都未被触发一次。未触发的技能不一定没用但大概率是场景没覆盖到或者描述有问题。我们会对长时间未命中的技能做一次 review查一下是技能定义不清晰导致模型选不到还是本身已经过时没有存在必要。该合并的合并该下线的地下线技能库保持精简是很重要的事情太臃肿的技能清单会让模型的注意力分配和召回准确率同时恶化。agent-skills 这套体系跑了几个月之后我最深的体会是技能系统的复杂度不在工程代码而在对“智能体能力边界”的理解。你定义的不是函数而是模型做决策时的参考系。参考系越清晰、越收敛模型的行为就越稳定。现在每次新接一个 Agent 需求我会先问一句它的能力能不能拆成一个树状结构每个叶子技能都能独立测试、独立迭代如果能那它值得用 agent-skills 这套思路来做如果不能那大概率只是又一段提示词上的自嗨。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/8 11:01:36
Unity运行时模型导入与位姿持久化实战
2026/10/8 11:01:35
ezCAD2二次开发C#脚手架:COM封装与自动化制图实践
2026/10/8 10:56:33
Prisma3D是什么?解析非标3D生成工具的技术定位与实践边界
2026/10/8 12:57:11
Java机器学习分布式系统故障诊断:从特征工程到模型训练的完整实现
2026/10/8 12:57:11
FufuLauncher账号管理:扫码、密码、短信3种登录方式与多账号快速切换完全指南
2026/10/8 12:57:10
rtklib_java项目新增模块:rtklib-research与rtklib-stream功能详解
2026/10/8 12:57:10
eFuse+MCU:嵌入式电源硬保护与策略管理设计实战
2026/10/8 12:57:10
电子保险丝与STM32G474的电源路径保护设计实战
2026/10/8 12:52:08
AWS本地化Jev决策模型:TypeSafe与Strands Decider实战
2026/10/8 0:04:11
Agent Skills 完全指南:原理、写法、安装与实战避坑
2026/10/8 0:04:11
Agent Skills 实战:从 Genkit 定义到 GKE 部署与排查
2026/10/8 0:04:11
Agent Skills 实战:从设计到调试的完整指南
2026/10/8 5:02:14
Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化
2026/10/7 9:55:49
多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系
2026/10/7 14:02:03
hindsight:面向LLM应用的事后可观测性工程实践
2026/10/8 4:30:43
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/8 2:46:15
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/8 4:32:33
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)