dsh agent loop 詳解:一次對話是怎麼跑起來的

從輸入領取到 turn/end:turn 生命週期、外掛攔截點、loop 與 subagent/Agent Teams 的辨析,以及防止失控的 loop guard。

最近更新: 2026-10-03

不管你在終端機、網頁還是桌面應用程式裡用 dsh,背後驅動對話的都是同一具引擎:agent loop。它拿到你的訊息,問模型下一步要做什麼,執行模型選定的工具,再週而復始,直到這個 turn 沒有積欠的事情為止。看過模式、外掛、子代理的教學之後,如果你還想弄清楚「輸入和回答之間到底發生了什麼」,這一頁就是缺的那塊原理。

本文所有內容都以官方架構文件和公開討論串為依據,來源在內文和頁尾都附上連結;文件裡用什麼事件名稱,我們就用什麼名稱,不做逆向猜測。涉及版本的行為一律以官方 changelog 為準。

太長不看

  • ▸step 是一次模型請求加上它呼叫的工具;turn 是零個或多個 step,從領取輸入開始,到「沒有積欠」時關閉。
  • ▸agent loop 本身也是一個外掛(core/agent-loop 是預設驅動),每個階段都是事件,其他外掛都可以攔截。
  • ▸瀑布類事件(agent/pre-step、agent/request、llm/stream、tools/*)要求監聽器呼叫 next() 放行;agent/turn-stopping 可以終止一個 turn。
  • ▸subagent 和 Agent Teams 在 loop 之上而不是裡面;loop 失控幾乎都是外掛設計問題,社群已有成熟的 guard 做法。

agent loop 是什麼,不是什麼

DeepSeek Harness 建構在 Cordis 外掛框架上:服務、型別化事件、可復原的副作用都掛在同一個共享上下文裡。官方文件把話講得很明白——這個產品的每一個部分都是外掛,模型轉接器、工具註冊表、工作階段日誌,連同 agent loop 本身。core/agent-loop 是實作 Agent 介面的預設驅動,而且可以透過設定替換。

這一頁只需要記住兩個定義,都出自官方 turn flow 文件:

Turn(輪)

零個或多個 step。turn 在領取第一筆輸入之前開啟,在沒有積欠時關閉。

Step(步)

一次模型請求加上它呼叫的工具。同一場對話裡工具往返三次,就是同一個 turn 裡的三個 step。

Agent loop

重複 step 循環的驅動器:領取輸入、組裝提示詞、呼叫模型、執行工具、判斷是否還欠下一個 step。

一個 turn 的完整生命週期

官方文件直接公布 turn 的事件序列。下圖按順序走一遍:等寬標籤裡的都是文件裡的真實事件名稱,也就是你寫外掛時要監聽的名字。

  1. 1

    turn 開啟

    持久化
    turn/start

    turn/start 觸發,迴圈從 inbox 領取下一步輸入和一筆排隊訊息。注入的上下文要等下一則「喚醒訊息」才會生效。

  2. 2

    組裝提示詞與工具

    拼裝提示詞分區和工具 schema,投影執行時期上下文。模型看到的歷史來自工作階段日誌,不是某個漂浮在記憶體裡的陣列。

  3. 3

    輸入閘門

    agent/pre-step

    agent/pre-step 的監聽器可以改寫或拒絕剛領取的訊息。這是第一道瀑布:每個監聽器都必須呼叫 next() 讓鏈條繼續。

  4. ↳

    被拒絕就關閉

    turn/end

    訊息被拒絕,或首次 enter 被改寫為空,這個 turn 會以「零 step」的狀態持久化關閉。

  5. 4

    一個 step:模型請求

    step/start · llm/stream

    step/start 之後,agent/request 解析實際路由,請求從日誌推導並凍結,模型回覆經 llm/stream 串流回傳。

  6. 5

    工具管線

    持久化
    tools/pre-execute → execute → post-execute

    每次工具呼叫都走 tool/call → tools/pre-execute → tools/execute → tools/post-execute → tool/result 這條有護欄的鏈。失敗的 step 會記錄缺失的工具結果。

  7. 6

    還有下一步嗎?

    step/end

    step/end 之後迴圈做判斷:工具還欠一次請求,或新輸入到了,就領取下一個 step,迴圈繼續。

  8. 7

    停止檢查

    agent/turn-stopping

    agent/turn-stopping 是沒有 next() 的序列事件。監聽器在這裡可以讓 turn 停下來——這是官方文件寫明的 turn 攔截機制。

  9. 8

    turn 關閉

    持久化
    turn/end

    沒有積欠時 turn/end 觸發。turn/*、step/*、訊息事件和 tool/* 是持久會話事件,重啟後仍在;其餘都是活躍擴充點。

兩個細節值得記住:step 內的重試不會重新走提示詞組裝和 agent/pre-step;「模型可見即已寫入日誌」是硬規則——每次模型請求都必須能從工作階段日誌完整重建。

外掛從哪裡接入 loop

官方文件裡沒有「hook」這個詞,官方說法是事件,其中大多數是瀑布(waterfall):監聽器拿到上下文後必須呼叫 next() 放行,也可以在放行前改寫酬載。最重要的是四族,而 agent.inject() 是從 loop 外部注入模型可見上下文的官方入口:

把守輸入:agent/pre-step

改寫或拒絕迴圈剛領取的訊息,它決定這個 step 接受什麼輸入。

攔模型請求:agent/request、llm/stream

在模型呼叫串流輸出前觀察或改造它;這個階段的取消不會提交系統提示詞,也不會提交使用者訊息。

包住每個工具:tools/pre-execute、tools/execute、tools/post-execute

每次工具呼叫外圍有護欄的執行管線——審核、日誌、策略類外掛的標準落點。

終止 turn:agent/turn-stopping

序列、沒有 next()。在這裡回傳停止決策即可結束 turn——loop guard 類外掛依賴的就是這個事件。

外掛開發指南.

agent loop、subagent、Agent Teams 怎麼分

「dsh agent swarm」這類搜尋把三個不同層次混在一起。把每一層都錨定到 loop 上,就再也不會混:

agent loop

一個 agent 的引擎。本頁講的 turn、step、事件,都是單一 loop 驅動單一工作階段的故事。

Subagent(子代理)

由你的 agent 衍生的第二層 agent 實例。官方把 subagent provider 定義在同一個介面後面——「從全新的子 agent 到另一個產品裡委託的 turn」都算,每個 subagent 跑自己的 loop。

Agent Teams(實驗性)

官方可選的協作 seam:持久花名冊、任務板、信箱,疊在可續跑的 subagent 之上。它是單一 loop 之上的協調層。

「Swarm」

社群對多 agent 編排的俗稱,不是 dsh 官方功能名稱。讀到它時,看協調是臨時起意還是結構化,分別對應 subagent 和 Agent Teams。

子代理指南.

loop 失控與 loop guard

loop 的設計目標就是會結束:turn 在沒有積欠時關閉,agent/turn-stopping 的存在意義就是讓監聽器能喊停。所以失控幾乎都出在「餵給 loop 的東西」上——通常是某個外掛在不斷注入新輸入。

記錄最完整的案例是官方討論串 #4819:社群外掛 dsh-agent-loop 在模型只輸出推理、沒有可見文字時自動續跑——注入一則 notice 訊息推著迴圈往前走。但注入的訊息沒有寫 message id,冷復原時工作階段日誌驗證失敗(「session event lacks an identified message」),整個會話打不開。討論串裡得出的修復思路就是標準的 guard 做法:合成訊息走正常的 createUserMessage 通道,而且在 append 時就驗證事件形狀,而不是只靠復原時把關。

  • ▸限制圈數——每個 turn 設輪次上限,是所有 loop guard 配方的第一條不變量。
  • ▸偵測無進展——連續兩個 step 沒有任何變化,就停下來,別再續了。
  • ▸同錯熔斷——同一個錯誤出現兩次就斷路,比燒 token 的重試風暴便宜得多。
  • ▸保留明確出口——loop 永遠要有一個人類可見的退出方式。

上下文壓縮指南.

常見問題

關於 dsh agent loop 的簡短回答,細節都在上文。

dsh 的 agent loop 到底是什麼?

就是預設驅動器 core/agent-loop:把你的輸入變成模型請求和工具呼叫,一個 step 接著一個 step 循環,直到這個 turn 沒有積欠為止。

turn 和 step 有什麼差別?

step 是一次模型請求加上它呼叫的工具;turn 是零個或多個 step——領取輸入時開啟,沒有積欠時關閉。一個 turn 裡可以有很多個 step。

外掛是怎麼接入 agent loop 的?

透過事件。agent/pre-step 把守輸入,agent/request 和 llm/stream 貼著模型呼叫,三個 tools/* 事件包住每次工具執行,agent/turn-stopping 可以終止 turn。瀑布類監聽器必須呼叫 next() 放行。

agent loop、subagent、Agent Teams,我需要哪個?

單一工作階段的工作,只需要 loop。任務值得獨立上下文時派 subagent(它自帶 loop);多個 agent 要共享花名冊、任務板和信箱,才上 Agent Teams。

agent loop 會失控一直跑嗎?怎麼防止?

loop 本身在沒有積欠時會結束,但持續注入輸入的外掛能讓它一直活著。官方討論串 #4819 記錄了真實案例;標準 guard 是輪次上限、無進展偵測、同錯熔斷和明確出口。

看懂 loop 之前要先學 Cordis 嗎?

不用。turn 流程本身自洽,事件名稱和順序夠寫大多數外掛了。要替換服務(例如換掉 loop 驅動器本身)時才真正需要 Cordis。

繼續閱讀

和 loop 同層或直接使用它的指南:子代理、模式、預設與上下文壓縮。

來源與證據

頁面機制均以官方架構文件、討論串 #4819 和 v0.2.1-alpha.1 發行說明為依據;涉及版本的行為以官方 changelog 為準。Loop Guard 不變量來自社群協定。

DSH Plugins 是獨立的 DeepSeek Harness 外掛市集,與 DeepSeek 官方無關,也不代表官方背書。第三方外掛未經安全稽核,安裝前請審查原始碼。

每週取得最新的 DeepSeek Harness 外掛,絕不濫發。