跳至主要內容

    Agent 駕馭工程懶人包 (4)|Agent 跑到一半能插話嗎?三家的注入規則

    Agent 做到一半發現方向錯了,你的新指示何時進得去?整理 OpenAI Responses API 與 Codex CLI、Anthropic Messages API 與 Claude Code、Pydantic AI 的中途引導規則,附對照表。

    sunny 桑尼· · 21 MIN READ · 93 次瀏覽

    Agent 駕馭工程懶人包 (4)|Agent 跑到一半能插話嗎?三家的注入規則
    本文目錄

    在終端機看著 Codex 或 Claude Code 往錯的方向跑,你打了一句「先別動資料表結構」,按下 Enter。這句話什麼時候會被模型讀到?正在跑的測試會被砍掉嗎?送出去之後,你還要不要等這一輪結束?

    2026 年 10 月 15 日發布的 Codex CLI 0.163.0,在 release notes 裡寫了這一行:

    "Send a follow-up while Codex is responding to steer it immediately." (OpenAI, Codex CLI 0.163.0 release notes, 2026-10-15)

    這個行為在 0.159.0(2026-09-29)還是選用開關,到 0.163.0 才改成預設。Claude Code 的文件對同一個動作給的答案不一樣:Enter 是排隊,工具呼叫結束後才讀到。Pydantic AI 則在 2026 年 5 月的 v1.101.0 加了 enqueue,讓程式能把新指示排進執行中的 Agent。三家對「新指示何時進得去」的規則各不相同,這篇把它們放在同一張表上。

    文中的「中途引導」(steering)指在 Agent 執行中途插入新指示,改變它的方向;「注入」(injection)指把一段內容放進下一次送給模型的請求。

    快速回答 依 2026-10-23 查閱的文件,三家的插話都排在待處理的工具結果之後,差別在誰排隊:OpenAI Responses API 由伺服器排隊,限 GPT-6 系列且要走 WebSocket;Anthropic Messages API 只規定訊息格式,文字放在 tool_result 之後,上一輪若有尚未回結果的伺服器端工具,該則 user 訊息只能放 tool_result;Pydantic AI 用 enqueue(訊息排隊功能)排隊,可選下一次請求或本來要結束時送達。自己做 Agent,我會先做「下一次請求前送達」;工具若一次跑幾十分鐘,就要再支援中斷,免得插話等太久。

    為什麼插話不能想插就插?

    插話要配合工具呼叫與結果的順序安排。以 Anthropic Messages API 為例,工具結果必須緊接對應的工具呼叫,新增的文字再放到結果之後,一起送進下一次模型請求。

    Anthropic 的 Messages API 文件把這條規則寫得最直白:

    "Tool result blocks must immediately follow their corresponding tool use blocks in the message history." (Anthropic, Handle tool calls, 查閱於 2026-10-23)

    文件接著規定,裝著工具結果的那則 user 訊息,tool_result 區塊必須放在內容陣列最前面,文字要放在所有工具結果之後;文字放在前面會得到 400 錯誤。文件列的常見錯誤訊息是「tool_use ids were found without tool_result blocks immediately after」。OpenAI 的函式呼叫文件另有配對要求:每個 function_call_output 要用 call_id 指回它對應的那次呼叫。文件沒有說明漏掉輸出時的行為,本篇不推測。

    圖 1 插話的送出時機與生效點。上排是各家文件寫的可送出時機,下排是生效點。依據:Anthropic〈Handle tool calls〉、Claude Code〈How Claude Code works〉、Pydantic AI 文件〈Messages and chat history〉、OpenAI〈Mid-turn steering〉,皆查閱於 2026-10-23。把四者畫在同一條時間軸上是本站歸納。

    讀圖時看下排:四個實作的插話都排在 tool_result 之後、下一次模型請求之前。上排的送出時機各不相同,下面三節依序比較排隊的方式、對執行中工具的處理,以及送達的優先序與限制。

    插話由誰排隊、什麼時候生效?

    三家都讓插話等到下一次模型請求才生效,差別在排隊的人:OpenAI 由伺服器排隊,Anthropic 的 API 只管格式、排隊交給應用程式,Pydantic AI 由框架內建佇列排隊。

    OpenAI:伺服器排隊,自動接成新回應。 依 OpenAI 的 Mid-turn steering 文件(查閱於 2026-10-23),對進行中的回應送出 response.steer,伺服器先排隊,再自動建立帶著新內容的下一個回應,呼叫端不用再送 response.create。這項功能只支援 GPT-6 系列模型,傳輸要用 WebSocket 連到 Responses API;GPT-5.6 與更早的模型不支援。收到 response.created 之後,在同一條連線送 response.steer,帶上該回應的 ID 當 previous_response_id,欄位只接受 type、previous_response_id 與 input。伺服器回 response.steer.accepted,意思是「已排隊」,還沒有生效。原回應如果被插話打斷,會以 response.incomplete 結束,incomplete_details.reason 為 "steered";如果它先完成,就保持完成狀態。

    圖 2 response.steer 的事件順序。依據:OpenAI〈Mid-turn steering〉,查閱於 2026-10-23。

    Anthropic:API 只管格式,排隊交給應用程式。 在本篇查閱的 Messages API 文件裡,沒有看到專門用來插話的事件。文件給的正確範例,是 user 訊息先放 tool_result,後面接一段文字,內容是「What should I do next?」。把排隊做進產品的是 Claude Code,它的文件〈How Claude Code works〉寫:

    "If Claude is running tool calls, it reads the message as soon as those calls finish, within the same turn, and adjusts before its next step." (Anthropic, How Claude Code works, 查閱於 2026-10-23)

    要在自己的程式裡做,Claude Agent SDK 的串流輸入模式(streaming input mode)提供「排隊訊息:依序處理,可中斷」。文件同時寫明,單則輸入模式不支援動態排隊與即時中斷。

    Pydantic AI:框架內建佇列。 這個功能在 v1.101.0(2026-05-21)加入,release notes 寫「Add pending message queue (ctx.enqueue / agent_run.enqueue)」。依官方文件,有三個入口:工具或 capability hook 裡的 RunContext.enqueue、驅動 agent.iter() 的外部程式用的 AgentRun.enqueue,以及即時(realtime)session 的 RealtimeSession.enqueue。簽名是 enqueue(*content, priority='asap'),回傳一個 enqueue_id;送達時事件串流會吐出帶著同一個 ID 的 EnqueuedMessagesEvent,客戶端因此看得到插話何時生效。文件把 'asap' 稱作其他框架常說的 steering。

    從工具裡 enqueue 的內容,會放進包含該次工具結果的模型請求;兩者在 Pydantic AI 中分別稱為 ToolReturnPart(工具結果)與 ModelRequest(送給模型的一次請求)。平行呼叫時,文件有兩句看似不同的話:一句說每個呼叫的內容跟在自己的結果後面,另一句說整個請求裡所有工具結果都排在排隊內容之前。兩句合起來讀,是同一個 ModelRequest 內先排完所有工具結果,再依各呼叫 enqueue 的先後排隊內容。文件的原句是:

    "The model still gets all of a request's tool results ahead of the enqueued content, as providers require." (Pydantic AI 文件, Messages and chat history, 查閱於 2026-10-23)

    執行中的工具會被取消嗎?

    OpenAI 的 steering 不會取消,Claude Code 的 Enter 也不會,三家各有另一個專門的中斷入口:Codex 的 interrupt、Claude Code 的 Esc、Pydantic AI 的 AgentRun.cancel()。

    OpenAI 的 steering 文件寫明:已經送出的輸出不會被改寫,做過的動作不會被撤銷,已經開始的工具不會被取消。Codex CLI 是 OpenAI 自己的 coding agent,情況不同。0.159.0 的 release notes 寫,選用的 instant_interrupt 開關讓新輸入在模型回應中,或長時間執行的 code-mode 呼叫中,轉向 Codex。Code Mode 的執行區塊稱為 cell,裡面還會呼叫其他工具。0.163.0 把這個開關改成預設,並多了一句:

    "Interrupting a turn also stops active Code Mode cells and their nested tool calls." (OpenAI, Codex CLI 0.163.0 release notes, 2026-10-15)

    也就是說,Codex 的「中斷」會停掉正在跑的 Code Mode cell 與其中的工具呼叫,這和 Responses API 文件「不取消已開始的工具」的描述不同。兩者的對應關係,release notes 沒有說明;0.159.0 的變更清單裡有一項標題為「Preserve WebSocket continuations when steering a turn」,但內容未說明。

    Claude Code 的互動模式文件(Interactive mode)把三個動作的差別列得很清楚:

    項目行為補充

    Enter
    行為
    排隊,不中斷該輪;工具結束後讀到
    補充
    該輪結束仍在排隊的訊息依序自動送出
    Esc
    行為
    取消執行中的工具呼叫
    補充
    已完成的工作保留,排隊訊息接著送出
    Ctrl+Enter(v2.1.275 起)
    行為
    立刻送出排隊訊息
    補充
    v2.1.281 起能背景化者轉背景,其餘中斷

    表 1 Claude Code 在執行中輸入訊息的三個動作。來源:Anthropic〈Interactive mode〉,查閱於 2026-10-23。

    Ctrl+Enter 的細節要看版本:v2.1.275 起提供這個按鍵,但分流行為從 v2.1.281 才有。v2.1.281 起,能移到背景的工作(shell 指令、子代理)移到背景繼續跑,Claude 在同一輪讀到訊息;只在寫回應,或在跑不能移到背景的工作時,則中斷該輪。依文件,v2.1.281 之前,這個按鍵在兩種情況下都中斷該輪,也就是更早版本一律中斷。

    Pydantic AI 的文件未說明 enqueue 對執行中的工具有什麼影響,只把 'when_idle' 描述為不想打斷 Agent 時用;AgentRun.cancel() 是另一個動作,會取消執行中的工具 task。

    送達優先序、上限與斷線怎麼處理?

    三家都有各自的限制:OpenAI 限制排隊狀態只存在連線上,Anthropic 的 maxTurns 會讓排隊訊息另開一輪,Pydantic AI 有 asap 與 when_idle 兩種優先序,並建議設 UsageLimits。

    OpenAI:失敗碼、等待中的插話與斷線。

    • 如果回應正在等用戶端的工具結果或核准,插話會留在佇列,伺服器送 response.steer.pending,列出缺哪些輸入;要先用 response.create 把結果送回,不必重送插話。
    • 失敗時是 response.steer.failed,常見代碼有 invalid_input、steering_not_supported、response_not_found、too_many_pending_steers。
    • 排隊中的插話只存在目前這條連線,沒有跟回應一起儲存;文件要求呼叫端自己記錄送過的插話,斷線後不能假設它還在。

    Anthropic:伺服器端工具與 maxTurns。 Handle tool calls 文件有一條針對伺服器端工具的例外:如果上一輪助理還呼叫了一個尚未回結果的伺服器端工具,這則 user 訊息只能放 tool_result;文字接在後面會讓回合提早結束,直接呼叫的伺服器工具則會得到 400 錯誤。agent loop 文件還補了一個細節:串流輸入時,如果一則訊息在該輪因達到 maxTurns 而結束時還在排隊,它不會被塞進該輪最後一次模型呼叫;Claude Code 會為它另開一輪,輪數重新計算。

    Pydantic AI:兩種優先序與兩個限制。 優先序的定義來自 API 參考:

    項目送達時機補充

    'asap'(預設)
    送達時機
    下一次模型請求
    補充
    本來要結束時改為多跑一次請求
    'when_idle'
    送達時機
    只在 Agent 本來要結束時
    補充
    排在 asap 之後,不打斷進行中工作

    表 2 enqueue 的兩種優先序。來源:Pydantic AI〈Agent run API reference〉,查閱於 2026-10-23。

    文件列了兩個限制。run(Agent 從開始到結束的一次完整執行)結束後再呼叫 enqueue 會丟出 UserError,因為沒有地方可送。如果每一步都有東西在 enqueue,每次「本來要結束」的轉向都會再開一次模型請求,run 會一直跑下去,文件建議在 run 上設 UsageLimits 當保險。使用 Temporal 執行 Agent 時,工具內的 ctx.enqueue 無法把插話傳回這次 run。工具是在 activity(工作步驟)中執行,必須改從 workflow(流程控制)端呼叫 AgentRun.enqueue。

    三家放在同一張表,差在哪裡?

    三家的差別在誰排隊、執行中的工具會不會被取消、有沒有分優先序,共通點是插話都排在待處理的工具結果之後。

    項目可注入時機限制用途

    OpenAI Responses API steering
    可注入時機
    回應進行中,用 WebSocket 送 steer
    限制
    限 GPT-6 系列;不取消已開始的工具
    用途
    加需求、改方向
    OpenAI Codex CLI(0.163.0 起預設)
    可注入時機
    模型回應中或長時間 Code Mode 呼叫中
    限制
    中斷會停掉 Code Mode cell
    用途
    送出追問即轉向
    Anthropic Messages API
    可注入時機
    同一則 user 訊息,接在 tool_result 後
    限制
    不能插在 tool_use 與結果之間
    用途
    文件範例:接著問下一步
    Claude Code 排隊訊息
    可注入時機
    工具呼叫結束後讀到;該輪結束仍排隊者依序送出
    限制
    Esc 取消執行中的工具
    用途
    修正方向、補充背景資訊
    Claude Agent SDK 串流輸入
    可注入時機
    session 內排隊送出,可中斷
    限制
    單則輸入模式不支援排隊
    用途
    多輪互動、即時中斷
    Pydantic AI enqueue
    可注入時機
    asap 為下一次請求;when_idle 為本來要結束時
    限制
    run 結束後呼叫丟 UserError
    用途
    轉向,附 enqueue_id 追蹤

    表 3 三家的注入規則。來源:OpenAI〈Mid-turn steering〉與 Codex CLI release notes;Anthropic〈Handle tool calls〉〈How Claude Code works〉〈Streaming Input〉;Pydantic AI 文件與 v1.101.0 release notes,皆查閱於 2026-10-23。欄位內容是本站整理,「用途」欄未特別標示者取自文件原文的用語。

    把表 3 讀成三種規則,是本站的歸納:OpenAI 是事件式,Anthropic 是格式式,Pydantic AI 是佇列式。

    外部事件(webhook、告警)該用什麼身分注入,兩家文件的結論一致,只在位置上有分歧。Pydantic AI〈Messages and chat history〉直接點名 webhook:

    "Deliver those as data — enqueue the payload as user content, or return it from a tool — and reserve SystemPromptPart for instructions you wrote yourself." (Pydantic AI 文件, Messages and chat history, 查閱於 2026-10-23)

    Anthropic〈Handle tool calls〉則說不受信任的內容要放在 tool_result,不要放進 system 或一般 user 文字。兩邊都說當資料送、不放 system;差別是 Pydantic AI 也接受 user content,Anthropic 指定 tool_result。

    工程上的意思: 如果你在做控制 Agent 執行流程的程式,也就是駕馭層,這張表會影響你怎麼組下一次模型請求。要支援插話,組下一次模型請求時,得先檢查哪些工具呼叫還缺結果,再依各家格式把工具結果排在插話內容之前,Anthropic 規定得最明確,OpenAI 的函式呼叫文件只規定 call_id 配對,沒有規定訊息內的排列順序。我會在呼叫端留一份插話紀錄:OpenAI 文件說排隊的插話不會跟著回應保存,斷線後不能假設它還在。

    我會先做一種送達方式,也就是「下一次請求前送達」,等真的有需求再加「本來要結束時才送」。這是我的建議,沒有任何一家的文件這樣規定。理由有兩個。第一,三家的主要路徑都是「下一次請求前」(Pydantic AI 的預設是 'asap',Claude Code 的 Enter 是工具結束後讀到,OpenAI 的 steer 是排到工具結果之後)。第二,Pydantic AI 文件自己提醒,若每一步都有東西在 enqueue,run 會持續轉向,所以要設上限。這個做法的前提是:你的 Agent 每次送出模型請求前,有一個步驟能讀佇列。如果你的工具一次要跑幾十分鐘,只做這一種,使用者的插話會等很久,這時才需要像 Codex 那樣支援中斷。

    還有哪些事,現有文件沒有答案?

    下面三件事,本篇查閱的文件未給出可以直接採用的答案。

    • 插話與核准同時在等,誰先? OpenAI 文件寫明,回應正在等用戶端的工具結果或核准時,插話留在佇列,要先送結果。Claude Code 與 Pydantic AI 的文件,本篇查閱的頁面未說明插話與人工核准請求的優先序。
    • 被打斷的動作怎麼收拾? OpenAI 文件說明不撤銷已完成的動作;Codex 的中斷會停止 Code Mode cell。寫到一半的檔案或跑一半的遷移,由誰檢查,release notes 與 API 文件未說明。
    • 插話到底提高多少成功率? 本篇查閱的文件未提供對照實驗的數據,不能由文件推論「允許插話」比「重開一輪」更好。

    下一篇回答另一個問題:一輪做完之後,誰來說它做對了?

    常見問題

    中途引導和中斷有什麼不同?

    中途引導是把新指示排進下一次請求,中斷是停止目前的工作。OpenAI Responses API 的中途引導文件寫明不取消已開始的工具;Codex CLI 0.163.0 的 release notes 寫中斷會停止 Code Mode 的執行區塊(cell)及其中的工具呼叫;Claude Code 的 Esc 會取消執行中的工具呼叫並保留已完成的工作。

    Anthropic API 能在 tool_use 之後直接插一則 user 訊息嗎?

    不能插在工具呼叫(tool_use)與結果(tool_result)之間,文件規定中間不能有其他訊息。一般情況可把插話文字放在同一則 user 訊息內,接在所有工具結果之後;若上一輪還有尚未回傳結果的伺服器端工具,這則訊息只能放 tool_result。若把其他訊息插在工具呼叫與結果之間,文件列的常見錯誤訊息是 tool_use ids 後面沒有緊接 tool_result;伺服器端工具那種情況,依文件是回合提早結束,直接呼叫的伺服器工具則得到 400 錯誤。

    Pydantic AI 的 asap 和 when_idle 該選哪個?

    文件給了各自的用途:'asap' 用在新內容要盡快送到模型時,進下一次模型請求;'when_idle' 用在不想打斷 Agent、但要它做完手上工作後接著處理追加任務時,只在本來要結束時送,排在 asap 之後。照這兩條準則,修正方向用 asap,追加任務用 when_idle。我會先用預設的 asap,等真的出現追加任務的需求,再加 when_idle;這是我的判斷。

    排隊中的插話會不會因為斷線而消失?

    OpenAI 的 steering 文件說會:排隊中的插話只存在目前連線,沒有跟回應一起儲存,呼叫端要自己記錄送過的插話。Pydantic AI 的文件只提到 Agent 的一次完整執行(run)結束後,再用 enqueue 加入訊息會丟出 UserError,這條限制無法回答斷線後排隊訊息是否保留。Claude Code 的排隊訊息保存方式,本篇查閱的文件未說明。

    延伸閱讀

    參考資料

    留言0

    登入後就能留言。

    登入