前一天我們把 Agent Task 變成一個真正有 State 的系統。
下一個問題自然是:
如果任務要跑 20 分鐘,誰來執行?
很多 Demo 會直接在 Request Handler 裡呼叫 Agent:
HTTP Request
↓
Agent Loop
↓
Tool Calls
↓
完成
↓
HTTP Response
如果 Agent 只跑 5 秒,沒問題。
但任務一旦變長,這種設計會遇到:
所以 Long-running Agent 需要 Background Execution。
第一個錯誤等號是:
開一個 Background Thread,就有 Background Execution。
Thread 只把工作移出目前 Call Stack。
它沒有解決:
真正的 Background Execution 需要一個 Durable Job Model。
可以拆成:
API
↓
Create Task
↓
Enqueue Job
↓
Background Worker
↓
Load Task State
↓
Run Agent Step
↓
Persist Checkpoint
↓
Continue / Pause / Complete
API 的責任是建立任務。
Worker 的責任是執行任務。
這樣 Client 不需要保持 Connection。
Queue 不只是「排隊」。
它負責建立 Producer 和 Worker 之間的邊界。
Producer 可以快速接受任務。
Worker 可以根據能力與資源慢慢處理。
Queue 也可以支援:
對 Agent 特別重要,因為不同 Task 的成本差異很大。
長任務最好切成可 Checkpoint 的 Step。
例如:
Load Task
↓
Run one agent turn
↓
Persist
↓
Decide next state
↓
Re-enqueue if needed
這樣 Worker Crash 時,只損失一小段工作。
如果一個 Worker 連續跑 40 分鐘都不存狀態,那仍然不是真正 Durable。
如果多個 Worker 同時看到同一個 Task,誰可以執行?
需要 Lease 或 Lock。
例如:
worker_A
取得 task_123 lease
有效 60 秒
只要 Lease 有效,其他 Worker 不應該同時執行。
Worker 需要定期 Heartbeat。
如果 Worker 掛掉,Lease Expire,其他 Worker 才能接手。
這避免同一個 Agent Task 被重複跑兩次。
很多 Queue 只能保證:
Job 至少會送達一次。
不一定只送一次。
因此 Worker 必須假設:
同一個 Job 可能被執行兩次。
這又回到 Idempotency。
例如:
不要期待 Queue 幫你提供 Exactly-once Side Effect。
如果一瞬間進來 10,000 個 Agent Task,系統不應該全部同時跑。
因為每個 Task 可能會消耗:
Queue 可以配合:
建立 Backpressure。
這是一個很重要的 Production Control。
不是所有 Task 都一樣重要。
例如:
P0
Production Incident
P1
Interactive User Request
P2
Batch Analysis
P3
Nightly Cleanup
如果 Background Queue 完全 FIFO,一個大 Batch 可能把 Interactive Request 卡住。
所以 Priority 應該是 Task Metadata。
答案通常是兩層。
處理 Worker 層級失敗:
處理任務語意失敗:
不要把所有 Agent Failure 都交給 Queue 重送。
否則一個 Permission Denied Task 可能被重新執行十次。
Task 在 Background 完成後,使用者怎麼知道?
常見方式:
重要的是:
Execution 和 Delivery 應該分離。
Worker 完成 Task,不代表一定要當場把結果送給 Client。
Long-running Agent 最糟糕的體驗之一是:
Running...
然後 20 分鐘沒有任何訊息。
Task 可以保存 Progress:
Step 3/7
正在驗證修正
Completed:
- 找到 root cause
- 修改 payment timeout handling
Current:
- running integration tests
Progress 不一定要由模型自由生成。
可以從 Task State、Tool Calls、Plan Step 結構化產生。
Subagent 不一定等於 Background。
一個 Child 可以同步執行。
也可以被放到 Queue。
如果 Child Task 很重,放到 Background Worker 有幾個好處:
這時 Parent 等的是 Child Task State,而不是一個 Function Return。
Parent Task 被 Cancel 時,需要決定:
Cancellation 應該明確定義 Scope。
如果同一個 Job 因 Infrastructure 問題重試多次仍失敗,可以進 Dead Letter Queue。
這表示:
系統無法自動恢復,需要人工檢查。
Dead Letter 不應該偷偷消失。
它應該有:
Process 一掛全部消失。
Crash 後整段重跑。
造成重複 Side Effect。
同一 Task 被多 Worker 執行。
語意錯誤被無腦重送。
流量一來把 Model/API 全部打爆。
至少加入:
這樣 Agent 才真正能離開同步 Request。
Background Execution 的核心不是「把程式丟到背景跑」。
而是:
讓 Task 可以離開原本 Request,仍然被可靠執行、暫停、重試、取消與恢復。
下一篇會談 Scheduling:
Background Task 是現在執行,那如果是明天早上、每週一、或條件成立時才執行呢?
完整系列與程式碼範例收錄於 https://github.com/hardness1020/awesome-agent-architecture