iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0

開場故事

很多人第一次看 AI Agent 的流程時,都會不自覺把它想成一條線。

收到任務
-> 做事
-> 完成
-> 回覆

看起來很乾淨,也很合理。
問題是,真實世界幾乎沒有這麼乖。

任務一進來,常常馬上變成:

  • 先判斷要不要接
  • 接了之後要不要拆
  • 拆出去後要不要等
  • 等回來之後要不要再補查
  • 補查完還要不要重試
  • 做到一半 session 可能 reset
  • 工具結果太多還會先被壓縮

所以第 14 天我想講的是:

流程不是直線,OpenClaw 的工作流思維是怎麼形成的?

這一篇我想把它寫成一個很工程的結論:
OpenClaw 不是用「一個長流程」理解任務,而是用「一組會流動、會分岔、會回收的工作流節點」去理解任務。

今天要解的問題

  • 為什麼 OpenClaw 不把任務看成單一路徑?
  • lanequeue 在工作流裡扮演什麼角色?
  • 為什麼背景任務、子代理、cron、reset 都會影響流程?
  • session reset 為什麼不是瑕疵,而是 workflow 的一部分?
  • pruning、compaction 為什麼會改變流程的形狀?
  • 為什麼說 OpenClaw 不是聊天機器人,而是工作流引擎?

架構總覽

如果把 OpenClaw 的工作方式畫成圖,它不是單線,而比較像一張網。

網的節點包括:

  • 主代理的當前 turn
  • 子代理的 background run
  • session queue 的排隊
  • lane 的序列化處理
  • reset 的切換
  • pruning 的上下文縮減
  • compaction 的歷史摘要
  • announce / handoff / fallback 的完成回流

這些不是附帶功能,而是同一條工作流的不同切面。

OpenClaw 的核心思路很像這樣:

  1. 有事先排進可執行的序列
  2. 需要並行的就拆出去
  3. 需要等待的就轉成事件
  4. 需要續接的就靠 session 或 transcript 接上
  5. 需要縮上下文的就做 pruning 或 compaction
  6. 需要切換狀態的就 reset

所以你如果只盯著「這一輪回答了什麼」,很容易看不懂 OpenClaw。
你得把它看成一個持續流動的系統。

原始碼節錄

先看 lane 的概念。這裡很直接,工作進入序列化 lane 的時候,系統會打診斷事件。

📄 原始碼:src/logging/diagnostic-runtime.ts:35-51

function logLaneEnqueue(lane, queueSize) {
	if (!areDiagnosticsEnabledForProcess()) return;
	diag.debug(`lane enqueue: lane=${lane} queueSize=${queueSize}`);
	emitInternalDiagnosticEvent({
		type: "queue.lane.enqueue",
		lane,
		queueSize
	});
	markDiagnosticActivity();
}

function logLaneDequeue(lane, waitMs, queueSize) {
	if (!areDiagnosticsEnabledForProcess()) return;
	diag.debug(`lane dequeue: lane=${lane} waitMs=${waitMs} queueSize=${queueSize}`);
	emitInternalDiagnosticEvent({
		type: "queue.lane.dequeue",
		lane,
		queueSize,
		waitMs
	});
	markDiagnosticActivity();
}

這段看起來像純 logging,但它透露的訊息很重要:

  • 工作不是隨便衝進去做
  • 它先進 queue,再進 lane
  • 進 lane 之後才是序列化執行
  • 出 lane 時還會記錄等待時間

換句話說,OpenClaw 不把流程看成「直接處理」,而是看成「先排隊,再流動」。

再看 session reset。

📄 原始碼:src/gateway/session-lifecycle-state.ts(本機版本行號已變動,僅標到檔案)

function isStaleLifecycleEventForSession(params) {
	return Boolean(params.owningSessionId && params.currentSessionId && params.owningSessionId !== params.currentSessionId);
}

這句很短,但意思很清楚:

  • 如果 session 已經換了 sessionId
  • 舊 lifecycle event 就不該再改新 session row

這代表 reset 不是旁支,而是工作流切斷與換檔的正式機制。

接著看 session management 文件怎麼說 reset。

📄 文件:docs/concepts/session.md:69-69

Sessions are reused until they expire under `session.reset`:

- **Daily reset** - new session at a configured local hour
- **Idle reset** - new session after inactivity
- **Manual reset** - type `/new` or `/reset` in chat

Heartbeat, cron, exec, and other system-event turns may write session metadata, but those writes do not extend daily or idle reset freshness.

這裡的重點不是「會 reset」,而是:

  • workflow 的連續性不是靠 metadata update 撐住的
  • 真的有互動,才算進度有延續
  • 系統事件寫入不等於工作在前進

再看 pruning。

Session pruning trims old tool results to keep context lean and caching efficient.

Pruning is in-memory only -- it does not modify the on-disk session transcript.
| Pruning | Trims tool results |
| Compaction | Summarizes conversation |

這裡其實是在講兩個不同層次的 workflow 變形。

  • pruning 是讓當下上下文不要太胖
  • compaction 是讓歷史對話可以縮成摘要

它們不是單純優化效能,而是直接改變任務在模型眼中的形狀。

最後看子代理和收尾怎麼接回主流程。

📄 原始碼:src/agents/openclaw-tools.ts(本機版本行號已變動,僅標到檔案)

