首页/新闻资讯/正文详情

业务工具与售后工作流 DAG:从「每意图一张图」的弯路到「审批是事件」

发布时间:2026/9/26 4:04:34 来源:云帆数科 栏目:资讯中心
业务工具与售后工作流 DAG:从「每意图一张图」的弯路到「审批是事件」
业务工具与售后工作流 DAG从「每意图一张图」的弯路到「审批是事件」语言 / Language中文 系列第七章目录 上一章决策层、持久化与闸门硬化项目Agentdemo007 —— 电商智能客服 Agent技术栈Java 17 / LangGraph4j固定工作流子图/ LC4j 工具前向 / HITL L2 三级持久化周期2026-09-12设计 方向纠偏→ 09-15工作流冲刺→ 09-19~20提交制 对账修复验证规模workflow 74 例 HITL 84 例 业务工具 36 例单测全量回归随各 Phase 交付源码github.com/Gavincui123/Agentdemo007前言业务工具层要回答的问题是当对话需要真的办事——查订单、办退款、建工单——怎么把 LLM 的不确定性关进确定性系统的笼子。这一章的主线不是设计展示是弯路和事故清单我先在每意图动态生成 DAG上犯了一次系统性过度设计设计推演阶段自己否决了自己落地后又接连踩到 LangGraph4j 的迭代预算陷阱、一个被用户看成系统说谎的小写订单号、一次管理台必现的 409 对账故障。最后靠两次原则级收口定型——审批是事件、建单走四态幂等门——每一段弯路的尽头都站着一条现在还立着的规矩。一、方向纠偏「每意图动态 DAG」被否决的经过业务工具层的第一份设计per-intent-dag雄心勃勃每个意图动态生成一张 DagSpec 图按需编排节点。这个方向在设计推演阶段就被我自己否决了回滚记录就写在计划文档的开头RoutePlan 只是每请求的结构化路径计划本身无 DAG低风险意图靠现有固定 Order 链加 #135 自跳过也无 DAGDAG 的落点只有一处——高风险操作时在 LangGraph 构建固定工作流子图。否决的理由今天看依然成立动态图的拓扑随 LLM 输出漂移。不可测——每个输入都可能长出一张新图用例没法写不可审计——事后说不清当时到底跑了哪张图不可回归——golden 用例锚不住拓扑。固定子图加明确的进入条件售后动作 订单号把要不要跑图交给上游决策层第六章图本体保持死板。死板是特性不是缺陷。同一份设计里还埋着一个运行时坑MAX_ITERATIONS从 10 放大到 20。原因很反直觉——LangGraph4j 的迭代预算按 generator yield 计数不是按节点数每个节点内部的多次 yield、条件边的重入都计数10 在 deny-retry 边界就会 trip。这类框架计量单位与直觉不符的坑属于不写进文档就一定会有人再踩一次的。二、售后工作流图五个节点与两种裁决机械事实不符ORDER_NOT_FOUND / ORDER_NOT_OWNED或 Agent 裁决 INELIGIBLE政策资格 → Agent 裁决 pass / uncertain进入refund_request / return_requestquery_user用户信息query_order订单信息query_policy政策召回RAG 单通道validateRejected业务驳回·非系统失败submit_ticket建 HITL 工单挂起等审批决议 管理台状态事件APPROVED / REJECTED / TIMEOUT落地的工作流子图很克制五个节点、一条条件边。查用户、查订单、查政策是三步串行取证validate 是唯一的裁决点submit_ticket 把通过者送进 HITL 工单挂起等审批Rejected 是业务驳回出口。关键设计在 validate 节点里两种裁决的分工// capability/workflow/AfterSaleWorkflowGraph.java —— 机械事实与政策资格分层// 机械事实校验存在/归属——非政策判断保留代码内短路即驳if(ordernull){ReasonfailReason.ORDER_NOT_FOUND;returnMap.of(FAIL_KEY,fail,OUTCOME_KEY,(AfterSaleWorkflowOutcome)newAfterSaleWorkflowOutcome.Rejected(…));}StringuidresolveUserId(ctx);if(uid!null!uid.equals(order.userId())){ReasonfailReason.ORDER_NOT_OWNED;returnMap.of(FAIL_KEY,fail,OUTCOME_KEY,(AfterSaleWorkflowOutcome)newAfterSaleWorkflowOutcome.Rejected(…));}// 政策资格 → Agent 裁决2026-09-19 用户裁决政策知识query_policy 召回 实时事实//订单记录 当前日期一并交模型三态裁决裁决器内部全降级失败UNCERTAIN fail-safe// 到人工绝不冒充业务驳回、绝不盲目放行机械事实订单在不在、是不是你的留在代码里——确定性判断不需要模型意见短路即驳政策资格7 天无理由适不适用这一单交给模型三态裁决——它需要读召回的政策、比对订单记录和当前日期。裁决失败的落点既不是拒绝也不是放行而是UNCERTAIN进人工审批且管理员重点复核。不确定是一种合法输出fail-safe 到人模型意见永远不可能单独驳回或放行一笔业务。业务驳回还有一层语义收口Rejected是业务终态话术直接答复这单不符合条件不是DegradationScenario——系统没坏是业务说不。把业务结果混进降级枚举监控就会把正常业务拒绝算成故障率。三、一次误拒的两个教训小写订单号与空表对账3.1 用户说 “ord-001”入口归一化实测用户小写输入 “ord-001” 原样进OrderQueryService的精确键查找 → miss → 误判ORDER_NOT_FOUND答复订单不存在。订单明明就在 mock 里用户视角这就是系统说谎。修复在服务端入口做防御性归一化// capability/business/OrderQueryService.java —— mock 三笔订单覆盖 validate 全部分支publicOptionalOrderRecordfindByOrderId(StringorderId){if(orderIdnull){returnOptional.empty();}// 防御性归一化trim大写调用方可能传用户原话里的 ord-001精确键会 missreturnOptional.ofNullable(ORDERS.get(orderId.trim().toUpperCase(java.util.Locale.ROOT)));}教训一句话标识符在系统边界处归一化一次而不是要求每个调用方记得归一化。这条后来写进了订单号提取的统一契约raw 优先、standardQuery 兜底《决策层、持久化与闸门硬化》§2.4。3.2 更疼的一个mock 与 DB 各说各话2026-09-20 联调管理台点批准退款必然 409「订单不存在」——而工作流校验明明通过了。排查结论写在BizOrderSeedRunner的 javadoc 里是一教科书级的数据源分裂数据源分裂根因工作流图校验订单存在/归属走 OrderQueryService 内存 mock……而 HitlBusinessGate 对账走 biz_order 表——表只有 DDL 无种子运行时恒空 → 管理台 confirm 必然 fail-closed「订单不存在」。两条链路各自正常校验查内存 mock查得到对账查 biz_order 表按 fail-closed 拒绝——单看都对合起来必坏。修复是启动时BizOrderSeedRunner写入与 mock同源对齐的三笔演示订单配两条铁律fill-if-absent只补空缺不覆盖——业务表是对账锚点种子绝不回写业务状态否则测试数据会污染真实审批结果app.biz-order.seed.enabledfalse可关生产接真数据。mock↔DB 对齐由BizOrderSeedRunnerTest断言钉死——对齐不是口头约定是测试。四、审批是事件一次原则翻转最初的设计是请求内等待工作流发起审批后请求线程挂起等管理台决议桥唤醒机制恢复执行。语义直观但三个毒副作用很快显形请求线程被审批时长绑架Tomcat 线程池会被审批队列占满审批等待与超时语义纠缠HITL_TIMEOUT 话术发出去之后决议才到算谁的恢复路径复杂桥的状态机要处理进程重启。2026-09-20 将裁决整体翻转管理台人工hitl_ticket 表售后工作流管理台人工hitl_ticket 表售后工作流请求线程到此结束——不存在请求内等待决议不受任何请求超时影响等待窗口/桥唤醒已整体退役建单幂等键 wfa:{action}:{orderId}即返回1话术「已提交等待人工审批」短路收尾2confirm / reject纯状态变更事件3confirm 批准 → AfterSaleBusinessExecutor 执行wfa 单不经 resumeresume 属 hitl: 检查点单恢复通道4原则的原话落在代码注释里原则审批是事件、Agent 最小权限——建单即返回无请求内等待。……决议 状态事件Agent 只查询进度。……等待窗口/桥唤醒已整体退役超时不可能影响决议。——TicketApprovalSubmitter / AfterSaleWorkflowGraph翻转后的世界简单了很多请求线程生命周期到建单为止WORKFLOW_APPROVAL_TIMEOUT场景保留只为指标兼容决议语义上已不可能超时恢复是显式管理动作——先过HitlBusinessGate业务对账再 CAS 消费检查点第六章的三级持久化正好接住。等待一个人类从来就不该发生在请求线程里这一条适用于一切带人工环节的系统。三个环节的实测截图正好凑成一次完整闭环五、建单幂等四个状态的门高风险动作的幂等要答两个问题幂等键怎么选命中之后每个状态去哪。工单按业务幂等键查询工作流审批单wfa:{action}:{orderId}、L2 检查点单hitl:{action}:{entity}两套单的分派口径同构只有一处刻意不同——这正是本节最想讲清的地方。先看 L2 检查点单HitlStep610的四个去向// capability/hitl/HitlStep.java —— 建单幂等2026-09-18 L2OptionalHumanTicketexistingticketService.findByIdempotencyKey(idempotencyKey);if(existing.isPresent()){HumanTicketpriorexisting.get();switch(prior.status()){casePENDING-{// 复用挂起单重复请求/网关重试/重开会话不再爆单checkpoint 缺失则补挂重启丢失兜底context.setHitlTicketId(prior.id());ensureCheckpoint(context,prior,idempotencyKey);// …省略 log/metricsreturnnewStepOutcome.ShortCircuit(DegradationScenario.HITL_TIMEOUT);}caseAPPROVED-{// 幂等放行人工已批准过该业务动作恢复锚定的放行语义带外预批准同语义// …省略 setHitlTicketId/log/metricsreturnnewStepOutcome.Proceed();}caseREJECTED-{// 人工已驳回该业务动作不再重审防驳回后换会话重提绕过审批// …省略 log/metricsreturnnewStepOutcome.ShortCircuit(DegradationScenario.HITL_TIMEOUT);}caseTIMEOUT-{// 超时单人工未决议允许重新建单键索引指向新单走下方正常流程// …省略 log无 return——落到方法下方的正常建单流程}}}四个去向各有一个为什么PENDING 复用是防重复轰炸——重复请求、网关重试、重开会话都不再爆单checkpoint 缺失还要补挂兜住重启丢失APPROVED 放行是审批语义的兑现——这笔钱人工批过了再问一遍不能再执行一遍TIMEOUT 重建是给人改口的机会键索引指向新单REJECTED这一格两套单刻意走了两个方向检查点单上面这段HitlStep代码驳回后不再重审而退款退货真正走的工作流审批单TicketApprovalSubmitterwfa:键工作流审批单的幂等键javadoc 写明差异REJECTED 不封禁再申请——PENDING 复用同单、APPROVED 已受理不重建防重复业务动作、REJECTED/TIMEOUT 重建新单。驳回是那张工单的终局事件不是对用户的永久禁令重建的是一张新工单照样要人工审审批权始终在人手里放开重建不构成绕过。幂等门真正要堵的是已批准的工单被重复兑现和同一申请轰炸出十张挂起单——这两条两套门都堵死了。六、这一章带走的六条动态图是系统性过度设计的典型症状。LLM 决定要不要进图图内部保持固定——灵活性与可测试性的边界画在图的门口而不是图里面。框架的计量单位要先核实再设预算。LangGraph4j 的 yield 计数坑属于不记录必复发类。机械事实归代码价值判断归模型不确定归人。validate 节点的三态裁决pass / rejected / uncertain让模型的意见永远不可能单独驳回或放行一笔业务。数据源分裂是集成事故的第一大来源。两条链路各自测试全绿照样联调必坏对齐要用种子加断言钉死且种子不得回写业务状态。带人工环节的流程等待必须发生在请求之外。审批是事件建单即返回、决议是状态变更、恢复是显式管理动作——超时语义才可能与审批语义彻底解耦。幂等门的每个状态都是一个产品决策。复用、放行、不重审检查点单、允许重建工作流单——枚举不全的幂等只是防重复提交枚举全了才防得住重复执行。七、已知边界诚实清单userId 客户端声明订单归属校验的uid来自ChatRequest.userIdnull 兜底 baked 10086 供演示真鉴权接入后 per-request 注入收口。单实例语义工单状态机与检查点消费为单实例口径多实例需 DB 乐观锁第六章已登记。演示身份与 mock 数据ORD-001/002/003 覆盖 validate 全部分支是演示口径真实接入后 mock 退役、对账链路不变。本文机制出处capability/workflow/AfterSaleWorkflowGraph / WorkflowExecutionStep / TicketApprovalSubmitter、capability/hitl/HitlStep / HitlResumeService、capability/business/OrderQueryService / BizOrderSeedRunner设计沿革见 business-tools-workflow-dag 与 per-intent-dag。相关阅读系列目录 · 第六章·决策层、持久化与闸门硬化 · 第四章·L0 业务键注册表 · 下一章全链路延迟与稳定性调优

