跳到主要内容

把聊天机器人升级成任务系统:状态机、任务队列和工具结果持久化怎么设计

· 阅读需 5 分钟
一介布衣
全栈开发者

聊天机器人刚起步时,很多事情都很顺。用户发一句话,模型回一段结果,页面把消息 append 上去,看起来就已经像个产品了。真正开始露出边界,通常是在需求变成这样的时候:帮我整理这批资料,明天继续;如果权限不足就先挂起等审批;调用外部系统失败就自动重试;执行到一半也要能从详情页接着看。到这一步,你会突然发现,消息列表已经不够当系统主结构了。

我现在越来越不把这类升级理解成“聊天产品加几个高级能力”,而是把它看成一次抽象迁移:从消息流产品,变成任务系统。前者的核心对象是 message,后者的核心对象必须是 task。

什么时候消息流开始不够用

只要出现下面几种情况,聊天消息就不再适合当唯一真相源:

  • 一次请求会跨多次页面刷新继续执行
  • 工具调用结果需要被后续步骤继续消费
  • 任务可能进入等待人工、等待权限、等待外部系统的状态
  • 用户不只想“看到回答”,还想看到进度、失败原因和恢复入口

这类需求表面上都是交互增强,底层真正变化的却是对象边界。系统不再只是在回答一句话,而是在执行一个可以持续存在的任务。

我现在更愿意先把任务对象定义清楚

我更喜欢从一份正式的任务对象开始,而不是继续把状态塞进消息附加字段里:

{
"taskId": "task_902",
"sessionId": "sess_77",
"traceId": "tr_55",
"goal": "review-and-publish-blog-post",
"status": "waiting_human",
"currentStep": "policy_review",
"inputSnapshotId": "snap_118",
"toolPolicyId": "tool-policy@1.3",
"idempotencyKey": "publish:post_2025_12_22",
"artifactIds": ["art_21", "art_22"],
"createdAt": "2025-12-22T21:30:00Z"
}

这个对象的价值不在于看起来更“工程化”,而在于系统终于能回答几个一直绕不过去的问题:这次请求现在处于什么阶段、哪些输出已经落盘、恢复时应该从哪一步接着跑、外部动作是否已经执行过。

状态机比消息顺序更适合描述任务生命线

聊天模式里,大家很容易默认“按消息先后推断状态”。这在单轮对话里还能凑合,一旦任务会跨工具、跨时间、跨人工介入,这种推断就会变得非常脆弱。

我现在更愿意明确写出状态机,而不是让状态藏在一堆隐式条件里:

  • created
  • running
  • waiting_tool
  • waiting_human
  • retrying
  • failed
  • completed
  • cancelled

状态机最值钱的地方,不是画图好看,而是让恢复和审计终于有边可依。系统不会再靠“看最后一条消息像不像执行中”来猜当前状态,而是能明确知道下一步允许发生什么、失败以后该回到哪里。

任务队列和幂等键最好一起设计

很多团队在这一步会先上队列,再慢慢补幂等。我的经验是,这两件事最好一开始就一起想。因为只要任务开始异步执行、自动重试和人工补跑并存,系统马上就会遇到“这次外部动作到底要不要再执行一遍”的问题。

比如“发布一篇文章”“创建一个工单”“给 CRM 写一条跟进记录”,这些都不适合被无脑重复。队列只负责把任务排起来,幂等键负责保证同一个业务动作不会因为重试而被重复落地。少了后者,任务系统会很快把自己变成脏数据制造机。

工具结果必须持久化,不然恢复时只剩聊天残影

聊天界面有一个很强的错觉:只要消息还在,任务就还在。实际上很多关键信息并不会稳定留在聊天记录里。工具调用拿回来的结构化结果、外部系统返回的 id、审批结论、失败重试次数,这些东西如果不单独持久化,页面一刷新、上下文一截断,系统就只剩下“好像之前做过点什么”的残影。

所以我现在会要求工具结果至少留下三层东西:

  • 原始结果快照
  • 归一化后的业务结果
  • 与任务对象的引用关系

这样不管是从详情页恢复、后台重跑,还是做事故回放,都不会只能靠自然语言消息去猜当时发生了什么。

聊天界面可以保留,但它更适合当壳,而不是当真相源

我并不是否定聊天界面。很多任务的入口、解释和人工介入都依然适合用对话承载。真正需要升级的,是系统底层不要再把消息列表当成唯一数据结构。聊天界面更像交互壳,任务对象才应该是真正的业务骨架。

当这层骨架立起来以后,很多之前很别扭的需求就会顺得多:列表页可以看所有任务,详情页可以看步骤和产物,聊天页继续保留自然交互,后台则能用同一份任务对象做排队、恢复和审计。

我真正想保留的结论

从聊天机器人走向任务系统,最本质的升级不是会不会多调几个工具,也不是界面从对话框变成看板,而是把“对话”背后的真实工作抽成一个可治理的任务对象。只要任务对象、状态机、队列幂等和工具结果持久化这几层先立住,聊天产品才能真正长成一个可以持续执行、持续恢复、持续审计的系统。