教程
AI Agent State 是什么?2026 Agent 状态管理、JSON State、Memory、Workflow 与任务执行完整指南
聊天记录不是状态。Agent 能暂停、恢复、交给下一跳,靠的是一份可校验的 JSON:目标、步骤、工具回执、记忆指针与任务信封。
2026 年把 Agent 跑进生产,卡点很少是「模型够不够聪明」,而是停机、重试、人工确认之后,它还记不记得自己做到哪一步。上一篇把 Agent 收成「观察—决策—调工具」循环,见 AI Agent 是什么。本篇补上循环之外的那一层:State。State 不是把整段对话塞进上下文,也不是向量库里的一段记忆。它是运行时当前机位的结构化快照——几乎总是 JSON。下面按 JSON State、Memory、Workflow 与任务执行拆开,并接到站内无状态 MCP、A2A、Structured Output 与 1M 上下文文。
Agent State 是什么:和聊天记录、Session 差在哪
最小定义只需要一句话:Agent State 是让一次 run 可暂停、可恢复、可回放的结构化快照。它至少回答四个问题:目标是什么、现在停在哪一跳、已经确认的工作结果是什么、下一步被谁拦住(工具、人、还是 maxSteps)。模型负责在当前观察上选行动;运行时负责执行并把机位写回这份快照。没有可校验的机位,循环只能靠「再把整段聊天贴回去」——那是聊天,不是状态管理。
聊天记录是给模型看的消息列表:user / assistant / tool。Session(OpenAI Conversations、previous_response_id、旧 Assistants Thread)是给供应商看的会话句柄:下一请求要带上哪些模型侧条目。State 是给你的运行时看的机位:发票对到哪、待确认金额、当前图节点、checkpoint id。三者可以共存,但不要互相冒充。把 messages[] 当成唯一真相,重试时就会重复扣款、重复发邮件;把 Conversation id 当成业务状态,供应商一切换,机位就丢了。Assistants 迁到 Responses 之后,会话原语变了,业务快照更不该绑在平台对象上——见 Assistants → Responses 迁移。
2026 年常见事故几乎都是「层搞混了」:把工具 arguments 写进 State、把 State 整包塞进下一轮 prompt、或把长期记忆当 checkpoint 回放。分层之后,调试才有抓手:模型看错了是观察问题;机位写错了是 reducer / Schema 问题;记错用户偏好是 Memory 问题。对照如下。
| 概念 | 谁读 | 丢了会怎样 |
|---|---|---|
| 聊天记录 / messages | 模型(本轮上下文) | 答非所问;一般能从 checkpoint 再投影 |
| Session / Conversation | 模型供应商 | 多轮推理条目对不上;你的业务机位仍应独立 |
| Agent State / checkpoint | 你的运行时、编排器 | 无法安全恢复;重试可能双写下游 |
| Memory | 跨 run 的检索与偏好 | 忘了用户习惯;不应当成当前步骤的真相 |
JSON State:checkpoint 才是契约
把 State 写成 JSON,不是为了好看,而是为了校验、Diff、回放。LangGraph 一类编排器在每个 super-step 落一份 checkpoint,用 thread_id 串起一条线,再用 checkpoint_id 指向某一拍;生产上用 Postgres / SQLite saver,而不是进程内 MemorySaver。名字会变,形状不应变:一份可 parse 的对象,带 schemaVersion、status 枚举、step、working、memoryRefs。序列化实现可以是 JsonPlus 或扩展 JSON,但你对外暴露、写日志、做联调的那一层,应是普通 JSON object——否则 Schema 校验与浏览器 Diff 都用不上。
下面这份快照只描述机位,不把 messages[] 或下游 HTTP 原文塞进来。业务字段进 working;工具调用只留 name 与 callId;记忆只留指针。完整对话可以从 checkpoint 再投影到模型上下文,不要反向把上下文当成 State。
{
"schemaVersion": "1.0",
"runId": "run_7c2a",
"threadId": "thr_invoice_42",
"goal": "Reconcile January 2026 paid invoices",
"status": "awaiting_tool",
"step": 3,
"maxSteps": 12,
"node": "call_tools",
"plan": ["searchInvoices", "sumTotals", "askConfirm"],
"working": {
"invoiceCount": 2,
"currency": "USD"
},
"pendingTool": {
"name": "searchInvoices",
"callId": "call_8f3a"
},
"memoryRefs": ["mem_user_prefs", "mem_last_reconcile"],
"checkpointId": "ckpt_3"
}
两种写法都成立:每次写全量快照,或写 JSON Patch / reducer 补丁。全量好 Diff、好回放;补丁省存储、要求补丁本身可校验。无论哪种,先定一份 Draft 2020-12 Schema:status 用枚举(running / awaiting_tool / awaiting_human / succeeded / failed / cancelled),step 是整数,working 的键来自业务,禁止 additionalProperties 把工具垃圾字段漏进来。最终给用户或下游系统的答案是另一份 Structured Output,不要和 checkpoint 共用一个文件——见 AI Structured Output。
Memory:回忆不是机位
Memory 解决「跨时间还该记得什么」,State 解决「这一拍停在哪」。2026 年常见三层:工作记忆(本轮上下文里的消息与最近 tool_result)、短期 / 线程记忆(同一 thread_id 上的 checkpoint 链,LangGraph 把这层叫 short-term memory)、长期记忆(跨 thread 的 Store:用户偏好、事实、程序说明)。把三层揉进一个大 JSON,看起来省事,回放和遗忘策略都会一起坏掉。
再按内容分:情景记忆(这次对账发生过什么)、语义记忆(用户喜欢美元合计)、程序记忆(「先搜发票再汇总」这类可复用步骤)。只有被引用进当前 run 的记忆,才应出现在 State 的 memoryRefs 里。上下文窗口涨到百万 token,也不等于可以取消这层指针——窗口是预算,不是真相。见 1M Token 上下文。
| 层 | 典型载体 | 不该塞什么 |
|---|---|---|
| 工作记忆 | 本轮 messages / tool_result | 跨会话的用户偏好全文 |
| 短期 / checkpoint | thread_id 上的 State 快照 | 向量库原文、未裁剪日志 |
| 长期 Store | 按 userId / namespace 的条目 | 当前 step、pendingTool、幂等键 |
| 模型侧 Session | Conversation / previous_response_id | 你的业务 working 对象 |
长期条目建议固定信封:id、kind、scope、text 或 data、source、updatedAt。source 写明是用户明示、工具回执还是模型总结——后两种要能作废。检索命中之后,只把 id 写进 State,全文按需注入上下文。示例:
{
"id": "mem_user_prefs",
"kind": "semantic",
"scope": "user",
"userId": "u_1042",
"text": "Prefers USD totals and weekday email summaries",
"source": "explicit_setting",
"updatedAt": "2026-09-01T09:00:00Z"
}
Workflow 与 Agent:谁画边、谁写 State
传统工作流(n8n、Temporal、自建状态机)的下一跳由人预先连好,State 是工作流变量:订单 id、已重试次数、补偿是否发出。Agent 的下一跳由模型根据当前这份 JSON 观察决定,State 还要记下 plan、node、pendingTool。2026 年生产上两者很少纯种出现:更常见的是「图 + 若干 Agent 节点」——边是工作流,节点内部是工具循环。一份 JSON State 同时服务两套读者:编排器读 status / node,模型只看到你投影出去的观察子集。
MCP 不管这件事。2026-07-28 一带的远程 MCP 把协议收成无状态 JSON-RPC:每次请求自带元数据,Server 不替你记住业务机位。那是传输层的正确选择,不是「Agent 不能有状态」。应用状态仍在你的 checkpoint。细节见 Stateless MCP 解析。工具 arguments 的 Schema 与 State Schema 必须分文件:前者描述这一跳入参,后者描述机位——见 MCP 与 JSON Schema。
多 Agent 横向委托走 A2A:对端是不透明的 Agent,任务有自己的生命周期(submitted / working / completed / failed)和 artifacts。那是另一份状态机,不要和本地 checkpoint 共用一个对象。编排器用 parentRunId 把它们钉在一起。对照 A2A vs MCP。换模型网关(例如本地 /v1)只改推理供应,不改 State 形状——契约稳定,降级才有意义。
任务执行:run、step、幂等与重试
执行层把 State 从「照片」变成「可恢复的机器」。每次用户目标开一个 runId;循环里每个工具 hop 一个 step;写下游(扣款、发信、建工单)必须带 idempotencyKey。崩溃后从最近 checkpoint 恢复时,已成功的 step 不得重放副作用。pending writes(部分节点成功、部分失败)应记在快照里,而不是靠运维猜。
人工确认是一等状态,不是特殊分支:status=awaiting_human,working 里放待确认对象,恢复时只允许有限的合法迁移(批准 → 继续,拒绝 → 失败或改 plan)。不要用「再问模型一遍」代替状态迁移——模型看不到你没写进观察的那次点击。maxSteps、用户取消、Schema 失败同样是停止条件,应写进 status,而不是只打日志。
平台会话与你的执行记录选一个历史主人。OpenAI Responses 可用 Conversation 或 previous_response_id 续上推理条目;那是模型侧的磁带,不是发票对账机位。推荐:你拥有 checkpoint 与任务信封,平台只拥有它必须拥有的 reasoning 条目(某些供应商在带 tool_calls 时要求原样回放 reasoning_content)。任务信封示例如下。
{
"taskId": "task_a2a_91",
"parentRunId": "run_7c2a",
"kind": "delegate",
"status": "working",
"idempotencyKey": "inv-jan-2026-reconcile",
"steps": [
{ "id": "s1", "name": "searchInvoices", "ok": true },
{ "id": "s2", "name": "sumTotals", "ok": null }
],
"artifacts": []
}
委托给子 Agent 时,把远端 taskId 写进本地 working 或 steps,而不是把对方 artifacts 摊进同一份 checkpoint。中间产物是新的 JSON 家族,最终 Structured Output 与 MCP arguments 都不要和它共用文件。现在就给每条工具日志打上 correlationId / runId,以后对账才对得上——DevDay 一类平台观测也按同一键对齐,见 OpenAI DevDay 2026 预测。
落地校验与 JSONVue 实操
每个 checkpoint 落地前固定三步:parse → Schema → 业务规则。模型再聪明,也不替代这三步。State 坏了比 arguments 坏了更危险:后者是一跳,前者是整条 run 的真相。
- checkpoint JSON.parse;失败则拒绝写入,保留上一拍 ckpt_id。
- 对照 State Schema(Draft 2020-12)校验 status / step / working;输出 path 与 keyword。
- 业务门:step 单调、幂等键稳定、memoryRefs 都存在、非法 status 迁移直接失败。
联调时把三份 JSON 并排:ckpt_n、ckpt_n+1、以及你投影给模型的观察。形状跳变几乎总在 reducer。浏览器里:JSON 格式化看清快照树;JSON Schema 校验卡住 State 与 Memory 信封;JSON Diff对比相邻 checkpoint。固定 fixture:valid、缺 step、非法 status,CI 与手工共用。
延伸阅读:AI Agent 是什么、Structured Output、Stateless MCP、A2A vs MCP、1M Token 上下文。
常见问题 FAQ
State 和 Memory 是一回事吗?
不是。State 是当前 run 的机位(能否安全恢复);Memory 是跨时间的回忆(偏好、事实、旧情节)。checkpoint 链可以充当短期记忆,但长期 Store 不应写成 step / pendingTool。回放用 State,检索用 Memory。
上下文窗口到 1M 了,还需要 checkpoint 吗?
需要。窗口解决的是「这一轮能塞多少观察」,不解决「崩溃后从哪一跳继续」和「重试会不会双写」。把整段历史当 State,账单和故障面会一起变差。1M 是预算工具,checkpoint 是执行工具。
用了 OpenAI Conversation,还要自己存 JSON State 吗?
要。Conversation / previous_response_id 续的是模型侧条目,不是你的业务机位。供应商配额、区域切换或换网关之后,平台会话可能对不上。业务 working、幂等键和人工确认状态应落在你控制的 JSON 上。
Stateless MCP 是不是就不能做有状态 Agent?
能。协议无状态只表示每次 tools/call 自带参数,Server 不保存你的对账进度。应用状态放在你的 checkpoint;MCP 仍是工具发现与传输。把 inputSchema 和 State Schema 分成两份文件。
总结与下一步
2026 年的 Agent State 可以概括成:运行时用一份可校验的 JSON 快照记住机位,Memory 只提供被引用的回忆,Workflow 画边或把边交给模型,任务执行用 run / step / 幂等键把快照变成可恢复的机器。聊天记录和平台 Session 都不是这份快照的替代品。
下一步:写出你系统里的 State Schema 与一份 valid checkpoint;用 JSONVue 做相邻快照 Diff,再补上缺字段 / 非法 status 夹具。循环定义读 Agent 文,最终答复形状读 Structured Output,协议层读 MCP / A2A。