客服 Agent 这个方向我从最早的关键词匹配 人工兜底一路看到现在的多工具编排 知识检索 协议标准化 自动评测中间踩过的坑比想象中多得多。标题里说的渡劫 48 关一点都不夸张——一个能上生产的客服 Agent绝不是把大模型接上就完事它要过 Tool 调用、RAG 检索、MCP 协议对接、Eval 评测这四道大关每一关下面又藏着十几个小坑。这篇就把这四层拆开讲透从为什么这么设计到具体怎么落地再到实测中会翻车的地方尽量给到能直接抄作业的细节。不管你是刚接触 Agent 开发的新手还是已经跑通 Demo 但卡在效果上的老手都能从里面找到对得上号的那一关。1. 先搞清楚客服 Agent 到底难在哪很多人对客服 Agent 的想象是用户问一句模型答一句答不上来就转人工。这个理解在 Demo 阶段没问题但一上真实业务就崩。原因很简单——真实客服场景里用户的问题从来不是单轮、单意图、单知识源的而是多轮、多意图、跨系统、带情绪、带上下文依赖的。这就决定了客服 Agent 的本质不是一个问答模型而是一个调度系统。1.1 客服场景的三个硬约束第一个约束是准确性优先于流畅性。闲聊机器人答得天花乱坠没关系但客服说错一句这个可以退款可能直接造成资损。所以客服 Agent 的输出必须可追溯、可验证这就直接催生了对 RAG 和 Eval 的强需求。第二个约束是动作要能落地。用户说帮我查下订单到哪了Agent 不能只回答您的订单正在运输中它得真的去调订单查询接口拿到真实物流状态。这就是 Tool 调用的价值——让 Agent 从会说变成会做。第三个约束是系统要能扩展。客服背后往往挂着订单、物流、售后、会员、工单等一堆系统每接一个系统就要改一次 Agent 代码这种耦合是灾难。MCP 协议出现的意义就是把这层对接标准化让接一个新工具从改代码变成配配置。1.2 四层能力的分工关系把 Tool、RAG、MCP、Eval 这四层的关系理清楚后面才不会乱层级解决的问题类比缺失后的症状Tool让 Agent 能执行动作手只会说不会做用户要自己操作RAG让 Agent 答得准记忆胡编乱造答非所问MCP让工具接入标准化插座标准每接一个系统改一次代码Eval让效果可量化可回归体检改一处崩一处不敢上线这四层不是并列的而是有依赖顺序的先有 Tool 让 Agent 能干活再用 RAG 保证干得对然后用 MCP 把工具接入规模化最后用 Eval 把整个系统管起来。跳过任何一层后面都会加倍还债。1.3 为什么渡劫这个说法很贴切我见过太多团队的做法是先花两周把 Demo 跑通老板很满意然后直接上生产结果第一周就被真实用户问崩。问题出在 Demo 和生产的差距不是线性的而是断崖式的。Demo 里你只测了 20 个问题生产里用户会用 2000 种你没想过的方式问同一个问题。所以渡劫的核心含义是每一层能力都要经过真实流量的反复捶打才能从能跑变成能扛。下面四章就按这个顺序一层层拆。2. Tool 层让 Agent 从会说到会做Tool 调用是客服 Agent 的第一道关也是最容易被低估的一关。很多人以为 Tool 就是定义个函数让模型调实际上从工具设计到参数校验到错误处理每一步都有讲究。2.1 工具粒度怎么切才合理新手最容易犯的错是工具切得太细或太粗。切太细比如把查订单拆成查订单号查订单状态查订单金额三个工具模型要连续调三次才能回答一个问题延迟高、出错概率大。切太粗比如一个处理售后工具包揽退款、换货、维修参数复杂到模型根本填不对。我的经验是按用户意图切而不是按后端接口切。一个用户意图对应一个工具工具内部再去编排多个后端接口。比如查询订单物流就是一个工具它内部可能先调订单服务拿运单号再调物流服务拿轨迹但对模型来说只暴露一个入口。# 工具定义示例按用户意图切分 tools [ { name: query_order_logistics, description: 查询订单的物流状态。当用户询问订单到哪了、什么时候到、物流信息时使用。, parameters: { type: object, properties: { order_id: {type: string, description: 订单号18位数字}, phone_suffix: {type: string, description: 下单手机号后四位用于身份校验} }, required: [order_id] } } ]注意 description 的写法——它不是写给程序员看的是写给模型看的。要明确写清楚什么时候用这个工具这直接决定了模型的调用准确率。2.2 参数校验与身份验证不能省客服场景有个特殊性很多操作涉及用户隐私和资损。用户说帮我退款Agent 不能直接退得先验证身份。这个验证逻辑不能交给模型判断必须在工具层硬编码。我的做法是在工具执行前加一道前置校验中间件def execute_tool(tool_name, params, session): # 1. 身份校验敏感操作必须验证 if tool_name in SENSITIVE_TOOLS: if not verify_identity(session.user_id, params.get(phone_suffix)): return {error: 身份验证失败请提供下单手机号后四位} # 2. 参数校验类型、范围、格式 validated validate_params(tool_name, params) if not validated[ok]: return {error: validated[msg]} # 3. 执行 return TOOL_REGISTRY[tool_name](**validated[params])这里的关键认知是永远不要相信模型填的参数。模型可能把订单号填成手机号可能把日期填成明天可能漏填必填项。校验层是最后一道防线。2.3 工具返回结果怎么喂回模型工具执行完结果怎么给模型直接影响最终回答质量。我踩过的坑是直接把后端返回的 JSON 原样丢给模型结果模型被一堆无用字段干扰回答得乱七八糟。正确做法是做一层结果裁剪和结构化。后端返回 50 个字段只挑模型需要的 5 个并且用自然语言结构化混合的方式给# 不好的做法 return json.dumps(raw_response) # 50个字段全丢过去 # 好的做法 return { summary: 订单已发货当前在杭州转运中心, status: 运输中, estimated_arrival: 2024-06-15, latest_trace: 2024-06-13 14:30 已到达杭州转运中心 }提示工具返回里如果有时间、金额这类关键信息一定要格式化好再给模型不要让模型自己去解析时间戳它经常算错。2.4 工具调用失败的兜底策略真实环境里工具会失败——接口超时、服务降级、参数错误。这时候 Agent 不能直接崩要有兜底。我的策略分三级可重试错误超时、限流自动重试 2 次间隔递增参数错误把错误信息返回给模型让它重新填参数最多重试 1 次系统错误直接转人工并附带错误上下文这里有个细节重试次数要严格控制。我见过有团队设置重试 5 次结果一个慢接口把整个对话拖死。客服场景对延迟敏感单次工具调用超过 3 秒就该考虑降级了。3. RAG 层让 Agent 答得准而不是答得像Tool 解决了会做RAG 解决答得准。客服场景里大量问题是知识型的——退换货政策、保修范围、活动规则这些答案不在数据库里而在文档里。RAG 就是把这些文档变成 Agent 能检索的知识。3.1 客服知识库的特殊性通用 RAG 教程讲的都是把 PDF 切块、向量化、检索但客服知识库有几个特殊点第一知识有强时效性。活动规则这周有效下周就废了如果检索到过期知识比不检索还糟。所以客服 RAG 必须带时间过滤检索时优先返回有效期内的内容。第二知识有强层级。一个退货政策下面可能分七天无理由质量问题退货特殊商品退货多个子条款检索时如果只召回片段模型可能答得不完整。这时候需要父子块检索——召回子块但把父块一起给模型。第三知识有强冲突。不同文档可能对同一问题有不同说法旧版 vs 新版必须有一套优先级规则来决定用哪个。3.2 分块策略别再用固定长度切了固定 512 token 切块是通用做法但客服文档里经常出现一个条款被切断的情况。我的做法是按语义结构切# 按标题层级切分保留上下文 def chunk_by_structure(doc): chunks [] for section in doc.sections: # 每个二级标题下的内容作为一个块 content section.title \n section.body # 如果块太大再按段落切 if len(content) MAX_CHUNK: chunks.extend(split_by_paragraph(content)) else: chunks.append({ content: content, metadata: { doc_id: doc.id, section: section.title, effective_date: doc.effective_date, category: doc.category } }) return chunks关键是 metadata 要带全——文档 ID、章节、生效日期、分类这些在后面检索过滤时都要用。3.3 检索环节的混合策略纯向量检索在客服场景不够用因为用户经常问的是精确的专有名词比如XX 型号保修几年这种用关键词检索更准。我的做法是向量 BM25 混合检索再加重排序检索方式擅长不擅长向量检索语义相似、口语化提问精确匹配专有名词BM25关键词精确匹配同义改写、语义理解混合重排兼顾两者实现复杂度高具体流程是向量检索召回 Top 20BM25 召回 Top 20合并去重后用重排模型如 bge-reranker精排取 Top 5 给模型。实测下来混合检索比纯向量在客服场景的召回准确率能提升 20% 以上。3.4 RAG 的常见翻车点翻车点一检索到了但模型没用。有时候检索结果明明包含答案模型却视而不见。这通常是 prompt 没写好要在 prompt 里明确要求必须基于检索内容回答检索内容没有就说不知道。翻车点二检索到多个冲突答案。模型可能把两个矛盾的条款都答出来。解决办法是在检索后做冲突检测同一问题有多个答案时按生效日期和优先级选一个。翻车点三知识库更新不及时。活动规则改了但知识库没同步Agent 还在答旧规则。这需要建立知识库更新流程最好能对接业务系统的变更事件自动触发重建索引。注意RAG 不是建好就完事它是一个需要持续运营的系统。我建议每周做一次检索质量抽检看 Top 5 召回里有多少是真正相关的。4. MCP 层把工具接入从改代码变成配配置前面 Tool 层讲了怎么定义工具但如果每接一个后端系统都要写一遍工具代码团队会被拖死。MCPModel Context Protocol的价值就是把这层标准化——工具提供方按协议暴露能力Agent 侧按协议消费双方解耦。4.1 MCP 到底解决了什么问题在没有 MCP 之前接一个订单查询系统是这样的写工具定义、写参数校验、写调用逻辑、写结果处理每个系统一套。有了 MCP 之后订单系统自己实现一个 MCP Server暴露查询订单这个能力Agent 侧只需要配置这个 Server 的地址就能自动发现并调用它的工具。这个变化的意义在于职责分离业务系统最懂自己的接口让它自己维护 MCP ServerAgent 团队专注在编排和效果上不用管每个系统的细节。4.2 MCP Server 的接入实操接入一个 MCP Server 通常分三步配置连接、发现工具、调用工具。// Agent 侧的 MCP 配置 { mcpServers: { order-service: { command: npx, args: [-y, company/order-mcp-server], env: { API_BASE: https://internal-api.company.com/order } }, logistics-service: { command: npx, args: [-y, company/logistics-mcp-server] } } }配置好之后Agent 启动时会自动连接这些 Server拉取它们暴露的工具列表合并到自己的工具集里。整个过程不需要改 Agent 的核心代码。4.3 多 MCP Server 的工具冲突处理当接入多个 Server 后很容易出现工具重名或功能重叠。比如订单服务和售后服务的 Server 都暴露了一个query_order工具。这时候需要一套命名空间和优先级规则工具名加 Server 前缀order.query_order、aftersale.query_order配置优先级同名工具按配置顺序先匹配到的优先描述去重如果两个工具功能相同保留描述更详细的那个我踩过的坑是两个 Server 的工具描述都很模糊模型随机选一个结果调错了系统。解决办法是在 Agent 侧维护一份工具路由表对模糊工具做显式映射。4.4 MCP 的稳定性与降级MCP Server 是独立进程会挂、会超时。Agent 侧必须做健康检查和降级class MCPClient: def __init__(self, server_config): self.config server_config self.healthy True self.last_check 0 def call_tool(self, tool_name, params): if not self.healthy: # 降级返回缓存结果或转人工 return self.fallback(tool_name, params) try: return self._do_call(tool_name, params, timeout3) except TimeoutError: self.mark_unhealthy() return self.fallback(tool_name, params)关键认知MCP 让接入变简单了但没有让稳定性问题消失。每个 Server 都是一个潜在的故障点Agent 侧必须有兜底。5. Eval 层让 Agent 效果可量化、可回归前三层做完Agent 能跑起来了。但能跑和跑得好之间隔着 Eval 这一层。没有 Eval你改一个 prompt 不知道是变好还是变坏加一个工具不知道有没有引入回归这种状态下根本不敢上线。5.1 客服 Agent 的评测维度客服 Agent 的评测不能只看答得对不对要分多个维度维度衡量什么评测方式意图识别有没有理解对用户想干嘛人工标注 模型打分工具调用该调工具时调了没、参数对不对轨迹比对知识准确性答案和知识库是否一致事实核查话术质量语气、礼貌、清晰度模型打分 人工抽检安全性有没有越权、泄露、乱承诺规则 红队测试每个维度都要有独立的评测集和指标不能混在一起看。5.2 评测集怎么建才有效新手常犯的错是评测集太小、太干净。20 条精心构造的问题测出来 95% 准确率一上生产就崩。我的经验是评测集要满足三个条件第一规模够。至少 200 条起步覆盖所有主要意图每个意图至少 10 条。第二来源真实。最好从真实客服日志里采样保留用户的原话包括错别字、口语、省略。我见过太多评测集是产品经理想象出来的问题和真实用户问法差十万八千里。第三有标准答案。每条评测样本要有期望的工具调用轨迹和期望的答案要点这样才能自动比对。# 评测样本示例 { query: 我上周买的那个耳机还没到帮我看看, expected_intent: query_logistics, expected_tools: [query_order_logistics], expected_answer_points: [订单状态, 预计到达时间], must_not_contain: [无法查询, 请自行联系] }5.3 自动化评测流水线评测要能自动化跑否则每次改动都靠人工测效率太低。我的流水线是这样的触发每次 prompt 或工具变更自动触发评测执行用评测集跑一遍 Agent记录完整轨迹比对工具调用轨迹和期望比对答案要点用模型核查报告生成各维度得分和基线对比标出回归项卡点关键指标低于阈值时阻断发布def run_eval(agent, eval_set): results [] for case in eval_set: trace agent.run(case[query]) results.append({ case_id: case[id], intent_ok: trace.intent case[expected_intent], tools_ok: trace.tools case[expected_tools], answer_ok: check_answer_points(trace.answer, case[expected_answer_points]), safety_ok: check_safety(trace.answer, case[must_not_contain]) }) return aggregate(results)5.4 线上效果的持续监控离线评测过了不代表线上就好。线上要做持续监控重点看几个指标转人工率Agent 没搞定的比例这是最直接的失败信号工具调用成功率调用失败率高说明工具或参数有问题用户追问率用户连续追问同一问题说明第一次没答好负面反馈率用户点不满意的比例这些指标要能按意图、按工具、按时间段下钻才能定位问题。我建议做一个每日效果看板让团队每天都能看到 Agent 的健康度。提示线上监控发现的问题要定期回流到评测集里形成发现问题-补充评测-修复-回归验证的闭环。这是 Agent 持续变好的唯一路径。6. 四层打通后的整体架构与踩坑复盘前面四层分开讲了但真实系统里它们是交织在一起的。这一章讲整体架构怎么搭以及我在打通四层过程中踩过的几个典型坑。6.1 一次完整对话的流转过程用户问我上周买的耳机还没到帮我看看系统内部是这样流转的意图识别判断为查询物流意图RAG 检索检索物流相关政策比如发货后 3 天可查工具选择从 MCP 注册的工具里选出query_order_logistics参数填充从对话上下文里提取订单号缺失则追问工具执行通过 MCP 调用订单服务拿到物流状态结果整合把工具结果和 RAG 知识整合成回答安全校验检查回答里有没有越权承诺输出返回给用户同时记录轨迹用于 Eval这个流程里任何一步出问题最终效果都会打折。所以调试 Agent 时一定要能看到每一步的中间结果否则根本不知道问题出在哪。6.2 踩坑复盘工具和 RAG 的边界模糊我遇到过一个典型问题用户问退货要多久到账Agent 有时候调工具查退款进度有时候查 RAG退货政策。原因是这个问题的意图本身模糊——如果用户已经申请了退货应该查工具如果还没申请应该查政策。解决办法是在意图识别阶段做二次澄清检测到模糊意图时先追问一句您是已经申请了退货想查进度还是想了解退货政策这比让模型猜要靠谱得多。6.3 踩坑复盘MCP 工具描述质量参差接入多个 MCP Server 后我发现工具调用准确率反而下降了。排查后发现是某些 Server 的工具描述写得太烂比如查询订单这种描述模型根本不知道什么时候该用。解决办法是在 Agent 侧做工具描述增强维护一份工具描述覆盖表对描述质量差的工具用更清晰的描述替换。这虽然有点打补丁的味道但在 MCP 生态还不成熟的阶段是必要的过渡手段。6.4 踩坑复盘Eval 指标好看但线上差有一次离线评测各项指标都 90%上线后转人工率却高达 40%。排查后发现评测集和真实流量的分布差异太大——评测集里都是标准问法真实用户却大量使用方言、缩写、错别字。解决办法是用真实流量持续补充评测集并且做分布对齐——评测集的意图分布要和线上一致。这个坑让我深刻认识到评测集的质量比评测方法更重要。6.5 给不同阶段团队的建议最后按团队阶段给点实在建议刚起步先把 Tool 和 RAG 做扎实别急着上 MCP 和 Eval。工具能调通、知识能答准就已经能解决 70% 的问题。有了一定规模开始做 MCP 标准化把工具接入的边际成本降下来。同时建最小可用的评测集至少覆盖核心意图。准备上生产Eval 必须成体系线上监控必须到位。没有这两样不要上生产。已经在生产重点做效果闭环——线上问题回流评测集评测发现问题驱动优化优化后再回归验证。这套东西我前后折腾了大半年最大的体会是客服 Agent 的难点从来不在模型而在工程。模型能力是天花板但工程能力决定你能不能摸到天花板。Tool 让 Agent 有手RAG 让 Agent 有记忆MCP 让 Agent 有标准接口Eval 让 Agent 有反馈——四层缺一不可而且必须按顺序扎实做。急着跳步的最后都会在某一关加倍还回来。