相关推荐

从能跑到敢公开:一个客服 Agent 的决策层、持久化与闸门硬化实录
从能跑到敢公开:一个客服 Agent 的决策层、持久化与闸门硬化实录

从能跑到敢公开:一个客服 Agent 的决策层、持久化与闸门硬化实录 2026-09-18 Agentdemo007 系列第六章(系列目录),上一篇《检索侧演进》;此时延迟已从 80.5s 压到 6.1~11.9s(调优实录见第八章)… · 2026/9/26 4:04:34

if constexpr:C++17 编译期分支,为什么它能取代 SFINAE
if constexpr:C++17 编译期分支,为什么它能取代 SFINAE

写模板函数时最常见的困境是:一个逻辑,但对不同类型的处理方式不一样——指针要解引用,非指针直接用;容器要遍历,标量直接打印。C11 时代这事只能靠 SFINAE 把逻辑拆到多个重载里,或者写 std::enable_if 的… · 2026/9/26 4:04:34

Simulink电机控制仿真面试指南:从FOC建模到工程落地
Simulink电机控制仿真面试指南:从FOC建模到工程落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 4:04:34

阿里云ECS上基于kubeadm搭建Kubernetes最新稳定版集群实践
阿里云ECS上基于kubeadm搭建Kubernetes最新稳定版集群实践

