大家好,我是大煊,一个写了几年 Java,最近在啃 AI Agent 的后端。
相信很多朋友都听过 Memory、RAG,今天来聊聊 Tracker(追踪器)。它的作用也和"记忆"有关,但不是怎么让模型多记几句话,而是一个更工程化的场景:当 Agent 开始接业务任务时,怎么保存它执行到哪一步了?
记忆不是只有 Memory 和 RAG
我刚开始看 Agent 记忆这块,也有一个很自然的误解:
是不是加一个 Memory,把历史上下文存起来,就算 Agent 有记忆了?
再往后看 RAG,又会觉得:
那我把历史对话、用户资料、业务知识都丢进向量库,需要的时候检索一下,不就解决了吗?
后来按客服 Agent 的业务链路拆开看,才发现这事没那么简单。
Memory 更像"长期印象"。
RAG 更像"查资料"。
但 Tracker 解决的是另一件事:当前这件事进行到哪一步了。

所以这篇真正想聊的不是"怎么让模型多记几句话"。
而是:当 Agent 开始接业务任务时,系统里有没有一个地方,专门保存它执行到哪一步了?
这就是 DialogueStateTracker 的价值:它不是让模型更聪明,而是让系统自己别忘事。
我更愿意把它理解成:Agent 的运行时状态中心。

这张图是这篇的核心:LLM 不是状态中心,Tracker 才是。LLM 负责理解和表达,业务动作交给 Tool,状态交给 Tracker。
一个客服请求,背后其实是一串状态变化
拿"查订单"举例。
text
用户:我要查订单
Agent:请提供订单号
用户:123456
Agent:您的订单已发货
但系统背后发生的是:
这张图里,LLM 只负责理解和表达。
真正让系统跑起来的,是 Tracker 在旁边不断记录:
text
当前意图是什么
当前流程是什么
哪些信息已经收集
哪个工具已经调用
工具结果是什么
下一步应该做什么
没有这些状态,Agent 就会变成一个"每轮都像第一次见你"的聊天窗口。
Tracker 到底存什么?
我现在会把 Tracker 拆成五类东西。
| Tracker 里的东西 | 白话解释 | 客服例子 |
|---|---|---|
| 对话历史 | 用户和 Agent 说过什么 | "我要查订单""请提供订单号" |
| 槽位 Slots | 业务字段 | order_id=123456 |
| 流程 Flow | 任务走到哪一步 | 正在查订单 / 正在退款 |
| 最近动作 | 上一步执行了什么 | 刚调用订单查询 |
| 序列化状态 | 能不能保存和恢复 | 服务重启后继续处理 |
Tracker 不像"记忆力",更像一个带生命周期的对话上下文。
Controller、Service、Action、LLM 不要各自记一份状态。
大家都读写同一个 Tracker。

这就是统一状态源的价值:别让每个模块各记各的,不然一复杂就会互相打架。
还有一个小点也挺关键:Tracker 不是把所有历史都塞给 LLM。
它可以保存完整状态,但真正喂给模型的,通常只是一部分对话历史和必要业务信息。剩下的槽位、工具结果、流程状态,更多是给程序自己判断下一步用的。
Slot(槽位):把聊天里的关键信息变成业务字段
客服 Agent 最怕一件事:
用户明明说了订单号,系统后面却用不上。
原因很简单:自然语言历史不是业务字段。
用户说:
text
我的订单号是 123456
系统真正需要的是:
text
order_id = 123456
这就是 Slot(槽位)。

Slot 有点像表单字段。
退款要订单号,改地址要新地址,贷款要金额,人工转接要问题类型。
这些都应该从聊天里沉淀成结构化字段。
但这里有个边界很重要:
| 信息来源 | 谁来写入 | 例子 |
|---|---|---|
| 用户说出来的信息 | LLM 可以提取 | 订单号、地址、退款原因 |
| 系统查出来的信息 | Action 写入 | 订单状态、退款结果、会员等级 |
这件事不能混。
LLM 可以帮你理解"用户说了什么",但不要让它凭感觉决定"订单是否发货"。
订单状态必须来自订单系统。

这张图的重点是边界:理解归 LLM,事实归业务系统。
到这里,Tracker 已经不只是"聊天记录"了。它开始变成当前任务状态的容器。
Tracker 和 Memory 不是一回事
前面已经说了 Memory / RAG / Tracker 的区别,这里再从生命周期看一眼。
| 模块 | 解决的问题 | 例子 |
|---|---|---|
| Tracker | 当前这件事做到哪了 | 正在退款,已收集订单号 |
| Memory | 这个用户长期是什么样 | 喜欢中文、偏好某品牌 |
| Knowledge Base | 企业知道什么 | 退款规则、商品说明 |

这三类东西生命周期完全不同。
Tracker 里的"当前退款到确认金额"可能 10 分钟后就没用了。
Memory 里的"用户喜欢中文回复"可能几个月后还有效。
Knowledge Base 里的"退款政策"属于企业公共知识,不应该混进某个用户会话。
边界不清,Agent 项目越做越乱。

这张图我会贴在所有 Agent 状态设计文档最前面:生命周期不同,存储位置就不该一样。
Tracker 解决的三个生产问题
第一个:上下文丢失
用户说完订单号后,Agent 要知道这个数字属于刚才的"查订单任务"。
这靠的不是模型玄学,而是 Tracker 记录:
text
active_flow = query_order
order_id = 123456

第二个:任务无法恢复
用户退款到一半,页面关了。
下次回来,系统要知道:
text
退款流程已经走到确认金额
订单号已经收集
身份已经验证
如果 Tracker 能序列化,就可以保存到 Redis 或数据库里,后面再恢复。
第三个:多模块状态不一致
没有统一 Tracker 时,很容易出现:
text
LLM 以为在退款
Action 以为在查订单
前端显示人工接管
数据库里还是旧状态
这就是状态中心的价值。
不是为了"架构好看",而是为了避免业务系统各说各话。

一个系统越像"能办事的人",越要有清楚的状态中心。
这次对我最大的提醒是:看 Agent 架构时,不要只问"模型能不能理解",还要问"系统有没有地方保存当前任务状态"。
如果这个问题没想清楚,后面接多少 Memory、RAG、Tool,都会越做越乱。