首页/新闻资讯/正文详情

Agent技能体系实战:从工具混乱到高效编排的完整指南

发布时间:2026/9/25 13:57:07 来源:云帆数科 栏目:资讯中心
Agent技能体系实战:从工具混乱到高效编排的完整指南
做Agent开发一段时间的朋友大概率都遇到过同一个问题功能越加越多技能越堆越乱Agent用起来反而越来越“笨”——该调用的工具不调用不该调用的天天瞎调用翻日志排查的时候人都要疯掉。我自己手头这个项目技能数量从最初的5个扩展到50多个的时候这个毛病彻底爆发了技能命中率肉眼可见地往下掉参数解析错得离谱线上告警一个接一个。后来我把整个Agent技能体系推翻重做了一遍才把局面救回来。这套围绕“agent-skills”的落地方案适用于所有以LLM为大脑、外围挂了无数工具和API的Agent项目今天完整整理出来给正在搭技能体系或者打算重构的朋友做个参考。这套方案主要解决三个问题一是怎么定义一套标准技能接口让LLM和开发人员都看得懂二是技能数量多了之后怎么做注册、发现、编排和调度而不是拿一个tools列表硬塞给模型三是上线之后怎么评测、怎么快速排查问题让技能体系可持续迭代。文章里我会结合一个“竞品信息跟踪Agent”的完整案例把每个环节的设计思路、数据结构、核心代码和踩坑记录都摊开来讲。1. 为什么需要一套完整的Agent技能体系1.1 从“一堆工具”到“一套技能”是Agent规模化的分水岭很多Agent项目在起步阶段都是这么干的写几个普通函数然后按模型的Function Calling格式拼成一个tools数组每次请求全量塞给模型。5个工具的时候没问题15个工具的时候凑合能跑到30个工具以上就开始出妖了。原因并不难理解。模型在每一步推理时要从所有工具里选出当前意图对应的那个工具描述越长、数量越多选择难度就指数级上升。而且不同的工具之间天然存在语义重叠比如“搜索新闻”和“搜索网页”在描述上容易让模型犯迷糊还有大量的工具参数其实是有隐式依赖的比如先拿到URL才能抓取页面但模型如果没按顺序来后面每一步都是错的。这里的本质是把“工具”单纯理解成了函数而不是把“技能”当作一个独立的工程实体。工具只是执行层的一个函数签名技能则包含能力声明、参数契约、执行逻辑、运行约束、版本信息、评测记录甚至还包括技能之间的编排关系。当项目规模变大没有这层抽象Agent核心逻辑就会被工具的细节淹没。我重构之后得出一个结论技能体系的建设成本在技能数量少于10个的时候确实高于直接写tools列表但一旦超过20个系统性地组织技能的能力就变成整个Agent能否稳定运行的关键。1.2 技能、工具、工作流先把概念边界划清楚在动手之前有必要把几个高频词的定义彻底捋清楚因为团队协作时概念不一致会直接导致代码结构混乱。工具Tool是最底层的原子函数比如“调用HTTP接口”“读取数据库”“发送钉钉消息”。它不做复杂决策输入输出都是机械的。技能Skill是面向任务的能力单元底层由一个或多个工具组合而成。技能有明确的能力边界、适用场景、参数契约和失败处理策略。比如“搜索竞品新闻”这个技能内部可能调用搜索API、抓取页面、解析正文可能还要去除广告和重复内容但对外暴露的接口就是一个入参query字符串、输出结构化新闻条目列表。工作流Workflow是技能之上的业务流程编排描述“先执行哪个技能、满足什么条件后再执行哪个技能、异常时怎么降级”。同一个工作流里可能编排多个技能支持分支、循环、并发和人工审批节点。这三层是逐步递进的关系。我在重构时的第一刀就是把之前全部塞在tools里的“伪工具”按这个标准拆开有的降级成底层工具有的封装成技能有的抽出来做成工作流。这个动作做完之后整个系统的可维护性立刻上了一个台阶。1.3 技能体系要解决的四个核心问题把目标拆开来看一套完整的技能体系需要回答四个问题第一能力如何描述。LLM不是人它只能通过文字描述来理解技能是干什么的因此描述必须准确、结构化、可计算。这涉及技能的名称、说明、参数Schema、返回结构。第二能力如何注册和发现。技能不能只活在代码里需要一个“技能注册中心”统一登记所有能力。当技能越来越多Agent执行时要从技能库中快速找出与当前意图匹配的能力而不是把全部技能都喂给模型。第三能力如何编排和调度。单个技能是点把技能串成一条能完成任务的链路是线只有点线结合Agent才能处理真实业务。编排层要支持顺序、分支、并发、聚合、人工确认等模式。第四能力如何评测和迭代。技能改了描述、调了参数之后到底是变好还是变差不能靠感觉要有一组评测集、一套评测流程来兜底否则就是盲人摸象。下面每一章我对应用方案展开细说。2. 技能的定义与注册为Agent划清能力边界2.1 一份标准的技能契约长什么样我在项目里用的技能接口参考了很多行业内主流Agent框架的做法最终沉淀成下面这个结构。它不是简单的函数签名而是一个完整的能力契约。dataclass class Skill: name: str # 技能唯一标识动词_名词格式如 search_web description: str # 给LLM看的自然语言说明包含适用/不适用场景 parameters: dict # 参数SchemaJSON Schema格式 returns: dict # 返回结果Schema用于解析和校验 execute: Callable # 真正执行的函数 timeout_ms: int 10000 # 执行超时控制 concurrency_limit: int 5 # 并发上限防止拖垮下游 version: str 1.0.0 # 技能版本 metadata: dict field(default_factorydict) # 权限、成本、负责人等信息在给技能写name的时候我强烈建议统一用“动词_名词”格式比如search_web、fetch_page、send_email。原因是LLM在文本生成时对这种语义明确的命名方式理解准确率更高而且后续做技能检索和调试也一目了然。避免使用a1、func_b这类无意义名称。description字段是整个技能契约里最重要的部分。它不是写给项目经理看的而是写给LLM看的。写description时必须在脑子里模拟一次调用场景模型面对用户的一个复杂意图要判断当前技能是否匹配它有足够的信息吗2.2 description的写法让模型一眼就懂一段合格的技能描述至少要包含以下三层信息第一层是核心能力。一句话说清楚做什么例如“抓取指定URL的网页内容并转成干净的纯文本”。第二层是典型适用场景。给出具体的示例例如“当用户需要了解某个新闻页面的正文、获取博客文章内容、提取商品详情时使用”。第三层是反例和不适用场景。明确写清楚什么情况下不要用例如“当用户只需要搜索结果摘要时不要用应该使用search_web”。很多开发人员写description时只写第一层甚至只写“抓网页”三个字结果模型该用的时候不用、不该用的时候乱用。加了反例之后技能误用率能下降一大截这个细节实测效果非常明显。我的description模板大致是这样的技能名称search_web 核心能力对指定的查询词做Web搜索返回排序好的结果列表含标题、URL、摘要、发布时间。 适用场景 1. 用户询问最新新闻、特定事件或产品信息 2. 需要获取某个话题的多个来源汇总 3. 后续需要抓取某个网页详情页前的信息收集。 不适用场景 1. 用户已经给出明确URL应使用fetch_page而不是search_web 2. 用户要查询内部数据库或知识库使用query_knowledge_base 3. 仅需要对已有文本进行总结直接调用大模型不需要搜索。用这种模板写完之后整体技能的命中率提升非常明显。2.3 参数Schema才是真正的“防呆设计”参数用JSON Schema定义这样既能给LLM做Function Calling的格式约束又能在执行前做一次硬校验拦截那些“看起来合法但实际非法”的参数。举个实际例子。search_web技能有一个date_from参数用来限定搜索时间范围。如果不做校验模型可能生成“2025-13-40”这种日期或者结束日期早于开始日期。这种错误如果在执行层才暴露日志排查成本很高甚至可能直接把Agent的后续流程带偏。所以在技能执行器里每次调用前都要用jsonschema库做一次参数校验再加一层业务规则校验import jsonschema import datetime def validate_skill_params(skill, raw_params): # 1. JSON Schema格式校验 jsonschema.validate(instanceraw_params, schemaskill.parameters) # 2. 业务规则校验 if skill.name search_web: if date_from in raw_params and date_to in raw_params: fmt %Y-%m-%d d1 datetime.datetime.strptime(raw_params[date_from], fmt) d2 datetime.datetime.strptime(raw_params[date_to], fmt) if d1 d2: raise ValueError(fdate_from({d1}) 晚于 date_to({d2})请检查参数)校验失败时返回给模型的错误信息同样要友好。不是简单抛一个Exception而是返回结构化错误说明哪个参数不合法、应该怎么改。这样才能让模型在下一轮自动修正。2.4 技能注册中心单一可信来源技能一旦成规模就不能散落在各个模块里。我建了一个技能注册中心本质上就是一张表加一个加载器。注册中心是技能的“户籍系统”记录技能名、版本、当前是否可用、负责人、调用统计等。表结构大致如下CREATE TABLE skills_registry ( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(128) UNIQUE NOT NULL, version VARCHAR(32) NOT NULL, description TEXT NOT NULL, parameters_schema TEXT NOT NULL, returns_schema TEXT, status VARCHAR(16) DEFAULT active, timeout_ms INTEGER DEFAULT 10000, concurrency_limit INTEGER DEFAULT 5, owner VARCHAR(64), updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );所有技能必须在注册中心登记后才能被Agent发现和调用。这个设计有两个好处一是新加入的同事只需要看注册中心就能了解到整个系统的能力地图二是上线新技能时可以做灰度先将status设为inactive只注册不暴露测试通过后再放开。在实际项目里我会加一个“技能冲突检查”的流程。每次注册新技能时用名称相似度和语义相似度对比已有技能如果存在明显重叠要求提交者说明两个技能的区别。这个机制能有效避免技能库的重复膨胀。3. 技能编排与调度把单点能力串成完整业务3.1 编排的四种基本模式单个技能能回答“某一步怎么做”但真实用户往往给的是更复杂的任务。这时候就需要在工作流层把多个技能编排起来。我在项目里常用的编排模式有四种顺序编排是最简单的前一个技能的输出作为后一个技能的输入形成一个Pipeline。比如查询天气再生成穿衣建议先取数再渲染图表都是顺序流的典型场景。条件分支是根据参数或前置结果决定走哪个分支。比如用户查询订单状态时如果订单状态是“已发货”则调用物流查询技能如果是“已取消”则调用退款进度查询技能不能一视同仁调同一个接口。映射-聚合模式适合批量处理例如用户要求“分析今天的全部新闻”先把新闻列表映射成多个摘要任务并发执行再把所有摘要聚合成一份综合报告。并行编排则是在多个独立技能之间同时执行最后统一汇总例如同时查询股票行情、行业新闻和公司公告三个技能没有依赖关系可以并行跑省时间也省Token。在代码层面我实现了一个简单的编排引擎用YAML定义工作流支持这几种模式。workflow: daily_news_report steps: - id: step1 skill: search_web params: query: 今日要闻 next: step2 - id: step2 skill: fetch_page params: url: ${step1.results[0].url} next: step3 - id: step3 skill: summarize_text params: text: ${step2.content}这个引擎不复杂核心是执行每个step时去注册中心查找对应的技能执行完把结果放进共享上下文供后续step用${step_id.字段}引用。3.2 技能路由不再把全部技能塞给模型技能数量超过30个以后把所有技能定义全塞给LLM的做法不管是Token成本还是效果上都不可接受。我改为用“先检索、后调用”的路由策略。具体分三步。第一步把技能的description在注册时转化成向量存入向量数据库。第二步用户请求到达时先用意图识别模型或语义检索找出最相关的5到10个技能。第三步只把这些候选技能的定义传给LLM做Function Calling。这里有一个细节值得注意。语义检索的召回率直接决定后续决策质量因此description里一定要包含足够多的同义词变体。比如“查询”和“搜索”在描述里最好同时出现“抓取”和“爬取”同理。我在重构时专门对存量技能做了一轮描述扩充效果立竿见影。3.3 技能的依赖关系与资源共享技能之间并非完全独立。fetch_page依赖company_config里的反爬配置send_email依赖SMTP连接池。如果一个技能被多个工作流同时调用还要考虑资源的公平分配。我在技能定义里增加了一个depends_on字段声明该技能依赖哪些底层资源或前置技能。注册中心在加载技能时做依赖检查确保所有依赖都存在执行时按依赖顺序初始化资源。并发是另一个大坑。早期没有并发控制的时候feed抓取技能一旦被触发会对同一个目标站点发起几十个并发请求直接把对方服务器打挂自己的IP也被封了。后来我在技能执行器里加入了信号量控制按技能维度和目标域名维度双重限流。import asyncio skill_semaphores {} domain_semaphores {} async def run_skill_with_limits(skill, params): skill_sem skill_semaphores.setdefault( skill.name, asyncio.Semaphore(skill.concurrency_limit) ) domain extract_domain(params.get(url, )) domain_sem domain_semaphores.setdefault(domain, asyncio.Semaphore(2)) async with skill_sem, domain_sem: return await skill.execute(params)这个问题太容易被忽视了很多项目都是上线一段时间后在告警里发现的。技能编排做得再优雅底层资源被打爆一样白搭。4. 技能执行、上下文与容错机制4.1 技能调用的可观测性没有Trace就别谈排查Agent一次任务往往要经历“意图识别→技能检索→多次技能调用→结果汇总”多个环节任何一步出错都需要能在日志里快速定位。可观测性不是锦上添花而是刚需。我在技能执行器里统一埋点每次调用都会生成一条Trace记录技能名、入参、出参、耗时、错误信息、调用链ID。import time import uuid async def run_skill(skill, params, trace_idNone): trace_id trace_id or uuid.uuid4().hex call_id uuid.uuid4().hex start time.monotonic() log_entry { event: skill_call_start, trace_id: trace_id, call_id: call_id, skill: skill.name, version: skill.version, params: mask_sensitive(params), } try: result await run_skill_with_limits(skill, params) log_entry[event] skill_call_end log_entry[duration_ms] int((time.monotonic() - start) * 1000) log_entry[result_summary] summarize(result) return result except Exception as e: log_entry[event] skill_call_error log_entry[error_type] type(e).__name__ log_entry[error_msg] str(e) raise finally: logger.info(log_entry)日志里必须对敏感参数做脱敏处理比如密码、Token、手机号。否则排查问题的时候日志本身可能变成另一个安全事故。配合链路追踪系统每一步耗时、每一个错误都能在界面上串成一条完整的调用链。后续做技能优化时看到耗时主要集中在哪一步心里就有数了。4.2 上下文管理技能间的信息传递不能靠全局变量Agent执行过程中每个技能可能需要访问前置技能的结果。早期我图省事用了个全局字典当上下文结果一是变量名冲突二是不同技能之间耦合越来越重三是日志里根本看不清谁往里面写了什么。现在我用一个显式的上下文对象按作用域隔离。每个技能的参数和结果都存在独立的key下面通过上下文管理器取值。class SkillContext: def __init__(self): self._store {} def set(self, key, value): self._store[key] value def get(self, key, defaultNone): return self._store.get(key, default) def get_with_template(self, template_str): # 解析 ${step1.results[0].url} 这样的模板引用 import re pattern r\$\{(\w)\.([\w\[\]\.])\} def replacer(match): step_id match.group(1) path match.group(2) value self._store.get(step_id, {}) # 简化起见只做了点号属性访问数组索引可以按需扩展 for part in path.split(.): if [ in part: attr, idx part[:-1].split([) value value.get(attr)[int(idx)] else: value value.get(part, None) if value is None: return return str(value) return re.sub(pattern, replacer, template_str)这样做的好处是逻辑清晰。每个步骤之间只通过显式的引用方式传递数据工作流定义里能看出来谁依赖谁出问题也能快速锁定是哪一步的下游消费方。4.3 失败重试与降级让技能链“软着陆”真实环境中技能调用不可能永远成功。HTTP超时、第三方限流、反爬拦截、下游接口报错都是家常便饭。我在技能执行器里内置了三层容错策略。第一层是重试。对超时和5xx类错误做自动重试采用指数退避策略避免对下游造成更大压力。默认重试2次间隔0.5秒起步翻倍增长。第二层是降级。如果某个技能持续失败根据技能注册中心配置的fallback字段切换到备选技能。比如fetch_page失败时降级为search_web的缓存摘要接口虽然拿不到完整正文但至少不中断对话流程。第三层是用户告知。经过前两层仍然失败时不掩饰错误而是生成一条友好说明让用户知道“当前暂时无法获取页面内容”并给出可能原因和替代建议。这一点很多Agent做得极差明明接口超时了还在硬编“已获取到最新信息”用户体验非常糟糕。容错机制的配置最好做成可调整的不同技能有不同策略。比如查询类技能超时还能接受但支付类、下单类的技能绝对不能盲目重试否则可能产生重复订单。5. 技能评测与迭代没量化就没优化5.1 四层评测维度技能的改动往往修了一个问题又引入了另一个问题。比如把description写得更详细A场景命中率上去了B场景可能因为描述太长导致模型注意力偏移。要控制这种回归评测体系必须跟上。我的做法是把评测分成四个层级L1是技能发现正确率也就是模型能否从技能库里选出正确的技能。L2是参数解析正确率技能选对了但参数填错了同样会失败。L3是执行成功率技能调用是否顺利完成。L4是返回质量技能返回的结构和内容是否符合下游使用要求。每一层单独评分任何一层失败都算整个调用失败。这样定位问题时能直接知道优化要打在哪个环节。5.2 构造评测集至少覆盖四类意图评测集不需要一开始就做得很大但覆盖度必须够。我建议最少包含以下几类用例正常用例是标准场景输入意图明确技能选择和参数解析都应该一次到位。干扰用例是表面相似但实际需要不同技能的输入测试模型能否抵抗描述相似带来的误召。复杂复合用例则是需要多个技能协作才能完成的输入。边界用例则测试参数边界比如时间范围为空、URL带中文编码、空列表等。以竞品跟踪Agent为例我准备了这样几条评测用例输入1正常用例查一下A公司上个月发布了什么新产品 预期search_web → queryA公司 新产品 date_from上个月1号 date_to上个月最后一天 输入2干扰用例把这篇新闻的正文帮我提取出来链接是xxx 预期fetch_page不能走search_web 输入3复合用例总结一下最近一周B公司的融资动态 预期search_web → fetch_page取前3条链接 → summarize_text → 汇总输出 输入4边界用例搜索“人工智能大会” 预期query无误日期参数可以不填不影响执行有了评测集之后每次修改技能定义、路由逻辑或执行器我都先跑一遍完整评测分数不低于基线才允许上线。这套流程虽然简单但帮我在重构期间拦住了好几次“优化了个寂寞”的改动。5.3 从线上日志反哺评测集评测集不是一次性建好的而是持续从线上日志中沉淀出来的。我每周例行做一次“错例复盘”把线上失败率高的技能调用调出来分析是模型选错了、参数解析错了、还是技能本身报错。每发现一类新问题就抽象成一条新的评测用例塞进评测集。这样一个月下来评测集从最初的20条能扩充到100条以上覆盖的场景越来越全系统整体的稳定性也会同步提升。还有个经验是建立“技能健康分”机制。每个技能根据自己的调用次数、失败率、重试率、耗时变化算出一个0到100的健康分。低于60的技能自动触发告警相关负责人在周会上给出整改计划。这个机制不复杂但对推动技能持续维护非常有效。6. 实操案例从零构建一个“竞品信息跟踪Agent”技能包6.1 需求拆解与技能清单设计用前面讲的整套方法完整走一遍“竞品信息跟踪Agent”的搭建过程。这个Agent的定位是每天早上定时抓取指定竞品的最新新闻、版本发布、招聘动态生成一份结构化简报推送到工作群。拆解之后需要以下技能search_web(query, date_from, date_to)搜索指定关键词返回结果列表fetch_page(url)抓取网页详情返回结构化文本parse_content(html, selectors)从HTML中提取正文、标题、发布时间summarize_text(text, max_words)对长文本生成摘要diff_track(current, previous)对比当前与上次抓取结果识别新增或变更条目notify_webhook(webhook_url, message)把结构化消息推送到群机器人每个技能都按第2章的标准写了description、参数Schema和超时策略。注册中心里登记完这个Agent就有了完整的“能力地图”。6.2 工作流编排从触发到推送的完整链路工作流定义如下workflow: competitor_daily_tracking triggers: - cron: 0 8 * * * steps: - id: search_news skill: search_web params: query: ${workflow.competitor} 新闻 date_from: ${yesterday} date_to: ${today} - id: fetch_top3 skill: fetch_page params: url: ${search_news.results[0:3].url} mode: parallel - id: parse_pages skill: parse_content params: html: ${fetch_top3.output.html} selectors: [article, .content, #main] - id: summarize_pages skill: summarize_text params: text: ${parse_pages.content} max_words: 200 - id: check_changes skill: diff_track params: current: ${summarize_pages.output} previous: ${workflow.last_snapshot} - id: notify_group skill: notify_webhook params: webhook_url: ${workflow.group_webhook} message: ${check_changes.diff_summary}这个工作流体现了顺序编排、并行编排和条件分支的综合使用。fetch_top3是并行步骤对三个URL同时抓取。check_changes的结果如果是“无变化”则通过条件分支跳过了notify_group避免每天推送重复内容。6.3 执行效果与问题复盘这套流程上线后实际跑了两周整体效果很稳但也暴露了一些问题挑两个有代表性的说。第一个问题是初始版本漏掉了diff_track技能。那几天每天早上群里都会收到同样的新闻摘要因为同一篇新闻每天都搜索得到。后来加上diff_track做快照对比重复推送才算解决。这个问题的本质是需求拆解阶段没有把“增量更新”这个隐性需求翻译成技能。第二个问题是search_web的date_from参数写成了必填。但在实际使用中用户根本不总是需要时间范围尤其一些突发新闻场景搜索最近三个月就是默认行为。后来我把默认值逻辑下沉到技能内部参数标为可空模型被卡住的情况少了很多。顺带提一个经验工作流的每一个步骤都要预置“无结果时怎么办”的行为。比如搜索没有返回任何结果是直接结束还是换一个宽松的关键词再搜一次这个分支逻辑不写清楚Agent就会被“空结果”卡死然后在日志里留下一条极其隐晦的索引错误。6.4 上线后的持续追踪工作流每天跑完后我会额外收集几个指标每一步技能的平均耗时、成功率、Token消耗、以及最终的推送条数。这些数据汇总成一张趋势表一旦某天耗时翻倍或者成功率先降后升去日志里翻Trace就是最快的定位方式。为了让这套体系更好维护我还给每个技能配了一个卡片文档记录它的owner、最近更新日期、主要调用方以及历史故障记录。最开始觉得这样做有点重但后来团队扩到5个人一起维护这套卡片反而成了新成员最好的入门资料。7. 几个容易忽视但非常关键的经验7.1 技能命名的长期影响技能的name字段一旦定了很难改因为可能会被其他工作流引用。所以命名规范必须在第一天就想清楚。我见过有人用search_web_v2这种带版本的命名结果版本一多技能列表看起来极其混乱。建议的做法是一个能力对应一个技能名升级时保持name不变靠version字段区分。如果需要彻底改变技能行为宁可新起一个更准确的名字并把旧技能标记为deprecated通过注册中心的冲突检查和推荐功能逐步引导迁移。7.2 description的“反例”比“正例”更重要这一点前面提过但这真的是所有经验里性价比最高的一个。给技能写反例本质上是在帮LLM建立排除法。LLM在做决策时能明确知道“不做什么”比只知道“做什么”往往更稳。比如notify_webhook这个技能如果不写反例模型可能在任何需要发送消息的场景都选它。加了反例“仅在用户要求推送消息到群机器人时使用仅生成文本回复时不要用”之后误用率几乎降到零。7.3 技能评测要放在一个独立环境跑千万别在主开发环境里做技能评测否则变量太多评测结果根本没有参考价值。我专门起了一个独立的评测环境固定大模型版本、固定技能库每次评测只允许改动一个变量要么改描述、要么改参数Schema、要么改路由逻辑。只有在这种“单变量控制”的前提下评测分数的变化才有归因意义。否则A和B两个改动同时上了线效果变好或变坏你根本不知道是哪一个起作用。7.4 别忘了技能本身的“用户”最后分享一个心态上的转变。很多Agent开发者习惯性地把技能看成“给LLM调用的函数”要什么签名就给什么签名。但我后来发现更好的思路是把技能当成一个独立的产品它有明确的使用文档、有版本、有负责人、有反馈渠道。使用技能的“用户”有两个一个是开发人员另一个是LLM。开发人员需要能看懂、好维护、方便调试LLM需要描述清楚、参数语义明确、功能边界不与其他技能重叠。两边的体验都要照顾到。我在项目里强制要求任何新技能提交时必须带上两份说明一份给人看的机读注释一份给模型看的description。同时规定凡是技能被模型连续误调用3次以上必须回查并修改description——听起来很基础但坚持执行下来整个技能库的质量管控就有了抓手。做Agent技能体系没有一劳永逸的答案它是一个持续优化的过程。先把注册、编排、评测、复盘这套地基打稳后面新技能的接入、新场景的扩展才会越来越顺。这篇内容里提到的所有设计和代码都是从实际项目中沉淀下来的希望能帮你少走几步弯路。

