ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

腾讯云上AI Skills实战:从堆Prompt到Agent可复用技能包重构

腾讯云上AI Skills实战:从堆Prompt到Agent可复用技能包重构 如果你也和我一样在腾讯云上维护过 Agent 项目大概率经历过这种场景模型本身很聪明但项目做得越久它越像一个什么都懂、什么都不精的实习生。我最近把一个内部监控 Agent 从纯 Prompt 架构重构成了 AI Skills 架构说实话重构完最明显的感受不是模型变强了而是我终于把一套可复用、可评审、可回滚的完整判断经验真正交到了它手里。这篇文章就把我这段时间在腾讯云环境里落地 AI Skills 的完整思路和操作过程拆开讲。我会先解释 Skills 为什么能解决 Agent 项目会而不精的尴尬再给出一个可以直接抄的 SKILL.md 最小结构接着讲云服务器、API 网关、LiteLLM Proxy 这些腾讯云相关组件是怎么串起来的最后用排查 CPU 异常这个真实技能做全流程拆解并分享几个排查踩坑的真实经历。适合正在做 Agent 开发、被提示词越写越长所困扰、想把重复工作沉淀成可复用能力的人。1. 为什么 Agent 越全越废AI Skills 到底改了什么1.1 传统 Agent 的瓶颈不在模型而在经验无处存放先说我之前那个项目是怎么翻车的。最初版本把运维手册、常见命令、判断逻辑全部塞进 system prompt为了让它看起来全能我还把告警处理、日志检索、服务健康检查的注意事项都写了进去。结果是上下文越来越长模型的行为越来越飘。同一个CPU 高的问题上午它能给出正确排查顺序下午同样的输入它就换了一套说法甚至偶尔会凭空捏造一些并不存在的诊断步骤。后来我把问题归因到模型的上下文窗口不够大上但实际上现在模型的上下文已经很大了真正的问题是知识一旦全部塞在提示词里既没有结构也没有按需加载的入口。Agent 每次处理任务都要在一大堆可能相关的指令里自己挑重点挑错了行为就漂移。这就像一个实习生面前堆了三百页规章制度遇到问题时他根本不知道该翻哪一页。AI Skills 的核心思路就是把这三百页规章制度拆成一本本按场景分类的操作手册。每个 Skill 解决一类具体问题包含完整的判断流程、执行脚本、参考材料。模型不需要在每次对话时都读到全部手册它只需要根据任务描述先判断现在应该调用哪个技能然后按技能定义逐步执行。也就是说知识从常驻上下文变成了按需加载的能力包。1.2 Skills 和 Function Calling、MCP、Prompt 的边界在哪很多刚开始接触的人会问Skills 和函数调用有什么区别和 MCP 又是什么关系我的理解是这样的用一张表可以看得很清楚。技术/方案解决的问题适合的场景短板Prompt 直接注入把经验一次性告诉模型简单任务、一次性对话上下文膨胀、行为漂移、不可复用Function Calling让模型按 JSON Schema 调用函数单次原子操作、参数明确表达不了复杂判断流程也没有领域知识承载MCP统一工具访问协议需要接入大量外部系统工具对内部简单服务来说偏重AI Skills把完整工作方案沉淀为可插拔技能包需要模型掌握一段有流程、有经验的判断过程对 Skill 文件设计和环境集成有要求拿日常类比来说Function Calling 更像是给实习生一个计算器告诉它按哪个键能算出结果MCP 是给实习生一把能打开所有办公室的万能钥匙去哪都能取数据AI Skills 则是给每个岗位单独写一份工作手册手册里写清楚什么情况该做什么、做到什么程度算完成、常见坑在哪里。实际项目里它们不是互斥的。我的做法是能用 Function Calling 解决的单步调用就不过度封装需要对接外部工具时考虑 MCP而凡是涉及多步骤判断 经验知识沉淀的工作流全部整理成 AI Skills。避免一上来就搞复杂化。1.3 在腾讯云环境里看 AI Skills我发现它其实是个配置层腾讯云上跑 Agent 项目最常用组合是云服务器 容器/进程管理 API 网关 模型服务。你会发现大部分组件的稳定性问题都已经解决了真正没解决的是业务经验放在哪儿。我以前把经验放在代码里改一条判断逻辑要重新部署整个服务后来放在提示词里改起来倒是方便了但是每次改动都会影响其他行为。AI Skills 最大的好处是它是一个独立于主程序的配置层。Skill 文件随版本仓库走改了一个技能不会影响其他技能Agent 框架本身只需要提供加载技能、解析 SKILL.md、执行对应脚本的机制。这个特性在腾讯云这种多环境部署场景下特别有价值。开发环境、测试环境、生产环境可以各自挂载不同版本的技能库灰度发布时也不用重新构建镜像。后面第 5 部分我会讲到一个真实事故当时就是因为技能版本和生产环境不一致导致排查了整整一下午所以这个点我后面会专门强调。2. 最小可用交付一个 SKILL.md 从零到能跑2.1 一个 Skill 目录里到底放什么先给出一份我常用的 Skill 目录结构。这个结构不是拍脑袋定的而是考虑了谁来读、谁来执行两个角色框架/模型需要读 SKILL.md 来决定要不要用、怎么用执行层需要跑 scripts 里的脚本来拿真实数据模型可能需要查 references 里的扩展材料来理解背景assets 里通常放图片或辅助资源不是每个技能都必需skill-cpu-troubleshoot/ ├── SKILL.md ├── scripts/ │ ├── collect_cpu_metrics.py │ └── probe_process.sh └── references/ ├── common_cpu_issues.md └── metric_glossary.mdSKILL.md 是整个技能的入口相当于一本书的目录和摘要。scripts 是真正干活的工具references 是给模型备查的背景知识。为什么要拆这么细因为模型的推理成本是跟着 token 走的。如果你把脚本、参考文档全都塞进 SKILL.md模型每次触发这个技能都要读一遍毫无必要。正确做法是SKILL.md 只保留精简的决策流程和步骤遇到需要深入理解的知识再去 references 里检索。2.2 一份可以直接拿去改的 SKILL.md 模板下面是我在项目里经过多轮迭代后沉淀下来的模板。你不用照抄全部字段但 name、description、正文的何时使用和操作步骤是必需的不然 Agent 框架没法做技能召回模型也不知道执行边界。--- name: cpu-troubleshoot description: Use when server CPU usage is high, system load is elevated, response time degrades, or users report service slowness. Triggers CPU diagnostics workflow and returns possible causes. --- # CPU Troubleshoot ## When to Use - 监控告警显示 CPU 使用率持续超过阈值 - 用户反馈服务响应变慢且怀疑与资源竞争有关 - 例行巡检时需要对 CPU 状态做快速评估 ## Workflow 1. 先运行 scripts/collect_cpu_metrics.py获取当前 CPU 使用率、负载、Top 进程列表。 2. 对比 references/metric_glossary.md 中的指标说明判断是否存在异常进程。 3. 如果发现可疑进程使用 scripts/probe_process.sh PID 查看该进程的线程数、内存占用和启动命令。 4. 将诊断结果整理为现象描述、可疑进程、可能原因、下一步建议。 ## Boundaries - 本技能只做诊断和分析不做任何变更操作。 - 不负责自动 kill 进程、重启服务。 - 如果分析结果指向数据库慢查询或网络延迟转交对应技能处理。 ## Dependencies - 需要 Python 3.8 和 psutil 库 - 需要在目标服务器本地执行或通过远程执行通道调用2.3 写 SKILL.md 最容易翻车的三个地方第一description 写得太广告、太模糊。比如全面的 CPU 诊断技能高效分析 CPU 问题这种描述模型做技能召回时根本不知道怎么匹配。description 里应该写清楚触发场景最好包含典型关键词比如CPU 高load average响应慢。我见过项目里模型放着现成技能不用就是因为 description 没写触发词模型根本没意识到这个技能可以用。第二Workflow 写得太抽象。只写分析 CPU 问题是不行的模型拿到这种步骤还是会自由发挥。要让 Workflow 足够原子化每步要么是运行哪个脚本要么是对比哪个参考文档要么是输出什么格式的结果把经验固化在流程里而不是让模型临场发挥。第三SKILL.md 越来越长最后变成一篇论文。一旦超过 60 行就说明有内容应该拆到 references 目录。SKILL.md 要做的是索引不是百科。我见过有人把一整个运维知识库塞进一个 SKILL.md结果模型读前面的内容就已经把注意力耗光了真正执行时反而漏步骤。3. 云上接线把 Skill 暴露给 Agent 的那条链路3.1 Skill 脚本需要一个稳定的运行底座Skill 定义写好之后最核心的问题是里面的 Python 脚本、Shell 脚本到底在哪里执行我最初的想法是让 Agent 服务直接在本机执行所有技能脚本但很快就发现问题——Agent 服务跑在 Docker 容器里技能脚本需要访问宿主机的系统指标、进程列表、日志文件权限边界非常难处理。后来我调整了架构用一句话概括Agent 主程序负责思考决策独立的技能执行服务负责真正干活。每个 Skill 的脚本被封装成一个带 HTTP 接口的执行服务监听在本机或内网某个端口。Agent 通过判断认为需要某个技能时就调用这个执行服务对应的接口把参数传进去拿回结构化结果继续分析。这种拆分看似多了一层调用实际上解决了很多问题。技能脚本出现 bug 时可以单独调试、单独重启不影响 Agent 主进程脚本需要更高权限时也只需要提升技能执行服务的权限不用把整个 Agent 服务提权。安全边界清晰很多。3.2 域名与反向代理不要把服务端口直接扔公网如果技能执行服务只在内网使用最简单的方案是让 Agent 服务直接访问内网 IP。但如果你的 Agent 需要对外提供 API或者技能执行服务要和外部系统做集成就必然要解决入口问题。我的建议是不要怕麻烦配置一个独立的二级域名通过 Nginx 反向代理把请求转发到本机的技能执行服务。腾讯云控制台添加域名解析后把二级域名解析到服务器公网 IP然后在 Nginx 里做转发。实际配置类似下面这样server { listen 443 ssl; server_name skill-api.example.com; ssl_certificate /etc/nginx/ssl/example.com.pem; ssl_certificate_key /etc/nginx/ssl/example.com.key; location /cpu-troubleshoot/ { proxy_pass http://127.0.0.1:9001/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 300s; } }这里有个关键经验Nginx 代理后面技能执行服务的超时时间一定要调大。默认的 60 秒超时在诊断脚本需要采集多轮数据时大概率不够用。我自己被这个默认超时坑过不止一次后面还会展开讲。更重要的是腾讯云安全组的配置。我强烈建议你只放行真正需要的入站端口。如果对外只提供 HTTPS 服务那就只放行 443如果需要 SSH 管理再把 22 放行给固定 IP。技能执行服务的原始端口比如 9001不要直接暴露在公网让它只监听 127.0.0.1 或内网地址就够了。网上那种把所有端口全部打开的说法在实践里是最危险的操作没有之一。安全组的最小放行原则对生产环境来说就是底线。3.3 LiteLLM Proxy 在这条链路里解决什么问题如果你只接一家模型厂商那直接配置 Agent 的 base_url 就行。但实际做 Agent 项目时很少有人只用一家模型。不同任务的成本差异很大简单的技能调用用便宜的小模型就够了复杂的推理和长链路规划需要能力更强的大模型。LiteLLM Proxy 是我现在用的核心组件。它相当于一个统一模型网关把各家模型 API 全部转换成 OpenAI 兼容格式Agent 只需要面向一个固定的/chat/completions接口开发。而且它天然支持模型路由和故障回退主模型超时或限流时请求会自动降级到备用模型。我的一份最小 LiteLLM 配置长这样model_list: - model_name: cheap-fast litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: strong-model litellm_params: model: openai/qwen-max api_key: os.environ/QWEN_API_KEY litellm_settings: fallbacks: [{cheap-fast: [strong-model]}] num_retries: 2 request_timeout: 300配置完之后Agent 的 base_url 指向 LiteLLM Proxy 的地址然后在 Prompt 或技能里声明本技能建议使用 cheap-fast 模型。这样技能执行成本可控而复杂主流程可以切到 strong-model。对需要稳定输出的场景这是一层非常实用的保险。还需要强调的是LiteLLM Proxy 的 request_timeout 必须和技能执行链路整体超时匹配。如果技能脚本采集数据需要 90 秒Proxy 却只给 30 秒超时那 Agent 必然拿到超时错误。这条链路上的超时配置不是孤立的得从 Agent 到 Proxy 到执行服务全链路统一设置。4. 完整实战让 Agent 学会排查 CPU 异常4.1 需求切片别让 Agent 当全栈运维我在实际业务里遇到的场景是线上服务出现 CPU 使用率飙升值班同学需要快速判断是业务流量上涨、慢查询拖累、还是进程死循环。最开始我想做一个运维全能 Agent让它一键搞定所有问题后来发现这是错误的打开方式。原因是一键搞定所有问题意味着技能边界极其模糊模型要么不知道该从哪里下手要么在个别环节过度自信。正确做法是把需求切成一个个可以独立验证的技能CPU 异常检查、磁盘空间检查、日志关键词检索、服务健康状态探测。每个技能只负责一件事技能之间通过建议转交衔接。这套思路就是 AI Skills 编排的基础。4.2 完整 S​​KILL.md 和背后的 Python 实现以 CPU 异常检查为例完整技能定义可以这样写--- name: cpu-troubleshoot description: Use when server CPU usage is high, load average is rising, users report service slowness, or monitoring alerts trigger on CPU. Analyzes metrics and returns possible causes. --- # CPU Troubleshoot ## When to Use - CPU 使用率连续超过 80% - load average 持续走高 - 服务响应慢怀疑与资源竞争有关 ## Workflow 1. 执行 scripts/collect_cpu_metrics.py --top 5获取系统整体 CPU、load、Top 进程。 2. 读 references/common_cpu_issues.md将 Top 进程和常见问题模式做匹配。 3. 如果发现嫌疑进程继续执行 scripts/probe_process.sh pid获取线程数、工作目录、父子进程关系。 4. 按固定模板输出诊断报告。 ## Output Format 现象 - 嫌疑进程 - 可能原因 - 建议动作。原因分类须从 references 中选择不自行发明。 ## Boundaries - 只读检查不执行任何 kill、重启或变更操作。 - 无法确定原因时明确写无法判断并建议进一步检查项。配套的采集脚本不需要很复杂。我用的一个简化版本如下#!/usr/bin/env python3 import os import sys import psutil def main(): top_n 5 if len(sys.argv) 2 and sys.argv[1] --top: top_n int(sys.argv[2]) print(CPU percent:, psutil.cpu_percent(interval1)) print(Load average:, psutil.getloadavg()) print(Memory percent:, psutil.virtual_memory().percent) print(f\nTop {top_n} processes by CPU:) procs [] for proc in psutil.process_iter([pid, name, cpu_percent, memory_percent, cmdline]): try: info proc.info info[cpu_percent] proc.cpu_percent(interval0.1) procs.append(info) except (psutil.NoSuchProcess, psutil.AccessDenied): continue procs.sort(keylambda x: x.get(cpu_percent, 0), reverseTrue) for p in procs[:top_n]: cmd .join(p.get(cmdline) or [])[:120] print(f{p[pid]}\t{p[name]}\t{p[cpu_percent]:.1f}%\t{p[memory_percent]:.1f}%\t{cmd}) if __name__ __main__: main()这段脚本的核心目的是给 Agent 提供当下最值得关注的进程。不要让 Agent 直接读一堆/proc文件然后自己分析脚本层把原始数据筛选成结构化结果模型才能真正专注于判断。4.3 实测效果对比同一个问题的前后差异我把同一个问题分别抛给改造前的 Agent 和改造后的 Agent差异非常直观。对比维度改造前纯 Prompt改造后AI Skills收到CPU 飙高后首轮动作直接给出 5 条通用排查建议先运行采集脚本拿到当前真实 Top 进程诊断依据依赖模型记忆中可能过时的经验依赖脚本返回的真实数据 技能内参考文档出现陌生进程时容易猜测编造可能原因能区分已知模式和未知情况未知时如实说明输出稳定性同一问题多次回答不一致输出模板固定边界清晰变更操作偶尔会建议直接 kill 进程受到 Boundaries 限制只读分析这种差异在公司内部试用时感觉特别明显。不了解技术细节的同学用改造后的 Agent也能按照固定报告格式理解当前服务状况不再被模型一堆模棱两可的通用建议淹没。这就是把工作方法沉淀成 Skill 之后得到的实际收益。5. Skills 失灵时我从日志里学到的三件事5.1 事件一Agent 说找不到技能其实是目录层级错了有次我把新写的磁盘检查 Skill 放上服务器Agent 却始终说我没有可用的磁盘检查技能。我看技能文件名没问题、内容格式也没问题一度怀疑是框架的 Bug。后来逐个目录排查才发现我在打包时多套了一层目录# 错误结构 skills/ └── skill-disk-check/ └── skill-disk-check/ ├── SKILL.md └── ... # 正确结构 skills/ └── skill-disk-check/ ├── SKILL.md └── ...Agent 框架在扫描skills/目录时会把每个一级子目录视为一个技能。我多套了一层框架读到的其实还是文件夹下一层SKILL.md 没有被正确解析。这种情况不会直接报错只是技能静默失效。排查这类问题我建议按这个顺序检查先看技能目录层级是否符合框架约定再确认 SKILL.md 首行是否是 YAML frontmatter而且 frontmatter 之前不能有空行、不能有 BOM 头。很多从 Windows 编辑器中复制出来的文件会带 BOM几行不可见字符就足以让解析失败。5.2 事件二执行超时但不是模型的问题当时 Agent 在跑日志分析类技能到第三步时频繁报 execution provider 超时。我一开始以为是模型响应慢给 LiteLLM Proxy 调了超时甚至在 Agent 框架里也加了重试。结果问题依旧。后来我手动执行了一下技能脚本发现单次采集日志要跑 100 多秒因为脚本要从几个 GB 的日志文件里做正则匹配。链路变成了Agent 调用技能执行服务 - 脚本跑 100 秒 - Nginx 默认等 60 秒就断开 - Agent 收到超时错误。中间任何一个环节超时配置不匹配最终表现都是Agent 执行失败。排查这类问题有三个关键步骤缺一不可手动运行技能脚本并计时确认脚本本身的执行时长用time curl http://127.0.0.1:9001/...测试技能执行服务的响应时长检查 Nginx、Agent 框架、LiteLLM Proxy 各层的超时配置以最长耗时为准统一调大事件二给我的教训是遇到 Agent 执行超时先不要怀疑模型能力也不要急着换更贵的模型。先定位瓶颈是在模型思考还是工具执行。绝大多数超时问题根源在工具执行链路的某个隐式默认值。5.3 事件三容器内访问不到宿主机的技能服务有一版架构我把 Agent 主程序放在 Docker 容器里技能执行服务直接跑在宿主机上。奇怪的是在宿主机上用curl 127.0.0.1:9001一切正常但容器里的 Agent 怎么都访问不到。查了一圈才发现技能执行服务启动时监听的是127.0.0.1:9001。这在宿主机本地访问没问题但容器里的请求会先走到 Docker 网桥再由宿主机内核转发到目标地址。而监听在 127.0.0.1 的服务只接受本机回环接口的流量根本不会处理来自 Docker 网桥的转发请求。解决办法有两种要么让技能服务监听内网 IP0.0.0.0:9001再通过腾讯云安全组限制只允许内网来源访问要么在 Docker 启动时用--network host模式直接共享宿主机网络栈。我最终选择的是第一种因为这样安全边界更清晰不会因为 host 网络模式导致端口全部暴露。故障现象排查方向最终解法Agent 完全不认某个技能目录层级、SKILL.md 格式修正目录结构检查 frontmatter技能执行时报超时脚本耗时、Nginx/Proxy 超时配置统一调大全链路超时容器内无法访问技能服务监听地址、网络模式监听内网 IP 安全组限制来源Agent 行为不受 SKILL.md 约束是否误用了旧的技能版本服务重启后重新加载技能目录6. 一组 Skill 就是一名员工多技能编排与迭代心得6.1 技能粒度的划分宁可多而专不要少而全当你有十几个 Skill 之后会发现一个新问题模型在召回技能时可能出现误判。比如CPU 高和内存高都会导致服务慢如果两个技能的 description 都写了服务变慢模型可能不知道该调用哪个。我的经验是技能粒度一定要偏专。一个 Skill 对应一个明确的触发场景、一套清晰的判断流程。与其做一个系统巡检技能不如拆成 CPU、内存、磁盘、网络、日志五个独立技能。这样每个技能的 description 可以写得很精确包含更多可区分的触发词。模型做召回时的准确率明显会提高。六七个技能是使用体验的一个分水岭。技能太少Agent 容易自由发挥技能太多如果命名和描述没有做好分类召回又会混乱。比较好的做法是给技能加上统一前缀比如ops-cpu-troubleshoot、ops-disk-check然后在 description 里强调触发词。这样即使技能库扩展到几十个模型也能通过前缀语义理解能力域。6.2 技能的依赖与权限要单独管理如果你把技能脚本当成一段普通代码来处理会遇到很现实的权限问题。有的脚本需要读系统日志有的脚本需要调用外部 API有的脚本甚至需要访问数据库。如果把所有权限都授予 Agent 主进程风险非常大——模型一旦在某个任务里被骗或产生幻觉可能造成越权操作。我现在的做法是给技能执行服务做独立的权限控制。每个技能通过配置声明自己需要访问的资源比如运行用户白名单 API可写目录执行服务在运行技能前先做一次权限校验。这和给不同员工发不同门禁卡是一个道理。Agent 的聪明要建立在边界明确的基础上否则能力越大出错时的破坏力也越大。6.3 SKILL.md 也要纳入版本管理而且要和 Agent 版本联动技能文件本质上是代码必须放进 Git 仓库。只改了一行脚本代码就导致 Agent 行为变化这类问题在项目里太常见了。没有版本管理的技能库等于给 Agent 装了一个无法回滚的大脑。我的实践要求是Agent 框架每次发布都固定一个技能版本号技能库通过 Git tag 进行管理。每个 SKILL.md 的变更必须有明确的 commit message而且要有对应的测试用例。所谓的测试用例不一定很复杂可以是一组黄金问题集即在某个技能修改之后把之前踩过的典型案例重新跑一遍确认没把原来已经修复的问题带回来。这个操作成本很低但对技能库的稳定性帮助非常大。最后说点实际的个人体会。如果你正在被 Agent 项目跑起来了但不好用的问题折磨我建议别急着换模型也别继续堆 Prompt而是先挑一个你每天都会重复处理的任务把它做成最小的 Skill 试运行。按本文第 2 部分的模板写一版 SKILL.md放到自己的环境里跑一遍你会立刻感受到角色边界清楚带来的稳定性提升。等两三个核心技能跑顺了再去扩张技能库保持多一点专、少一点全的节奏全能 Agent反而会一步步接近。
返回列表