采购审批“卡死”?别急,不是系统崩了,是它走错了路

采购审批“卡死”?别急,不是系统崩了,是它走错了路

你有没有遇到过这种情况:在系统里输入“采购10部电机”,点击发送,然后……页面开始转圈,转了一分多钟,最后要么没反应,要么突然就通过了,连个确认的机会都没给你?

这不是系统“卡死”,也不是你网络不好。今天我们就来拆解一个真实的技术案例——Webchat采购流程的“不通”之谜。你会发现,问题根源不是代码写错了,而是系统里藏着“两条路”,而你的消息,偏偏走了那条老路。

两条路,一条通罗马,一条堵在路上

我们先来看一个有趣的现象:同样的“采购10部电机”,从飞书端发送,系统会先弹出一个确认框:“您确认要采购10部伺服电机,预算9万元吗?”你点“批准”,它才继续执行。整个过程流畅、自然,就像有个助手在跟你确认。

但从Webchat(网页聊天)端发送,系统直接开始跑流程,然后页面就“死”了。等了一两分钟,要么没反应,要么直接生成订单——完全没有中间确认环节。

为什么会这样?因为这两个入口,走的是完全不同的两套后端路径

老路:直来直去,但堵得慌

Webchat端走的是“老路”。当你在输入框里输入“采购10部电机”,前端通过关键词匹配,命中了一个叫 DS-PROC-001 的数字员工,然后调用 sendToStaff() 函数,向后端发送一个 POST 请求。

后端收到请求后,进入 digital-staff/index.js 这个旧模块。这个模块有个“硬伤”:它调用采购流程时,忽略了你输入的意图和参数。也就是说,无论你说“采购10部电机”还是“采购一把椅子”,它实际执行的都是一组硬编码的默认值:{product:'伺服电机', quantity:10, budget:90000}

更麻烦的是,这个旧模块执行的是“完整模式”(phase='full')。在这个模式下,采购工作流会走完所有8个步骤,包括第7步——等待老板确认。这个确认机制是通过轮询一个文件来实现的:系统把确认请求写入一个JSON文件,然后每1秒读取一次,直到文件状态变成“已批准”或“已拒绝”,或者超时(默认1分钟)后自动批准。

问题来了:这个文件谁来改?需要另一个接口(/api/digital-staff/confirm)来触发。但如果前端没有集成这个确认接口的交互,用户就只能在页面干等,看着转圈圈,直到超时自动通过。

这就是你感觉“狂转然后没反应”的根本原因——前端在等一个永远不会来的确认响应

新路:分两步走,优雅从容

飞书端走的是“新路”。它通过 boss-scheduler/index.js 这个新模块来调度,执行的是“预确认模式”(phase='pre_confirm')。

在这个模式下,采购工作流只跑前6步,不会阻塞等待确认。跑完后,系统返回一个确认问题:“您确认要采购吗?”然后通过一个叫 ConfirmNeededError 的机制,把状态挂起,等待用户响应。

飞书前端收到这个确认请求后,会弹出一个交互式的确认框,用户点击“批准”或“拒绝”,系统再通过 resume 接口继续执行后续步骤。

整个过程是异步的、非阻塞的。用户不会感到卡顿,系统也不会“死掉”。

问题不止一个:前端也有“间隙”

除了后端路径分立,前端代码也有个小bug。Webchat端有两个不同的采购调用函数:sendToStaff()runProcurementViaStaff()

  • sendToStaff()
用于关键词匹配输入框文本,它在发送POST请求之前就设置了SSE(服务器推送事件)的消息监听,所以不会丢消息。
  • runProcurementViaStaff()
用于快捷按钮“采购助手”,它是在POST请求之后才设置消息监听。如果SSE在请求响应之间推送了日志消息,这些消息就会被“漏掉”,导致前端状态更新不及时。

这个“间隙”虽然不致命,但也会让用户体验打折扣。

三个修复思路,让采购流程“丝滑”

既然问题找到了,怎么修?这里给你三个方案,从推荐到最小改动,按需选择。

方案A:重构后端路由(推荐)

最彻底的方案:把Webchat端的后端入口,从旧模块 digital-staff/index.js 改接到新模块 boss-scheduler/index.js

这样,Webchat和飞书走同一条路径,获得统一的“预确认”+“resume”机制。前端只需处理一种返回格式,后端只需维护一套逻辑。一劳永逸。

方案B:保持双路径,修复旧路径

如果你不想动路由,也可以只修旧路径。让旧模块也改用“预确认模式”,通过返回 {type:'confirm'} 而非阻塞的 waitForBossConfirmation 来实现确认。同时,让前端的 runProcurementViaStaff 函数(已有确认弹窗逻辑)对所有的数字员工通用。

方案C:最小修复,只改阻塞点

最小改动方案:只修改旧模块的 runProcurement() 函数,让它也使用“预确认模式”,不走阻塞的文件轮询。然后在后端POST handler中检查返回结果,如果有 needsConfirmation,就返回 {type:'confirm'}。前端收到后,弹出确认框即可。

为什么会有“两条路”?

看到这里,你可能会问:为什么一开始要搞两条路?

这其实是技术演进中常见的问题。团队在开发新功能时,往往会先做一个“快速验证”版本(旧路径),然后再重构出一个更健壮的版本(新路径)。但重构完成后,旧路径没有被完全替换,导致两个版本并行运行。

旧路径的优点是“快”——开发快,上线快。缺点是“糙”——硬编码、阻塞、忽略参数。新路径的优点是“稳”——参数化、异步、可恢复。缺点是“慢”——开发周期长,需要更多测试。

在快速迭代的业务压力下,这种“新旧并行”的情况并不少见。但问题在于,新旧路径的入口没有统一,导致不同渠道的用户体验割裂。

左帮右臂:让数字员工“走对路”

作为一家专注于智能体技术的公司,左帮右臂(BossAgents)的核心理念就是:让数字员工像人一样工作,而不是像机器一样死板

在这个案例中,我们看到了一个典型的“数字员工调度问题”。一个采购数字员工,本应理解用户的意图、提取参数、分步执行、请求确认。但因为后端路径分立,它变成了一个“聋子”——听不见用户说什么,只能执行硬编码的任务。

左帮右臂的智能体平台,从设计之初就避免了这个问题。我们的 LiteScheduler 调度引擎,天然支持“分阶段执行”和“异步确认”。无论用户从哪个入口发起请求——Webchat、飞书、企业微信、还是API——都会走统一的调度路径。

我们的数字员工:

  • 听得懂
:通过意图识别和参数提取,理解用户真实需求
  • 分步走
:将复杂任务拆解为多个阶段,每个阶段可独立确认
  • 不阻塞
:需要确认时,优雅地挂起,等待用户响应,而不是让页面转圈
  • 可恢复
:用户确认后,从挂起点继续执行,不丢上下文

如果你也在为数字员工的“卡顿”、“不通”、“体验割裂”而头疼,不妨想想:你的数字员工,走对路了吗?

左帮右臂,帮你把每一条路都铺平。

← 返回案例列表
分享:
🤖 Try Now →
🤖
🎁