ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用AI Skills打造全能Agent:腾讯云部署实战全记录

用AI Skills打造全能Agent:腾讯云部署实战全记录 做一个真正能自动干活的 Agent光会把大模型的接口接上去是远远不够的。这阵子我一直在腾讯云上折腾一套带自定义技能的全能 Agent最后落地的核心思路就是把“会做什么”拆成一个一个 AI Skills让模型按需加载、按规则执行。今天这篇就是这次实践的全记录环境怎么搭、技能怎么写、镜像怎么推送、部署时踩了哪些坑全给你讲透。适合正在做 Agent 开发的人也适合刚听说 skills 和 agent 这两个词但一直没搞清楚区别的入门者。先给结论一套能稳定跑起来的 Agent不在于模型参数有多大而在于你有没有把“能力”和“决策”拆清楚。AI Skills 负责封装能力Agent 负责做决策腾讯云负责提供服务器、容器镜像和域名这些底座。下面我按实际动手的顺序从概念、环境、技能编写、部署到问题排查一步一步过。1. AI Skills 的本质把 Agent 从“聊天机器”变成“执行机器”1.1 一个 Agent 的组成远不止大模型先说个很多人容易踩的误区以为 Agent 就是“大模型 提示词”。真这么干你做出来的东西顶多算个聊天机器人离 Agent 差得远。我理解的一个能稳定干活的 Agent至少由这几部分拼起来LLM 引擎负责理解、规划、生成是大脑但不是全部。Agent 调度逻辑负责决定“下一步该调用什么”这是决策层。工具执行层真正去查数据库、发请求、跑脚本的一层。记忆模块记录对话历史、任务状态、技能执行结果保证长任务不丢上下文。安全约束控制权限、校验输入输出防止模型乱调危险操作。AI Skills 在这套结构里正好卡在“工具执行层”和“调度逻辑”之间。它比普通函数多一点比完整的 Agent 少一点。你可以把它理解成一份“岗位说明书 操作手册”的打包文件告诉模型这个技能是做什么的、什么时候该用、需要传什么参数、执行后返回什么格式。没有 Skills 的 Agent对具体业务一无所知只能泛泛地聊。有了 Skills它才知道挨着腾讯云服务器该怎么做 Redis 巡检、看到日志该怎么定位故障、拿到需求该怎么执行部署。Skills 是 Agent 从“嘴炮”变成“能干”的分水岭。1.2 Skill、Tool、Harness、Agent 到底差在哪里热词里很多人搜“skill 和 agent 的区别”“harness 和 agent 的区别”我一句话总结这几个词不是同层级的概念放在一起比较本身就是很多教程的坑。我用生活里开餐厅打比方Agent 是店长。他看情况决定客人点了菜该让后厨做店里没食材了该让采购去补。他负责“决策”和“安排”。Skill 是后厨的“招牌菜谱”。它描述了一道菜怎么做、需要什么食材、出锅标准是什么。模型看到 Skill就知道遇到对应场景该怎么处理。Tool 是具体的锅碗瓢盆。Skill 最后调用的是 ToolTool 真正去执行命令、请求 API、操作文件。Harness 是餐厅的整套运营流程和规章制度。它负责把“店长的想法”翻译成“后厨能执行的动作”并把权限边界、异常处理这些兜底逻辑管起来。所以Agent 决定“用不用某个 Skill”Harness 保证“Skill 执行时不出格”Tool 负责“真正把事情办掉”。你可以在一个 Agent 里挂多个 Skills每个 Skill 里再封装多个 Tool。理解了这个层次后面写代码、排查问题都会顺很多。1.3 为什么好的技能是“可复用能力包”把能力写成 Skill最大的收益是可复用。第一次给 Agent 写“腾讯云服务器巡检”这个技能可能要折腾一下午但写完以后新开一个 Agent 项目直接把 Skill 目录丢进去就能用。我自己的做法是把经常重复做的事情尽量沉淀成 Skill比如日志分析、Redis 运维、容器部署检查、域名解析排查。实践中有个很关键的认知写 Skill 和写 Prompt 不一样。Prompt 是给模型看的一次性指令写完就散在对话里。Skill 是结构化的独立文件有名字、有描述、有参数定义、有执行脚本既能让模型读懂也能让程序调用。这个结构性差异决定了 Skill 可以被检索、被编排、被多 Agent 共享而 Prompt 只能靠复制粘贴。把这层关系吃透之后你再去看各种 Agent 框架的文档基本不会迷路。2. 腾讯云环境准备服务器、域名、镜像仓库一条龙2.1 服务器初始化与 Docker 安装做 Agent 服务没必要一上来就买高配机器。我这次用的是腾讯云 2C4G 的轻量应用服务器系统选的 Ubuntu 22.04日常跑 Agent 服务加 Redis 完全够用。如果你的 Agent 要本地跑模型或者处理大量并发建议直接上 CVM内存起步给到 8G但大多数人做实验和中小业务2C4G 起步就行后续不够再纵向升级。服务器买到手之后别急着装环境先把安全组端口规划好。我一般是只放行 22 端口SSH、80/443 端口对外服务其他端口一律不开。Agent 服务如果需要外部调用也不要裸奔 8080建议通过 Nginx 反代或者直接用域名加 HTTPS 访问。安全组宁严勿松后期再按需放通比我一个新手时期把端口全开半年没人管要稳得多。然后装 Dockersudo apt update sudo apt upgrade -y curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin sudo systemctl enable --now docker sudo usermod -aG docker ubuntu这里有两个细节。第一不要在 root 用户下直接跑容器建议创建一个普通用户比如 ubuntu加入 docker 组日常操作都用普通用户执行权限隔离更干净。第二国内服务器直接拉 Docker Hub 官方镜像经常不稳定后面我会讲怎么结合腾讯云的镜像加速和容器镜像服务来解决。2.2 腾讯云二级域名怎么申请和解析很多人搜“腾讯云怎么申请二级域名”其实二级域名不是“申请”来的是在你的主域名下加一条 DNS 解析记录。前提是你先有一个备案通过的主域名。如果你的服务器在大陆地域域名解析到这台服务器之前必须完成 ICP 备案否则解析了也访问不了这个流程建议提前处理。操作步骤很直接登录腾讯云 DNSPod 控制台进入你的主域名。添加记录类型选 A主机记录填你想用的前缀比如agent记录值填服务器的公网 IP。TTL 选默认的 600 秒即可解析生效一般几分钟到半小时。生效后agent.你的域名.com就会指向你的服务器。如果服务器走的是 IPv6记录类型就选 AAAA。如果你只是做本地测试不想绑域名也可以把 Agent 服务直接监听在 IP 的对应端口上但生产环境强烈建议走域名 HTTPS不然模型服务、回调地址、外部系统对接都会遇到麻烦。我这次实际用下来有了域名最大的便利就是配置回调地址时不用记 IP后面接入外部 API 也省心得多。2.3 Docker 推送腾讯云 TCR 的完整流程Agent 写好后我习惯先打成 Docker 镜像再推到腾讯云容器镜像服务 TCR部署时直接从仓库拉取。这样换机器、扩容、回滚都比在服务器上手工装环境靠谱。腾讯云容器镜像服务的控制台里要先完成三步开通服务、创建命名空间、创建镜像仓库。命名空间相当于镜像的目录镜像仓库则是具体镜像的“户口”。我一般按项目分命名空间比如agent-lab镜像仓库名就叫my-agent。本地推送的命令# 1. 登录 TCR用户名填腾讯云账号 ID密码填访问凭证 docker login ccr.ccs.tenyun.com -u 账号ID # 2. 给本地镜像打上 TCR 的 tag docker tag my-agent:latest ccr.ccs.tenyun.com/agent-lab/my-agent:latest # 3. 推送 docker push ccr.ccs.tenyun.com/agent-lab/my-agent:latest这个过程中最容易栽跟头的地方有三处第一访问凭证不是登录密码需要在控制台单独申请建议设短有效期第二镜像名和命名空间必须全小写第三如果推送经常断多半是公网带宽限制可以把镜像分块上传或者用内网模式。我自己第一次推的时候没创建访问凭证直接拿登录密码登折腾了半天发现 401后来才知道要先去控制台生成凭证。服务器拉取时也是同样登录后docker pull。为了部署时不用手动登录我一般会在服务器上配置好凭证文件或者用 TCR 提供的免登录拉取方式具体看你用的是私有仓库还是公开仓库。公开仓库确实方便但生产环境镜像尽量私有。3. 亲手写一个 AI Skills从文件结构到参数设计3.1 SKILL.md 是技能的核心说明书AI Skills 的文件结构并不复杂关键在于约定清晰。我用的是目前社区比较通用的标准一个技能对应一个目录目录里必须有核心说明书SKILL.md其他辅助文件按需添加redis-ops/ ├── SKILL.md ├── scripts/ │ └── redis_check.sh ├── assets/ │ └── config_templates/ └── requirements.txtSKILL.md是整个技能的灵魂它既是给模型看的说明书也是给调度器判断“什么时候该调用这个技能”的依据。我建议在文件头部用 YAML front matter 写元信息正文用 Markdown 写详细说明。字段大致长这样--- name: redis_ops description: | 当用户需要排查 Redis 连接失败、修改密码后无法重启、查看 Redis 状态等运维场景时使用。 也适用于服务器上 Redis 配置不正、端口被占用、日志报错等问题。 version: 1.0.0 parameters: type: object properties: action: type: string enum: [status, reset_password, restart] description: 要执行的操作类型 password: type: string description: 新密码仅在 reset_password 时必填 required: [action] ---正文部分重点写清楚“适用场景”“使用步骤”“注意事项”和“返回格式”。模型是靠 description 来匹配技能的所以 description 一定要把触发条件写具体宁可啰嗦也不要含糊。比如别只写“Redis 运维”要写“Redis 连接失败、修改密码后重启失败、端口被占用等场景”这样模型遇到实际问题时才容易把它匹配上。3.2 一个 Redis 运维技能的完整示例光讲结构太空我拿这次实践里真实用到的 Redis 运维技能做个演示。因为热词里就有“主要是我在腾讯云服务器上安装redis但是我修改redis密码之后再重启redis就一直不”这类问题非常适合做成 Skill。先看SKILL.md的正文部分# Redis 运维技能 本技能用于腾讯云服务器上 Redis 的常见运维操作包括查看服务状态、修改密码后重启、排查启动失败原因。 ## 适用场景 - redis-cli ping 返回无法连接 - 修改 requirepass 后重启 Redis 失败 - Redis 服务启动后立即退出需要查看日志定位原因 ## 使用步骤 1. 首先通过 systemctl status redis 查看服务状态判断进程是否存活 2. 查看 Redis 日志默认位于 /var/log/redis/redis-server.log 3. 检查配置文件和实际加载的配置文件是否一致重点看 requirepass、bind、protected-mode 4. 执行对应操作查看状态 / 重置密码 / 重启服务 ## 注意事项 - 修改 Redis 密码前先备份原配置文件 - 修改完成后必须重启生效建议先 stop 再 start避免老进程占用端口导致新进程起不来 - 密码不要用空格和特殊转义字符避免配置解析问题 - 如果是腾讯云安全组限制修改配置后还要检查端口是否放行对应的执行脚本scripts/redis_check.sh#!/bin/bash ACTION$1 case $ACTION in status) systemctl status redis-server --no-pager redis-cli -h 127.0.0.1 ping ;; reset_password) NEW_PASS$2 if [ -z $NEW_PASS ]; then echo 请提供新密码 exit 1 fi sudo sed -i s/^# requirepass .*/requirepass ${NEW_PASS}/ /etc/redis/redis.conf sudo systemctl stop redis-server sudo systemctl start redis-server redis-cli -h 127.0.0.1 -a ${NEW_PASS} ping ;; restart) sudo systemctl restart redis-server systemctl status redis-server --no-pager ;; esac别小看这个朴素的结构。模型拿到这个 Skill 之后看到“redis 修改密码后重启一直不”这种用户描述会先匹配 description然后按 SKILL.md 里的步骤去执行。参数 schema 又保证了 action 不会传成奇奇怪怪的字符串。这种“描述 步骤 脚本”的组合就是 AI Skills 能落地的关键。3.3 技能的边界划分与颗粒度把握写 Skills 没有标准答案但我在实践中总结出几条颗粒度原则一个技能只做一件事。“Redis 运维”可以是一个技能但别把它和“MySQL 数据备份”塞到一起。技能目标单一description 就更容易写清楚模型调用时才不容易出错。描述里写清触发条件。这是最容易偷懒的地方。我见过很多 Skill 的 description 就一句话“用于 Redis”结果模型判断不了什么时候该用。你应该写“当 Redis 无法连接、修改配置后重启失败、需要查看服务状态时使用”。参数尽量枚举。能用 enum 约束的值都列清楚模型不是每时每刻都聪明给它的选择越少它出错概率越低。脚本要幂等。同一个技能脚本被模型重复调用是常态脚本设计成可重复执行才不会把服务器状态搞乱。另外Skill 的代码一定要在本地先测。我这次就吃过亏SKILL.md 写得很漂亮结果脚本里有几个变量没转义模型调用后返回一堆乱码排查了半天才发现是脚本本身的问题。技能脚本和业务代码一个待遇必须做单元测试。4. 把 Agent 接上 Skills再部署到腾讯云4.1 用代码方式理解 Skill 接入原理Skill 接入 Agent在工程上本质上是把 Skill 翻译成模型可调用的函数。我用一个简单示例说明。假设你已经定义好redis_ops这个 Skill在 Agent 的代码里需要把它注册成一个工具函数并把函数声明传给模型import json import subprocess def redis_ops(action: str, password: str None) - str: Redis 运维status / reset_password / restart cmd [bash, skills/redis-ops/scripts/redis_check.sh, action] if password: cmd.append(password) result subprocess.run(cmd, capture_outputTrue, textTrue) return result.stdout if result.returncode 0 else result.stderr # 把这套声明给模型模型就知道什么场景调这个函数 tool_specs [ { type: function, function: { name: redis_ops, description: 排查 Redis 连接失败、修改密码后无法重启、查看 Redis 状态等问题, parameters: { type: object, properties: { action: {type: string, enum: [status, reset_password, restart]}, password: {type: string, description: 新密码仅重置密码时传入} }, required: [action] } } } ]接入之后模型会在对话过程中判断用户意图生成一个工具调用请求。Agent 框架拿到请求后执行对应的 Python 函数再把结果返回给模型模型根据结果继续组织回答。这一来一回就是 Agent 使用 Skill 的最基本链路。在这套链路里tool_specs里的description对应的是 SKILL.md 的 description函数体对应的是 scripts 脚本的逻辑。很多框架会自动帮你完成这些映射但底层原理都一样。理解了这一点你换任何框架都不慌。4.2 本地调试先当普通函数测起来上云之前我强烈建议先在本地把 Skill 当普通函数跑通。别嫌这一步麻烦它至少能帮你过滤掉三成问题脚本本身报错、参数传递错误、返回格式不符合预期。我的做法是这样的在本地把redis_check.sh放到一个临时目录用普通调用方式直接测./redis_check.sh status ./redis_check.sh reset_password Test12345确认脚本逻辑和返回值都正确后再把它接到 Agent 框架里。用 Agent 框架的对话式调试故意输入“帮我查一下 Redis 状态”“改下密码之后重启”这类自然语言观察模型是否正确地选择了 skill、传参是否正确、执行返回是否被模型正确理解。本地调试最有用的一点是你可以把模型输出、函数入参、函数出参全部打印出来。日志一旦打印出来问题基本一目了然。很多时候模型没调用 Skill不是因为框架出问题而是因为 Skill 的 description 写得不够具体或者参数 schema 和脚本对不上。这些全部在本地循环修改比推到腾讯云上再慢慢看日志效率高好几倍。4.3 Docker Compose 部署 Agent Redis 记忆存储Agent 需要记忆。聊到一半模型必须知道前面说了什么执行到一半模型也必须有地方记录任务状态。我这次直接把 Redis 复用成 Agent 的记忆存储正好一台服务器上既有 Agent 又有 Redis省心。在服务器上创建docker-compose.ymlversion: 3.8 services: agent: image: ccr.ccs.tenyun.com/agent-lab/my-agent:latest container_name: my-agent restart: always ports: - 8080:8080 environment: - REDIS_URLredis://:your-redis-passwordredis:6379/0 - AGENT_LOG_LEVELINFO depends_on: - redis redis: image: redis:7-alpine container_name: agent-redis restart: always command: [redis-server, --requirepass, your-redis-password, --bind, 0.0.0.0] volumes: - redis-data:/data healthcheck: test: [CMD, redis-cli, -a, your-redis-password, ping] interval: 10s timeout: 3s retries: 5 volumes: redis-data:为什么要用 Redis 做记忆存储而不是 SQLite因为 Agent 的记忆天然适合用 KV 列表结构会话历史可以按 key 存任务状态可以设置 TTL 自动过期多个 Skill 并发执行时 Redis 的连接管理也比 SQLite 单文件锁要省心。restart: always保证服务崩溃后自动拉起。密钥通过环境变量注入不写死在镜像里镜像本身可以放心推到镜像仓库。启动命令docker compose pull docker compose up -d docker compose logs -f agent这里的坑在于如果 Redis 修改了密码启动顺序和密码不一致Agent 连接 Redis 就会失败。同时如果服务已经在跑改了配置一定要docker compose down docker compose up -d单纯restart有时候不会重新加载新的环境变量。5. 常见问题与排查技巧实录5.1 Redis 修改密码后重启失败的完整排查热词里有个非常典型的痛点修改 Redis 密码后重启一直不成功。我在腾讯云服务器上复现过这个问题原因通常不是你以为的那个而是下面几个叠加。第一个原因新旧配置文件不一致。很多人用systemctl edit redis或者改/etc/redis/redis.conf但实际 Redis 加载的是/etc/redis/redis-server.conf改错文件自然不生效。排查命令很简单systemctl show redis-server -p FragmentPath redis-server --version ps aux | grep redis先确认 Redis 到底加载了哪个配置再动手改。第二个原因老进程占着端口。改完配置你执行sudo systemctl restart redis-server结果 Redis 起不来看日志发现Address already in use。这是因为旧进程没有干净退出新进程绑不上 6379 端口。解决办法是先sudo systemctl stop redis-server确认进程退出后再start。第三个原因密码里有特殊字符。requirepass不是放在引号里解析的如果密码带#、空格、$这类字符很可能被配置解析砍掉一半。我在脚本里就吃过这个亏后来统一用字母和数字组合问题立刻消失。第四个原因protected-mode和bind配置的联动。如果 Redis 没设密码或者密码没生效客户端从腾讯云外网连 Redis 会被 protected-mode 拒掉这其实是安全机制在起作用。你把密码设置好并把bind 0.0.0.0配上外部才能正常访问。别一发现连不上就关 protected-mode安全底线别放松。排查时直接看日志journalctl -u redis-server -n 50 --no-pager日志里一般会直接告诉你失败原因比到处猜强太多。5.2 Docker 推送 TCR 失败的原因清单推送镜像到腾讯云容器镜像服务最常见的报错我整理成了一张表现象大概率原因处理方式denied: requested access to the resource is denied没登录或账号没有该仓库权限先docker login ccr.ccs.tenyun.com确认使用访问凭证unauthorized: authentication required登录凭证过期或使用临时密钥已失效重新生成访问凭证并登录name unknown/repository name not known命名空间或镜像仓库没创建或者 tag 写错去控制台确认命名空间和仓库名tag 改成镜像仓库地址/命名空间/仓库名:版本推送中途卡住、超时公网带宽限制镜像太大使用内网/VPC 推送或分块推送或换基础镜像减少体积manifest invalidtag 里的镜像名带了/或其他非法字符镜像仓库名用全小写不要下划线我自己踩得最多的就是登录凭证这件事。腾讯云 TCR 的登录用户名是腾讯云账号 ID密码不是用户密码而是单独创建的访问凭证。第一次用错确认后以后再没在这卡过。另外如果镜像体积很大建议用.dockerignore先把本地日志、依赖缓存排掉基础镜像尽量用 alpine 这类精简版推送和启动都快很多。5.3 Agent execution terminated 报错处理思路很多 Agent 框架在工具执行异常时最终只会给你一段干巴巴的错误agent execution terminated due to error。第一次遇到的人容易懵以为是自己代码哪里有问题其实这个报错只说明一件事Agent 的某一次工具调用失败了并且错误没有被兜住。处理思路分三步。第一步开调试日志。把 Agent 的日志级别调到 DEBUG重点看每次工具调用的入参和出参。很多框架会打印tool_call的完整信息你一眼就能看出是模型传错了参数还是脚本本身崩了。没有日志就只能瞎猜。第二步定位错误层级。错误可能出在三个位置模型生成超时或格式不对、工具函数内部抛异常、工具返回的格式模型没法解析。我遇到最多的是第三类脚本输出了一堆非结构化日志模型的上下文被搞混然后判定“无法继续执行”。解决办法是在 SKILL.md 里约定返回格式比如统一返回 JSON{ status: ok, message: redis restart success, data: {} }第三步给工具加异常拦截。每个工具函数都包一层 try-except出了错返回结构化错误信息而不是让异常直接杀穿 Agent 主循环。这一步做完execution terminated 的报错基本可以被消除大半。实际上“agent execution terminated”很多时候不是故障而是 Agent 自己“不想干了”。模型判断当前工具返回的结果已经没法继续完成任务或者上下文里没有可用的 Skill 来处理后续步骤就会主动终止。这时候你要做的不是盯着报错看而是回去检查Skill 的 description 是否足够覆盖用户场景工具返回的信息是否足够让模型继续把这些补上Agent 才能真的“全能”。5.4 腾讯云注册提示网络环境异常怎么办新用户注册腾讯云时有时会遇到提示“您所处的网络环境异常无法进行注册”。这个提示通常是账号安全风控拦截了当前网络出口 IP多见于公司局域网、公共 Wi-Fi 这类共享出口 IP相邻的人可能因为某些恶意操作被拉进了风险名单整段 IP 都遭殃。我能给出的处理办法有几种先换网络环境试。最简单的是切到手机热点用手机流量完成注册和验证成功率很高。清除浏览器缓存和站点数据关闭广告拦截插件再重新进入注册页。换一个浏览器或者开启无痕模式排除本地浏览器插件干扰。如果还是不行等几个小时再试。风控名单有时会定期刷新过段时间出口 IP 可能就恢复正常了。这个过程里千万不要去折腾什么“换 IP 工具”“加速器”之类的旁门左道既不稳定也容易触发更严厉的风控。我用手机热点解决过两次基本百试百灵。最后再分享几个从这轮实践里沉淀下来的建议这次项目做完我个人的最大感受是Agent 开发不是一个“搭个框架就跑”的活它更像是在训练一支队伍——模型是新人Agent 是队长Skill 是给新人准备的岗位手册而腾讯云上的服务器、域名、镜像仓库就是这支队伍的训练场和作战基地。Skill 写得好不好直接决定队长指挥得顺不顺新人干活稳不稳。如果你正准备做自己的第一个 Agent我的建议是先挑一个最常做的操作比如“查看服务器状态”或者“Redis 巡检”把它写成第一个 Skill在本地跑通再部署到云上。别贪多一个 Skill 养成之后你就会对整套链路有感觉第二个、第三个只是复制粘贴的问题。还有两个反复踩过坑之后的硬建议第一密钥和密码永远不要写死在镜像里用环境变量或者密钥管理服务不然镜像推到仓库就等于把密码交了第二任何修改无论是 Redis 配置还是 Agent 代码都要明确“改的是哪个文件”线上排查时先看日志再看配置最后再看网络这条顺序能省下一大半时间。这套 Agent 后续还可以往记忆增强、多 Agent 协作、定时任务方向发展下一次有机会再单独写一篇。这次就先到这希望你也能把自己的 Agent 一步步养起来。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进