ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Agent 状态管理工程笔记

Agent 状态管理工程笔记 摘要:LLM 每次调用都无状态,Agent 要"记住上一句"必须自己管理状态。本文把这套机制拆成三层——装上下文的容器(Session)、容器里会变的活数据(State)、可中断/回放的冻结副本(Checkpoint),并对照 OpenAI Conversations、LangGraph、AgentScope 2.0 的真实 API 落地,最后给出 token 墙、checkpoint 膨胀、session 串味等工程坑的应对策略。《Agent 工程笔记》系列Agent Loop 工程笔记Agent 状态管理工程笔记(本篇)Agent 消息与事件工程笔记Agent 中间件工程笔记Agent 工具调用工程笔记Agent MCP 工程笔记Agent Skill 工程笔记一、为什么需要这套东西1.1 从 Tomcat 切入:无状态传输之上必须重建状态HTTP 本身是无状态的——每一次请求都是全新的,服务端不记得"上一句"。Tomcat 的HttpSession干的事,就是在「无状态的传输层」之上,于端点(服务端)把"状态"攒起来:给每个浏览器发一个JSESSIONID,后续请求带上它,服务端据此找回这个人的购物车、登录态。图:Tomcat 的 HttpSession 与 Agent 的 Session 同构——传输层无状态,靠 session 容器在端点重建状态。session 的本质就是通讯层上的会话状态管理——它解决的是"传输无状态、但业务需要有记忆"这个矛盾。1.2 同构到 Agent:LLM 也是无状态的LLM 的 API 和 HTTP 同构——每次调用都是无状态的,模型不记得上一轮发生了什么。agent loop(见 《Agent Loop 工程笔记》)每跑一轮,都得把完整历史重新拼进 prompt 再发给模型:所以 agent runtime 必须像 Tomcat 一样,在端点把"状态"攒起来——这就是session。区别只在"状态里装了什么、谁消费它"(下一章展开)。(这里说的"完整历史"是理想模型:受 token 窗口限制,现实里每轮塞回 prompt 的往往不是原始全量,而是经过滑动窗口、摘要或压缩后的上下文——这层约束正是下一节"内存墙"的来源。)图:agent loop 每轮从 session 读全量历史、追加新消息、调 LLM、执行 tool、把结果写回,循环往复。1.3 一个先抛的关键差异Tomcat 的 session 基本不用操心容量:它吃内存,靠 timeout 清理即可。但Agent 的 session 有 token / context 上限这道"内存墙"——历史越长,每轮重发的 prefill 越贵,超了窗口就报错。这道墙逼出了两件 Tomcat 没有的东西:上下文压缩 / 截断 / 滑动窗口:历史不能无限堆积,得经营。Checkpoint(检查点):因为 agent 工作流是可中断、可回放的状态机(见 2.3),需要在某步把状态冻存下来。于是三件套成形:装状态的容器(session)、容器里会变的数据(state)、可中断/回放的冻结副本(checkpoint)。后面四章逐一拆。二、是什么:拆成三层2.1 Session —— 无状态传输上的状态容器Session = 把多次交互串起来、并圈定作用域的容器。它存在的意义是"连续性"——让本来无状态的调用看起来有记忆。Session 里通常装四样东西:装的东西例子属于哪类数据(见第三章)transcript(对话记录)messages[]、tool 结果state 层(会演化)working state(工作记忆)scratchpad、当前计划state 层config(会话级固定配置)用哪个模型、什么人设session 层(固定)metadata(会话元数据)session_id、owner、ttlsession 层(控制面)图:Session 容器承载的四类数据——transcript、working state 属于 state 层;config、metadata 属于 session 层。Session 在 Agent 语境下有两个含义:状态容器(主流):单次对话的上下文背包,上面整篇讲的这个。通讯连接:在多 agent 系统里,Agent A 给 Agent B 发消息那条"通道"有时也叫 session——更接近一次会话连接而非状态容器。AgentScope 2.0 用 sub-agent + event stream 承担这条"线"(1.0 的msghub已在 2.0 移除),见 4.3。有没有无状态的 session?有。Session 可只当"标识符/令牌",服务端不持任何状态:JWT 型:session 就是客户端带的一个签名 token,里面塞了身份/claims,服务端每请求无记忆、靠 token 自证。session 在,但服务端 state = 0。Agent 里的无状态变体:把 thread_id 当路由键传,但上下文放客户端或每轮从日志重算,服务端不存对话。所以"session"有两副面孔:有状态 session(Tomcat、LangGraph thread,容器+服务端持有的 state)与无状态 session(JWT,仅一个 id/令牌)。2.2 State —— session 里会变的活数据State = 某一时刻"当前是什么"的数据集合。它是可变的、实时的:FSM 的current_state、agent 的messages[]、scratchpad、workflow 位置。state裸奔出现时指当前那份。一个容易含糊的问题:历史数据还叫 state 吗?三种情况:历史住在 state 里面(最常见):当前 state 的messages[]字段装的就是历史对话记录,随 state 一起被每轮重发给 LLM。历史是 state 的一个字段,但这段历史序列本身叫transcript / message history,不单叫"state"。事件溯源下,历史比当前 state 更"真":在 event-sourcing 系统里,事件日志是唯一真相,当前 state 只是对日志fold/replay出来的投影。Git 即此模型——commit 历史是真相,某次 checkout 只是物化出来的 state。过去的那份 state,叫 checkpoint:被冻存下来的过去 state 快照,它们曾是 state,现在叫checkpoint / historical state。叫法含义是"当前"吗current state / live state此刻的活数据是history / transcript / message history对话记录序列(常作为 state 的字段)否event log / audit trail事件日志(溯源模型下的真相)否checkpoint / snapshot过去某刻的 state 冻结副本否(“曾经的当前”)图:左为"当前 state 包含历史"的快照优先模型;右为"事件日志是真相,当前 state 是投影"的溯源模型。数据边界:固定 config(用哪个模型、什么人设)归 session 层;运行中派生/累积的东西(计划、中间结果)归 state 层。这条线划在"固定描述"还是"演化内容"上。2.3 Checkpoint —— state 的冻结副本Checkpoint = 在某个步骤,把当前 state 冻结一份存下来。它是 state 的快照,不是 state 本身。为什么 agent 框架要有它、Tomcat 没有?因为 Tomcat 处理一个请求是短暂、不可中断的——请求进来、处理完、回响应,中间不会"挂起等人审"。而 agent 工作流(带 tool call、多步规划、人工审核)是个状态机:跑到某一步可能要暂停、等人确认、或崩了要恢复。Checkpoint 为这个准备:断点续跑:崩了/停了,从最近一个 checkpoint 接着来。时间旅行 / 回退:回到第 N 步重选一条路(用update_state改写状态再续)。人机交互(human-in-the-loop):在 checkpoint 处暂停,人改一下 state 再 continue(LangGraph 的interrupt()+Command(resume=...),旧式interrupt_before=[...]等价)。所以三者在 LangGraph 里分工最干净(也是"checkpoint"最常出现的地方):thread = session,state = 被 nodes 反复改写的 typed 对象,checkpoint = 每步落盘的 state 快照。2.4 承上启下三个概念各自是什么已经讲清,总结一下:session 是带生命周期的定位键(可有状态可无状态),state 是定位键下的活内容,checkpoint 是内容在某一刻的定格。图:Session ⊇ State ⊇ Checkpoint;容器装着活数据,活数据被冻成快照,虚线表示每步对 state 拍快照。三、怎么分层:数据落位与管理正交3.1 容器 ⊇ 活数据 ⊇ 快照
返回列表