尧图精选

腾讯云AI Skills实战:让Agent从能聊天变成能干活

🕒 发布时间:2026/9/5 4:35:25 📁 来源:尧图网络
把一个 Agent 从“能聊天”调成“能干活”我前前后后折腾了差不多三个月。最后真正起作用的不是换了更强的模型而是老老实实把一批腾讯云 AI Skills 设计清楚了。现在回想起来这个认知反转是项目从“demo 看起来很酷”走向“真能被同事用起来”的分水岭。这篇文章更多像是我自己的实践笔记Agent 到底应该拆成哪几层Skill 和 Tool 的边界在哪儿一个技能要写到什么程度模型才会稳定调用上线之后又踩过哪些奇奇怪怪的坑。我尽量用项目里的真实例子来讲而不是罗列概念。如果你正在做 Agent 应用或者刚接触 AI Skills正准备给自己的智能体扩展能力这篇应该能帮你少走不少弯路。1. 整体设计与思路拆解全能 Agent 并不是“一个大模型”1.1 为什么只靠提示词养不成全能智能体刚开始做项目时我和大多数人的想法一样把大模型的 Prompt 写得足够详细把背景知识、行业术语、任务规则全部塞进 System PromptAgent 看起来就“懂很多”。这个思路在前两个星期内确实有效因为场景还停留在问答和简单生成上。等任务真正变成“去拉数据、做分析、写报告、再归档”这种完整闭环时问题一下就暴露了Prompt 越来越长模型开始抓不住重点。我把几十条规则塞进去结果它常常为了满足后几条而忽略最核心的目标。工具函数也越来越多大模型面对十几个 function 的时候选错工具的频次明显升高。后来我在腾讯云 AI Skills 上尝试换了一种思路不再试图让 Agent“全知全能”而是给它配一群“随时可召回的专项外包”。每个 Skill 负责一个小而完整的执行能力比如读取 Git 提交、解析缺陷单、渲染固定格式的周报。Agent 本身更像一个项目经理负责理解用户意图、拆分任务、调用合适的外包并按结果组织回复。这个转换对我帮助很大也让我相信一件事所谓全能感其实来自 Task 分解能力和大量边界清晰的子技能不是靠一个超大模型硬撑起来的。1.2 Skill、Tool、Workflow 的边界要分清楚做 AI Skills 之前有必要先区分几个容易混淆的概念。因为如果边界没搞清楚后面拆 Skill 的时候一定会乱七八糟。我先用自己熟悉的方式做个不严格的类比。Tool 是一个具体的执行动作像一只手它可以“删除文件”“发 HTTP 请求”“查数据库”。Workflow 是一条固定的流水线像一条产线输入原料经过几道固定工序输出成品。而 Skill 更像是“某个工种的手感 工具 操作规范”它可能包含如何判断什么时候该出手、用哪个工具、按什么顺序执行、遇到不同材料怎么做调整。放在腾讯云 AI Skills 这类体系里一个 Skill 通常使用结构化定义来告诉模型它的用途、参数、输出然后内部去调用函数或者一个 HTTP 服务。之前有人问我“我直接把函数定义成 function calling 不行吗为什么还要封装一层 Skill”我的回答是可以但只适用于三五个函数的场景。函数一多模型就分不清“get_commits”和“query_git_history”有什么区别你也不可能靠多写几个同义函数来提升准确率。Skill 层真正解决的问题是把“我要不要用你”和“我该如何用你”这两件事浓缩成一段可被模型理解的高质量描述。它对上屏蔽掉执行细节对下封装好工具调用的参数规则本质上是在给模型做信息减负。下面用一个表总结我自己的使用心得层级类比是否由大模型动态决定典型作用Tool手通常由模型按需选择单点执行常见于函数调用Skill工种需要模型先判断意图再调用一个完整的能力单元可以跨多个工具Workflow流水线通常由代码或特定编排触发固定流程稳定性要求高1.3 Agent 与 Skill 的职责拆分我最后采用的架构可以简单描述为Agent 理解目标Skill 负责执行Memory 负责保存中间过程而人的职责是设定评审节点。听起来很顺但实际操作起来并不容易。Agent 天生擅长把任务说得头头是道却不一定清楚自己到底有没有能力执行某个子任务。我的一个经验是在任务拆解的阶段就加入一个“可行性检查”的习惯Agent 开出的每个子任务必须对应一个已经注册好的 AI Skill对应不上的要么重新表述任务要么明确告诉用户这个需求当前无法自动完成。这样做的价值非常明显Agent 不会再“外包”给自己根本做不到的能力。它知道自己的边界反而回答得更可靠。我会把这个原则写进 Agent 的系统 Prompt“不要假设你可以调用不存在的技能你只能调用下方列出的 AI Skills缺乏技能时请直接说明无法处理哪些部分。”1.4 什么样的场景最适合先上 AI Skills结合我的实践下面几类任务最值得优先做成 AI Skills需要频繁调用外部系统数据的任务比如查工单、查监控、查代码仓库输出格式高度固定的任务比如周报、发布说明、故障报告需要严格保证操作顺序的任务比如先备份再迁移、先回归测试再上线多 Agent 共用一套能力的场景比如不同的 Agent 都要做“文件归档”那就值得抽成一个公共 Skill。不太适合一开始就做成 Skill 的是这类场景任务本身依赖大量开放性讨论用户需求在不断变化最终结果没有明确结构。这种需求更适合让 Agent 自由对话而不是把它限制在一套技能流程里。过早固化反而是负担。2. 核心细节解析把一个 Skill 写到让模型“无脑”可用2.1 名称和描述是第一位的它是给模型看的说明书我在腾讯云 AI Skills 里写技能时第一个版本经常偷懒直接把内部函数名抄上去比如叫get_commits描述写成“获取提交记录”。这样做模型不是不能用而是用得很糙用户问“这周咱们系统改了什么”模型往往不清楚应该调用这个技能甚至会在没有足够上下文时直接用编造的数据回答。后来我把命名和描述当成一份“给模型的销售文案”来写。名称要能体现职责范围描述则要让模型看到它的时候能回答三个问题这个技能是干什么的什么场景下用户意图和它匹配什么情况下不应该调用它一个后来效果还不错的例子name: fetch_commits_between_refs description: 获取同一个代码仓库两个 git 引用分支、标签或 commit之间的提交列表。 当用户想了解某次版本更新包含哪些变更、生成发布说明、对比两个版本的代码差异时可以调用本技能。 如果用户只是询问某个文件的当前内容或要修改代码不应该使用本技能。加了这段描述之后模型在“生成发布说明”这个高频场景下的工具选择准确率提升得很明显。不要小看 description 里的“不应该调用”这半句它起到的负面排除作用很关键能避免模型在意图模糊时抱着“顺手试一下”的心态乱调。2.2 参数结构的设计原则平铺优先善用枚举模型填参数的能力和你给的 Schema 结构强相关。我自己吃过一次亏设计一个“生成发布报告”技能时参数一开始是嵌套对象外面套 repo 信息里面套过滤条件再里面还嵌了一个 labels 数组。看起来非常规整但在多次真实调用中模型偶尔会漏掉内层字段或者把 team 名称误填到 repo 的 owner 字段去。后来我遵循了几个原则错误率降了很多能平铺尽量平铺不要让模型做多层“对象翻译”每个字段写清楚它到底接受什么值能用 enum 就用 enum必填字段必须显式声明required防止模型漏传字段描述里可以补充一两个示例值尤其是格式不直观的参数。下面是我后来常用的参数结构长这样的一个示例{ type: object, properties: { repo_name: { type: string, description: 仓库名称例如 myapp, examples: [myapp] }, base_ref: { type: string, description: 起始 git 引用通常是主干分支名或上个版本 tag }, head_ref: { type: string, description: 结束 git 引用通常是待发布分支名 }, template: { type: string, enum: [simple, detailed], description: 输出模板simple 只列标题detailed 带 commit message 和作者 } }, required: [repo_name, base_ref, head_ref] }模板参数用 enum 而不是自由字符串是我后来习惯的设计方式因为自由字符串会让模型产生很多变体比如Simple、simple mode执行层还要做归一化。给死选项反而更省心。2.3 输出和异常要让模型“看得懂接得住”不少 Skill 只定义了成功返回的结构却忽略了失败返回这是个大坑。Agent 在调用技能之后还需要根据结果决定下一步动作如果技能抛出一大段堆栈或者一段含糊的中文错误模型就只能在原地打转。我建议所有 Skill 在异常情况都返回统一结构{ ok: false, code: RATE_LIMITED, retryable: true, message: 调用第三方接口触发限流建议 30 秒后重试, next_steps: [wait_and_retry, notify_user] }code字段用于机器判断retryable让 Agent 决定要不要重试message给模型生成用户可读的解释next_steps则直接告诉模型还可以做哪些选择。设计这个结构花了我们半天时间但在线上明显减少了 Agent 遇到错误后“反复重试同一个请求”的呆滞行为。另外成功返回也尽量结构化成字段而不是让技能直接返回一大段人类语言。模型对一段文本做二次解析容易出错但如果返回的是结构化对象Agent 可以直接把关键字段用于生成最终答案。我自己曾经让技能返回一整篇 Markdown后来又写了一个“提取核心要点”的步骤纯属多此一举。早点把输出拆成summary、highlights、detail_markdown并存的格式会更顺手。2.4 技能的版本管理别偷懒接入 AI Skills 后我一开始只维护“最新可用版本”结果改了一个技能参数第二天发现 Agent 突然不调用另一个旧技能了。后来我给每个核心技能补上版本号并在 description 里注明“当前版本 v2支持 xxx 参数”。模型对版本的感知可能没有那么强但至少可以靠日志追踪是什么时候开始行为变化的。需要注意给模型声明版本号也不是越细越好像v2.3.1这种粒度意义不大。推荐只在技能有破坏性变更时跳一个大版本并在描述里写清楚变更点比如“v3 版本开始新增自动去重不再需要传入 dedup_key”。3. 实操记录给“发版 Agent”补齐三件核心 AI Skills3.1 先定义场景把发版前的手动检查变成 Agent为了讲清楚具体怎么操作我选一个实际做过的场景研发团队的“发版 Agent”。它要做的事情不复杂每次准备上线前负责汇总代码变更、检查工作项状态、生成一份发布说明并提醒相关人确认。过去这个流程靠一个人手工打开 Git 平台、项目管理后台、再粘贴到文档里需要二十分钟到半小时。用 Agent 之后我们希望把过程缩到两分钟以内而且结果要稳定可靠。围绕这个场景我们没有做一个“什么都会的大 Agent”而是拆成三个相互独立的 AI Skills技能名用途关键输入输出fetch_commits_between_refs获取两个版本的提交记录repo_name, base_ref, head_refcommit 列表load_project_tasks拉取关联工作项状态repo_name, ref, task_keys任务状态列表render_release_notes按模板生成发布说明commits, tasks, styleMarkdown 文本最关键的是最后一个技能。写发布说明时直接让大模型读几百行 commit message 很容易抓不住重点。由技能先完成数据清洗和聚合再交给模型润色措辞效果稳定得多。这也是我想强调的一点AI Skills 不一定非要追求端到端智能它先把脏活累活干好就已经有很大价值。3.2 一个完整的 Skill 清单长什么样我通常在腾讯云 AI Skills 的控制台里创建技能时会先维护一份描述清单manifest它更像技能的“元数据”。一个最小可用的清单包含这些内容name: render_release_notes version: 1.0.0 description: 基于预聚合的提交列表和任务列表生成结构化的 Markdown 发布说明。 适用于发版前准备 Release Notes、上线公告或变更同步文档。 数据请先通过 fetch_commits_between_refs 和 load_project_tasks 获取。 input_schema: type: object properties: commits: type: array description: 预聚合后的提交对象数组每个对象至少包含 message 和 author tasks: type: array description: 关联任务数组每个对象包含 title 和 status style: type: string enum: [simple, detailed] description: simple 适合群内快报detailed 适合正式归档 required: - commits - style output_schema: type: object properties: content: type: string description: 最终生成的 Markdown 文案 stats: type: object description: 包含 commit_count、task_count 等统计信息这里有一个容易忽略的点我在 description 里明确写了“数据请先通过 fetch_commits_between_refs 和 load_project_tasks 获取”。这其实就是为 Agent 提供了一条“协作路径”。有了这句话Agent 就不会在调用 render_release_notes 时临场编造一批不存在的 commit 对象。实际配置 Skill 时你不需要完全照抄这份 YAML因为不同平台的字段可能稍有差异。核心思路是输入字段尽量结构化输出字段包含模型后续需要的数据描述部分把技能间的前置依赖讲清楚。3.3 执行体里的三道工程防线一个 Skill 的内在逻辑往往不复杂真正决定它稳不稳的是三道防线。第一道防线是参数校验。不少模型填出来的参数可能格式怪异比如日期写成了“下周三早上”。执行体不能假设入参一定正确我的做法是先做一层校验把不符合 schema 的输入挡在门外返回一个可读的错误码。宁可让 Agent 重新表达需求也不要让它拿着错误参数去第三方系统里跑一遍。第二道防线是幂等控制。像“拉取提交”“查询任务”这类只读技能天然幂等不需要过度设计但如果是“创建任务”“发送通知”这类可能产生副作用的能力就必须考虑重复调用造成的脏数据。我惯用的方案是技能接收一个可选的request_id如果请求表里已经有相同 request_id 的执行记录就直接返回上一次的执行结果。这个字段有时候模型不一定传所以在执行体里也要支持由调用方自动生成。第三道防线是超时与外部依赖降级。执行体调用 Git 平台 API 或内部服务的耗时波动很大如果超时设置得太短技能会在 Agent 最需要它的时候掉链子。我会根据不同接口的历史分位值来设置超时通常取 P95 再乘以一点五以上而不是粗暴地统一设成 3 秒。另外对于关键只读接口可以先在代码里做一层短时间缓存避免同一个 Agent 会话内反复触发外部请求。下面是一个简化版执行体的伪代码展示def run(inputs: dict) - dict: commits inputs.get(commits, []) style inputs.get(style, simple) if not commits: return {ok: False, code: EMPTY_INPUT, message: 没有收到提交数据} # 归一化风格参数 chosen_style simple if style ! detailed else detailed content render_markdown( commitscommits, tasksinputs.get(tasks, []), stylechosen_style, ) return { ok: True, content: content, stats: { commit_count: len(commits), task_count: len(inputs.get(tasks, [])), }, }这个例子虽然短但已经体现了三个关键点前置校验、参数归一化、结构化返回。3.4 将技能挂到主 Agent 上常驻还是按需路由技能设计好之后还有一个很实际的问题要不要把所有技能常驻挂到主 Agent 的上下文里我的经验是不要。常驻工具数量一多大模型的选择准确性会下降。我实测下来把一个中等模型能稳定处理的函数数量控制在 8 到 12 个以内会比较合适超过这个量误调用和漏调用都会增加。这里分享两个管理技能数量的做法。第一种是高频技能常驻。比如 fetch_commits_between_refs、load_project_tasks 这类会被频繁调用的技能直接挂载到主 Agent 上让模型随时可用。第二种是低频技能通过“技能路由”按需暴露。比如 Agent 一共有 30 个技能但只有 10 个是高频的剩余 20 个不会在每个对话里都用上。我会加一个dispatch_skill技能它接收用户意图描述再由后端配置去唤起真正的低频技能。这样主 Agent 的上下文中永远只有十来份技能说明但能力边界并没有缩水。这种分层设计有一点一定要注意路由技能的描述要足够宽能覆盖那些不常用但必要的能力否则 Agent 根本不知道有这些隐藏技能的存在。我使用的方法是在dispatch_skill的参数里增加一个skill_tags枚举把所有低频技能的领域标签列出来比如[archive, security_check, metrics_explain]等。Agent 不确定具体技能时至少可以正确选择领域再由执行层完成最终分发。4. 进一步让 Agent 记住做过的事AI Skills 与记忆的配合4.1 Skill 保持无状态记忆别塞进技能里AI Skills 和 Agent 记忆经常被混为一谈。技能本身应该是无状态的它不负责记住用户偏好或历史会话否则同一个技能在多轮对话里复用时会积累不可控的副作用。举个例子如果我在“生成发布说明”的技能里记录用户上次选的风格是 detailed这次调用就可能带着旧状态输出可用户当前的需求也许是 simple。技能一旦带状态就破坏了可复用性。正确的做法是把那些需要跨任务保留的信息放到 Agent 的记忆模块通过多轮对话时由 Agent 主动注入必要的参数来影响技能执行。我当时在腾讯云上调试 Agent 时发现如果不刻意区分两者很容易写出“技能内部维护了一个全局 config”这种烂代码。后来反思比起给技能加状态不如让 Agent 在每次真正执行前想清楚这个用户偏好在当前任务里是否依然有效如果有效就以参数形式传给技能如果无效就重新询问确认。4.2 把调用历史本身做成一个只读技能另一个我用得比较顺手的方案是把“历史调用记录”做成一个只读技能而不是塞在 Agent 状态里。这个技能接收时间范围、技能名、目标对象 ID 等字段返回过去这段时间执行过什么任务、结果如何。它的应用场景不是闲聊而是帮助 Agent 避免重复动作。例如 Agent 接手一个新的周报任务时发现用户今天凌晨已经让另一个自动化任务生成过类似的发布说明它就可以先检查结果而不是盲目再执行一遍。实现层面很简单在技能执行体里查询每类关键操作的审计记录即可返回时给 Agent 一个清晰的建议字段suggest_action例如use_existing或need_refresh。用户看到的效果就是 Agent 变“聪明”了知道什么时候复用历史成果、什么时候重新计算。4.3 记忆内容也要定期整理当记忆越积越多时原本用来帮 Agent 的上下文反而变成干扰。我每隔一段时间会对记忆做一次归档清理把成功任务的关键结果抽取成摘要把已经过期的临时信息删掉只保留对后续决策有用的稳定知识。这里可以专门做一个summarize_conversation_history技能由它对会话历史做压缩和摘要。我也吃过这方面的亏有一版 Agent 把每次调用 commit 接口的详细响应都存进了长期记忆词汇量不大但历史越积越长提问的响应速度下降得很快。后来加了记忆归档技能把原始执行结果压缩成“某个仓库、某段时间、变更范围、涉及的模块、最终结论”信息密度上来了上下文占用也小了很多。5. 实际跑起来后我踩过的坑和调优记录5.1 技能执行成功但 Agent 没有用它拿到结果技能正常执行了返回也正确最后 Agent 却还是凭自己的“印象”回答用户。这个问题非常隐蔽一度让我怀疑模型是不是没读懂技能输出。排查后发现两种原因。第一种是系统的提示词没有要求模型必须引用技能结果。模型发现上下文里已经有一些关于项目的描述就直接拿着旧信息生成答案。解决办法是在系统 Prompt 中写明当用户任务涉及数据变更、查询或外部信息时只能基于技能返回的结果做答不得用 model 本身的知识库推测。第二种原因是技能输出的字段名不够直观。模型取数时抓不到关键位置所以答非所问。我给这类问题补了一个标准每个技能返回结果中要有一个字段叫answer_summary它是一句可以让模型直接引用的概述。模型可以快速确定它该围绕什么来回复用户。5.2 工具调用循环和 Token 爆炸另一个高频问题是 Agent 在技能之间反复横跳。比如用户想生成发布说明模型先调了 fetch_commits_between_refs拿到一堆 commit但随后又怀疑数据不完整再次调用同一个技能却加了不同参数拿回相似的返回循环了两三次才继续。整个过程浪费了不少 token还延长了用户等待时间。我的对策有几条给 Agent 的水平推理设置最大调用轮数超出就停技能执行阶段尽量把数据一次查全把“去重”“聚合”这类逻辑前置到技能内部不要指望模型自己反复抽样在技能描述里直接写明“本技能一次调用已经包含全部提交无需重复调用”。这些都可以显著减少无效循环。尤其是第二点把聚合逻辑做进技能里对模型特别友好。5.3 权限边界不要交给模型自觉用 AI Skills 扩展 Agent 能力后权限管理会变成隐形风险。不要假设模型会在执行危险操作前主动判断“这个用户有没有权限”因为它很容易被诱导。更可靠的办法是权限判断下沉到技能执行体技能内部校验用户身份、校验资源归属、校验操作类型不符合条件就直接拒绝返回。Agent 只能决定是否发起动作但没有能力越过执行体的权限限制。我给迁移类、删除类、通知类技能都加了双保险执行体里做权限判断另外要求必须传入确认参数confirmed: true否则返回“需要用户显式确认”。这个设计一开始觉得麻烦但后来帮我们挡掉了至少两次误操作风险。5.4 常用问题排查速查表我把调试过程中常见的问题整理成一张表遇到问题可以照着快速定位现象可能原因建议排查方向技能完全没有被调用用户意图与技能描述不匹配重写 description加入更明确的触发场景技能被调用但参数明显是猜的schema 的字段说明不清晰给字段补充 examples减少自由格式字符串调用后 Agent 忽略返回结果输出结构不直观或系统提示没要求引用增加 answer_summary 字段在系统提示里强调引用规则同一技能被反复执行技能返回值没有给足“结束条件”明确单次调用是否包含全部信息必要时给重复保护执行正确但用户觉得结果不完整技能能力粒度太粗考虑拆成更细的技能或让 Agent 分步调用多个技能大量工具导致调用混乱常驻技能太多缩减常驻数量低频能力改走路由技能这张表看起来简单却是我们调整 Agent 行为时最常翻阅的索引。很多问题原本会花几个小时观察日志才能定位现在对照表里查一遍通常十分钟内能锁定方向。5.5 关于模型选型与技能数量的一点体会我在部署过程中试过不同能力的模型作为 Agent 的主控发现模型体量确实会影响它对技能描述的遵循程度。小模型在技能数量多时更容易误判同一套技能配置换到大模型上表现会稳定很多。但这不代表技能设计可以马虎。恰恰相反模型的容错能力只能兜底一部分问题真正决定 Agent 上限的仍然是技能本身边界清不清晰、描述准确不准确、返回结构规不规范。另外给技能做“上线后回归”也很重要。我每次修改一个核心技能里的描述都会用一组历史真实问答来回放一遍看 Agent 的调用行为是否发生变化。这样能避免“优化了一个技能结果其他场景不调用了”这种连锁反应。6. 一些踩过坑之后沉淀下来的习惯说几点我现在做 Agent 相关项目时长期在用的习惯可能对你有参考价值。第一每新增一个 AI Skill都要写清楚“什么情况下不该用”。功能描述只能让模型知道这个技能可以做什么负面描述才能帮它避开大部分误调用。我见过很多技能因为少写了这一句在线上被模型以一种非常离谱的方式触发。第二新技能上线时不要一次性挂给所有 Agent。先在一个低风险场景里跑几天看调用日志、看错误率、看用户反馈判断稳定后再扩大范围。如果一上来就全局生效出了问题影响面会很大回滚也更麻烦。第三定期清理“僵尸技能”。有些技能上线后一周都没有被任何 Agent 真正调用过说明它要么需求不够真实要么描述表达得有问题导致模型始终发现不了它。我一般会选择改进描述再观察一周仍然没有调用就果断下线或合并避免这些无效技能继续占用 Agent 的上下文空间。我现在的项目已经不像第一个版本那样为了“全能”堆了一堆能力反而刻意保持精简。核心策略是主 Agent 下常驻技能不超过十个低频能力走路由所有技能都经过严格的输入输出结构设计再配合一个完整的调用日志和审计链路。这样一套组合下来AI Skills 才能真正成为 Agent 的助力而不是变成一团让模型混乱的函数清单。如果你也在做 Agent试着从最小闭环开始挑一个每天都会重复、结果格式相对固定的任务把它做成一个 Skill再用一个简单 Agent 去调用它。跑通之后再逐步扩展其他技能。这个路径可能没有“一步到位”的兴奋感但一定比上来就搭一个二十个技能的复杂系统要可靠得多。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →