教程
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。