1. 运单助手改错了 40 单,卡在哪一环
一家物流企业的客服中心,一天接三千多通电话。客服高频处理两件事:查运单现在到哪了、客户要求改派送时间。企业给客服接了一个运单助手,接了两条接口,一条查运单,一条改派送。
上线第一周就出了问题。
改错单。助手判断客户的要求已经说清楚了,直接调改派送接口把时间改了,没有让客服点确认。有些客户在电话里说的「明天」其实指的是「明天同一时间」,客服本来会再确认一句。一周下来改错了 40 单。
填错参数。改派送接口要两个值:期望派送日期和期望时间段。客户说「明天上午」,助手把「明天上午」整个填进了日期字段,接口返回格式错误。助手把报错原文丢给客服看,客服也不知道该填成什么样。
超时没人管。运单查询接口在高峰时段会超时。助手回一句「系统繁忙,请稍后再试」,客服只能自己打开另一个系统再查一遍。这一步没省下时间,反倒多了一个说不清的环节。
三个毛病各在一处:一个动作该不该让它自己动手,每个参数要交代到什么程度,动作做不成的时候谁来收拾。
2. 工具调用让模型自己挑动作
2.1 模型不执行,它只发出一个调用请求
工具调用(Tool Call)指模型在回答过程中,判断需要动一下外面的系统,就输出一段结构化的调用请求,写明要调哪个工具、参数是什么;平台拿到这段请求去真正执行,把结果塞回窗口,模型接着往下写。
模型自己不碰系统。它生成的是文本,执行的是平台。这一点对产品经理有两个直接后果。
一是模型可以写出一个参数填错的调用请求,平台照样会去执行。参数的含义、格式、取值范围,得在工具的定义里写清楚,指望模型猜是不行的。
二是凡是执行动作,都要经过平台这一层,所以权限、确认、日志都有地方可加。加在哪、加到什么程度,是这一集后面几节要讲的事。
模型发出的那段调用请求,平台拿它做了什么
客服问一句
- 客服在助手里输入帮我看看运单 SF7781234567 到哪了
- 窗口里此刻装着系统提示词、这张工单的字段、这一句提问
- 模型手上的东西几个工具的名字和说明,运单系统的连接不在它这一层
这时候模型只知道自己有哪些工具,碰不到运单系统。
模型写出调用请求
- 工具名
query_waybill - 入参
{ "waybill_no": "SF7781234567", "with_route": true } - 模型这一轮输出只有这一段结构化请求,没有多余的解释
模型生成的是文本,它自己一个动作也没执行。
平台核完再执行,把结果塞回窗口
- 平台这一层校验工具名存在、
waybill_no符合运单号格式、这位客服有运单查询权限 - 工具返回
{ "status": "运输中", "current": "杭州转运中心", "eta": "明天上午" } - 窗口里新增这一段工具返回(Tool Result)
执行发生在平台这一层,权限和日志都挂在这里。
模型接着把答复写出来
- 客服看到这单目前在杭州转运中心,预计明天上午派送
- 后台记下调用时间、调用人、工具名、入参、返回结果
参数写错平台也会照发,取值范围得在工具定义里写死。
模型只发请求,动手的是平台。
2.2 一次叫一个,还是一起叫
模型可以一次只发一个工具请求,也可以在同一轮里发好几个。判断标准是这些动作之间有没有依赖。
没有依赖的可以一起发。客户问「这单现在在哪,什么时候能到,能不能改成明天下午」,查运单、查预计到达时间、查可改的时间段这三件事互不依赖,同时发出去,返回再汇总,比一件一件排队快。
有依赖的必须串着来。改派送这个动作的前提是先知道这单现在是什么状态:已经在派送途中的单子不能改,已签收的更不能改。这类动作要等前一个工具返回结果,再决定下一步发什么。
产品经理在设计需求时要把这个依赖关系写出来。写出来了,研发才好决定哪些能并行、哪些必须等;写不出来,模型自己判断,多半会把不该同时发的动作一起发出去。
2.3 同一套接口可以包成不同粒度的工具
运单系统里其实只有两条接口:一条按单号查,一条按单号改。到了智能体这边,可以包成两种工具。
包得细,就是「查运单」「查预计到达时间」「查可改时间段」「改派送时间」四个工具,每个工具只干一件事,参数少、说明短,模型不容易用错,代价是调用次数多。
包得粗,就是一个「处理运单事项」的工具,参数里带上动作类型。调用一次就能办一串事,但它对模型的要求高,参数填错的机会也大。
常见做法是两头都要一点:高频、简单的动作包细一点,跑得稳;低频、需要连着办几件事的,允许包粗一些。具体怎么切,第 5 节展开。
3. 每个工具都要交代清楚三件事
3.1 参数的三个信息写全
一个参数要写清三样:它是什么含义、必填还是选填、格式和取值范围。少写一样,模型就开始猜。
拿改派送这个工具说事。它有两个参数。
| 参数 | 含义 | 必填 | 格式与取值 |
|---|---|---|---|
| expect_date | 期望派送日期 | 必填 | 格式 YYYY-MM-DD,必须是今天之后的日期,最多 7 天后 |
| time_slot | 期望时间段 | 选填 | 只能填 上午 9:00-12:00、下午 13:00-18:00、晚间 18:00-21:00 三个值之一 |
客服中心那个「明天上午填进日期字段」的错,就出在这张表没写。写全之后有个额外好处:模型在参数不合规的时候会先追问一句,而不是硬填一个值让接口报错。
取值有范围的参数,还要写清超范围怎么办。日期超过 7 天的,是拒绝还是转人工,这是产品经理要定的,模型定不了。
3.2 超时、重试、熔断、限流各管什么
接口是会坏的。四种情况要分开处理,它们解决的不是同一个问题。
| 情况 | 说的是什么 | 常见做法 |
|---|---|---|
| 超时(Timeout) | 接口在规定时间内没返回 | 设一个等待上限,运单查询这类接口按 3 秒 |
| 重试(Retry) | 失败之后再试一次,很多失败是偶发的 | 重试 2 次,间隔 1 秒、2 秒;写操作要带幂等键,避免重试把同一件事做两遍 |
| 熔断(Circuit Breaker) | 连续失败多次,先把这条路断开 | 连续失败到阈值就先不调了,过一段时间再试,避免把已经压垮的系统继续往上压 |
| 限流(Rate Limit) | 单位时间内允许的调用次数 | 每个账号每秒钟 20 次;超了要排队或者拒绝,不能一直打 |
四个都要有默认值,不能等出故障的时候临时定。产品经理要做的是知道这四个值各是多少、超了之后用户看到什么。
同一个超时,三种设置下客服看到的不一样
四个默认值
- 超时上限3 秒
- 重试2 次,间隔 1 秒、2 秒
- 熔断连续 5 次失败触发
- 限流每个账号每秒 20 次
- 这一次的现场运单查询接口在高峰时段变慢,第 1 次调用 3.2 秒返回,超出上限
四个值都要有默认值,出事才有地方对。
用默认值跑一遍
- 客服看到的那一屏「这单目前在杭州转运中心,预计明天上午派送」
- 下面一行灰字本次查询因接口超时重试过一次(只对客服可见)
故障被平台消化掉了,客户看不出刚才出过问题。
重试改成 0 次
- 客服看到「运单系统暂时没有响应,已经帮你转人工查询」,旁边一个「转人工」
重试一归零,故障直接露到客服面前。
熔断阈值改成连续 2 次失败、限流改成每秒 2 次
- 熔断后「运单查询已暂停,稍后自动恢复」,状态灯转黄,旁注「熔断已触发,剩余 30 秒内不再调用」
- 限流后连跑 10 次查询前 2 次通过,后面 8 次排队,排在最长的那个标「等待 4 秒」
熔断护住被压住的系统,限流的代价是有人要等。
四个值先定默认值,出事才有地方对。
3.3 接口挂了以后给什么兜底
失败处理只是把损失压小,兜底解决的是「这事还办不办得成」。三类兜底按代价从低到高排。
第一类是给替代路径。运单查询挂了,如果系统里还有一张本地缓存的运单快照,就先按快照答,并明确告诉用户这是几分钟前的数据。
第二类是降级处理。查不到实时位置,就先答「今天上午已经到达杭州转运中心」,这一步是准确的,只是不够细。
第三类是转人工,把已经收集到的信息一并交给人工。客服中心那个案子里,转人工的时候要把单号、客户说的时间、已经试过哪些动作一起带过去,不能让客服从头问一遍。
三类都要写进需求,还要写清各自在什么情况下触发。只写一句「失败要给用户反馈」,等于没写。
4. 权限给到够用为止
4.1 只读和可写分开
查运单和改派送,看起来都在同一个系统里,权限性质完全不同。前者看一眼,后者改了别人的东西。这两类工具从一开始就要分开授权。
只读的工具可以放开一点,让智能体自己判断什么时候用。可写的工具要额外加两道:调用前要有人确认,调用后要有记录。客服中心那 40 单改错,缺的就是调用前那道确认。
4.2 写操作用谁的身份
工具调用是以某个身份打出去的。用客服本人的账号,系统里留的是客服的操作记录,出了问题算在客服头上;用平台自己的服务账号,操作记录归平台,但这一步是谁要求的就查不到了。
常见做法是服务账号加上操作人。调用日志里同时记两条:实际调用用的是平台账号,发起这个动作的人是哪一位客服。出口处写清这两条,审计才查得到人。
有柜台、有窗口、有外呼的业务,还要注意一件事:智能体的账号权限和它服务的那个人的权限要一致。客户经理能看的客户,智能体才替得了他;权限放得比人还大,等于绕过了原本的授权。
4.3 一个工具能给多大范围
权限不是只有开关两档,还能按范围收。
按对象收:查运单的工具只接受本公司承运的单号,别的公司的单号直接拒绝。
按字段收:改派送只能改期望时间和期望时间段两个字段,运单号、收货地址这些改不了。
按条数收:一次只能改一单,不允许批量改。
按时间收:派送当天下午 6 点之后不接受改期,这跟业务规则一致,也顺带挡掉了一批不现实的请求。
这几条收范围的规则,都是产品经理在需求里能写清楚的,代价很小,出事的概率降得很多。
5. 工具粒度怎么切
5.1 万能工具和碎工具都不好用
一个「万能工具」,把所有接口都塞进去,参数里带动作类型。它的问题在模型这一端:参数多、含义杂,填错的机会大,出错之后还不好定位是参数的问题还是接口的问题。
一堆「碎工具」,一个动作一个工具,模型要先在几十个选项里挑。工具多到一定程度,模型挑错的概率上升,工具定义本身也要占窗口。
切法按三条走。同一件事里的高频动作合并成一个工具,减少来回;一次调用里参数总在三个以内的,说明粒度合适;出错之后要能一眼看出是哪个动作坏的,做不到就要拆。
5.2 高频操作要做到稳
客服中心天天要查运单,一天几千次。这类高频操作值得单独做厚一点:参数给默认值、返回结果按固定格式、常见失败都兜住。
低频操作相反,头一回用可能就是最后一次用,做个能用的版本就够,不用花大力气打磨。
判断高频还是低频,看业务量。写需求之前先去问一句:这个动作一个月跑多少次,出错一次影响多少人。答不上来的,说明需求本身还没调研清楚。
5.3 能改数据的操作先读后写
改派送这个动作,正确的顺序是先查后改。
先查这一次是为了给动作做条件判断:这单现在是什么状态、有没有已经安排好的派送任务、上一次改期是什么时候。查完再决定改不改、怎么改。中途接口返回「已签收」,就停下来,不往下走。
先读后写还有一个附带好处:出问题的时候有据可查。日志里能同时看到改之前的状态和改之后的状态,回溯改了哪一步很快。
6. MCP 把接线这件事标准化
6.1 写一次到处能用
前面的内容都在讲单个工具怎么定义。真正麻烦的是规模:一家单位里可能有五个系统、几十条接口,每个智能体平台都要重新接一遍,接口改一次,所有接过的平台都得跟着改。
MCP(Model Context Protocol,模型上下文协议)解决的就是这一段。它把「一个外部系统能提供哪些能力」写成一套标准格式,谁按这个格式实现一次,任何支持这套标准的智能体都能接上它。接口变了,改服务端那一份,客户端不用动。
对产品经理来说,判断要不要走 MCP 看两条:这套能力会不会被多个智能体用;这套接口以后会不会经常改。两条里有一条是,就值得按 MCP 接。
6.2 三类能力:工具、资源、提示词
一个 MCP 服务器对外提供三类东西,名字和用途不一样。
| 类别 | 是什么 | 运单系统的例子 |
|---|---|---|
| 工具(Tools) | 可以被调用、会改变状态或返回结果的动作 | 查运单、改派送时间 |
| 资源(Resources) | 只读的数据,按需取回来,不产生动作 | 运单的完整轨迹记录、配送网点清单 |
| 提示词(Prompts) | 预先写好的模板,用来引导出更复杂的流程 | 「改期申请」的规范提问模板 |
三类里工具用得最多,资源是这几年被低估的一块:只读数据放在资源里,比包成工具更合适,因为它不产生任何动作,风险低,取用也简单。
6.3 服务器和客户端,本地和远程
MCP 这一套里有两个角色。服务器是提供能力的那一头,通常由系统方或平台方维护;客户端是使用能力的那一头,装在智能体平台里。
接法分两种。本地接法是把服务器进程装在同一台机器上,两边通过标准输入输出通信,适合开发调试,也适合数据不出本机的场景。远程接法是服务器挂在网络上,客户端通过 HTTP 连过去,适合多个客户端共用一套能力的场景。
两种接法的产品差别在两个地方:本地接法数据不出本机,远程接法要考虑网络、鉴权和跨地域;本地接法更新要挨个机器装,远程接法改一次全都生效。
7. 智能体之间怎么对话
7.1 A2A 和 MCP 管的不是一件事
MCP 管的是智能体去够工具,接完就回来了。有一类活接不回来:对方本身就是另一个智能体,它有自己的模型、自己的工具、自己的判断过程。这类协作靠 A2A(Agent-to-Agent,智能体到智能体)。
A2A 里有个类似名片的做法,叫智能体名片(Agent Card),写的是这个智能体能办什么、怎么找到它、要什么凭据。主智能体拿到名片,把任务发过去,对方用自己的模型和工具办完,把结果交回来。
一句话分清:MCP 是握手,A2A 是派活。握手的对象是一套接口,派活的对象是一个能自己做判断的智能体。
7.2 ANP 管的是网络里的发现
智能体多了以后会出现第三个问题:谁知道网络里有哪些智能体、谁能办什么事。ANP(Agent Network Protocol,智能体网络协议)管的就是这一段,做的是服务的注册、发现和路由。它现在还在社区讨论阶段,没有成熟生态,产品经理知道它要解决什么就够了,不急着选型。
三种协议的分工可以这么排:MCP 解决够得着工具,A2A 解决找得到合作的智能体,ANP 解决在成百上千个智能体里找到该找的那一个。
7.3 协议对产品设计的约束
用上这些协议之后,需求里要多写三件事。
身份。跨智能体调用的时候,用谁的身份发出请求、对方看到的操作人是谁,得在对端的记录里能对上。
计费。A2A 那种派活,对方用的可能是别家单位的模型,这次调用算在谁的账上、额度怎么分,要提前说清。
责任。对方智能体给出的结果错了,算谁的责任。常见做法是主智能体做最终判断,外部智能体给的结果只当参考,关键动作仍然要人确认。
8. 运单助手按什么粒度接线
运单助手最后接了两个工具,一个查询工具、一个改期工具。
查询工具只读,参数只有一个运单号,返回固定字段:当前状态、所在城市、预计派送时间、最近一次扫描时间。超时上限设 3 秒,重试 2 次,间隔 1 秒和 2 秒;三秒还没回来就先按 5 分钟前的快照答,并带一句「数据可能有几分钟延迟」;快照也没有就转人工,把单号一起带过去。
改期工具可写,参数三个,格式和取值范围在工具定义里写全。调用前必须由客服点一次确认,确认框里显示「原时间」和「新时间」两行,点完才发出。工具内部先查后改:状态不是「运输中」的直接拒绝,返回一句可读的理由。
权限收在三处:只能改本公司的单号;只能改期望日期和时间段两个字段,一次一单;派送当天下午 6 点之后不再受理。写操作的日志同时记平台账号和发起人。
后来客户在电话里说「能不能改成明天上午」,助手不再直接改,先答一句「可以改到明天上午 9 点到 12 点,确认改吗」,客服点确认,单子才动。那一周改错 40 单的事,第二周降到 0。
9. 这个工具能不能接进来
| 问题 | 答「否」的时候怎么办 |
|---|---|
| 这个动作有没有现成的接口? | 没有接口的,先评估是走操作电脑那条路,还是推动把接口做出来 |
| 这个动作会不会改变系统里的数据? | 会改数据的,必须加人工确认和操作日志,不能只做技术对接 |
| 它的参数是不是每一项都写了含义、必填和取值范围? | 补全工具定义,取值范围有边界的还要写清超范围怎么办 |
| 这个动作一个月跑多少次? | 跑得少的先做能用的版本,跑得多的要单独把稳定性和速度做厚 |
| 接口失败的时候用户看到什么? | 写成可核对的文案,并写清什么情况下转人工 |
| 这个工具用谁的身份调用? | 用服务账号的,日志里必须同时记发起人 |
| 一次能改多少条、能改哪些字段? | 补上条数和字段的限制,能一次改一单就不要允许批量 |
| 这个动作有没有它必须依赖的前置条件? | 有依赖的写成「先读后写」,并把判断依据写进工具说明 |
八条都能答「是」,这个工具可以接。
10. 三种看起来接好了、其实没接好的情况
接口接上了,参数没交代。 工具能调通,但模型不知道「明天上午」该填成什么,于是照着原话填。参数定义那一栏空着或者写着「字符串」,等于把这活儿留给了模型的运气。
给了写权限,没给确认。 只在最后加一句「请谨慎操作」没有用,模型每次的判断都不一样。写操作要卡在平台那一层:动作发出之前停下来等人点一下,这一层比写在提示词里可靠。
失败扔给用户。 接口超时就回一句「系统繁忙」,把问题原样交给用户。失败处理要按超时、重试、熔断、限流四件事各定一套,再配上快照、降级、转人工三类兜底。
11. 接口接通之后,还剩一类问题答不上来
接口这一段能带走的判断有四条:一个动作怎么描述给模型才不容易填错参数、参数写错和接口挂了分别怎么兜、权限收在哪一层、这套接口值不值得按 MCP 的标准做一次。
工厂、医院、银行这些地方,大量问题并不需要动系统,只需要找到那份文件里的一段话。工具接得再全,也答不上「这条制度怎么规定的」这类问题。下一份材料讲资料怎么进库、怎么被找回来,以及答不准的时候先怀疑哪一环。