3台阿里云服务器,一个下午,把Kubernetes集群最新稳定版完整跑通,这事说难不难,但你要是在网上搜教程,大概率会卡在镜像拉取、安全组、containerd配置这几个地方。这篇文章就把我2026年3月11日这次实操的完整过程整理出… · 2026/9/26 4:45:45

边缘多源流式数据聚合:基于 Streams API 的低内存管道
边缘多源流式数据聚合:基于 Streams API 的低内存管道

边缘多源流式数据聚合:基于 Streams API 的低内存管道在小工具的后端网关中,当用户请求生成一份包含**“上游大模型流式思考 天文月相数据 个人历史习惯统计 本地古诗词推荐”**的复合长手账画报时,传统的服务端聚合方式通常是&#xff1a… · 2026/9/26 4:45:45

Vue.js渐进式框架实战:从入门到工程化与面试考点全解析
Vue.js渐进式框架实战:从入门到工程化与面试考点全解析

做过几年前端之后回看,我对Vue.js最服气的一点,恰恰是“渐进式框架”这个定位。它不是那种逼你全量拥抱的“全家桶式”框架,而是允许你从一个页面、一个按钮、一个组件开始,一点一点把整个前端工程带起来。这个设计哲学&#xff0… · 2026/9/26 4:45:39

