回合引擎:一則訊息如何走完整流程

這一頁以執行路徑為主軸,搭配設計取捨與實作驗證,讓你不只看懂流程,也能評估改動風險。

90 秒總覽

回合引擎(QueryEngine)負責把「使用者訊息」變成「可控的執行回合」。它不只送 API,還會組裝 system prompt(含條件式 memory prompt)、處理使用者輸入、記錄 permission denials、累積 usage 與持久化 transcript。你可以把它視為單回合的交通總站。

執行路徑(主骨架)

使用者提交 prompt
建立回合 context(模型、工具、權限、system prompt parts)
執行 processUserInput(可能直接結束,不進 query loop)
先寫入使用者 transcript(確保可 resume)
若 shouldQuery=true 才進入 query loop
模型輸出可能觸發 tool_use,回寫 messages 後再迭代
達到完成邊界後輸出 result(usage / permission_denials / transcript)
flowchart TD
  A[使用者輸入] --> B[submitMessage]
  B --> C[建立回合 context]
  C --> D{shouldQuery?}
  D -->|否| E[本地結果分支]
  D -->|是| F[query loop]
  F --> G{是否呼叫工具}
  G -->|是| H[tool run + result]
  H --> F
  G -->|否| I[完成訊息]
  E --> J[result]
  I --> J
  J --> K[usage/持久化/permission_denials]

路徑判讀重點

  • 真正的「完成」不是模型輸出一句話,而是收尾步驟完成。
  • QueryEngine 會把工具權限拒絕累積成 permission_denials,隨 result 一起回傳。
  • 會話持久化不是只在尾端寫入;進 query 前就會先記錄使用者訊息,避免中斷後無法 resume。
  • memory prompt 是條件式載入(需 custom system prompt + memory override)。

關鍵決策(為什麼這樣設計)

決策 1:把回合責任集中在引擎層

原因:避免工具層各自管理 usage、持久化與結束條件,導致行為分裂。

代價:引擎會變成高複雜度模組,改動需要更嚴格回歸測試。

決策 2:回合內允許多次 tool/model 循環

原因:真實任務常需要工具結果再推理,不可能單次推論結束。

代價:需要明確 completion boundary,否則容易迴圈失控。

決策 3:尾段整合系統訊息並隔離失敗

原因:QueryEngine 會在尾段整合 query 產生的系統訊息(包含 compact/stop-hooks 相關),並把結果統一輸出,避免中途污染主回合。

代價:尾段邏輯較複雜,需要清楚區分主回覆完成與附加系統訊息處理。

替代方案與取捨

方案 優點 缺點 為何未採用/何時可採用
把執行拆成多個小協調器 單檔更乾淨,責任更局部 跨協調器狀態傳遞成本高 目前回合資料耦合高,拆分前要先穩定介面
工具層自行處理錯誤與持久化 工具可獨立優化 行為不一致,除錯困難 除非有嚴格 shared contract,否則風險過高
每次模型輸出都立即落盤 資料最完整 I/O 負擔高,互動延遲增加 除非改成分層緩衝,否則不適合主路徑

失敗路徑與防護

Failure 1:prompt 過長造成回合中斷

症狀:模型拒絕處理或輸出錯誤事件。

防護:在回合層做可恢復錯誤分流,避免直接崩潰 UI。

Failure 2:權限拒絕被誤判為系統卡住

症狀:工具被拒絕後沒有正確回顯,使用者誤以為回合無回應。

防護:明確呈現 permission_denials 與拒絕原因,將拒絕視為可觀測結果而非靜默失敗。

Failure 3:回合尾端 hook 失敗污染主流程

症狀:主回覆完成但後續狀態錯亂。

防護:hook 走非阻塞與錯誤隔離,僅回報失敗摘要不破壞主回合。

實作驗證(你改完要怎麼確認)

  • 送出一個不需工具的 prompt:確認回合正常完成並持久化。
  • 送出會觸發工具的 prompt:確認 loop 可正確往返並收斂。
  • 製造可恢復錯誤(例如限制條件):確認引擎能回報而非直接崩潰。
  • 檢查 stop hook 副作用:確認主回覆完成後,附加功能才執行。

這四步對應「主路徑、工具路徑、錯誤路徑、尾端路徑」,是最低可接受驗證集。

← 上一頁 下一頁:服務與 MCP →