资讯动态

想清楚这几点,才能让LLM智能体从“会聊天”到“会干活”

发布时间:2026/10/8 21:21:47 来源:尧图企业网站定制
1. 从会聊天到会干活Agent Skills 解决的到底是什么过去大半年我一直在折腾基于大模型做自主智能体AI Agent的工程化落地。从最初模型加提示词的玩具玩法到后来必须面对真实业务里的任务拆分、工具编排、失败恢复我越来越确认一个判断Agent 能不能真正干活瓶颈往往不在模型智商而在技能Skills怎么设计、怎么组织。agent-skills 这个概念说的就是让智能体从能聊走向能干的那条关键路径。先说个直观对比。纯对话场景里模型只需要理解用户意图并生成文字但要让它执行任务比如帮我把这批订单数据按区域汇总再生成一份周报发给负责人模型自己做不到——它没有访问数据的权限没有操作表格的能力也不知道发周报这个动作对应哪个系统。这时候你就需要把数据汇总、生成周报、发送消息这些能力封装成一个个可被模型调用的技能模块。每个技能模块承载一段具体能力模型在推理过程中根据需要挑选并调用它们整个 Agent 才能完成闭环。Skill 和常说的 Tool/Plugin 有区别这点值得深究。早期 Agent 框架里的 Tool 一般指一个单一函数比如搜索网页、执行代码输入输出都很简单。但真实业务里一个完整任务往往需要多步操作查询数据库、清洗数据、调用另一个 API、按模板输出结果。把这些步骤硬拆成多个 Tool 让模型自己拼接极易出错模型经常记不住步骤顺序、漏掉中间环节。Skill 更像一个打包好的工作流单元包含了目标定义、输入契约、执行逻辑、校验规则和失败处理。对模型来说一次调用完成一件事容错率明显提高。我的理解是Agent Skills 的本质是把模型决策和具体执行解耦。模型只负责判断现在该用哪个技能、参数怎么填技能内部的事情由代码保证。这就像你请了个实习生你自己负责安排任务和验收结果至于他具体怎么操作只要在既定流程内完成就行。这个抽象层次一旦搭对了Agent 的稳定性会有质的提升。适合读这篇文章的人我大致分三类一是正在用 LangChain、CrewAI 等框架做 Agent 原型但总觉得能跑通但不可靠的开发者二是想在业务系统里接入智能体能力却不清楚技能边界怎么划的架构师三是纯粹好奇模型怎么能操作外部系统的技术爱好者。下面我说的都是自己实测过的方案和踩过的坑不一定是最优解但肯定能帮你少走几周弯路。2. Skill 的解剖学一条技能从声明到执行要过哪几关一个合格的 Skill在设计层面至少要拆成五层元信息层、参数契约层、执行器层、校验层、权限层。很多人只写了执行器其他几层全省略结果技能在 demo 里好用一上真实场景就各种翻车。2.1 元信息层模型靠这一段文字认识你的技能元信息是模型决策的依据通常包括技能名称和描述。别小看这段描述它直接决定模型在什么场景下会选你这个技能。描述写得含糊模型就可能该用的时候不用、不该用的时候乱用。我见过最典型的反例有人写了一个query_orders技能描述是查询订单。结果模型在处理统计本月销售额时宁可用一个名为analyze_data的通用技能瞎猜也不愿意调query_orders因为查询订单听上去只是拉列表跟算销售额没关系。后来把描述改成根据指定时间范围、区域、客户等条件从订单数据库查询原始订单记录返回结构化字段列表供后续统计或报表分析使用路由准确率一下子从六成不到提到了九成以上。2.2 参数契约层给模型一个填空题而不是论述题参数契约就是技能接收的输入结构用 JSON Schema 描述即可。核心原则是能枚举的字段就枚举能设默认值就设默认值不要把开放式的自然语言留给模型自由发挥。比如一个发送通知的技能参数应该明确channel字段只能是email、sms、webhook三种值而不是让模型传任意字符串。模型不是不聪明而是你一旦给了它自由它就会发挥想象力传一个wechat出来。参数裸奔的技能轻则报错重则出现安全风险。2.3 执行器层技能的核心逻辑保持纯粹执行器是技能真正干活的代码。我的建议是执行器内部只做与该技能职责相关的事情不要掺入模型推理逻辑、不要掺入业务规则之外的附加操作。一个技能只做一件事做好做彻底。举个实际的例子。我写过一个generate_weekly_report技能最初版本里既包含数据聚合逻辑又顺便把汇总结果写进了数据库还在最后给管理员发了封邮件。结果一次数据源抖动整个流程在聚合阶段就失败了但因为邮件发送在最后一步导致用户收到一封周报生成成功的邮件但实际周报根本没生成。这就是技能职责不纯粹带来的连锁事故。后来我把发邮件拆成独立技能由上层编排按需调用。2.4 校验层执行前和执行后都要过一道安检执行前校验输入参数的范围、格式、必填项执行后校验输出结果是否符合预期。输出校验常被忽略但这恰恰是 Agent 可靠性的分水岭。比如一个fetch_webpage_content技能返回结果可能是正常的正文也可能是 404 页面、验证码页面、空页面。你必须在技能内部做一层是不是有效内容的判断而不是把任何字符串都当作成功结果返回给模型。模型看到乱七八糟的内容会基于垃圾信息继续推理错误会一路放大。2.5 权限层技能能力的边界必须有硬约束每个技能都应该声明自己需要的最小权限。技术上建议在技能层做两件事一是对操作对象做白名单限制比如只允许访问指定目录、指定 API 域名二是对高风险操作加入人工确认点。我团队里有个血的教训一个execute_shell_command技能完全裸奔Agent 在一次任务中执行了一条rm -rf命令删掉了测试环境的临时目录虽然没造成生产事故但所有人都吓出一身冷汗。从那以后我们的所有技能都强制过权限层高危操作必须二次确认。技能能力边界画清楚Agent 才能放心地交到用户手上。3. 路由决策的真相LLM 到底是怎么选中你的技能的很多做 Agent 的人都有一个误区以为给 Agent 塞的技能越多越好。实测下来恰恰相反技能库膨胀到一定规模后模型的选型准确率会明显下滑。理解模型的选技能机制是设计技能库的前提。3.1 模型选技能的底层逻辑描述匹配加上下文联想目前主流 Agent 框架里模型选技能基本靠两看一看技能描述与当前任务的语义相似度二看技能参数与用户请求里信息的匹配度。这个过程很像你在搜索引擎里输入关键词系统选出最相关的几条结果。所以技能描述的写作质量直接决定它能不能被搜中。一个很实用的写法是场景描述式写法不用干巴巴说这个技能是什么而是说这个技能解决什么问题、适合在什么情况下用。比如描述一个translate_text技能与其写翻译文本不如写将用户提供的中文、英文或其他语言文本翻译成指定目标语言适用于跨语言交流、文档翻译、内容本地化等场景。描述里出现越多与真实使用场景重叠的词汇模型选中的概率越高。3.2 技能数量陷阱为什么库越大越不聪明我做过一个对比实验同一套任务集分别用 5 个技能、15 个技能、40 个技能的配置跑。结果令人意外15 个技能时任务成功率最高约 88%5 个技能时因为能力不足成功率为 72%40 个技能时反而掉到 76%。技能越多模型在选哪个这一步消耗的上下文越多选错的可能性也越大而且多个相似技能之间会产生干扰。这里有个实操建议每新增一个技能先问自己三个问题——这个技能和已有技能的功能边界是否清晰有没有可能是某个已有技能的参数变体用户需求里出现这个技能对应场景的频率真的高吗如果三个问题都答得不干脆就先别加用在已有技能里加参数来替代。3.3 路由测试不要等上线了才发现选错路由准确性是可以前置测试的。我的做法是建一个路由测试集准备 50 到 100 条真实用户请求每条请求标注期望选中技能和参数期望值跑一遍 Agent 调用链统计选型准确率。这个测试集应该持续积累——每次线上遇到路由选错的情况就把对应请求加入测试集并修正描述形成回归测试。实测下来路由准确率在 90% 以上才适合上生产环境。低于这个线问题大多数出在描述语焉不详少数出在技能边界重叠。先处理描述再考虑合并技能一般都能提上来。这一步看起来占用时间实则是 Agent 上线投产前性价比最高的投入。4. 手写一个 Skill 的完整过程从需求到能跑通理论知识说了一堆下面用一个实际例子走一遍完整流程。我选一个比较有代表性的技能summarize_document作用是读取文档内容并生成结构化摘要。这个技能覆盖了解析、调用模型、输出校验三个典型环节适合当模板参考。4.1 需求拆解先写清楚这个技能不做什么动手写代码前先把这个技能的边界钉死。summarize_document的需求可以拆成这样输入文档路径、摘要长度短/中/长、摘要语言做什么读取文档、清洗文本、调用 LLM 生成摘要、输出结构化结果不做什么不做文档翻译、不保存摘要结果除非上层另行要求、不处理加密文档失败处理文档不存在返回明确错误文档为空返回提示LLM 调用超时重试一次边界写清楚的最大好处是后续写summarize_document的人不会顺手把翻译功能也塞进来。技能职责混乱九成是从顺手加个功能开始的。4.2 技能清单与执行器代码层面的最小实现技能清单用 YAML 声明结构如下name: summarize_document description: 读取本地指定路径的文档内容支持 txt/md/pdf 按用户指定长度生成结构化中文摘要 适用于文档速读、报告提炼、会议纪要整理等场景。 parameters: type: object properties: doc_path: type: string description: 文档的本地绝对路径 length: type: string enum: [short, medium, long] default: medium language: type: string enum: [zh, en] default: zh required: [doc_path] returns: type: object properties: summary: type: string description: 生成的摘要文本 word_count: type: integer description: 摘要字数执行器部分我用 Python 写def run(ctx, doc_path, lengthmedium, languagezh): # 1. 校验参数 if not path_exists(doc_path): return {success: False, error: document_not_found} # 2. 读取并清洗文本 text read_document(doc_path) if len(text.strip()) 20: return {success: False, error: document_empty} text clean_whitespace(text) # 3. 调用 LLM 生成摘要 max_len_map {short: 100, medium: 300, long: 600} try: summary llm_summarize(text, max_lenmax_len_map[length], langlanguage) except TimeoutError: summary llm_summarize_retry(text, max_lenmax_len_map[length], langlanguage) # 4. 输出校验摘要不能为空且有实际内容 if not summary or len(summary) 10: return {success: False, error: summary_generation_failed} return {success: True, result: {summary: summary, word_count: len(summary)}}注意第三步的重试逻辑只对超时这种可重试错误做重试对模型返回内容不合规这种确定性错误不做无谓重试直接走失败分支。很多人把所有异常都包一层重试结果模型每次都返回同样错误白白浪费时间和 token这个习惯要改。4.3 真实场景验证拿脏数据试别拿干净数据试技能写完第一轮测试你会发现一切正常因为你用的是精心准备的 PDF 和文档。第二轮请务必拿真实世界里的脏数据试扫描版 PDF没有文本层、加密文档、超大文件、只有图片的 Markdown、编码混乱的 txt。每个都能单独写一个处理分支。我遇到最多的情况是 PDF 解析出来的文本里夹杂大量换行和特殊字符直接把文本塞给模型摘要质量很差。后来我在清洗环节加上了一个简易的段落合并规则连续换行超过两个的视为段落分隔符单个换行且前后都是中文的视为同一段落。清洗后摘要效果提升明显。这类处理细节不会写进框架文档但 Skills 稳定性的差距就是这么一点点抠出来的。5. 线上踩坑实录Skill 最容易翻车的五个场景前面讲的是设计方法这一节专门说坑。以下五个问题是我在多个项目和客户现场真实遇到过的按出现频率从高到低排列。5.1 描述歧义导致路由错乱这是频率最高的问题。表现是同一个用户请求这次选中技能 A下次选中技能 B结果完全不一样。比如技能库里同时有analyze_sentiment和extract_keywords两个技能描述都包含分析文本这个短语。用户在请求里说帮我看看这段评论的态度模型一会儿选这个一会儿选那个。解决办法就是前面说的描述里尽量写场景话术把技能适用场景的典型表达写进去减少模糊匹配的空间。如果两个技能的描述都改过之后还是容易混淆就说明这两个技能的边界本身就不清晰考虑合并成一个技能用参数区分。5.2 参数幻觉模型编出根本不存在的参数LLM 存在幻觉不仅体现在回答内容上也体现在填参数上。用户说帮我查一下上周的数据模型可能把日期参数填成上周一的日期但你的系统里上周的定义是自然周还是滚动 7 天模型不知道于是它按自己的理解填。解决这个问题的思路不是试图让模型更聪明而是在参数契约层把不确定性消掉能定义枚举就定义枚举能用相对时间描述就用相对时间描述不行就在参数说明里给出明确示例。我们有一个query_analytics技能参数里有个date_range字段说明里直接写着支持格式today、yesterday、last_7_days、last_30_days、this_month、YYYY-MM-DD 到 YYYY-MM-DD模型填参数准确率立刻上了一个台阶。给模型越明确的选项模型就越少自由发挥。5.3 非幂等操作遇上重试机制Agent 框架普遍内置重试逻辑技能调用失败就重试一次。对幂等操作查询、读取、生成没问题但对非幂等操作创建订单、发送邮件、扣减库存就是灾难。我亲眼见过一个场景Agent 调用创建工单技能超时框架自动重试一次结果同一个工单创建了两遍。如果你在使用某个框架务必检查它的重试策略是否对所有技能生效然后在技能清单里对非幂等技能显式声明retryable: false。如果你的框架不支持这个字段就在技能描述里写清楚该操作不可重复执行如果超时请先查询确认操作结果再决定是否重试。有些坑是框架自带的你不主动绕它迟早让你交学费。5.4 上下文污染上一个技能的输出干扰下一个技能的决策Agent 长期运行多个技能后对话上下文里会堆积大量中间结果。模型在做下一次技能选择时会受这些历史输出影响。最经典的场景用户先让 Agent 查了某公司的财报数据然后说帮我也查一下对比公司的数据。模型可能因为上下文里已经有一堆某公司数据就把对比公司误识别为同一家公司。缓解手段包括技能之间传递结果时只传必要字段不要全量 dump每轮任务完成后对上下文做压缩或截断保留用户原始意图和下轮所需的最小信息对敏感场景干脆给 Agent 限定每轮任务独立执行不参考上一轮输出。上下文污染没有一个一劳永逸的解法但能做到及时清理就能规避大部分问题。5.5 技能状态共享和竞态冲突多线程或并发场景下使用技能如果技能内部依赖共享状态比如模块级变量、临时文件、数据库全局表会出现竞态问题。我遇到过一个诡异 bug两个用户同时触发同一个技能A 用户拿到的结果里混着 B 用户的数据。排查下来发现是技能内部用了一个模块级缓存字典没有加锁。教训是技能执行器应该遵循无状态设计所有状态显式存放于上下文中或由外部存储管理。如果业务上必须有缓存也要做好隔离按用户维度或任务维度分 key。这不仅是技术洁癖而是一旦 Agent 被多用户使用就会暴露的问题。6. 让 Skill 真正可维护测试、版本与灰度的一点体会技能写出来只是开始真正考验功夫的是后续迭代维护。这一节分享我在技能测试、版本管理和灰度发布上的实操做法。6.1 给每个 Skill 配一套夹具测试前文提到路由测试集这里再说技能功能测试。每个技能都应该有一套固定的输入输出样例类似单元测试里的 fixture。执行器改代码之前先跑一遍 fixture 确保没回归改完之后再跑一遍确认修复生效。我的 fixture 分三类正常输入验证主流程、边界输入空值、超长值、非法值、异常输入文件不存在、服务超时、无权限。每类准备 3 到 5 个样例就够。实测下来这个做法的价值不在能发现多少 bug而在改代码时敢不敢下手。没有 fixture 保护的技能每次改动都像走钢丝。6.2 技能也要版本化描述变化更要慎重技能版本管理有两个层面执行器代码层面的版本控制用 Git 就行以及技能清单本身的语义化版本。特别要提醒的是描述字段的改动对线上行为影响极大因为它直接改变模型的路由选择。我把改描述视为高优先级变更必须走 review 流程不能像改普通注释那样随意。有一次我改了某个技能描述只是加了一句也支持处理 CSV 格式结果第二天线上监控显示这个技能的调用量暴涨了三倍因为模型开始把各种文件处理请求都路由到它头上。描述就是技能的门面你想清楚再改。6.3 小流量灰度用数据说话再全量Agent 技能更新强烈建议做小流量灰度。在真实业务里你把旧技能替换成新技能之前先让 5% 到 10% 的流量跑新的对比成功率、耗时、token 消耗这三类核心指标。等新技能连续稳定运行一段时间后再逐步扩到全量。这一节想强调的是技能不是写出来就完事的静态资产它需要持续观察、迭代和淘汰。我每次迭代一个技能都会把这次的改动原因和效果记录在技能的 README 里三个月之后再回看你会很清楚每个决定是怎么来的。最后说点实在话如果只留一条经验给你我想说Agent 的能力上限不是模型决定的而是你技能库的质量决定的。模型是那个想做事的实习生Skill 是你给实习生准备好的工具和流程。工具顺不顺手、流程清不清晰决定了他能不能办好差事。我在实际迭代中还有一个习惯每个季度把技能库整体清点一遍删掉低调用量的技能合并边界模糊的技能重写描述含糊的技能。这个动作像给仓库做大扫除每次做完后续新技能的定位都会更清晰路由准确率也会跟着提升。关于是否有必要换更复杂的 Agent 框架我的态度是先把手上的技能打磨扎实再考虑框架升级。框架只是壳技能才是核。希望这篇文章能帮你把技能设计这份功夫练扎实少踩几个我踩过的坑。

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

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

免费获取报价 →
↑