FEATURED ARTICLE / 01

INSIGHT / REPORT / UPDATE

深度资讯 资讯中心

审批一加,MCP工具就找不到了

易游体育官方网页版-今日赛程与赛事资讯编辑部 491 阅读 约 5.5 分钟

查工单没问题,排班也没问题。可只要在“花钱”的工具前面加一道人工审批,重启就报错: Tool order_part not found 。一个做派单助手的开发者,就这样撞上了框架的边界。 他给一家虚构的现场服务公司写了个调度助手。调度员输入“WO-1043 现在什么状态”或者“给 WO-1044 订一个 3 kW 加热元件”,助手负责回答。背后挂了三个工具: lookup_work_order :读站点、资产、问题、技师和时间段,自己跑。 schedule_visit :给技师排一个时间窗,自己跑。 order_part :订备件,要花钱,必须等人点头。 整套东西他都想用 Dart 写:助手服务、工具服务、Flutter 客户端,共用一套类型。不要 Python 边车,也不要中间塞个 Node 服务。 架构拆成四块,全是 Dart。后台是一个 MCP 服务器,走回环地址上的 Streamable HTTP,任何 MCP 客户端都能接;助手是一个 Genkit flow,从那个 MCP 服务器拿工具,从不直接 import 后台;每个花钱的工具前面挡一道审批中间件;HTTP 面只有一个 POST /dispatchAgent 加一个健康检查。 后台明明和助手在同一个进程里,为什么还要套 MCP?因为边界本身就是目的。哪天工单搬到真实系统,只需要换掉 MCP 服务器,助手、提示词和测试都不用动。 工具描述里特意写了“which costs money”。模型也会读到这句话。 类型只写一份,三个运行时共用。同一个 DispatchAnswer,既是模型的结构化输出 schema,也是 flow 的 HTTP 响应,还是 Flutter 客户端反序列化用的类型。这个文件不 import dart:io,所以客户端能从同一份 import 构建出 web、iOS 和 macOS 版本。改一个字段,build_runner 重新生成,编译器会告诉你所有受影响的地方。 审批闸门的逻辑是:中断、挂起、重启。toolApproval 接收一份“可以不问就执行”的工具清单,其余一律中断生成。模型请求 order_part 时,响应带着 finishReason == FinishReason.interrupted 回来。flow 把此前的对话和这个被中断的工具请求一起存到某个 approvalId 下,立刻回给客户端: {"result": {"answer": "Ordering \"Heating element 3 kW\" for WO-1044 needs your approval.", "orderIds": ["WO-1044"], "approvalId": "approval-1"}} Flutter 客户端弹出“批准”和“拒绝”。下一次调用把 approvalId 连同 approved 一起送回来。批准就重启那次挂起的调用,工具真正执行,模型根据真实结果作答;拒绝则工具永不执行,模型收到“Declined by the dispatcher. Nothing was ordered.”作为工具输出,再用自己的话向用户解释。 每个 approvalId 只能应答一次,首次使用就从待处理表里删掉,所以连点两下也不会订出两个加热元件。挂起的审批存在内存里,这是给 --max-instances 1 的 Cloud Run 演示做的刻意选择:一个实例,一张表。重启就忘,超出演示范畴就该放进 Firestore 或数据库。 然后就是那个 bug。查询正常,预订正常,审批提示也正常弹出来。他点了批准,重启失败,报 Tool order_part not found。 根因在 Genkit Dart 1.0.1 里。MCP 工具注册时用的是带命名空间的名字 work-orders/order_part ;模型看到的是短名 order_part,回传的也是短名;正常工具循环通过一张短名映射表找到工具,没问题;但恢复路径(interruptRestart)调用工具执行器时没带那张表,退回去按 order_part 查注册表,查不到,抛异常。 也就是说,任何带命名空间的工具(也就是每一个 MCP 工具)都能正常工作,直到你在它前面放一道审批。他用假模型和两个测试复现了:一个用普通工具名,一个用 work-orders/order_part。普通的过,带命名空间的挂。然后他通过 dependency_overrides 给本地那份 genkit 1.0.1 打了补丁,把映射表传给恢复路径,两个测试都绿了。 问题连同复现和根因提交到了上游,编号 genkit-ai/genkit-dart#657,修复以 #658 开放:恢复路径现在用和循环一样