相关推荐

重磅!DeepSeek-V3.2-Exp 发布百万输出仅3元|附完整论文中文翻译与 TaoToken 配置骨架
重磅!DeepSeek-V3.2-Exp 发布百万输出仅3元|附完整论文中文翻译与 TaoToken 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 13:56:36

2026腾讯云服务器一年多少钱?30台CVM配置价格与选型指南
2026腾讯云服务器一年多少钱?30台CVM配置价格与选型指南

1. 为什么“一年多少钱”这个问题,从来都不是一句话能答完的每次有人问我“腾讯云服务器一年到底多少钱”,我都不会直接甩一个数字过去。不是我不想说,而是这个问题本身就问得不够精确——就像你问“买一辆车多少钱”,销售没法回答… · 2026/9/25 13:56:29

C++模板编译期计算:从递归实例化到constexpr的现代实践
C++模板编译期计算:从递归实例化到constexpr的现代实践

模板编译期计算这个话题,搁在C社区里基本就是模板元编程的代名词。我最早接触它是在读Loki库和Boost.MPL源码的时候,第一感觉是这玩意儿不像代码,更像在给编译器出谜题——你写一套规则,编译器在编译阶段替你跑完所有“计算”&… · 2026/9/25 13:56:23

Django基于Python的农业科学文献相似性检索与推荐系统设计
Django基于Python的农业科学文献相似性检索与推荐系统设计

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 一、 技术栈 本系统采用前后端分离的架构设计,主要技术栈如下: 1. 后端 (Backend) 核心框架: Django 4.x / Django REST framework (DRF)编程… · 2026/9/25 14:25:17

