尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

腾讯云多智能体工作流实战:AI Skills决定Agent能力边界

腾讯云多智能体工作流实战:AI Skills决定Agent能力边界 最近一直在折腾 Agent 相关的落地项目在腾讯云上一路从零搭起了一套基于 AI Skills 的多智能体工作流。刚好这次把中间踩过的坑、试过的方案、最后跑通的最佳实践整理出来给同样想从“聊得好”跨到“干得成”的开发者一点参考。先说结论Agent 之间真正的差距不在模型本身而在你给它配了多少高质量 Skills。模型决定天赋Skills 决定能力边界。一个只会通用对话的 Agent跟一个能自主查数据、写代码、调接口、做分析的 Agent体验是代差级的。这篇文章我会从架构思路、Skill 设计、腾讯云部署、容器化、以及排错经验几个维度完整拆一遍所有操作都是我自己跑过的命令和配置可以直接照做。1. 全能 Agent 的整体设计为什么“模型Skills”才是正解1.1 先搞清楚 Agent 和普通对话机器人到底差在哪很多刚接触 Agent 的朋友容易把它理解成“接了 API 的聊天机器人”其实这是根本性的误解。普通对话系统是“你说一句它回一句”本质是单轮或短上下文的文本生成而 Agent 的核心是目标驱动你给它一个目标它自己拆分步骤、选择工具、执行动作、根据结果修正路径直到完成任务。我在腾讯云上跑通的这套系统架构上分了三层最底层是大模型推理负责语言理解、逻辑推理、任务拆解。我用的是腾讯云上托管的混元大模型 API兼容 OpenAI 格式接入成本很低。中间层是 Agent 调度框架负责任务循环感知-规划-行动-观察维护短期上下文和长期记忆管理每次行动后的结果回传与重规划。最上层就是 Skills 层把“搜索网页”“执行 SQL”“调用 API”“生成图表”“操作文件”“读取日志”等具体能力封装成一个个可被 LLM 调用的 Skill。这三层里面前两层现在方案都很成熟真正拉开差距的就是 Skills 层的设计质量。为什么这么说因为模型能力的天花板是固定的但 Skills 可以让同样的模型去操作不同的工具、接触不同的数据源、完成不同领域的任务。所以我把大量精力放在如何设计、封装、测试和部署 Skills 上这也是本文想重点分享的内容。1.2 AI Skills 的本质把“会说”变成“会做”Skills技能这个概念你可以直接类比成给 Agent 装“外挂插件”。一个 Skill 通常包含三部分Skill 元数据技能名称、描述、适用场景、参数定义。这部分是给大模型看的描述写得越精准模型越知道什么时候该调用它。调用逻辑真正执行任务的代码。可以是 Python 函数、API 封装、Shell 脚本等Agent 通过函数调用的方式触发它。返回结果执行完成后返回给大模型的数据。返回的数据要结构化、要精简让模型能快速理解“刚才发生了什么、下一步该干什么”。举个例子。假设我要让 Agent 具备“分析服务器日志”的能力最朴素的做法是在提示词里告诉它“请分析日志”模型就会瞎猜、胡编。但正确的做法是写一个analyze_logs(since, level, pattern)的 Skill模型只需要确定调用参数剩下的正则匹配、日志解析、统计聚合全部由 Skill 代码完成最后返回“错误类型 Top10”“时间分布”“异常片段”等结构化结果模型基于这个结果继续规划下一步行动。这个设计有个关键好处把确定性的事情交给代码把不确定性的事情交给模型。日志格式解析、计算、数据查询这类活儿代码比大模型可靠得多而决定“先查什么、再查什么、发现异常后该怎么做”这才是模型该干的事。人尽其才物尽其用。1.3 为什么我把部署目标选在腾讯云市面上云厂商很多我在腾讯云上落地有这几个实际考虑国内访问速度稳定我自己和团队都在国内腾讯云的服务器、API 调用延迟低不折腾。开发者生态配套完整云服务器 CVM、轻量应用服务器、容器镜像服务 TCR、API 网关、对象存储 COS 都能打通一个账号搞定所有环节。大模型 API 同生态优势混元大模型 API 跟腾讯云在同一个账号体系下密钥管理、账单、限流策略统一省去了来回切换多个平台的心智负担。镜像服务对 Docker 友好腾讯云容器镜像服务 TCR 个人版可以免费使用内网拉取速度快特别适合 Agent 服务这种需要频繁更新迭代的场景。我最终的部署形态是Agent 核心服务跑在一台轻量应用服务器上用 Docker 容器化镜像推到 TCR服务器上通过docker compose拉取和更新。整套架构既不复杂又有足够的扩展空间。2. Skills 机制的核心设计与开发方法2.1 先想清楚一个合格的 Skill 应该长什么样Skill 设计是整个项目里面最考验功力的部分。我连续迭代了 5 个版本最后总结出一个好 Skill 的四条标准。第一职责单一。一个 Skill 只干一件事。不要写一个“全能处理函数”什么都能做这会让模型困惑也让调试变得困难。比如“查询 MySQL 数据”和“更新 MySQL 数据”要拆成两个 Skill而不是一个“MySQL 操作”Skill 加一个 action 参数。理由很简单模型对“什么时候该用什么工具”的判断主要依赖 Skill 描述里的场景匹配。描述越具体匹配越准确。第二描述精确、可被模型理解。Skill 的描述部分是写给大模型看的说明书。差的描述是“日志分析功能”好的描述是“当用户需要分析服务器日志、查找错误原因、统计异常频率时使用。参数 since 表示起始时间格式为 YYYY-MM-DD HH:MM:SS”。我见过大量项目 Skill 写得模糊结果模型要么死活不调用要么乱传参数。你写的描述决定了 Agent 的“判断力”。第三参数校验严格。模型生成的参数偶尔会有格式问题Skill 内部必须在执行前做参数校验并对错误给出明确的报错信息。这样一方面避免脏数据污染执行逻辑另一方面报错信息能作为反馈进入 Agent 的上下文帮助模型在下一次尝试时自我修正。第四返回结果结构化。Skill 的返回值不要是长篇大论的文本最好是 JSON 或表格形式。我习惯返回{status: success|error, data: ..., message: ...}这样的结构。结构化结果方便模型快速提取关键信息也能减少 Token 消耗。2.2 从零搭建一个 Skill 的完整流程以下是我在项目中反复使用的 Skill 开发流程以“查询服务器磁盘状态”为例第一步定义 Skill 元数据。在 Python 里我用装饰器加类的方式管理每个 Skill 是一个类关键属性包括name、description、parameters、run()。parameters 走 JSON Schema 格式里面定义参数名、类型、是否必填、枚举值、说明。模型会按照这个 Schema 生成调用参数所以字段说明要准确。第二步实现执行函数。使用腾讯云 CVM 的 API 或者直接df -h、iostat命令。我推荐在 Skill 内部优先使用编程语言库调用云 API比直接执行 Shell 更可控权限也好管理。第三步注册到 Agent 的 Skill 列表。Agent 启动时加载所有已注册的 Skill生成工具调用清单随系统提示词一并发送给大模型。工具清单要控制数量太多会让模型“选择困难”我的经验是保持在 10-20 个之间最优。第四步联调和验证。这一步最关键。我会刻意设计一些边缘场景来测试模型是否能正确路由。比如给一个模糊的请求“帮我看看服务器是不是快满了”看模型能否理解“快满了”对应磁盘使用率查询并正确填充参数。如果描述不准确这里就会暴露出来。2.3 Skill 与 Agent 主逻辑怎么解耦架构上一个容易犯的错是把 Skill 直接写在 Agent 主逻辑里搞成硬编码。我目前的方案是在主服务里定义一个 SkillManager负责动态注册、加载、卸载 Skill。每个 Skill 独立成文件或独立成模块Agent 主循环只负责“读状态 - 决定调用哪个 Skill - 执行 - 结果回灌”Skill 的增删不影响主流程。这个设计带来一个实际好处上线新技能不需要重建整个 Agent。我只需要把新 Skill 的镜像或者代码推上去通过配置中心热加载Agent 立刻拥有新能力。有一次我临时给 Agent 加了个“汇率查询”技能从写完代码到线上生效前后不到 10 分钟。这种迭代速度对做原型验证和业务试错都极其重要。3. 腾讯云环境准备与 Agent 核心开发3.1 服务器选型与基础环境搭建先说服务器选型。Agent 服务本身逻辑不复杂主要吃内存和网络带宽。我选的腾讯云轻量应用服务器 2C4G 配置跑 Docker、Nginx、Agent 服务完全足够。如果你的 Agent 会经常处理大数据量文本比如大批量文档、长日志建议选 4C8G。但初期没必要一上来就买高配后面全是云原生扩展随时升配。系统我选了 Ubuntu 22.04 LTS干净稳定第三方软件源支持好。装好系统后第一步就是安全组配置只放行必要端口22 用于 SSH最好改成密钥登录80/443 用于 Web 访问其余全部拒绝。然后执行系统更新、装基础工具apt update apt upgrade -y apt install -y git curl wget vim ufw docker.io docker-compose-pluginDocker 装好后记得把当前用户加入 docker 组不然每次都得 sudousermod -aG docker $USER newgrp docker这里有个小坑Ubuntu 源自带的 docker.io 版本通常不是最新的如果后续用到较新的 compose 语法建议直接安装 Docker 官方源。我个人图省事用系统源也够了但如果你要跑 GPU 版模型推理还是去官方源装带 NVIDIA Container Toolkit 的版本。3.2 Agent 核心服务代码结构我用的开发语言是 Python 3.11框架层面没有套现成的 Agent 框架而是自研了一个轻量调度核心。有人会问为什么不直接用 LangChain我的考虑是自研可以完全控制上下文的组织和 Skill 调用的细节对调试更友好。如果你图快用 LangChain 或 Semantic Kernel 也没问题但理解核心原理是必须的否则出了问题根本无从查起。项目结构大致如下agent-service/ ├── main.py # FastAPI 入口 ├── agent/ │ ├── core.py # Agent 调度核心 │ ├── memory.py # 对话记忆与长期存储 │ └── llm_client.py # 混元大模型 API 客户端 ├── skills/ │ ├── register.py # Skill 注册管理器 │ ├── search_web.py # 联网搜索 Skill │ ├── query_mysql.py # MySQL 查询 Skill │ ├── file_operate.py # 文件读写处理 Skill │ ├── call_api.py # 通用 API 调用 Skill │ └── visualize.py # 数据可视化 Skill ├── utils/ │ ├── config.py │ └── logger.py ├── requirements.txt └── Dockerfile核心调度逻辑简化后是这样的循环async def run_agent(user_input: str): messages build_context(user_input) for step in range(MAX_STEPS): response await llm.chat(messages, toolsskill_manager.get_tool_schemas()) if response.finish_reason tool_calls: for tool_call in response.tool_calls: result await skill_manager.execute(tool_call) messages.append(format_tool_result(tool_call, result)) else: return response.content return 已达最大步数限制任务未完成每次模型返回“需要调用工具”时Agent 就把工具名参数传给 SkillManager执行完把结果追加到消息列表再丢给模型继续规划。这个循环简单但非常有效。我设置的MAX_STEPS是 15防止个别任务无限循环烧 Token。3.3 混元大模型 API 的对接细节腾讯云混元大模型 API 走 OpenAI 兼容协议所以只需要改 base_url 和 key。我用的是工具调用模式需要在请求里传tools参数。这里有一个很重要的细节tools 参数每一项的格式必须严格匹配 OpenAI Function Calling 规范否则模型会忽略工具。另外每个模型的上下文长度是有限的。当对话轮次多、工具调用结果大时很容易撑爆上下文。我的解决方案是对工具返回结果做截断超过 2000 字符的自动压缩摘要。对历史对话做滑窗保留系统提示词 最近 10 轮 本轮工具结果。长期记忆存入独立的向量数据库按需检索不塞进主上下文。这套策略跑下来上下文使用率长期稳定在 60% 以下既保证了质量也控制了成本。4. Skills 实战案例让 Agent 真正“全能”起来4.1 联网搜索 Skill信息获取不再是模型“幻觉”第一个必须装的能力就是联网搜索。没有它大模型的知识截止日期就像一个铁笼子永远只能回答“我训练时见过”的内容。我的搜索 Skill 实现思路通过腾讯云官方或者第三方搜索 API 发起搜索请求获取网页结果列表再根据 URL 列表抓取正文内容统一清洗成纯文本后提取关键段落。模型拿到的是清洗过的搜索结果而不是原始的 HTML 垃圾。期间遇到一个典型问题搜索结果的正文抓取经常因为目标网站反爬、编码混乱而失败。我在 Skill 里加了多重后备策略先试 requests 直连失败切换不同 User-Agent再失败用渲染服务抓取动态页面最后还拿不到就返回标题摘要。这样整体成功率从 60% 提升到了 90% 以上。4.2 文件处理 Skill批量操作从“不可能”变“小意思”Agent 要处理真实任务就离不开文件读写。我的第一个版本只支持读取文本文件后来发现用户经常要“统计这些日志里有多少 ERROR”“把这几百个 JSON 合并成一个 CSV”于是我把文件处理做成了一个通用型 Skill支持按扩展名自动分发到不同处理函数。这个 Skill 的核心技巧是路径安全和格式校验。Agent 有时会生成奇怪的路径或者对不存在的文件继续操作。我在 Skill 里统一做了绝对路径规整、目录存在性检查、文件大小限制默认最大 10MB所有异常返回结构化错误信息让模型自己调整下一步。4.3 数据分析与可视化 Skill从“看数”到“出图”如果说前面的 Skills 是手脚那数据分析 Skill 就是大脑的延伸。我封装了两个一个负责执行 Pandas 聚合计算分组、均值、TopN、时间序列统计另一个负责用 Matplotlib 或 ECharts 生成图表。实现的时候我把“图表的类型选择”交给模型。模型根据用户的需求和数据结构决定画折线图、柱状图还是饼图然后调用可视化 Skill传入数据和图表类型Skill 负责生成图片并返回 URL。这样既发挥了模型对业务语义的理解能力又保证了计算和绘图的准确性。4.4 调用外部 API 的抽象 Skill做 Agent 很难不跟外部系统打交道但每个 API 的认证方式、请求格式都不同。如果为每个 API 写一个 Skill维护成本很高。我的方案是写一个通用 API 调用 Skill允许模型在运行时传入完整的请求配置method、url、headers、body并配合一个 API 凭证仓库。仓库里预存各系统的 base_url 和 token模型只能引用仓库中已有的凭证不能自行输入密钥。这一步非常重要防止模型把密钥写到日志或者提示词里泄露出去。安全合规在 Agent 里不是小事。5. 腾讯云部署全流程从代码到线上服务5.1 用 Docker 封装 Agent 服务项目开发完第一步是写 Dockerfile。我用的是多阶段构建先把依赖装好再复制代码跑起来。基础镜像选python:3.11-slim体积小、漏洞少。FROM python:3.11-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt FROM python:3.11-slim WORKDIR /app COPY --frombuilder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages COPY . . CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000]有个地方要注意镜像里不要存放任何密钥或敏感配置。我的做法是运行时通过环境变量注入或者挂载配置文件。这样镜像可以安全地推到公共或私有镜像仓库不会泄露凭据。5.2 推送到腾讯云容器镜像服务TCR腾讯云容器镜像服务个人版使用非常方便。开通后创建一个命名空间和镜像仓库然后用 docker 命令登录并推送docker tag agent-service:latest ccr.ccs.tencentyun.com/你的命名空间/agent-service:latest docker push ccr.ccs.tencentyun.com/你的命名空间/agent-service:latest推送速度取决于镜像大小我这个镜像大约 800MB首次推了 2 分钟左右。之后每次迭代我都把版本打上 tag比如:v1.2.0以便回滚。TCR 个人版有个非常香的优势同一账号下的云服务器拉取镜像走内网速度极快且不消耗公网流量。更新服务时服务器上直接docker pull ccr.ccs.tencentyun.com/你的命名空间/agent-service:latest docker compose up -d整个过程 10 秒完成Agent 就更新到了新版本。这种丝滑体验用传统 FTP 传代码更新是完全没法比的。5.3 Nginx 反代与 HTTPS 配置服务部署好了对外访问还需要一层 Nginx 反向代理。我的用途有两个一是统一入口管理多个服务Agent API、前端页面、包括后续扩展的其他微服务二是终结 HTTPS让客户端走加密通道。域名方面我给服务器申请了一个主域名然后在 DNS 解析里加了agent.xxx.com二级域名指向服务器 IP。腾讯云验证域名所有权很快同账号下 CDN 和 API 网关联动也方便。代理配置大概是server { listen 443 ssl http2; server_name agent.xxx.com; ssl_certificate /etc/nginx/ssl/agent.xxx.com.pem; ssl_certificate_key /etc/nginx/ssl/agent.xxx.com.key; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }证书我用的是腾讯云免费 DV 证书一年一换配置好后全链路 HTTPS安全省心。在做这个配置时我踩过一个坑Nginx 默认的client_max_body_size是 1MB当用户通过 Agent 上传较大的文件时直接被 413 拒掉了。后来在 server 块里加上client_max_body_size 50m;才解决。这个细节虽然小但线上环境很容易碰到。5.4 用 docker compose 编排依赖我的 Agent 服务并不是孤立运行的它还需要 Redis 做会话缓存、需要 MinIO 或 COS 存文件对象。用 docker compose 把整个依赖编排起来每次启动或升级都一条命令搞定。version: 3.8 services: agent: image: ccr.ccs.tencentyun.com/命名空间/agent-service:latest ports: - 8000:8000 environment: - LLM_API_KEY${LLM_API_KEY} - REDIS_URLredis://redis:6379 depends_on: - redis restart: unless-stopped redis: image: redis:7-alpine restart: unless-stopped这里我用.env文件存环境变量.gitignore里排除掉避免密钥入库。restart: unless-stopped保证服务异常退出后自动拉起减少人工介入。线上跑了一个多月稳定性非常好。6. 常见问题与排查技巧实录6.1 模型不调用 Skill 怎么办这是所有 Agent 项目里最经典的问题。症状是你明明给它配了很完整的 Skill 列表但它总是自己胡编答案从不调用工具。排查路径按这个顺序走先看工具描述是否模糊。描述里必须包含“什么时候用”“什么时候不用”以及关键场景举例。我之前写过一个“时间查询”Skill描述只写了“查询时间”结果模型完全无视改成“当用户询问当前日期、时间、时区时调用该 Skill 获取系统当前时间”后调用准确率明显提升。再看参数定义是否完整。参数缺失、类型错误、缺少必填项都会让模型不放心调用。最后确认请求里是否真的把 tools 传进去了。有时候代码改造后tools 参数被遗忘了模型当然只能空手作答。6.2 参数生成错、反复调用失败怎么办模型生成参数偶发不正确是比较常见的比如把时间格式从2024-01-01 12:30:00写成了2024/01/01 12:30或者多传了不存在的字段。我的策略分三道防线Skill 内部做容错解析支持多种常见时间格式自动补全缺失字段。捕获异常后返回给模型让它在下一轮自行修正。模型有自我纠错能力只要报错信息清晰大部分情况下第二轮就能调对。同一步骤连续失败超过 3 次Agent 强制终止并提示用户避免无线循环烧钱。实测下来加上这三道防线后工具调用的整体成功率能稳定在 95% 以上。剩下的 5% 通常是输入本身就有歧义属于用户需要重新描述的场景。6.3 上下文章节 OOM 与预算失控长任务的上下文增长非常快尤其是一次性塞入多个大文件内容时。我碰到过一次 OOM用户丢了一个 8MB 的 CSV 让 Agent 做分析Agent 读取后把整个文件塞进了上下文直接把服务打挂。解决方案是给文件型 Skill 加上“自动分段读取”逻辑默认每次只读前 100 行用于先验模型需要更多数据时再按需读取后续块。同时在主循环里设置 Token 阈值超过后自动触发摘要压缩。预算控制上我设置了单次会话的 Token 上限比如 50 万达到上限后强制结束并提示用户开启新会话。这样既保证了服务的可用性也避免了个别异常任务把账号的钱烧光。6.4 容器更新后服务没生效docker compose 更新镜像后需要显式重建docker compose up -d --build或者指定要重建的服务docker compose up -d --force-recreate agent我早期经常只docker pull以为更新完了结果跑的还是旧容器排查半天才发现问题是容器没重建。现在我把更新流程写成了一个脚本拉镜像-重建-检查日志-健康检查一步到位。另外提醒一句更新前最好先看一眼当前容器有没有未保存的状态比如内存里的对话记录、缓存文件等。Agent 类服务状态多尽量把状态外置到 Redis 或数据库中容器才能随时无痛销毁重建。6.5 服务跑着跑着宕机日志里全是内存错误2C4G 的轻量服务器跑 Agent 服务本身没问题但如果同时跑了 Redis、Nginx、多个 Python 进程内存就会吃紧。我的排查方式是free -h docker stats top -o %MEM用这三条命令快速定位是哪个进程占用了内存。解决方案有几个一是调低 Gunicorn/Uvicorn 的 worker 数默认 1 个 worker 即可二是给容器设置内存上限防止某个进程把整台机器拖垮deploy: resources: limits: memory: 1.5G我的经验是单 worker 限制内存 自动重启这个组合基本能保证服务长期稳定运行。你不需要一上来就买高配服务器先把资源管好才是正道。7. 从“能用”到“好用”我对这套实践的几点体会搞完这一整套东西我最深的感受是Agent 项目的复杂度不在于某一个技术点有多难而在于如何把模型、工具、部署、运维这些东西无缝地拼在一起。单项技术其实都有现成方案但把它们合理组织起来、并解决实际场景下那些琐碎而致命的问题才是真正的价值所在。比如 Skill 的设计如果你只是把它当“工具函数”写那 Agent 永远只能做 demo一旦你理解“Skill 是 Agent 认知边界的一部分”就会在元数据打磨、错误处理、返回结构这些细节上下足功夫。模型是大脑Skill 是四肢没有合格四肢的大脑再聪明也只能空想。关于腾讯云部署这块我现在的标准流程已经固化为本地测试 - 构建镜像 - 推 TCR - 服务器拉取运行。整个链路已经非常顺手。如果你刚开始接触我建议可以先不用管容器化直接在服务器上通过源码跑通一次等流程稳定了再套 Docker 和编排循序渐进不容易崩。最后再分享一个小技巧Agent 的开发过程中一定要把“观察日志”当成一等公民。我给 Agent 的主循环加了详细的结构化日志每次工具调用、每次参数生成、每次上下文压缩都会记录。线上出现问题的时候这些日志能帮你迅速定位是模型的问题、Skill 的问题还是环境的问题。没有日志的 Agent 项目排查问题的成本会翻好几倍。
返回列表