about image

分享这篇内容

如果文章对您有所帮助,欢迎将它分享给更多读者。

RELATED READING / 02

推荐阅读

从相近主题、延伸观点和最新动态中继续阅读,了解更多相关信息。

DISCOVERY BOARD / 03

继续发现

通过栏目导航和热点内容,快速进入更多文章页面。

热点新闻

既然日本不要,那就来中国!伊藤美诚

既然日本不要,那就来中国!伊藤美诚

掉出国家队就没饭吃了?伊藤美美未来的路,福原爱早就给出了答案! 日本乒协公布了最新的国家队名单,名将伊藤美美的名字赫然不在其中。很多人都在传她是不是无球可打、被日本队弃用了。但实际上,拿齐了奥运金银铜牌的她,根本不缺退路。无论是做商业赛、乒乓推广还是来中国交流,离开国家队体系并不代表职业生涯的终结,福原爱和张继科早就走通了这条新路。 说起伊藤美美,咱们国乒球迷对她是再熟悉不过了。这个2000年出生
里肯:目前我还没有考虑拜仁,首先希望周中的德国杯能够晋级

里肯:目前我还没有考虑拜仁,首先希望周中的德国杯能够晋级

直播吧10月26日讯 多特蒙德在下轮德甲将在客场挑战领头羊拜仁,多特蒙德总经理拉斯·里肯表示首先要踢好本周中的德国杯。 里肯强调:“让我们先做好眼前的工作,那就是先迎战不莱梅!说实话,我们甚至还没有考虑过拜仁。我们现在每三天就要踢一场比赛。本周二我们将在主场对阵实力不俗的不莱梅,我们显然希望能够在德国杯晋级。” 里肯接着说:“这场德国杯比赛的球票已经售罄,球迷们会充满热情。在上一轮德甲联赛时,我们
篮板输17个,布朗20中5!老詹复出苦吞首败,76人不能全指望熬老头

篮板输17个,布朗20中5!老詹复出苦吞首败,76人不能全指望熬老头

篮板输17个,布朗20投15铁!恩比德轮休、埃奇库姆伤停,41岁詹姆斯短暂休息一场后火线复出仍难阻76人苦吞首败,坐拥豪华四巨头的费城两大短板全暴露,新赛季想要争冠真不能全指望熬老头。 76人苦吞首败 开季连斩尼克斯、骑士、雄鹿拿下三连胜的76人主场迎战活塞,后者同样是新赛季76人东部的主要竞争对手之一,本场恩比德轮休,埃奇库姆因伤缺席,詹姆斯火线复出。 结果76人开局就被活塞打出15-1攻击波,
金球少年,英雄崛起!2026年金牛区“金球少年”校园足球联赛正式开幕!

金球少年,英雄崛起!2026年金牛区“金球少年”校园足球联赛正式开幕!

绿茵逐梦,热血启航 10月26日 由成都市教育局、成都市体育局指导 成都市金牛区教育局 成都市金牛区文化体育和旅游局主办的 2026年金牛区“金球少年”校园足球联赛暨 中青赛(成都赛区) 成都市青少年校园足球联赛(金牛赛区) 正式开赛 本次联赛揭幕仪式 在财贸职高(凤凰校区)顺利举行 同日 十大赛区赛事陆续打响 金球少年 英雄崛起 Jinniujiaoyu 本次联赛秉持“以足球之名,点燃梦想”的理
场均11.8分后他自称替罪羊:热火0胜4负谁该背锅

场均11.8分后他自称替罪羊:热火0胜4负谁该背锅

热火以 109比113 输给独行侠,赛季开局 0胜4负 。赛后,巴姆·阿德巴约(Bam Adebayo)把话说得很直:他觉得自己被当成了替罪羊。 “外面的声音总想把我变成替罪羊,这挺有意思的。”阿德巴约说,“等局面翻转、风向变了,就准备好接住那股能量吧。”这番话来自ESPN的报道。他没有回避球队眼下的处境,也没有把责任推给某一个人,只是明确表达了对“被单独拎出来”的不满。 数据确实不好看。本赛季至