尧图精选

从脚本到平台:Agent编排、多供应商与MCP/SKILL/RAG工程实践

🕒 发布时间:2026/10/2 5:09:09 📁 来源:尧图网络
把团队里的Agent项目从一套临时脚本迁到XXL-AI平台比我想象中要折腾。起初我以为只是把提示词和大模型API调用整理一下真正动手才发现Agent应用的复杂度根本不在“调模型”而在编排、工具接入、知识检索、并发和安全这些工程问题上。这篇文章就围绕XXL-AI的Agent编排、多供应商接入以及MCP、SKILL、RAG三种扩展机制聊聊我是怎么理解这套平台的以及在实际搭售前问答Agent时踩过的坑。如果你正在做Agent开发或者纠结要不要上平台这篇文章应该能给你一些参考。先说结论XXL-AI不是又一个模型封装SDK它把Agent运行拆成了“编排状态机 多供应商路由 可插拔扩展 工程化底座”四个核心层。下面我从实际问题出发逐层拆解。1. 从“连续调用模型”到“编排Agent”XXL-AI想解决的问题1.1 Agent业务与单次大模型调用的本质差距很多人第一次做Agent项目习惯性把大模型API调用包一层然后写一个循环收到用户问题拼接提示词调模型拿结果再拼接一轮。这样跑通一个Demo很快但一旦需求变成“问题可能涉及多个工具、多轮决策、中途需要等待用户确认、某个工具调用失败了要重试”这段代码就会迅速失控。我最早做过一个行程规划Agent需求是帮助用户规划出差路线。看起来简单实际需要同时调天气API、地图路程计算、日历查询还要根据用户预算给出方案。用裸脚本写第一版功能是能跑但每次改动都像在给一锅粥加料“如果地图服务超时怎么办”“如果天气接口返回异常怎么办”“如果用户临时改变目的地怎么办”。这些异常和分支逻辑堆在业务代码里和提示词搅在一起最后根本没法让团队其他人接手。Agent业务和单次模型调用的本质差距在于单次调用是“输入文本 → 输出文本”而Agent是一个带状态的执行过程。它内部有记忆、有工具调用、有分支决策、有异常恢复。这个过程必须被显式建模否则代码复杂度会随需求线性爆炸。1.2 编排层真正管理的状态、工具与异常恢复XXL-AI引入Agent编排层后我最直观的感受是业务逻辑终于从“大模型调用的夹缝中”抽出来了。编排层负责维护一次任务的完整生命周期比如状态是idle、tool_calling、waiting_user还是finished、error。每次调用大模型只是状态机里的一个Step工具执行是另一个Step不同Step之间通过事件驱动流转。这样做有个很实际的好处执行过程可以被持久化中断后能从最近一个稳定状态恢复。有一次我们线上环境发版正在跑的一批Agent任务被中断以前裸脚本只能全部重头跑一遍换成XXL-AI之后任务从tool_calling状态恢复继续执行后续步骤即可。这个能力不是花哨功能在真实生产环境里非常值钱。还有人问过“harness和agent区别是什么”。按我的理解Harness是Agent运行时的执行夹具负责调用、监控、资源隔离Agent本身是决策体。XXL-AI的编排运行时就是一种HarnessSkill可以理解成注入到Harness里的可复用决策包。两者配合而不是对立。1.3 平台与框架的边界为什么需要一个底座框架和平台的区别我是在多人协作了三个Agent项目之后才真正想明白的。框架给你类和函数平台给你运行时、控制台、权限、计费、可观测。当团队里五个人同时往一个Agent项目里塞技能和工具时如果没有统一底座很快会因为提示词格式不统一、工具权限没人管、日志格式各写各的而炸掉。XXL-AI把这类公共能力收敛成底座模型路由走统一出口工具通过MCP协议注册知识通过RAG服务挂载技能以SKILL形式共享。每个人只写自己负责的那个SKILL平台负责调度和治理。对我来说这套东西解决的不是“能不能做出Agent”而是“能不能持续稳定地做出一堆Agent”。2. 多供应商接入的工程实践协议统一、路由与故障转移2.1 为什么AI应用必须做多供应商抽象如果你只在Demo里用一个模型多供应商确实是多余设计。但一旦上线单点依赖的风险立刻暴露供应商限流、价格波动、某个模型在某类任务上表现突然变差都需要能快速切换。我甚至遇到过因为并发过高被供应商临时降到最低配导致整批任务超时的极端情况。把大模型供应商当成数据库驱动来做抽象是工程上的基本常识。应用代码不直接依赖任何一家API而是依赖一个统一的Provider接口。XXL-AI在这个接口上包了一层路由和容错应用只声明“我需要一个支持工具调用的高智能模型”由平台决定最终调谁。2.2 Provider适配层与统一请求结构XXL-AI的Provider适配层解决两类问题接口差异和模型能力差异。不同供应商的请求结构不一样比如OpenAI风格是messages toolsAnthropic风格是messages tools但字段定义不同。平台将这些统一成内部结构我只需要面向这个结构开发字段说明是否必须model模型标识如gpt-4o、claude-3-5-sonnet是messages对话消息数组支持system/user/assistant/tool是tools工具定义数组统一格式描述否temperature采样温度否max_tokens输出上限否工具调用的返回格式也被统一。我们在接入一个订单查询MCP工具时发现有的模型会把工具参数输出成JSON字符串有的直接输出对象有的会在参数里夹带解释性文字。如果不做统一解析层下游工具根本不敢直接消费这些参数。XXL-AI的运行时会在调用工具前对参数做一次schema校验和类型强制转换这极大减少了“模型生成非法参数”导致的运行错误。2.3 路由、配额与故障转移的落地配置我实际配置多供应商路由时主要设置了三种策略优先级路由、权重路由和成本路由。优先级路由优先使用主供应商主供应商不可用时自动切到备选适合对稳定性要求极高的场景。权重路由按比例分配流量比如主模型70%、备选模型30%用于灰度验证新模型。成本路由按任务场景区分复杂推理走旗舰模型普通问答走轻量模型控制月度账单。配置上类似这样provider: primary: type: openai base_url: https://api.example.com/v1 api_key_env: OPENAI_API_KEY weight: 70 priority: 1 secondary: type: anthropic api_key_env: ANTHROPIC_API_KEY weight: 30 priority: 2 failover: enabled: true max_retries: 3 circuit_breaker: error_threshold: 5 recovery_timeout_s: 30这里有一个我踩过的坑如果你只配置了故障转移但没有配连续错误熔断某家供应商开始持续超时的时候系统会傻乎乎地把所有请求都重试到同一家最后拖垮整体RT。加了熔断逻辑之后连续报错5次就把该路由置为半开状态等30秒再做一次探测效果立竿见影。3. “MCP SKILL RAG”扩展机制选型逻辑与协同边界3.1 MCP给Agent工具层套上软件协议的壳MCP的全称是Model Context Protocol本质上是应用层软件协议。有人问“MCP是软件协议那硬件协议那个概念叫什么来着”简单说硬件协议比如USB-C、HDMI是定义物理接口的电气规范和形态而MCP定义的是程序之间如何用JSON-RPC交换上下文和工具调用数据。两者层级完全不同MCP更像一个“软件层面的标准接口”。我用MCP最大的感受是工具接入终于有标准方式了。之前接一个企业内部订单系统要么写一个自定义HTTP封装要么把函数直接注册进系统换一个项目又要重新接一遍。现在只要把订单查询封装成一个MCP Server通过stdio或SSE暴露工具列表和调用方法任何支持MCP Client的Agent平台都能直接复用。实际项目中团队最常用的是两类MCP Server浏览器自动化类和业务系统类。比如浏览器自动化的场景有人纠结“browser use MCP和playwright MCP有什么区别”。我两个都试过简单区分playwright MCP暴露的是“打开页面、点击、输入、截图”这类细粒度操作原语适合你清楚每一步要做什么的自动化browser use MCP则偏任务型它会根据自然语言目标让模型自己规划点击路径适合不确定操作步骤的探索场景。选型时看你要的是“可控的遥控器”还是“放权的执行者”。MCP Server的典型实现并不复杂我写过一个最小的订单查询服务协议部分大致是先声明工具列表再监听调用请求把结构化参数传进来返回结果。平台侧只需要配置Server地址和允许暴露的工具白名单。3.2 SKILL把解题经验从“提示词”升级为可执行单元我在没有SKILL概念之前复用Agent能力的方式是复制提示词。问题是提示词只是文本没法携带参数校验、工具绑定和自检逻辑。比如我写了一个“客户跟进邮件生成”的提示词换一个业务场景提示词要改调用哪个CRM模板要改是否允许查历史订单也要改全靠手动。XXL-AI的SKILL机制把“一段提示词”扩展成了一个结构化技能包我通常按下面几块来定义skill: name: sales_followup description: 根据客户历史订单和沟通记录生成跟进邮件 trigger: intents: [跟进, 催单, 回访] steps: - step: 获取客户历史订单 tool: order_mcp params: customer_id: $slot.customer_id - step: 获取最近沟通记录 tool: crm_mcp params: keyword: $slot.customer_name - step: 生成邮件正文 model: high_intelligence instruction: 基于以上订单和沟通记录生成专业、简短、无AI腔的跟进邮件 guardrails: - 禁止编造未发生的订单状态 - 如果缺少客户ID则主动提问 output: format: markdown社区里现在很流行讨论“去AI味的skill”我的体会是单靠提示词写“不要客套、不要官方”没有用真正有效的是在SKILL里增加结构化规则比如禁止使用“首先、其次、最后”这类连接词邮件正文禁止超过三句话客套必须包含具体数字或时间点。规则越结构化模型越不容易往套路上飘。还有人拿“book to skill”做实验把一本书的解题方法论转成一个SKILL。我试过把一份售后服务手册转成SKILL核心是把手册里的“判断条件→处理动作→反馈话术”抽取成状态表而不是把整本手册塞进提示词。结果比直接RAG检索手册更稳定因为SKILL里已经固化了决策路径。3.3 RAG知识库的检索质量、多模态与本地化部署RAG是这个三件套里最容易被低估的。很多人以为RAG就是“PDF解析向量库相似度检索”做完才发现召回质量一塌糊涂。我在XXL-AI里用RAG服务搭建知识库第一步不是选向量库而是梳理文档结构。切分策略上我按语义块切分而不是死板按字符数切分。产品手册有章节、表格、参数列表如果一刀切512字符表格会被拆得七零八落。我的做法是表格按“标题表头行内容”整体打包段落按Markdown标题层级优先合并代码示例独立成块。文本块大小我控制在320到512 tokens之间太长会稀释相关性太短则上下文碎片化。衡量RAG好不好我盯的核心指标是rag hit rate也就是检索Top-K结果中真正包含正确答案的比例。如果这个指标低于80%不建议上生产。有个真实场景我们上传了产品价格表和FAQ线上用户问“A套餐包含哪些服务”系统经常从那批FAQ里召回“套餐怎么退订”的内容语义接近但答案方向完全不同。后来加了一个reranker重排层把向量召回结果再按语义相关性精排一次hit rate才从72%拉到89%。关于“RAG知识库能存储图片吗”这个问题答案是能但要看你怎么用它。简单做法是把图片文件本身存文件系统或对象存储向量库里只存图片的描述向量和元数据复杂做法是用多模态模型抽取图片中的文字和表格生成结构化文本后再走检索。我实际做售后知识库时很多用户问题涉及“界面截图”只用OCR文本召回效果一般最后是让多模态模型给每张截图生成了功能描述再和OCR文本一同做向量化召回准确率才明显提升。如果你对数据出域很敏感可以走本地化RAG方案。比如用Ollama部署本地embedding模型和本地向量库把整个RAG链路收在内网。做法不复杂Ollama拉一个embedding模型起一个向量库容器把“切分→embedding→入库→检索”写成脚本。XXL-AI支持配置本地embedding端点直接替换默认的云端embedding服务实现知识检索不出内网。3.4 三种扩展机制如何配合一个售前场景的切片MCP、SKILL、RAG不是三选一而是各管一段。我常用的一句话总结MCP连接外部世界RAG引入内部知识SKILL封装解题行为。拿售前问答Agent举例用户问“你们支持私有化部署吗”Agent先从RAG知识库检索“部署模式”相关文档如果没有现成答案就通过MCP的CRM工具查询该客户的行业和规模再结合SKILL里固化的“私有化部署评估流程”决定是否需要转人工。整个过程里RAG负责给事实MCP负责取动态业务数据SKILL负责规定“先查什么、再判断什么、什么情况下转人工”。如果只挂一个RAGAgent会变成“能说不能做”如果只接MCP它又缺乏对业务知识的理解只有SKILL没有前两者技能就只是空壳。三者叠起来才是一个完整的可交付Agent能力。4. 工程化底座状态机、并发模型、可观测性与安全边界4.1 状态机是Agent执行的核心骨架Agent编排器要解决的第一个问题是“这个任务跑到哪一步了”。我用XXL-AI时平台上每个Agent任务都会暴露当前状态和完整事件日志。比如一个售前Agent任务可以观察到processing.intent意图识别完成tool.order_mcp.call正在调用订单查询工具tool.order_mcp.result拿到订单结果rag.retrieve正在检索知识库model.generate正在生成最终回答finished任务完成事件驱动的好处是可以精准定位卡点。上次线上有个任务卡了十几秒没响应通过日志发现是卡在工具调用等待上因为目标MCP Server所在网络环境有抖动触发了超时重试。如果是一个黑盒的Agent循环这种问题根本无法排查。4.2 扛并发从同步调用到任务队列与Worker池“AI Agent怎么扛并发”是社区里问得很多的问题。我的经验是别让HTTP请求直接驱动Agent循环。线上真实场景中的Agent往往要多次调用模型和工具单次请求耗时动辄5到20秒如果每个用户请求都直接占一个工作线程系统很快会被拖垮。XXL-AI的做法是任务化。用户请求进入后先落一个任务队列Worker池从队列里消费任务执行Agent状态机。任务里保存了完整上下文因此可以在任意状态暂停、恢复也便于水平扩容。我按常规实践总结了一套参数参考任务队列容量设5000Worker池32个每个Worker并发处理8个Agent任务单机大概能扛住400个同时在跑的Agent任务。如果任务里有流式输出需求则通过SSE或WebSocket从Worker侧推给前端不额外占用网关线程。这里有个实际问题模型供应商的并发限制往往比你的Worker池更早到瓶颈。所以必须做两层限流一层在平台入口按用户或按场景做令牌桶限流另一层在Provider适配层对每个供应商单独控制并发水位。比如某供应商账号最多支持50并发平台侧就把对应Provider的并发数钳到40给重试和突发流量留缓冲。4.3 可观测与成本治理Trace、计费和评估Agent项目上线之后最怕什么怕出了错不知道是模型的问题、工具的问题还是提示词的问题。XXL-AI对每次运行生成一条完整Trace里面包含每一步的输入输出模型调用时长、Token消耗、工具调用结果、RAG检索命中情况。我排查问题时基本是先看Trace里哪个环节耗时最长、哪个环节出现了非预期结果。成本治理是另一个必须早做的基础设施。每个Agent任务会产生多次模型调用月度账单很容易吓人。我按场景建立了预算标签比如“售前问答”和“售后工单”分账再通过平台计费模块看到每个SKILL的平均单次成本。成本异常时优先检查是否出现“循环调用”有一次Agent卡在工具调用失败和重试之间同一个模型被调了十几次这种必须靠Trace抓。质量评估上除了人工抽检我还会配一个独立的“评测Agent”作为裁判把用户问题、Agent回答、检索内容一起喂给它打分。这本质上是LLM-as-judge跑批之后能看到不同SKILL、不同模型版本之间的质量差异用来决定是否切换路由权重。4.4 安全边界工具白名单、防注入与数据脱敏Agent安全是我最谨慎的一部分。平台上的工具越多风险面越大。XXL-AI里每个MCP工具都必须声明允许访问的资源域和操作类型比如一个订单查询工具只允许read不允许write一个“发送邮件”工具必须经过二次确认节点才能执行。数据脱敏也要在平台侧做。日志中心不能直接打印用户手机号、身份证号、订单金额等敏感字段我们在工具结果进入Trace之前统一做脱敏这样排查问题时能看到数据结构但看不到敏感值。如果模型回复中需要展示订单金额则由前端在拿到脱敏后的业务结果后自行格式化。Prompt注入是我特别提醒团队注意的点。用户输入的内容是数据不是指令。我们配置SKILL时会对用户输入里的“忽略以上指令”“执行系统命令”等模式做识别更严格的是在工具参数校验阶段禁止用户输入直接作为执行类工具的关键参数。比如“下单Agent”里收货地址和金额必须来自CRM和商品库而不是用户单方面提供这能从根本上防止诱导改价之类的问题。5. 完整实战在XXL-AI上搭建一个售前问答Agent5.1 需求拆解与Agent拓扑我以最近做的一个“售前问答Agent”为例讲一下完整链路。业务需求是潜在客户在官网提问Agent要能解答产品功能、部署方式、报价相关常识如果客户是留资用户还可以查询订单或试用状态客服主管需要能看到每一次对话的处理质量。拆解下来Agent需要三类能力产品知识问答、订单状态查询、销售话术规范。对应到XXL-AI就是三个SKILLproduct_qa、order_status、sales_followup。这三个SKILL共享一个RAG知识库和一个订单MCP工具但各自的触发条件和步骤不同。整体拓扑很简单用户提问先过意图识别路由到对应SKILLproduct_qa主要走RAG检索必要时用MCP查询用户所属行业模板order_status必走订单MCP同时从RAG检索“订单状态含义”的解释文案sales_followup组合上述能力按SKILL固化的邮件模板生成回复。模型侧我做了两级路由意图识别用轻量模型最终回复生成用高智能模型。这是控制成本的关键手段。5.2 MCP接通订单查询RAG挂载知识库SKILL固化销售链路订单MCP Server的配置我之前已经写过。实际操作中平台里只需要填Server地址、认证Token和允许暴露的工具名列表。业务系统那边不用改任何代码只要暴露一个标准的MCP端点即可。RAG知识库这边我传了三类文档产品手册、常见问题FAQ、报价规则。切分参数按语义块进行表格整体打包段落按标题层级合并。向量化用了通用embedding模型文本块约400 tokens。为了处理“图片能存吗”的问题我让多模态模型给每张产品截图生成了一句话描述描述文本进入索引图片源文件存在对象存储。SKILL方面我把销售链路固化成可执行步骤先判断用户是否已有订单或试用记录再决定推荐内容如果用户是政府机构或重点企业自动追加“支持私有化部署”的说明邮件或在线回复必须避免空泛套话要求至少包含一个具体的产品功能名称或数据指标。5.3 实测中的四个典型坑与处理方式说几个线上实际遇到的坑都是常规文档里不会写的内容。第一个坑是Agent反复调用MCP工具导致延迟增加。现象是一个简单问题Agent为了确认信息连续调了三次订单接口用户等得很不耐烦。解决方式是给工具调用加结果缓存同一任务内相同参数的工具结果直接复用同时在提示词里约束“只有在需要具体订单状态时才调用订单工具不要为了一般性介绍调用”。第二个坑是RAG检索到过期价格。产品调价后老报价单还在知识库里Agent偶尔会按旧价格回答。处理方式是在文档切分时把“版本号”和“生效日期”写入元数据构造RAG查询时强制过滤生效日期 当前日期并在SKILL里约定“价格类问题必须引用最新版本文档”。第三个坑是主模型故障后切换到备用模型返回格式不稳定。原来主模型习惯了输出结构化JSON数组备用模型有时输出Markdown列表导致前端解析失败。后来我让平台在切换路由时不光换模型还自动换掉对应的系统提示词模板并在输出解析层做了“容错提取”兜底。第四个坑是并发高峰期的供应商限流。演示日流量上来后某供应商直接拒绝了一部分请求。我们靠两级限流加退避重试解决平台入口按用户限流Provider层按供应商并发钳制同时给重试加入了指数退避而不是全部立即重试。这些坑单独看都不大但串在一起恰恰说明了“Agent能跑通”和“Agent能稳定跑”之间的距离。XXL-AI给我的最大价值就是把这些运维和工程层面的问题收拢进了平台让我能把精力放回业务逻辑本身。最后再分享一个小技巧。如果你也在做类似平台或Agent项目建议每次上线前跑一轮“异常注入演练”故意让某个MCP工具超时、让某个RAG索引失效、把某个供应商的密钥改成错的看Agent是否能优雅降级。我做过几轮之后系统从“一改配置就崩”变成了“最多提示用户稍后再试”这才敢把它放到生产环境里持续服务。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →