OpenAI Agents API 如何處理長時間執行的 AI Agent?Context、Tools、Subagents 與 JSON 狀態管理完整教學
9 月 10 日公測的賣點不是「再開一個 chat」。官方把 Codex 上跑了幾天的 harness 交出來:Session 續著,上下文會被 compact,subagent 自帶一份上下文。本文只寫長任務怎麼活:你存什麼 JSON,OpenAI 替你壓什麼,斷線後看哪段 items。
閱讀前速覽
| 物件 | 做什麼 | 你該存什麼 |
|---|---|---|
| Session | 可續的實例,跨小時、跨視窗 | session_id |
| Turn | 一次輸入啟動的非同步工作 | turn_id / 完成事件 |
| Items | 已儲存的訊息和工具呼叫 | 斷線後回放用 |
| Compact | 接近視窗上限時自動壓縮 | 關鍵欄位另存 |
| Subagent | 獨立上下文,並行干活 | 並行上限 |
空閒的 session 不等於這一輪成功。看 turn 事件和 items,不要看最後一句自然語言。
長任務活在 Session 裡,不活在更長的 prompt 裡
Agents API 處理長時間執行的辦法很具體:你建一個 durable session,後續輸入都打到同一個 session_id。接近上下文上限時,harness 自動 compact 早先的內容。獨立子任務可以派給 subagent。你不用自己拼完整聊天紀錄。
- 續跑:把
session_id跟業務會話綁在一起。同一條會話,不要新建第二個 session。 - 斷線:事件流不重放。把 session 和 items 拉回來,不要假設用戶端還記得上一跳。
- 錢和單號:compact 會丟掉細節。訂單號、金額、審批結果寫在你自己的 JSON 裡。
Session 和工具 JSON 怎麼接,見 OpenAI Agents API 完整解析。循環該不該交給託管,見 Agents API vs Responses API。若 Agent 和 Function Calling 還糊在一起,先讀 AI Agent 完整指南。
Session 續著,Turn 非同步跑
建立時一次宣告模型、工具、環境和是否開 multi_agent。官方建立口是 POST /v1/agents/sessions,header 帶 OpenAI-Beta: agents=v1。託管沙箱寫 openai_hosted:
{
"agent": {
"model": "gpt-6-astra",
"instructions": "Look up orders. Confirm before any refund. Delegate independent lookups to subagents.",
"tools": [
{
"type": "function",
"name": "lookup_order",
"parameters": {
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^[A-Z]-\\d{4}$" }
},
"required": ["order_id"],
"additionalProperties": false
}
},
{ "type": "web_search" }
],
"multi_agent": { "enabled": true, "max_concurrent_subagents": 3 }
},
"environment": { "type": "openai_hosted", "workspace_directory": "/workspace" },
"input": [
{
"role": "user",
"content": [{ "type": "input_text", "text": "Look up A-1042 and keep the case open." }]
}
]
}
同一條 session 上再發 agent.session.input.message。空閒就開新 turn;還在跑就轉向當前 turn。取消用 agent.session.input.cancel,session 和已儲存工作還在:
{
"events": [
{
"type": "agent.session.input.message",
"input": [
{
"role": "user",
"content": [
{ "type": "input_text", "text": "Warehouse marked A-1042 packed. Continue." }
]
}
]
}
]
}
看結局,不要看「現在閒不閒」。官方事件是 agent.session.turn.completed、failed、cancelled。turn 完成也不等於每個工具都成功。需要函數結果時,去讀 required_actions。
工具鏈跨小時,回寫還是 JSON
長任務裡,模型仍然只填參數。輪到你的 function,harness 停住,你按 turn_id / call_id 交結果。四小時後回寫,形狀不變:
{
"type": "tool_result",
"turn_id": "turn_4",
"call_id": "call_3c91",
"success": true,
"output": "{\"order_id\":\"A-1042\",\"status\":\"packed\"}"
}
function 要你執行;MCP 和 web_search 可以由 harness 自己走。subagent 繼承 MCP 和網頁搜尋,不繼承 function 工具。需要查自家訂單的副作用,留在主 Agent。
門還是 Schema。寬 object 在長任務裡更危險:compact 之後模型更容易填錯單號。MCP 那一行只是另一張工具表,邊界見 MCP Tool Schema vs Function Calling。
Compact 壓的是視窗,不是你的帳簿
官方寫明:接近上下文上限時,Agents API 自動 compact 早先內容,讓工作跨多個視窗。你不必自己實作壓縮。這和 Responses 上的 context_management / /responses/compact 不是同一層。
- Agents API:session 自己壓。你拿回 items,核對單號還在不在。
- Responses:要自己開 compact,或呼叫 compact 端點。加密的 compaction item 當下一窗的輸入,不要手剪。
- 兩邊都成立:壓縮丟細節。金額、確認、放行仍由宿主寫。
把 order_id 只活在對話裡,等於把帳簿交給摘要。Schema 怎麼當門,見 AI 為什麼需要 JSON Schema。
Subagent:並行,但上下文分開
打開 multi_agent.enabled 後,harness 自帶建立、傳話、等待、打斷。你不用自己宣告這些工具。items 裡會出現協調動作:
{
"data": [
{
"type": "function_call",
"turn_id": "turn_4",
"call_id": "call_3c91",
"name": "lookup_order",
"arguments": "{\"order_id\":\"A-1042\"}"
},
{
"type": "create_subagent_call",
"agent_id": "agent_main",
"task": "Compare A-1042 packing notes with the invoice."
}
]
}
- 獨立上下文:每個 subagent 自己一份。主 Agent 用 create / message / wait / interrupt 收口。
- 並行要封頂:預設最多 6 個(不含協調者)。生產裡寫死更小的數。
- 完成項 ≠ 子任務結束:
create_subagent_call完成,只說明派出去了。看agent.session.subagent.created和該 subagent 自己的 items。
handoff 該是可審計的 JSON,不是一句「請交給帳單組」。怎麼收成 Schema,見 JSON Schema 與 AI Agent 工作流。
你持有的狀態,不要指望 compact 替你記
OpenAI 替你存 session 設定、對話和已儲存工作。你至少還要一份業務狀態,斷線也能重建:
{
"session_id": "sess_8f21",
"order_id": "A-1042",
"last_turn_id": "turn_4",
"last_call_id": "call_3c91",
"awaiting": "tool_result",
"compact_checkpoint": "after_turn_3"
}
這份物件跟 Session、SDK session、Responses conversation、sandbox 都不是同一個資源。刪一份不會自動清另一份。資料駐留目前只在美國;自建沙箱也不等於 Zero Data Retention。
五步把跨視窗任務跑完
不要從示範影片倒推。按物件走:
- 建立一次 session,把
session_id寫進你的會話。工具表和 Schema 一次收緊。 - 訂事件再發後續輸入。先訂流,再打
agent.session.input.message,否則早期事件會丟。 - 停在 required_actions 就回寫。用同一對
turn_id/call_id,不要另開 session 重試。 - 斷線拉 items。流不重放。按
order=asc列出,對上單號和等待中的呼叫。 - compact 之後再核一次帳簿。摘要裡沒有
A-1042,下一跳就會填錯。
五步都落在物件上,長任務才是可恢復的。少一步,你就是在賭視窗還沒滿。
複盤長任務,先攤開兩段 JSON
出問題的多半不是模型變笨,是物件對不上。
- 把 session items 和你本地狀態 格式化,確認
session_id/call_id對得上。 - 用 JSONPath 提取 抽出
order_id、turn_id、subagent 的agent_id。 - compact 前後的 items JSON Diff。單號漂了,先看壓縮,再怪模型。
- 主 Agent 的 items 和某個 subagent 的 items 分開列。混在一頁裡,協調動作會對錯人。
- 訂單、session、內網 MCP 不要貼進公共格式化站。JSONSort 在瀏覽器本地跑。
兩段軌跡都能重建,你才知道任務是續上的,不是重新猜的。
常見誤區
- 以為空閒就是成功。看
turn.completed/failed/cancelled,再看工具結果。 - 斷線後等流重放。官方寫明流不重放。拉 session 和 items。
- 把單號只活在對話裡。compact 之後,摘要可能丟掉
A-1042。 - 開 multi_agent 卻不設並行上限。預設 6 個也會扇出 token 和副作用。
- 讓 subagent 去跑你的 function。子代理不支援 function 工具。查單留在主 Agent。
- 把 Session 和 Conversation 當成同一份。刪一份不會自動清另一份。
FAQ
長時間執行是不是把 prompt 寫得更長?
不是。靠的是 durable session、自動 compact、以及你自己存的業務 JSON。更長的系統提示解決不了視窗上限。
Agents API 的 compact 和 Responses 的 compact 能混用嗎?
不要混。Agents session 自己壓上下文。Responses 用 context_management 或 /responses/compact。兩套資源,兩套下一窗輸入。
斷線後怎麼恢復?
用存下來的 session_id 取回 session 和 items。流不會重放錯過的事件。先對齊 last_turn_id 和未完成的 call_id,再決定回寫還是續訊息。
subagent 能不能呼叫我的 lookup_order?
不能。官方寫明 subagent 不支援 function 工具。它們繼承 MCP、網頁搜尋和環境裡的檔案 / 命令。查自家訂單,留在主 Agent。
自建沙箱是不是就能做 Zero Data Retention?
不能。官方寫明 Agents API 目前只支援美國資料駐留,也不支援 ZDR。選 self-hosted 沙箱不會讓它變成 ZDR。
結論
長時間執行不是更聰明的模型。它是一份可續的 Session、一次自動 compact、以及你自己握住的 JSON 狀態。工具參數、turn 事件、subagent items,都只是這條鏈上的物件。
先寫清你斷線後還能不能重建 A-1042。能,任務才算活著。模型會換;session_id 和 Schema 應該先穩定。
延伸阅读
- OpenAI Agents API 完整解析 Session、Tool Calling、Schema 怎麼接
- Agents API vs Responses API 循環該由誰跑
- AI Agent 是什么?完整指南 執行時與 JSON 契約
- AI 为什么需要 JSON Schema Schema / Function Calling / Structured Output
- JSON Schema 与 Agent 工作流 把工具和狀態收成 Schema
- JSONSort 本地工具箱 格式化、校驗、Diff
- 全部文章 更多 JSON 與 AI 開發筆記
更新紀錄: 首次發布