从零到一:用腾讯云AI Skills搭建高效AI Agent的实战指南
1. 为什么要从“写代码”升级到“养 Agent”我最近在腾讯云上完整跑通了一个 Agent 项目从最开始的技能定义到模型接入再到记忆与工具编排前前后后折腾了两周。过程中踩了不少坑也把AI Skills和传统开发之间的差异想得更清楚了。这篇文章就把我验证过的方案、参数和排查思路整理出来给同样在搞 Agent 的朋友一条能直接抄的近路。先说结论Agent 不是“一个更大的模型”而是一套用模型做控制中枢、用技能做四肢、用记忆做上下文缓冲的系统。腾讯云的 AI Skills 在这个体系里扮演的是“四肢定义层”——它把可复用的能力比如查天气、读文件、算数学、调API封装成标准技能让 Agent 在需要的时候按需调用。我见过不少团队把精力全花在提示词上结果模型换一版就崩。真正稳的做法是把提示词里那些“会变化的动作指令”抽出来变成结构化的 Skill。这样做的好处有三个动作可复用同一个“读取Excel并汇总”的技能可以在数据分析 Agent、周报 Agent、财务 Agent 里反复用行为可观测技能被调用时会留下结构化日志出了问题能定位到具体环节升级不影响主干技能内部逻辑调整不影响 Agent 的编排流程隔离性更好。如果你还在纠结“AI Skills 到底和普通函数有什么不同”我的理解是普通函数是人写的逻辑AI Skills 是给模型写的逻辑。模型决定何时用、传什么参数、怎么处理返回结果——所以 Skill 的定义质量直接决定了 Agent 的智能上限。腾讯云 AI Skills 平台把这套东西的产品化做得比较完整一套 Skill 定义好之后既可以在同一个业务里复用也能跨业务共享这也是我最终选它落地的一个核心原因。2. AI Skills 与 Agent 的关系拆解2.1 Skill 是“会说话的 API”Agent 是“会思考的调度员”很多人问skill 和 agent 到底有什么区别我在项目里得出的理解是Skill 是能力单元Agent 是决策单元。一个 Skill 定义“我能做什么”一个 Agent 定义“我该做什么、怎么做”。打个比方Skill 好比工具箱里的扳手和螺丝刀每件工具都有明确用途Agent 是那个拿着工具箱的维修师傅他看到问题后判断“该用扳手还是螺丝刀拧几圈拧完怎么验收”。没有工具师傅再厉害也使不上劲没有师傅工具只能躺在那里。在腾讯云 AI Skills 里一个 Skill 最小包含三部分组成部分作用类比触发条件描述什么时候该调用这个技能工具的适用场景输入参数定义调用时需要哪些信息工具的规格尺寸输出逻辑定义如何加工输入并返回结果工具的操作结果Agent 则包含模型配置、技能列表、记忆策略、编排逻辑。Skill 是插在 Agent 身上的“外挂能力”一个 Agent 可以挂多个 Skill一个 Skill 也可以被多个 Agent 共用。2.2 我用 AI Skills 解决了什么问题我在这个项目里要做的是一个“全能型调研助手”。它可以接收用户的问题自己去拆分任务、检索信息、读取文档、生成报表。如果全用提示词硬刚我需要把“查询天气→读取文件→写表格→汇总结论”这套流程全部写在一个超长提示词里——且不说 token 消耗吓人一旦某个环节格式变了整个提示词就要重写。用 AI Skills 重构之后每个环节独立成一个 Skillweb_search负责搜索返回结构化结果file_reader负责读取 PDF/Word/Excel抽取关键内容data_analyzer负责对数据做统计和可视化report_writer负责合并信息生成最终文档。Agent 的编排逻辑只做一件事情判断用户意图决定调用哪些 Skill以及按什么顺序调用。这样不仅结构清晰而且单独替换任何一个 Skill 都不会影响整体流程——我实测过把data_analyzer从简版统计切到带图表的版本Agent 其他部分完全不用改。2.3 什么时候该上 Agent什么时候不该上并不是所有场景都适合做成 Agent。我自己的判断标准是任务有明确步骤但步骤不固定适合用 Agent——因为模型可以根据输入动态编排任务完全固定比如每天同一张报表直接用传统代码更稳定、更便宜依赖大量外部交互打开网页、点击按钮需要配合浏览器自动化工具复杂度会成倍增加对延迟要求极高的场景Agent 的模型推理时间可能成为瓶颈需要额外做缓存或预判。腾讯云 AI Skills 的价值在于即使你暂时不打算做完整 Agent先把手头一些调模型的逻辑封装成 Skill后续迁移到 Agent 架构的成本也会低很多。我这次就是这么一步步推进的。3. 我用 LiteLLM Proxy 做模型聚合的实战3.1 为什么需要 LiteLLM Proxy做 Agent 不可避免要和多个模型打交道。我在这个项目里同时用了三个模型一个负责对话理解、一个负责工具调用、一个负责最终报告生成。如果直接对接各家 API代码里会塞满不同的鉴权逻辑、超时设置、重试机制非常容易出问题。litellm proxy解决的就是这个痛点它提供统一的 OpenAI 兼容接口把不同模型包装成同一个调用方式。我在腾讯云服务器上部署了一个实例相当于把模型路由逻辑下沉到了独立服务Agent 本身不需要关心背后是哪个模型、API怎么鉴权。部署非常简单官方 Docker 镜像直接起docker run -d \ --name litellm-proxy \ -p 4000:4000 \ -v $(pwd)/litellm_config.yaml:/app/config.yaml \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml配置文件的写法model_list: - model_name: agent-main litellm_params: model: anthropic/claude-sonnet-4-20250514 api_key: ${ANTHROPIC_API_KEY} - model_name: agent-tool litellm_params: model: vertex_ai/claude-3-5-sonnet vertex_project: your-project vertex_location: us-central1 - model_name: agent-report litellm_params: model: openai/gpt-4o api_key: ${OPENAI_API_KEY}启动后Agent 端只需要配置一个 Base URLhttp://你的服务器IP:4000然后所有模型调用都走同一个接口通过model参数区分。3.2 多模型路由的关键配置技巧我在实际使用中总结了几条比较关键的经验模型重命名要有业务含义。agent-main、agent-tool、agent-report这样的名字让 Agent 的逻辑可读性更强后续切换模型厂商时只需要改配置不用改代码。重试和超时要在代理层统一设置。我最初在 Agent 代码里逐个模型配重试后来发现代理层设置更省事litellm_settings: drop_params: true num_retries: 3 request_timeout: 60 fallbacks: - agent-main: - agent-tool这里有个细节drop_params: true特别重要。不同模型对参数的接受度不一样OpenAI 支持temperature有些模型不支持开启这个选项后代理层会自动剔除不支持的参数避免报错。Fallback 配置我强烈建议加上。生产环境里一个模型不可用是常态设置好降级链能避免整个 Agent 挂掉。我有一个实战案例某次主模型限流由于配了 fallback请求自动切到了备用模型整个调研任务没中断。模型调用日志开启后排查问题会快得多litellm_settings: json_logs: true turn_off_message_logging: false set_verbose: true我的习惯是消息内容打日志涉及敏感信息时改成turn_off_message_logging: true只记录元数据。这个细节在多人协作或对接外部数据时比较重要。3.3 模型聚合层对 Agent 开发节奏的改善接入 LiteLLM Proxy 之后我开发 Agent 的节奏明显变了以前每试一个新模型都要写一段对接代码跑通之后再改回来现在直接在配置文件里加一行重启代理就生效。而且因为所有模型统一走 OpenAI 格式Agent 框架比如 LangChain、LlamaIndex、自研框架不需要感知底层的模型差异。这意味着框架升级或者换 Agent 框架时模型层完全不受影响——模型聚合层把“模型”和“业务逻辑”彻底解耦了。还有一点值得提如果在云端跑 Agent把 LiteLLM Proxy 单独部署在一台低配实例上我用的 2C4G 就够其他业务服务通过内网访问不暴露公网端口安全性会好很多。腾讯云的内网通信本身不额外计费这个方案性价比很高。4. Agent 的记忆机制与上下文管理4.1 短期记忆与长期记忆的取舍刚开始做 Agent 的时候我犯过一个典型错误把所有历史对话全部塞进上下文结果还没聊到第三个问题token 就爆了。后来才意识到Agent 的记忆是有层次的不加区分地全部保留既不经济也不聪明。我目前的分层策略是这样记忆类型存储方式保留策略典型用途短期记忆上下文窗口按条数/时间淘汰当前任务的即时对话中期记忆结构化摘要每次对话后刷新用户偏好、任务状态长期记忆向量数据库永久保存定期清理历史偏好、事实性知识在腾讯云 AI Skills 的环境里短期记忆直接由大模型上下文窗口承载中期记忆我通常用一个 JSON 对象维护每次对话结束后让模型输出“本次对话的关键信息摘要”写入一个专门的内存节点长期记忆则丢进向量库在需要的时候通过相似度检索拉取。4.2 用向量检索做长期记忆长期记忆的核心是“需要时能找到不需要时不打扰”。我用腾讯云向量数据库存储历史交互的向量表示每次 Agent 接收新任务时先从向量库检索和当前问题最相关的历史记录再决定要不要注入上下文。代码层面我用的是纯文本切块 调用 embedding 模型from tencentcloud.common import credential from tencentcloud.vdb.v20230601 import vdb_client, models def save_memory(user_id: str, content: str): vec embedding_model.encode(content) doc { id: f{user_id}_{int(time.time())}, vector: vec.tolist(), metadata: { user: user_id, content: content, ts: time.time() } } client.insert(doc) def recall_memory(user_id: str, query: str, top_k: int 3): query_vec embedding_model.encode(query) results client.search( collectionagent_memory, vectorquery_vec.tolist(), limittop_k, filter{user: user_id} ) return [r[metadata][content] for r in results]实际操作中有一个细节检索结果不是越多越好。我把 Top-K 默认设为 3再让模型判断这些历史记录和当前问题是否相关。这样做有一个好处如果历史记忆和当前问题无关模型可以直接忽略不会为了“使用记忆”而强行关联。另外长期记忆一定要做“遗忘机制”。我设定了一个 90 天的窗口超过 90 天的记忆自动归档不再参与日常检索。毕竟用户的兴趣和项目需求是会变的保留太多过时信息反而会干扰判断。4.3 上下文压缩的实操技巧当会话特别长时即使有记忆分层上下文还是会膨胀。我的处理方式是做“滚动摘要 原始裁剪”双通道def compress_history(messages, max_tokens8000): messages trim_to_token_limit(messages, max_tokens) current_summary summarize(messages) return { summary: current_summary, recent_messages: messages[-20:] }current_summary是前情提要放在系统提示词最前面recent_messages保留最近 20 条保证模型能理解正在进行的对话。这种方法比起单纯截断记忆连贯性会好很多。我测试过几种不同策略效果从好到差排列大概是滚动摘要原始截取 单纯滚动摘要 单纯保留最近N条 全部保留当token不足时会直接报错。前面两种在日常使用中差别不大但当用户突然反问“你刚才说的那个数据来源是什么”时滚动摘要的效果要明显好于简单截取。5. 工具调用的设计哲学与安全边界5.1 让模型稳定调用工具的 Schema 设计Agent 的能力上限很大程度上取决于工具定义是否清晰。我在使用腾讯云 AI Skills 的过程中反复调整过工具参数定义最终总结出几条比较实用的 Schema 设计经验。第一参数名用完整的自然语言词汇而不是缩写。比如不要用qry用query_string不要用doc用document_path。模型对语义化参数的理解准确率显著高于缩写尤其在多模型切换时不同模型对缩写的适应性差别很大。第二每个参数的描述里写明“什么时候传、什么时候不传”。比如{ name: web_search, parameters: { type: object, properties: { query: { type: string, description: 搜索关键词当用户明确要求搜索最新信息时提供此参数 }, time_range: { type: string, enum: [1d, 1w, 1m, 1y], description: 时间范围过滤默认为空只有用户指定时间偏好时才设置 } }, required: [query] } }第三工具说明要写“能做什么”也要写“不能做什么”。例如文件读取工具说明里可以加一句“仅支持 PDF、Word、Excel、TXT 格式不支持读取加密文档”。这样模型就不会尝试用不合适的参数调用减少无效调用次数。5.2 工具并行调用的编排策略我的调研 Agent 会经常同时调用多个 Skill。比如用户问“帮我整理最近一周的行业动态”它可能会同时触发搜索、新闻抓取、数据库查询三个技能。并行调用的编排点在 OpenAI 格式里通过tool_choice: auto开启模型自行决定并行调用哪些工具。我在 LiteLLM Proxy 里配置了max_parallel_tool_calls: 5防止一次调用过多工具导致下游服务压力过大。不过有个坑需要注意并行调用省时间但不同工具的返回速度差异很大。一个 Web 搜索可能要 3 秒一个本地文件读取只要 50 毫秒。如果 Agent 等待最慢的工具完成后才继续整体延迟会被拉高。我目前的方案是将快速工具和慢速工具分两个阶段调用先并行调快速的拿到结果做一轮初步分析再在第二轮调慢速工具。整体任务时间大概减少了 35%。5.3 安全边界权限最小化与敏感操作熔断这一点我觉得怎么强调都不为过。Agent 拥有调用工具的能力本质上就是拥有了一双能操作真实世界的手。如果安全措施不到位后果可能比写错代码严重得多。我在项目里建立了三层防护工具权限最小化每个 Skill 使用独立的最小化 API Key仅有完成自身任务所需的权限。比如file_reader只读文件不赋予写入权限email_sender只发信不赋予收件箱管理权限。敏感操作二次确认涉及删除、修改、发送、支付等操作Agent 只能生成“执行预览”必须由用户确认后才真正执行。我在编排层加了一个require_confirmation字段标记需要确认的工具。调用频次限制与熔断单 Skill 每分钟最大调用次数做成动态闸门连续失败超过 5 次自动熔断 10 分钟防止 Agent 在一个错误状态里反复重试把外部服务打爆。腾讯云平台上可以通过 CAM 角色为 Skill 绑定临时凭证这个方案比硬编码 API Key 安全得多。我建议所有涉及云资源操作的 Skill 都走这个通道——毕竟 Agent 的调用模式不可预测临时凭证能大幅度收敛爆炸半径。5.4 工具调用的可观测性设计Agent 出了问题最难排查的就是“它为什么这么调用”。我在所有 Skill 的入口和出口都埋了日志统一输出格式{ timestamp: 2025-01-15T10:23:45Z, agent_id: research-agent-prod, skill: web_search, input: {query: 腾讯云AI Skills 最佳实践}, output: {result_count: 10, top_hits:[...]}, latency_ms: 1243, status: success, error: null }这些日志统一写入腾讯云日志服务通过关键词检索就能快速定位到出问题的调用链。我甚至做了一个简单仪表盘展示每个技能的调用频率、成功率、平均耗时——当某个技能的成功率突然下降往往就是上游接口变更了或者参数格式失效了这时能第一时间收到告警而不是等用户报告。在实际工作中可观测性和安全防护一样重要。没有日志的 Agent 就像没有仪表盘的飞机飞得再高也心里没底。6. 完整实战5 步搭建一个可用的调研 Agent6.1 第一步定义核心技能集起步阶段不要贪多我建议从 3-5 个技能开始。我的调研 Agent 起步技能集是web_search搜索最新资讯file_reader读取本地/对象存储中的文档data_extractor从网页或文档中提取结构化字段report_writer根据信息生成 Markdown 报告。在腾讯云 AI Skills 控制台里逐个创建填好技能描述和参数 Schema。这个阶段的关键是把描述写清楚让模型知道什么时候该调用、参数含义是什么。我的做法是每条描述都包含“触发场景”和“典型用途”两部分。6.2 第二步接入模型并配置路由模型接入我推荐直接走 LiteLLM Proxy原因前面已经说过统一接口、集中管控、方便降级。我这里用一个便宜的模型做路由比如gpt-4o-mini或者deepseek-chat负责意图识别和工具选择权重较高的模型比如claude-sonnet负责内容生成和报告撰写。这种“小模型做调度、大模型做产出”的分配方式成本上能省下不少。我实测过同样的任务量纯用大模型调度比大小模型混合调度贵了大概 60%而效果差异并不明显。6.3 第三步搭建记忆层记忆层我分两部分短期记忆直接在对话上下文中维护通过compress_history做滚动摘要长期记忆写入腾讯云向量数据库用 embedding 模型做相似度检索。这一步要提前想好数据隔离策略。我是按user_id隔离的每个用户的记忆互不可见。如果你的 Agent 服务企业内部多个团队建议在 metadata 里加上team_id字段按团队维度隔离。6.4 第四步编排主流程主流程的伪代码如下def run_agent(user_query: str, user_id: str): # 1. 召回长期记忆 memories recall_memory(user_id, user_query) # 2. 组装系统提示词 system_prompt build_system_prompt(memories) # 3. 多轮工具调用循环 messages [{role: system, content: system_prompt}] messages.append({role: user, content: user_query}) for step in range(MAX_STEPS): response llm.chat(messages, toolsavailable_skills) if response.tool_calls: # 并行执行工具调用 tool_results execute_tools(response.tool_calls) messages.append(response.to_message()) messages.append(tool_results.to_message()) else: return response.content # 4. 超过最大轮数返回中间结果 return 任务复杂度超出预期请逐步细化问题。这里有几个参数值得关注MAX_STEPS我设为 6因为大多数调研任务在 4-6 轮工具调用内就能完成超过这个数基本说明编排逻辑有问题或者任务拆分不够清晰。execute_tools里用asyncio.gather做并行执行并设置统一的超时时间我用的 15 秒避免某个工具无限挂起拖垮整个任务。6.5 第五步日志、监控与迭代上线前我把日志推送到腾讯云 CLS设置了两个告警规则工具调用失败率超过 10%触发告警平均响应时间超过 20 秒触发告警。这两个指标基本覆盖了大部分线上问题。上线后我每天查看一次调用日志重点关注模型有没有出现反复调用某个工具的情况、用户有没有反馈“回答不完整”、工具的返回格式有没有因为上游变更而变化。我在跑了一周后发现一个有意思的现象file_reader的调用成功率只有 82%排查日志后发现有一类 PDF 文件结构不标准解析失败。我在技能描述里补充了一条“对于扫描版 PDF 请直接告知用户暂不支持”同时加了 OCR 预处理逻辑成功率提到了 96%。这就是“看日志→定位问题→迭代技能”的典型循环。7. 常见问题与排查技巧实录7.1 Agent 反复调用同一个工具这是我在调试中碰到最多的问题。模型像陷入死循环一样反复调用同一个工具拿到同样的结果。排查思路先看工具返回的是不是“空结果”。如果返回“无结果”模型又没有其他手段就会尝试重试。解决方式是在技能描述里写清楚“如果搜索结果为空直接在回复中告知用户不要重试”。再看是不是工具的参数一直不满足条件。比如要求time_range为空时才搜索但模型每次都带上一个无效值。这时候需要检查参数枚举定义是否完整。最后看编排层的轮次限制。就算模型真的陷入循环MAX_STEPS也能兜底强制退出不会无限烧钱。7.2 工具参数格式突然报错有次web_search突然大量报错查日志发现是上游搜索接口的返回格式变了字段title改成了headline。这个问题的根源是外部依赖变化Agent 无法自适应。解决思路是给解析层加“格式宽容度”title result.get(title) or result.get(headline) or result.get(heading) or 同时设置一个解析兜底如果所有字段都取不到就返回“该条结果解析失败”而不是直接抛异常中断整个流程。7.3 模型生成的工具参数不符合 Schema这是比较常见的问题。模型明明理解意图但调用参数时格式不对。我遇到的情况包括日期格式传成了2025/01/15而不是2025-01-15电话号码带了空格布尔值传了是/否而不是true/false。最有效的解法不是在提示词里一遍遍强调而是写一个Schema 校验 自动修复层from jsonschema import validate, ValidationError def safe_tool_call(tool_name, args): schema tool_schemas[tool_name] try: validate(instanceargs, schemaschema) return execute_tool(tool_name, args) except ValidationError as e: # 尝试自动修复常见类型问题 repaired auto_fix(args, e) return execute_tool(tool_name, repaired)auto_fix里做简单的类型转换比如字符串“是/否”映射到布尔值日期格式统一化成YYYY-MM-DD。实测下来自动修复能救回 40% 左右的参数格式错误剩下的会明确报错并返回给模型让模型自行纠正。7.4 上下文被塞满导致模型“失忆”长对话场景下模型一开始还能记住前文要求到后面就忘了。我排查过问题出在两处一是对话轮数太长超出了模型的有效注意范围。即使 token 没超早期的内容也会被稀释。我处理的方式是把用户的长期偏好比如“报告中要包含数据来源链接”这类要求提取到系统提示词固定位置这样每一轮模型都会看到而不是依赖从历史对话中回忆。二是摘要粒度太粗。我最初只写一句话“用户偏好简洁报告”但真实需求是“用户偏好简洁报告但数据表格需要完整呈现不要省略”。我优化了摘要模板改为结构化的偏好列表摘要质量提升明显。7.5 不同模型对同一技能的表现差异我在切换模型时发现一个有意思的现象同一个工具定义Claude 系列通常能正确解析复杂嵌套参数而一些轻量模型遇到嵌套 JSON 就糊涂了。解决方案是根据模型能力动态调整工具 Schema 复杂度。在 LiteLLM Proxy 层做模型分组轻量模型只分配简单技能单一参数为主重型模型才能访问嵌套参数技能。这样既保留了轻量模型的成本优势又不牺牲整体能力。8. 经验的扩展延伸8.1 从单 Agent 到多 Agent 协作这个项目做完之后我明显感觉单 Agent 的能力是有天花板的一个 Agent 既要理解用户意图又要执行复杂任务还要保证输出质量难度会呈指数上升。下一阶段我更看好“多 Agent 协作”的思路——用一个 Supervisor Agent 负责任务拆解和进度管理多个 Specialist Agent 各自负责一个领域。比如做市场分析Supervisor 会拆成“数据收集 Agent”“行业趋势 Agent”“竞争分析 Agent”三个子任务每个子任务有自己独立的技能集和记忆库最后汇总给 Supervisor 做综合判断。腾讯云 AI Skills 天然适合这种模式技能可跨 Agent 共享每个 Specialist Agent 的日志独立可查调试时能快速定位是哪个环节出了问题。我在本地已经用小规模多 Agent 方案验证过效果确实比单 Agent 好——尤其是在任务可以明确拆分的场景下各 Agent 互不干扰每个 Agent 的输出质量也更容易把控。8.2 将 Skills 沉淀为团队资产最后我想说一个更长期的规划视角。AI Skills 这个机制除了让单个 Agent 变强还有一个容易被忽视的价值——它是团队能力的沉淀载体。以前团队积累的业务知识存在文档里模型每次都要重新学习现在可以把特定领域的处理逻辑封装成技能做成团队共享的知识资产。新人加入时不需要从零理解所有业务细节直接调用团队沉淀好的技能就能快速上手。这种资产随用随取越用越准从长期来看可能是 AI Skills 最大的价值所在。我自己接下来会重点做两件事一是把调研 Agent 的核心技能抽成通用模板方便复用到其他项目二是尝试把技能的版本管理做得更规范每次改动都有 changelog这样团队协作时每个人都知道某个技能发生了什么变化避免“自己改完只有自己知道”的情况。