基于Django的消防安全知识学习平台:技术栈、背景意义与核心代码解析
基于Django的消防安全知识学习平台:技术栈、背景意义与核心代码解析

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 1. 项目背景与意义 消防安全是社会公共安全的重要组成部分,普及消防安全知识对于预防火灾、减少生命财产损失具有至关重要的作用。然而,传统的消… · 2026/9/25 14:25:11

Python 导入数据库操作实战:用 TaoToken 统一 Key 打通 MySQLdb 与 SQL 配置
Python 导入数据库操作实战:用 TaoToken 统一 Key 打通 MySQLdb 与 SQL 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 14:25:05

戈壁母亲剧情全解析:用TaoToken统一Key梳理人物关系与剧情脉络
戈壁母亲剧情全解析:用TaoToken统一Key梳理人物关系与剧情脉络

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 14:24:58

AIO Sandbox 实测:集浏览器、Shell、MCP与VSCode于一体的Agent沙箱
AIO Sandbox 实测:集浏览器、Shell、MCP与VSCode于一体的Agent沙箱

最近在调研 Agent 运行环境的时候,我又碰到一个很实在的开源项目:AIO Sandbox。它做的事情用一句话就能说清楚——把浏览器、Shell、文件系统、MCP 服务和 VSCode 全部塞进同一个容器,变成一个专门给 AI Agent 用的"绿色开发机"。以… · 2026/9/25 14:24:40

腾讯 QClaw 内测申请码到手,OpenClaw“龙虾”接入微信和 QQ:TaoToken 统一 Key 配置实战
腾讯 QClaw 内测申请码到手,OpenClaw“龙虾”接入微信和 QQ:TaoToken 统一 Key 配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 14:24:40

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码