分布式电源接入配电网潮流计算程序定制全解析
分布式电源接入配电网潮流计算程序定制全解析

我最早接触“分布式电源接入配电网潮流计算”这个需求,是因为一条10kV馈线末端接入几个兆瓦的光伏电站后,用传统的手算简化公式校核电压偏差,结果和实测数据差了将近两个百分点。从那之后我就明白,分布式电源接入后的配电网&#… · 2026/9/26 4:45:39

Windows 10 1803安全基线实战:策略导入、参数设置与故障避坑
Windows 10 1803安全基线实战:策略导入、参数设置与故障避坑

简介:针对Windows 10 1803版本的安全基线配置与核查工具包,适用对象为系统管理员、安全运维人员及合规审计人员,可用于政企桌面终端安全管控与等保合规建设,帮助快速落地企业级安全基线标准。压缩包为zip格式,共72个文… · 2026/9/26 4:45:33

知识竞赛系统开发实战:从题型建模到WebSocket实时同步
知识竞赛系统开发实战:从题型建模到WebSocket实时同步

简介:知识竞赛系统是一套基于C/MFC开发的可运行在线答题平台,面向高校学生、竞赛组织者及需要快速搭建答题场景的开发者,覆盖试题维护、参赛者管理、限时答题和自动排名等核心需求。压缩包共61个文件,约7.68MB,文件类型… · 2026/9/26 4:45:33

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码