
1. 找准Agent落地失败的病根技能是“能力”不是“功能”很多团队做Agent的第一版路径高度一致把大模型接上然后一股脑地把公司内部所有API都注册成工具再写一个循环让模型去调。Demo阶段效果惊艳模型看起来很聪明什么都能做。但一上生产就露馅任务稍微复杂一点就原地打转工具调用错乱明明该调A接口却去调了B接口最离谱的是模型会在同一个失败操作上反复重试六七次像极了卡在死循环里的人。我做过十几个Agent项目之后才意识到问题几乎都出在同一个地方——大家把“功能”当成了“技能”。功能是一个接口、一个能力点能完成一个孤立操作技能是一整套完整的、可被模型理解和复用的任务解决模式。一个技能背后至少有四样东西触发条件、输入输出契约、内部执行逻辑、异常恢复策略。绝大多数团队只做了第一样剩下三样全靠模型现场发挥那翻车就是必然的。拿“查询订单物流”这个场景举例。你给Agent注册一个query_logistics(order_id)工具它确实能查到物流信息但这只能算功能。真正的技能应该包含什么时候该调这个接口用户问“我的货到哪了”、订单号缺了怎么办主动追问还是从上下文里提取、查不到时的分级应对超时重试、换承运商渠道、转人工、结果怎么组织成用户能看懂的话术——把这些全部打包成一个完整方案才是技能。这个认知决定了整个Agent架构的走向。技能不应该是一个个孤立的函数而应该是一层独立于模型、独立于具体任务的知识层。模型负责理解意图和决策技能库负责提供“怎么做”的完整路径两者解耦之后Agent的行为才变得可控、可测、可迭代。这也是为什么自从想通这点我把项目里所有“工具注册表”全部推翻重写成“技能库”Agent的稳定性和可维护性直接上了一个台阶。2. 技能定义一份能被模型“读懂”的说明书比代码本身更重要2.1 技能描述的信息完整度决定模型的调用准确率技能定义的第一个核心问题模型怎么知道在什么时候用哪个技能很多人以为技能描述写得详细一点就行实操下来发现远远不够。一个结构完整、值得长期维护的技能定义至少应该包含以下六个字段字段作用示例name技能唯一标识命名要见名知意order_logistics_querydescription一段话说明这个技能是干什么的、什么时候用、什么时候不用用于查询电商订单的物流轨迹。当用户询问包裹位置、配送进度、预计到达时间时使用。不适用于售前咨询或退换货流程。trigger_conditions明确的触发条件列表包括正向和负向条件触发用户提到订单号/物流/快递/配送不触发用户只想了解运费规则input_schema结构化输入参数定义包括类型、必填性、来源说明order_id: string, requireduser_id: string, optional用于校验订单归属output_format输出结果的结构和字段status, current_location, estimated_arrival, history[]error_handling预期错误类型和对应的恢复策略订单不存在返回提示并询问新订单号接口超时最多重试2次失败后提示稍后再试这六个字段里最容易被忽视也最致命的是description和trigger_conditions。很多人的description写得模棱两可“查询物流信息”——太泛了模型根本判断不清楚边界。我习惯在description里写两到三个具体的使用场景示例甚至直接列出“什么时候绝对不要用”这对模型来说比抽象概括有用得多。2.2 YAML还是JSON技能声明的工程选型有了结构定义之后落地时第一个要做的决定就是技术格式。我试过纯代码注册、JSON Schema、还有一个用YAML维护的版本最终稳定下来的是“YAML写技能头信息 Python写执行逻辑”的组合。纯代码注册的问题是信息隐藏在代码里模型看不到完整语义——你不可能让模型去读你的源码。JSON Schema适合工具校验但作为技能描述给模型看嵌套层级太深可读性很差。YAML的优势是自然、层次清晰写出来的技能声明接近一份“给模型看的文档”肉眼也好审查。一个典型技能定义长这样name: order_logistics_query description: - 查询订单物流轨迹。当用户询问包裹到哪了物流什么状态什么时候能送到 时使用。如果用户只是想了解退款流程不要使用本技能。 version: 1.2.0 model_hint: gpt-4o-mini trigger_conditions: positive: - 用户提供或上下文包含有效订单号 - 用户表达查询物流/配送/快递状态的意图 negative: - 用户询问商品规格或库存 - 用户表达售后退款意愿 input_schema: order_id: type: string required: true description: 订单号优先从用户消息中提取缺失时主动追问 user_id: type: string required: false description: 用户标识用于订单归属校验可通过登录态获取 output_format: type: object fields: status: 物流状态枚举pending/shipped/delivered/failed current_location: 当前节点描述 estimated_arrival: 预计送达时间 history: 物流轨迹列表 error_handling: order_not_found: action: 询问用户核对订单号最多追问两次后转人工 api_timeout: retry: 2 fallback: 告知用户系统繁忙建议稍后重试 rate_limited: fallback: 稍等10秒自动重试一次仍失败则转为人工客服这种写法有两大好处第一模型在决策时读到的是一份意图明确、边界清晰的任务说明书而不是一个冷冰冰的函数签名第二运营和产品同学也能看懂这份声明可以直接参与技能行为的调整不需要每次都找开发改代码。2.3 版本管理和灰度发布技能也是要迭代的产品技能定义一旦进入维护阶段就不能再当静态配置来管理了。我踩过最深的坑就是直接改线上技能描述——改完效果没有立刻变好反而原来跑得好好的场景突然不触发这个技能了。后来查原因是描述里加了太多负向条件把模型给“吓退”了。现在我的做法是给每个技能加version字段并保留历史版本配合一套简单的灰度机制同一技能维护2到3个线上版本流量按比例分配比如v1.2占70%、v1.3占30%评估指标用准确触发率和用户任务完成率不看单个对话的直观感受新版效果确认后把旧版本下线同时把新版本的变更点追加到技能变更日志里方便回溯。一套技能库里可能有大几十个技能如果全都用这种灰度流程工程量不小。实际执行下来只有高频率、影响面大的核心技能需要这么精细低频长尾技能我通常只维护一个版本改了直接上出问题再回滚。分级的版本策略比一刀切高效得多。3. 工作流编排别把技能库写成死工具的堆砌3.1 原子技能与复合技能的层级划分技能列表攒到二三十个之后想靠模型自由发挥完成复杂任务就变得非常不可控。以“帮用户处理售后问题”为例——这里面包含了查询订单、判断售后政策、生成退货单、通知仓库、给用户反馈整整五个环节每一步涉及不同的技能。如果让模型在每一步都自己决策相当于让它做五次选择出错的概率是乘法叠加的。这时候就需要引入复合技能的概念。复合技能不新增业务能力而是把多个原子技能按固定流程串起来把“过程”封装成“结果”。模型面对售后请求时只需要触达最顶层的高阶技能内部怎么调用子技能、按什么顺序执行由编排层控制不让模型做多余决策。我习惯把技能分成三层层级定位示例原子技能不可再拆的基本操作对应单一工具或API查订单、创建退货单、查询库存复合技能按固定工作流编排多个原子技能完成一个明确的任务售后处理查订单→校验政策→创建退货单→通知仓库策略技能在多个可选路径中做路由决策处理高度不确定的任务售前咨询根据商品类型、用户意图决定走推荐、比价还是库存查询路径这个分层带来的最大收益是把模型的高频决策次数降到了最低。只有在策略层或者遇到边界情况时模型才需要“动脑子”其他环节全走确定性流程。确定性流程越多Agent的行为就越可预测出问题的排查范围也越小。3.2 顺序、分支、并行三种基础控制流的定义方式复合技能的工作流编排本质上就是定义三种控制流。我在这块走过弯路——第一版试图用通用工作流引擎结果配置复杂到业务方根本不愿意改。后来想明白了Agent场景下绝大多数流程只需要三种能力不需要把CICD那套都搬进来。顺序执行上一个技能成功输出后结果作为下一个技能的输入再执行下一个。售后流程里“先查订单、再判断政策、再创建退货单”就是典型的顺序依赖。条件分支根据某个技能的输出或当前上下文状态决定走哪条路径。例如“如果订单已发货走退货流程如果还没发货直接取消订单退款”。并行执行多个独立技能同时执行再汇聚结果。比如复盘一个客户的综合服务记录时可以并行调“订单历史”“工单记录”“沟通纪要”三个技能最后统一汇总。我用了一套很轻量的声明式配置来描述流程核心结构是steps数组加next跳转逻辑。比完整工作流引擎简单得多也足够支撑绝大多数Agent编排场景workflow { name: aftersale_process, steps: [ {skill: order_query, output: order_info}, {skill: return_policy_check, input: order_info, output: policy_result}, { branch: [ {if: policy_result.is_cancellable and order_info.status unshipped, next: order_cancel}, {if: policy_result.is_returnable and order_info.status shipped, next: return_order_create}, {default: human_service_transfer} ] }, {skill: order_cancel, next: notify_warehouse}, {skill: return_order_create, next: notify_warehouse}, {skill: notify_warehouse, next: final_reply} ] }3.3 复合技能的异常处理设计每个分支都要有兜底编排复合技能时最容易忽略的是异常传播问题。原子技能执行失败如果整个流程直接终止用户体感就是“机器人突然不说话了”更隐蔽的是某个技能返回了部分数据后续步骤拿着残缺数据继续往下跑产出一个完全错误的结果。我现在给每个复合技能定了几条硬规则不允许存在无兜底的流程路径。每条分支后面必须跟着一个default动作哪怕默认动作是“转人工”也不能让流程走到死胡同。关键步骤失败时采用“缓存降级”——用一个预设的兜底回复模板响应用户而不是把内部报错原样抛给用户。流程一旦发生回退需要在日志里记录回退原因和回退前的执行状态这一步对事后定位非常有帮助。经验定义一个复合技能前先花十分钟把所有可能走不通的路径列一遍画一张“失败路径表”再开始写代码。这张表在日常维护时远比流程主路径重要。4. 记忆、上下文与技能触发的协作关系4.1 任务记忆与长期记忆技能触发的决策依据技能的触发有一个前提模型需要足够多的上下文来判断该不该用这个技能。上下文从哪来来自两层记忆系统——任务记忆和长期记忆。任务记忆指的是当前对话过程中产生的信息例如用户刚说的订单号、上一步技能返回的查询结果。它的特点是动态、短命只在当前任务处理期间有效。任务记忆放在对话级上下文里通过摘要压缩和滑动窗口来控制token消耗。长期记忆则是跨会话的用户画像、历史行为偏好。比如用户过去三个月频繁退货有恶意退货的嫌疑那“售后退货”技能触发后就应该走更严格的审核分支。这类信息的来源通常是结构化存储数据库或向量库在会话开始时按需加载注入到系统提示词里。这两层记忆的分界直接影响技能触发的准确性。我初期踩过的一个典型错误是把用户的历史偏好一股脑全灌进上下文导致模型被大量无关信息干扰该触发“售后”技能时反而被“用户喜欢深夜下单”这种无关信息带偏。后来规定得很死只有当前技能声明了需要的记忆字段才允许注入对应的记忆数据。技能和记忆之间必须有一份显式的依赖声明否则不加载。4.2 技能触发判定路由模型还是语义检索还是指令匹配技能触发策略的选型决定了Agent在大规模技能库下还能不能保持稳定。技能数量超过20个之后我实测过几种方案结论非常明确单一模型自由决策function calling或tool use技能少时表现很好技能多了之后模型经常混淆两个相似技能的功能边界。比如“订单修改”和“订单取消”这种邻近意图模型的误触率会明显上升。基于用户意图的路由分类先让模型输出一段用户意图标签如“售后咨询”“物流查询”“商品推荐”再用这个标签过滤技能候选集。能把误触率降低不少但意图标签体系需要持续维护。语义向量检索预筛把每个技能的description用embedding向量化存储用户消息来时先做相似度检索找出Top5候选再交给模型精确决策。这种两阶段方案在高技能量级下最稳。我现在线上跑的就是“语义检索预筛模型最终决策”的双阶段触发。第一阶段把上百个技能收缩到五六个候选第二阶段把这几个候选的完整描述交给模型做最后选择。每轮多消耗的那几十毫秒和几次向量计算换来的是大幅度下降的误触率很值得。def select_skill(user_message, user_profile, available_skills): # 阶段一向量检索召回Top-K候选 query_vec embed(user_message user_profile) candidates vector_search(query_vec, available_skills, top_k5) # 阶段二将候选技能完整描述交给模型决策 prompt format_skill_candidates(candidates, user_message) chosen llm_select_skill(prompt) return chosen4.3 上下文窗口不够时的三个实用处理策略技能系统跑起来后一定会遇到上下文爆炸的问题。技能描述本身有长度工作流中间结果有长度会话历史有长度三者叠加很容易把窗口撑爆。我总结了三层递进的处理策略第一层技能描述瘦身。把description和trigger条件里的大段解释压缩成精炼的短语模型能理解即可不需要写成一篇小作文。技能的详细说明可以挂在外部文档只在执行阶段按需读取。第二层历史消息摘要化。超过一定轮数后把早期对话压缩成摘要保留关键实体订单号、地址、时间和用户最终意图丢弃过程性对话。第三层中间结果精简。工作流中上一个技能的输出不要全量灌给下一个技能。只提取下一个技能input_schema里声明的字段做一次字段级投影。这个优化通常能省掉50%以上的上下文开销。我见过一些团队在这块直接躺平上超长上下文模型硬扛。短期能用但成本翻倍、响应变慢对生产系统来说并不是健康的方案。5. 跑通完整Agent的最小可运行骨架5.1 核心模块与职责边界技能系统设计得再好最后都要落到一个能跑的Agent上。我建议所有Agent项目先搭一个最小可运行骨架不要一上来就上各种重型框架否则一旦出问题排查链路会非常长。一套干净的分层长这样编排层Orchestrator负责主循环。拿到用户消息更新记忆选择技能执行工作流生成回复。技能层Skills由技能定义和执行函数组成。技能之间互相不感知只通过输入输出契约通信。记忆层Memory管理短期会话上下文和长期用户画像。对外提供读写接口对内负责数据存储检索。工具层Tools实际的API调用封装、参数校验、错误重试。技能层依赖工具层但不关心具体对接的外部系统。5.2 主循环逻辑每一步都留出可观测的痕迹主循环是整个Agent的心跳我用伪代码把核心逻辑沉淀下来每次新项目都基于这套结构演进async def agent_loop(user_message, session): # 1. 检索相关记忆注入上下文 memory_context await session.memory.load(user_message) # 2. 技能选择双阶段触发 skill select_skill(user_message, memory_context, session.skill_registry) # 3. 执行技能原子技能直接执行复合技能走workflow result await execute_skill(skill, user_message, memory_context) # 4. 生成回复前记录执行轨迹 session.telemetry.record_execution_trace(skill.name, result) # 5. 生成最终用户回复 reply await generate_reply(user_message, result, memory_context) # 6. 异步更新长期记忆用户完成的任务、偏好变化等 await session.memory.update(user_message, result) return reply这个骨架最核心的点是每一步都留下了可观测的痕迹——技能选了谁、结果如何、耗时多久、有没有重试通通记录下来。上线后微调时的所有判断依据都来自这里。5.3 从演示到可用的第一个迭代闭环用骨架跑通之后下一个问题是第一个技能到底做什么能让整个系统进入可用的迭代轨道我的建议是选一个频率高、边界清晰、外部依赖少的小场景而不是一上来就挑战高难度复合流程。我自己通常拿“FAQ问答”或“简单订单查询”打样。这个选择有讲究第一询问量大能很快收集到真实的边界case第二技能定义清晰容易判断触发是否准确第三即使做砸了影响面也可控不会造成严重的业务问题。第一个版本的目标只有一个让技能的触发准确率超过90%、用户典型问题的解决率超过80%之后再考虑扩充技能。这个阶段不要贪多一个经过反复打磨、行为稳定可靠的技能价值远大于十个能用但不是很好用的技能。6. 给Agent配齐“手”工具调用与API装配细节6.1 工具层的三类装配方式技能描述的是“做什么”工具层解决的是“怎么调通”。在实际工程里外部系统的API风格千奇百怪有REST的、有RPC的、有老式SOAP的还有纯文件交互的。工具层的核心任务就是把这堆五花八门的接口封装成技能能统一调用的格式。我按集成难度把工具装配方式分成三类项目里根据实际情况混用方式适用场景优势劣势直连API客户端目标系统提供规范的RESTful接口简单直接开发成本低对老系统或接口不稳定的系统脆弱适配器模式需要屏蔽多个服务商的差异如多个物流平台统一上游差异技能层不用关心具体用了哪家增加一层抽象需要维护映射关系脚本/命令封装需要调用CLI、处理文件或执行本地操作能覆盖接口覆盖不到的场景输出解析是难点容易出幺蛾子这里我特别想强调适配器模式的价值。拿物流查询来说顺丰、圆通、中通的接口风格完全不同有的返回JSON有的返回XML有的鉴权方式还特别奇葩。如果没有适配器层统一转成标准结构技能层就得为每一家物流重复写一套分支逻辑技能定义也会越来越臃肿。适配器的本质是在外部系统的混沌和技能层的稳定之间加了一道缓冲。6.2 参数抽取、校验和幂等设计不能信任模型的输出工具调用环节翻车率最高的是模型抽出来的参数不合法。模型从用户话术里提取订单号看着像订单号但可能带了多余的空格、缺了几位、或者把收货人手机号误提成了订单号。如果工具层不设防这种脏数据会直接打到下游系统。我的做法是工具层必须做三层防护参数类型强制转换根据schema定义做类型转换和格式校验。字符串模板校验用正则数字做范围判断日期做合法性解析。业务级校验即使类型合法还要做业务规则检查例如订单号是否存在、订单是否归属当前用户。这一层能挡住绝大多数越权访问和无效查询。幂等控制对于创建类操作下单、退货、转账必须生成唯一的幂等键。重试时用同一个幂等键防止用户点两次提交之后产生两条重复工单。幂等这块我吃过一次大亏。当时做了一个“一键补发优惠券”的技能接口本身不具备幂等性某次网络超时后模型自动重试了一次同一个用户被补发了两次券。事后我们要求所有写操作的上游调用方必须带上request_id作为幂等键服务端做去重。这个设计必须在工具层强制约束不能指望业务系统自己处理。6.3 时间、时区、异步三个最容易翻车的隐性坑三个细节看着不起眼每个都让我在线上出过事故。时区问题。用户问“我昨晚下的单怎么还没发货”如果Agent的上下文里时间全是UTC而订单系统的发货判断用的是本地时间回答偏差可能长达半天。我在所有工具层统一约定时间入参统一为标准不带时区的UTC字符串输出前再转成用户所在时区。时区信息从用户画像获取拿不到的默认用服务端时区但必须显式声明不许搞隐式转换。日期语义问题。“下周三”“月底”“后天上午”这类自然语言时间表达模型经常解析错。尤其是跨月、跨年的场景“下周三”如果恰好是下个月1号很多模型会解析成当前月的同一天。我在工具层放了一个时间解析器专门处理这类相对时间表达解析完再让用户确认一次避免带病执行。异步任务问题。有些技能操作耗时很长比如批量生成报表如果同步等待整个Agent主循环会长时间卡住。我的处理方式是引入任务队列技能层发出创建任务请求立刻返回“任务已提交”的结果由后台worker异步执行完成后把结果写回任务状态表用户回访时再查询或通过消息通道主动推送。7. 测试、观测与生产环境稳定性7.1 技能级测试与端到端测试的分层体系Agent的测试和传统软件的测试有本质差异。传统软件是确定的输入和输出一一对应Agent有模型参与同样的输入可能产生不同的输出。因此测试体系必须分层设计不能只靠一套端到端用例。第一层是技能单元测试。针对每个技能定义准备几十条标准测试用例覆盖正例、边界、反例核心检验点是“该触发时是否触发、不该触发时是否误触发”。这类测试用真实模型跑但结果只做统计分析不以单条通过与否为判定标准而是看整批用例的触发准确率。第二层是工作流集成测试。模拟完整的多技能协作流程验证编排逻辑是否正确、状态传递是否一致、异常分支是否按预期走通。集成测试对可控性要求高我通常跑在mock环境下所有外部API都换成模拟服务。第三层是回归测试。每次技能定义变更、模型升级、工具接口调整后都要重跑前两层的完整用例集对比各项指标有没有回退。这一层极其重要——模型升级后同一个技能描述的表现可能悄然劣化不回归根本发现不了。7.2 观测体系每个失败决策都要可回放线上Agent跑起来之后最可怕的不是出错而是出了错找不到原因。我在项目里构建了一套最小可用的观测体系包含三张核心表请求日志表每次用户请求的完整记录包括用户消息、注入的上下文、选择技能的候选列表及打分。执行轨迹表技能的调用链、每个步骤的入参和出参、耗时、错误码、重试次数。决策追踪表模型的每次决策输出、选择的技能、置信度、最终任务结果成功/失败/降级。这套观测落地之后一个典型的价值场景是这样复盘用户投诉的用户说“我在Shopee买的东西没收到但Agent说我已签收”。调出执行轨迹后发现Agent选的是“国内物流查询”技能而不是“海外订单物流”技能因为用户描述中“Shopee”这个关键词的向量召回排名不够靠前没进Top5候选。问题定位到具体环节后修复方案也明确了——在“海外订单物流”技能的description里增加Shopee、Lazada等平台名词。经验凡是模型参与决策的环节必须记录它可选的候选集和最终选择。只记最终选择缺失对照信息等于没记。7.3 慢响应、限流、熔断稳定性三板斧Agent进入生产环境后稳定性的挑战往往不是来自模型本身而是来自外部系统和并发量。慢响应处理。Agent的完整链路包含模型推理、技能执行、外部API调用每一环都可能成为瓶颈。我给所有外部调用设置了分级超时快速查询类800ms写操作类2秒批量任务类5秒。超时后按技能定义的error_handling走降级路径保证用户永远在10秒内收到回复而不是干等一个卡死的请求。限流和熔断。技能调用内部埋了三层限流用户级每用户每分钟最多多少请求、技能级单个技能QPS上限、全局级Agent整体吞吐。前两层容易理解技能级限流特别适合保护脆弱的下游系统——比如某个老系统的数据库扛不住高频查询就在工具层针对它的查询技能单独限流。熔断采用经典的滑动窗口算法连续失败率超过50%时打开熔断直接降级到备用方案5秒后尝试半开恢复。这些机制带来的一个直接好处是即使某个外部API出了严重故障用户感知到的也只是“系统暂时查询不到信息请稍后再试”而不是整个客服机器人直接瘫痪。8. 从一套技能库到持续的技能运营8.1 通用技能集的分层参考作为参考我给自己常用的通用技能集做过分层整理这套结构在迁移到新项目时可以快速复用基础认知层系统Prompts、时间感知、用户时区识别、全局指令遵循。这层不对外暴露任何业务能力只负责让模型“好好说话”。通用工具技能计算器、搜索、网页抓取、文件读写、数据格式化等跨领域通用能力任何时候都能直接调用。领域能力层如“订单查询”“售后处理”“产品推荐”“工单创建”这是业务团队重点维护的技能群按业务域划分每个域一个技能模块。决策/编排技能负责路由、汇总、对比分析等元能力。比如用户问“综合对比这三款手机”由这个技能决定是调用产品查询、参数对比、还是推荐引擎。8.2 从通用到垂直迁移时保留什么、替换什么把一套通用技能库迁移到新业务领域时最容易犯的错误是“全部推倒重来”。我在几个项目里验证下来合理的迁移策略是这样的保留编排层、工具层架构、通用工具技能、记忆系统、监测体系——这些是工程底座跟业务关系不大直接复用。替换领域能力层的技能定义和执行逻辑。物流领域换成仓储、订单、DTS对接电商客服领域换成商品、订单、售后、营销。技能描述和工具适配器需要重新写但写之前先盘点老领域有哪些技能模式可以抽象复用。新增新领域的特有技能。迁移时一定会有一些技能是通用库里没有的这些往往是新项目的核心价值需要重点设计。我自己迁移过一个从电商客服到跨境物流客服的项目领域能力层几乎全部重写但底层骨架编排循环、技能注册机制、限流熔断、监测表结构一行没改整体从立项到上线只用了两周多。这就是前面所有设计工作积累下来的复利。8.3 技能运营机制埋点、数据回流和定期体检最后想聊一个很多人不会主动去做、但极其重要的环节技能运营。Agent上线只是起点真正决定Agent长期价值的是有没有一套让技能持续进化的运营机制。首先是埋点。技能执行成功或失败、用户是否满意根据后续消息判断、转人工率、任务完成时长这些指标都要自动化采集。我习惯在回复生成阶段打一个异步埋点事件避免影响主流程性能。然后是数据回流每周跑一次失败case分析把执行失败或用户不满意的对话聚类产出Top问题清单按优先级进入技能定义优化。这个机制保证了Agent不是静态部署完就没人管而是持续在变好。最后是定期体检。我给每个核心技能设置了一组健康指标触发准确率、平均执行时长、错误率、降级比例。每周晨会扫一眼哪个技能指标出现明显波动就拉出日志深挖。这一套下来整个技能库的运行状态是透明的、被管理的而不是像很多Agent项目那样上线后只能靠用户投诉来被动发现问题。