ARTICLE DETAIL

资讯详情

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

腾讯云AI Skills实战:Agent与Skill架构、部署与排障指南

腾讯云AI Skills实战:Agent与Skill架构、部署与排障指南 最近有好几个朋友问我同一个问题Agent 项目在本地能跑通一上云就各种翻车到底是怎么回事。这个问题我太有发言权了因为我在腾讯云上从零搭过一个完整的多技能 Agent中间踩过的坑两只手都数不过来。今天就把这套完整的实践过程拆开揉碎讲一遍重点说说腾讯云 AI Skills 怎么用、Agent 和 Skill 的关系怎么理清、部署到云上要注意哪些细节。如果你正准备在腾讯云上做 Agent 开发或者已经搭了个框架但发现它只能“聊天不能干活”这篇文章应该能帮你少走很多弯路。我会把架构选型、技能定义、记忆设计、镜像部署、常见排障全部串起来讲全程不掺水都是我实际验证过能跑通的做法。1. 先搞清楚Agent、Skill、Workflow 到底是什么1.1 Agent 不是聊天机器人很多初学者把 Agent 理解成“接了大模型 API 的聊天机器人”这是最大的误区。Agent 的核心是自主决策加工具调用。区别在于Chatbot 是你问一句它答一句Agent 是你给一个目标它自己规划步骤、调用工具、根据结果修正动作直到完成目标。举个例子普通的对话机器人收到“帮我把杭州明天适合出行的时段找出来顺便约个会议室”这种需求大概率只能给你一段泛泛的建议。而 Agent 会先拆解任务查天气、查会议室空闲、判断哪些时段合适、发起预约。每一步都需要调用不同的能力这些能力就必须以技能Skill的形式存在。我见过不少人把 Agent 做得特别“聪明”prompt 写了一长串结果一接真实业务就露馅。原因很简单思维再强手脚不够。一个没有技能支撑的 Agent 充其量是个“嘴强王者”你让它查天气它只能编你让它调接口它只能道歉。1.2 Skill 与 Agent 的边界一句话概括Agent 是大脑加调度器Skill 是手脚加工具包。Agent 负责理解、规划、拆解任务、观察结果Skill 负责具体执行某类动作。在腾讯云 AI Skills 这套体系里Skill 通常被定义成一个带元数据的能力单元包含名称、用途描述、入参出参结构Agent 通过函数调用或 HTTP 方式触发它。边界问题如果没理清后面写代码会非常别扭。我见过有人把所有逻辑都塞进 Agent 主进程结果 Agent 越写越长改一个业务细节就要动核心代码。正确姿势是Agent 只保留决策逻辑所有具体操作都下沉到 Skill。比如“查订单”是一个 Skill“改订单状态”是另一个 SkillAgent 本身不写业务代码它负责判断“现在该用哪个 Skill”。顺便说一句 Harness 和 Agent 的区别。Harness 是外部执行框架负责循环控制、停止条件、工具注册、日志追踪Agent 是里面的决策主体。很多“Agent 执行被终止”的问题根子不在 Agent 本身而是 Harness 的轮次上限或超时设置太激进。这块我在后面排查章节会细讲。1.3 为什么必须把能力“技能化”把能力封装成 Skill而不是把它写死在 prompt 里核心原因是三点可复用、可测试、可观测。可复用好理解一个写好的“天气查询”技能可以在旅游助手、日程管理、出行提醒多个 Agent 里共用不用重复开发。可测试意味着每个技能能单独输入输出验证出了问题能定位到具体技能而不是整个对话重来。可观测就更实际了技能调用有日志、有耗时、有成功失败统计你才知道 Agent 到底“卡”在哪一步。还有一个很现实的原因LLM 上下文窗口有限。把一堆工具描述全部塞进系统提示词不仅浪费 token还会让模型“选择困难”。技能化之后上层只暴露一段简洁的意图描述加参数 schema模型在需要的时候才加载对应技能这个思想其实和操作系统的动态加载类似。我在腾讯云 AI Skills 实践中最深的感触就是技能定义得好不好直接决定了 Agent 的上限。2. 腾讯云上的 Agent 架构选型2.1 手写还是用框架我一开始是纯手写派觉得框架黑盒太多不如自己控制一切。后来发现重复劳动实在太多会话管理、工具注册、重试机制、日志、限流这些工程问题每个都要自己写写完还要自己测效率很低。后来我调整了策略用开源框架承担 Harness 的工作把业务逻辑全部沉淀在 Skill 层。框架方面LangGraph、Dify 以及社区里一些轻量 agent 框架我都试过。我的建议是生产环境不要迷信任何框架也不要排斥框架而是把框架当成可更换的执行引擎。这样就算以后换框架Skill 资产还能保留不会被绑死。腾讯云开发者社区里关于 Agent 框架的讨论很多观点五花八门但大家基本都认同一点框架解决“怎么跑”的问题Skill 解决“能干什么”的问题两者要解耦。2.2 我的云端基线架构我最终跑通的架构长这样用纯文本画个拓扑用户请求 | v API 网关二级域名 HTTPS | v Agent RuntimePython 服务跑在 CVM |--- LiteLLM Proxy模型网关 |--- Skill Registry技能注册表 |--- MemoryRedis 会话记忆 | v 腾讯云容器镜像服务 TCR镜像分发 | v 各业务 Skill模块化部署可独立升级解释一下每一层的作用。API 网关负责对外暴露统一入口保证只有经过认证的请求能打到 Agent。Agent Runtime 是核心服务里面运行模型调用、技能调度、记忆读写。LiteLLM Proxy 放在模型和 Agent 之间管理多家模型的 key 和路由。技能层每个 Skill 独立部署可以单独更新而不影响主服务。这套架构最大的好处是职责分明出问题能快速定位。有一次用户反馈 Agent 回答特别慢我查了一圈发现不是模型慢而是某个 Skill 内部调了外部接口超时。因为链路分层清楚日志一拉就看到了。2.3 为什么用 LiteLLM Proxy 做模型网关如果你只接一家模型LiteLLM Proxy 的收益确实不大。但只要你有备用模型、要切换模型、要做 key 管理和权限隔离它就是刚需。我用 LiteLLM Proxy 把腾讯混元、DeepSeek、OpenAI 兼容接口都统一成了同一个 OpenAI 格式底座上层 Agent 代码不会因为换模型而改动。这套代理还顺手解决了几个麻烦事一是 API key 不用散落在多个服务里统一由代理管理安全性高很多二是可以做限流防止某个技能把配额打爆三是统一日志模型请求响应都能追踪。我的配置大致是model_list: - model_name: hunyuan litellm_params: model: tencent/hunyuan-lite api_key: os.environ/TENCENT_HUNYUAN_KEY - model_name: deepseek-chat litellm_params: model: deepseek/deepseek-chat api_key: os.environ/DEEPSEEK_API_KEY litellm_settings: drop_params: true max_retries: 2这里的 model_name 是给上层 Agent 用的逻辑名litellm_params 里写真实的模型名和密钥。切换模型时只需要改配置文件Agent 代码完全不用动。这个“逻辑名与真实模型解耦”的思路建议所有 Agent 项目都照做后面会省掉无数麻烦。3. Skills 定义与开发实战3.1 技能描述文件的“三句话原则”Skill 描述文件是整个 Agent 体系里最容易被低估的部分。描述写得太笼统模型不知道该在什么时候调它参数写得太粗糙模型给的入参根本不合法。我摸索出一套“三句话原则”每一个技能描述都按这个结构来写第一句话写触发条件什么类型的用户需求应该调用这个技能。第二句话写调用动作这个技能能做什么能力边界在哪。第三句话写关键限制有没有必须的关键信息默认值是什么。以天气查询为例我实际用的描述文件长这样name: weather_query description: | 当用户询问某个城市的天气、气温、降雨概率、空气质量、 或者出行是否适合时使用该技能。 一次只能查询一个城市不支持多个城市对比。 如果没有给出城市名称默认使用定位城市。 parameters: type: object properties: city: type: string description: 城市名称例如“杭州” date: type: string description: 日期格式 YYYY-MM-DD缺省为今天 required: - city注意 description 里我特意写了“不支持多个城市对比”这是给模型划清楚边界避免它拿着两个城市名来调用结果发现参数不合法还要重试。另外我还强调了“如果没有城市名默认定位”这个细节能明显提升体验让 Agent 少问一次废话。3.2 参数 Schema 少而精参数设计直接决定了工具调用的成功率我总结的教训是参数能少就少每个参数都要有清楚的中文描述和必填标记枚举值要写全。比如订单查询技能我一开始设计了 7 个参数包括订单号、用户 ID、下单时间范围、商品名称、订单状态、页码、页大小。结果模型经常“选择困难”要么漏填必填项要么把时间格式传错。后来我砍到了 3 个参数query支持订单号或商品名称关键词、status枚举待付款、已付款、已发货、已完成、page。模型一次就能给对。关于布尔参数我踩过一个坑某技能有个 is_refund 参数默认 false但模型有时候传字符串 false有时候传布尔 false类型不匹配导致调用报错。后来我干脆把布尔参数改成字符串枚举yes / no彻底绕开类型问题。涉及外部接口的技能还要加一层参数预检把模型生成的参数先校验一遍再去调真实接口宁可多写几行代码也别拿错误参数去污染业务数据。3.3 工具调用链路与错误处理一次完整的技能调用链是这样的模型理解用户意图返回 function call 指令Agent Runtime 从技能注册表里找到对应 Skill设置超时并执行执行结果转成结构化 JSON 返回给模型模型根据结果决定是继续下一步还是直接回答用户。错误处理是这个链路里最容易出问题的地方模型调用技能失败后经常“不知所措”要么重复调用同一个技能要么干脆认错说做不了。我的做法是给每个技能返回一个标准错误结构包含机器可读错误码、人话描述、给模型的建议import time def execute_skill(skill_name: str, params: dict) - dict: skill skill_registry.get(skill_name) if not skill: return { code: SKILL_NOT_FOUND, message: 技能不存在, suggestion: 告诉用户该功能暂未开放, } try: result skill.invoke(params, timeoutskill.timeout) return {code: OK, result: result} except TimeoutError: return { code: TIMEOUT, message: 技能调用超时, suggestion: 请缩小查询范围后重试, } except Exception as exc: return { code: ERROR, message: str(exc), suggestion: skill.fallback_advice, }这样模型拿到结果后能做出合理决策超时就缩小范围重试技能不存在就换个方式回答。另外每个技能都要单独设置超时时间外部接口调用一般设 5 到 10 秒内部纯计算可以 3 秒。宁可让 Agent 快失败也别让它傻等。4. 记忆系统让 Agent 从“失忆”到“记牢”4.1 三层记忆架构很多 Agent“聊着聊着就忘了”根因是没有记忆系统。我在腾讯云上实践出一套三层记忆架构短期记忆存当前会话的上下文通常是最近 N 轮对话放在 Redis 里带过期时间。长期记忆存用户的偏好、习惯、历史结论比如“用户偏好简洁回复”“用户常用收货地址是杭州”这部分会持久化。技能记忆存技能调用记录模型在多次调用同一技能时能参考上次输入避免重复提问。为什么技能记忆很重要举个例子用户让 Agent“帮我查上周的订单”Agent 调了订单查询技能返回结果里只有订单号和金额。用户接着说“第一个给我退款”如果 Agent 没有技能记忆它根本不知道“第一个”指的是哪个订单。有了调用记录它就能把上下文串起来。4.2 Redis 会话记忆的落地细节短期记忆我用 Redis 实现核心逻辑很简单用 session_id 做 key存一个 JSON 数组数组里是最近 20 轮对话。每轮新增时把最旧的那条挤出去写入后刷新过期时间TTL 我设的是 24 小时。import json import os import redis r redis.Redis( host127.0.0.1, port6379, passwordos.environ[REDIS_PASSWORD], decode_responsesTrue, ) def append_message(session_id: str, role: str, content: str): key fsession:{session_id} history json.loads(r.get(key) or []) history.append({role: role, content: content}) history history[-20:] # 窗口控制 r.setex(key, 86400, json.dumps(history))这里有两个容易忽略的点。第一Redis 的 key 一定要带前缀我用的 session:避免跟其他业务 key 冲突。第二窗口大小不是越大越好20 轮已经能覆盖绝大多数场景再长的历史要么用摘要压缩要么转成长期记忆硬塞上下文只会浪费 token 还降低响应质量。另外提醒一下Redis 连接参数里的密码千万别写死在代码里用环境变量注入。我把所有密钥类配置都放在 systemd 的 EnvironmentFile 或者 docker 的环境变量里代码仓库里只有占位符这是 Agent 项目安全的最低要求。4.3 长期记忆和向量检索长期记忆不能简单用 JSON 存因为搜索效率太低。我的方案是把用户偏好和技能调用摘要文本分块调用 embedding 接口做向量化存到向量数据库里。Agent 每次对话开始时先检索和当前会话语义最相关的 topK 条记忆作为背景信息注入 prompt。这个方案的落地细节是写入长期记忆的时机很关键。我是在技能调用完成、且对话产生明确结论后触发写入比如用户说“以后都先查天气再推荐穿搭”这种明显的偏好指令必须抓住。写入文本不要简单记“用户想要查天气”而是带上下文“用户希望出行推荐前先查询天气若气温低于 15 度应提示带外套”。这种带业务语义的记忆召回后对模型才有真正的参考价值。长期记忆这块初期不建议上太重的基础设施一个轻量向量库完全够用。等记忆量超过几十万条再考虑迁到腾讯云向量数据库或更专业的方案。5. 部署上线Docker、镜像仓库、二级域名与 HTTPS5.1 构建镜像并推送腾讯云容器镜像服务我在云上部署的教训是远程服务器上手工装环境是初级玩法一次两次能忍要频繁更新就完全不可控。后来全部改成容器化构建镜像推送到腾讯云容器镜像服务TCRCVM 上只负责拉取和运行。Dockerfile 我写得比较克制基础镜像直接用 python:3.11-slim依赖用腾讯云 pip 源加速避免超时FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://mirrors.cloud.tencent.com/pypi/simple COPY . . EXPOSE 8000 CMD [uvicorn, app.main:app, --host, 0.0.0.0, --port, 8000]镜像构建好后推送到 TCR 的流程是先登录仓库再打标签最后推送。腾讯云 TCR 有公网和内网两个入口CVM 和仓库在同一个地域时一定要用内网地址速度快很多docker login ccr.ccs.tencent.com -u your_username --password-stdin docker tag agent-runtime:v1 ccr.ccs.tencent.com/your_namespace/agent-runtime:v1 docker push ccr.ccs.tencent.com/your_namespace/agent-runtime:v1标签命名我建议加一层业务含义比如 agent-runtime:v1.2.0别用 latest 当唯一标签。latest 会造成“明明更新了镜像容器里还是老代码”的诡异问题。推送完成后CVM 上直接用 docker pull 拉取跑起来就完事。5.2 二级域名申请与 HTTPS 配置“腾讯云怎么申请二级域名”这个问题被问得特别多。其实二级域名的本质是在已备案的主域名下添加一条 DNS 解析记录。比如主域名是 example.com你在 DNSPod 控制台添加一条 A 记录主机记录填 dev记录值填 CVM 的公网 IP这样 dev.example.com 就是你的二级域名了。有了二级域名之后还要配 HTTPS因为很多回调场景比如企业微信、飞书、第三方 webhook都强制要求 HTTPS否则直接拒绝调用。我是用 Nginx 做反向代理把 443 端口的 HTTPS 请求转发到本机 8000 的 Agent 服务上server { listen 443 ssl; server_name dev.example.com; ssl_certificate /etc/nginx/ssl/example.pem; ssl_certificate_key /etc/nginx/ssl/example.key; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }证书我用的是腾讯云提供的免费 SSL 证书申请下来后配置到 Nginx 就行。有个细节提醒Agent 服务本身不需要绑定公网端口监听 127.0.0.1 就够了对外只暴露 Nginx 的 443 端口这样安全性和可维护性都好很多。5.3 进程守护与更新Agent 服务不能裸跑我用的是 systemd这样能满足开机自启和崩溃自动重启两个需求。实际配置片段[Unit] DescriptionAgent Runtime Afternetwork.target [Service] Userubuntu WorkingDirectory/opt/agent ExecStart/opt/agent/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 Restartalways RestartSec3 EnvironmentFile/etc/agent.env [Install] WantedBymulti-user.targetEnvironmentFile 这个字段是关键所有敏感配置包括 Redis 密码、模型 API key都在这个文件里代码仓库里不出现任何明文密钥。更新 Agent 镜像时我的流程是本地构建新镜像push 到 TCR然后 ssh 到 CVM 上 docker compose pull 再 up整个过程不用登录服务器装任何依赖。这也是容器化的最大红利发布流程从“登录服务器怀疑人生”变成了“三条命令搞定”。6. 常见问题与排查技巧实录6.1 Redis 改密码后重启失败这个坑太经典了必须单列一节。在腾讯云服务器上装 Redis修改 requirepass 之后重启一直失败多半是以下原因之一。第一个是 systemd 的 ExecStart 里没加载配置文件服务还在用默认配置启动Redis 根本读不到你改的密码。第二个是 redis.conf 文件权限不对导致 Redis 进程没有权限读取启动直接报错。排查顺序我总结成一张表症状可能原因解决方式systemd 启动失败ExecStart 未指定配置文件更新 unit 文件显式带配置路径前台启动正常systemd 失败unit 文件环境变量缺失检查 User、EnvironmentFile 配置Redis 起来了但客户端 AUTH 失败依赖方还在用旧密码同步修改所有连接 Redis 的服务配置外网连不上 Redisprotected-mode 和 bind 限制确认是否需要公网访问默认建议仅内网Redis 启动日志有权限报错配置文件权限过严调整 redis.conf 属主和读权限先跑 redis-server /path/to/redis.conf 前台启动确认配置本身没问题再排查 systemd顺序一定不要反。改完密码还有个连带问题所有依赖 Redis 的服务比如 Agent 的记忆模块、LiteLLM Proxy 的缓存都要同步改配置。我之前遇到过“Redis 进程明明是活的但 Agent 的存储模块起不来”的诡异问题最后发现就是密码没同步。6.2 agent execution terminated due to error这个报错我最早遇到时毫无头绪后来把执行链路一层层拆开才发现是技能调用超时。但不是只有超时会触发这个提示还有几个高频原因我也遇到Harness 的最大轮次设置过小模型还没完成任务就被强制终止某个技能抛了未捕获异常导致整个执行循环崩掉模型生成了不存在的技能名称调用时找不到对应函数。解决办法分三步。第一步给每个技能单独设置超时不要让一个慢技能拖垮整个 Agent。第二步Harness 的最大轮次从默认值往上调我的项目里设成 30 轮足够大多数任务使用。第三步给技能调用加一层“预检”在调真实业务接口前先校验参数合法性发现参数明显不对就及时返回错误别把脏数据带进真实系统。这里也顺带提一下 Agent 安全技能权限一定要最小化生产库的写操作、删操作别随随便便暴露给 Agent。我在技能注册表里给每个技能挂了所需的权限标签Agent 本身没有全局权限只有通过技能才能触碰数据这样即使模型被诱导乱来影响范围也有限。6.3 模型调用超时与限流本地调 DeepSeek 或腾讯混元一般很快但云上服务在高峰期经常遇到 30 秒超时尤其是 Agent 内部要连续调用多次模型时用户侧体感会被放大好几倍。核心解法是对外 API 改成异步任务加状态轮询不要让用户一直等同步响应模型调用侧做重试和熔断单个模型连续失败就切到备用模型。限流这块我踩过一个坑某天 Agent 突然大量调用某个模型把配额打爆了所有请求都被限流。后来我在 LiteLLM Proxy 层给每个逻辑模型加了速率限制再配合缓存机制重复的查询直接走缓存不重复消耗模型调用。Agent 项目上线以后一定要盯着一类指标技能成功率、平均耗时、模型调用成本这三项能反映系统八成以上的健康度。6.4 Agent 相关概念易混点速查我把这段时间被问到最多的几个概念整理成一张速查表建议收藏备用概念定位说明Agent决策主体负责理解需求、拆解任务、调用技能、复盘结果Skill能力单元封装具体业务动作可复用、可测试、可独立部署Harness执行框架提供循环、停止条件、工具注册等工程能力Workflow流程编排固定任务流程适合步骤明确的场景Framework开发框架已经实现的 Harness 加部分脚手架可以换成别的这份表特别适合面试和团队沟通概念一致了讨论方案能省一半时间。很多人纠结 Agent 和 Workflow 到底选哪个我的经验是任务路径变化多、需要模型自主决策的用 Agent任务每一步都固定、不需要发挥的用 Workflow别为了“智能”而上 Agent反而把稳定的业务搞得不稳定。最后分享一点我个人的体会。把 Agent 做成“全能”关键不在模型选得有多强而在技能资产积累得够不够多、够不够扎实。我在腾讯云上把这套体系跑通之后新增一个业务能力只需要写一个 Skill 定义文件再配上对应实现Agent 主流程完全不用动。这种“能力可插拔”的架构方式才是 AI Skills 实践带来的最大红利。如果你正在搭自己的 Agent建议先从一两个高频技能入手跑通整个闭环再逐步扩展步子太大容易摔技能多了管理成本也会上来。
返回列表