const SUBAGENT_SPAWN_ACCEPTED_NOTE = "Auto-announce is push-based. After spawning children, do NOT call sessions_list, sessions_history, exec sleep, or any polling tool. Track expected child session keys. Continue any independent work. If your final answer depends on child output, wait for runtime completion events to arrive as user messages and only answer after completion events for ALL required children arrive. If a child completion event arrives AFTER your final answer, reply ONLY with NO_REPLY.";

這一段其實就是 workflow 思維的縮影:

  • 任務拆出去後,不要卡在等待
  • 能繼續做的先做
  • 完成事件會回來
  • 回來的時候再整合

所以 OpenClaw 的流程不是直線,而是「分流 + 等待 + 回流 + 再整合」。

白話拆解

1. 直線流程只適合很短的任務

如果只是「查一個值」或「回一句話」,直線流程很漂亮。

但只要任務開始包含這些元素:

  • 要查資料
  • 要驗證
  • 要分派
  • 要回收
  • 要等結果
  • 要處理 reset
  • 要處理長上下文

你就會發現直線不夠用。

因為任務不再是一個點,而是一條會彎、會岔、會回來的路。

OpenClaw 不是不想要簡單,而是它知道真實工作本來就不簡單。
所以它把簡單抽象成多個可控節點,而不是硬把現實塞回一條線。

2. lane 是「先後順序」,queue 是「等待秩序」

這兩個概念很容易混在一起。

你可以把 queue 想成門口排隊的人,lane 想成被安排進去的工作通道。

  • queue 解決的是誰先來
  • lane 解決的是進去後怎麼跑

OpenClaw 為什麼要這樣分?
因為有些工作可以先排著,有些工作一旦進 lane 之後就必須被序列化,不能亂穿插。

這就是它工作流不是直線、而是有通道的原因。

3. reset 不是中斷流程,而是流程的一部分

很多系統把 reset 當成例外。

OpenClaw 不是。

它直接把 daily reset、idle reset、manual reset 變成 session lifecycle 的正式邏輯。
也就是說,流程設計時就要承認:

  • 工作會換日
  • 工作會閒置
  • 工作會被人手動切斷

如果不把這些狀況當成 workflow 的一部分,後面就只會一直出現「怎麼突然斷了」的錯覺。

4. pruning 和 compaction 是工作流的呼吸節奏

一個長流程如果不呼吸,最後就會爆掉。

OpenClaw 的 pruning 和 compaction 就像呼吸:

  • pruning 先吐掉一部分工具垃圾
  • compaction 再把長對話收成摘要

這樣 workflow 才能繼續往前,不會被舊輸出壓死。

更重要的是,這不是在破壞流程,而是在讓流程可以活得更久。

5. 子代理讓工作流從線變成樹

前面幾天已經看到子代理不是單純的「多一個 AI」。

放到 workflow 的角度,它其實是在把一條流程變成一棵樹:

  • 主節點負責控制與整合
  • 子節點負責局部處理
  • 完成後再回到主節點收斂

這跟傳統 pipeline 最大的差別是:

  • pipeline 偏線性
  • OpenClaw 偏樹狀與事件驅動

這也是它為什麼看起來像工作流引擎,而不是單純聊天機器人。

6. 完成不是終點,回流才是終點

OpenClaw 真正關心的不是「某個工作有沒有做完」,而是:

  • 做完之後結果有沒有被送回去
  • 送回去的內容有沒有對得上 requester
  • requester 能不能在正確時間收到它

所以 workflow 的終點不是 task done,而是 task done + delivered + integrated。

這一點很像真實工作。

你把報告寫完不算完成,
主管收到、看懂、整合進最後版本,才算完成。

設計取捨

  • 好處是 OpenClaw 能處理多段式任務,而不是只適合短問答
  • 好處是 queue、lane、reset、pruning、compaction 都被納入同一套工作流語言
  • 好處是背景任務和主流程可以分工,不會互相卡死
  • 好處是長上下文可以被壓縮,系統不必一直背著全部歷史
  • 代價是理解成本高,不能再用「一問一答」的思路看它
  • 代價是很多狀態需要靠 session / transcript / task run / announce 去拼
  • 代價是除錯時如果不懂 workflow,會很容易只看到表面現象

如果換成傳統聊天程式,設計會簡單很多。
但那樣一旦進到真實工作:

  • 會卡等待
  • 會卡同步
  • 會卡重試
  • 會卡交接

OpenClaw 的選擇就是:一開始就承認流程不是直線,然後把這件事做成能力。

今天的結論

  • OpenClaw 的工作流不是單線,而是分流、等待、回流、整合的網狀結構
  • queue 管等待秩序,lane 管序列化執行
  • reset 是 workflow 的正式分岔,不是意外故障
  • pruningcompaction 讓長流程可以維持呼吸,不被上下文撐爆
  • 子代理把流程從線性變成樹狀,主代理負責最後收斂
  • 真正的完成不是做完,而是結果回來並被整合

下一步

第 15 天我想接著看一個很現實的問題:

失敗不是結束,Agent 怎麼處理錯誤?

因為工作流一旦變成網狀,失敗就不再是單點中斷,而是會沿著流程傳開。這時候系統怎麼擋、怎麼記、怎麼補,就很重要了。


上一篇
第 13 天:一個任務拆成多段,OpenClaw 怎麼收尾
系列文
30 天走進 OpenClaw:一個 AI Agent 的誕生、掙扎與進化14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言