背景任務
了解長時間執行背景操作的守護線程與通知佇列。
你將學到什麼
有些操作需要時間。執行完整測試套件可能需要 30 秒。建構 Docker 映像可能需要 2 分鐘。部署到預備環境可能需要 5 分鐘。沒有背景任務的話,Claude Code 會閒置等待,消耗上下文和你的耐心。
完成後,你將了解:
- 為什麼某些任務應該在背景執行
- 背景任務的生命週期:啟動、監控、通知
- 通知佇列如何回報完成狀態
- 何時使用前景 vs. 背景執行
- 如何在等待時持續進行有用的工作
問題是什麼
考慮這個情境:
User: "Run the full test suite, then fix any failing tests."
Without background tasks:
AI: Runs test suite...
████████░░░░░░░░░░░░ 45%
... (you wait 90 seconds) ...
████████████████████ 100%
AI: "3 tests failed. Let me fix them."
這 90 秒被浪費了。AI 本可以在讀取測試檔案、分析可能的失敗模式,或準備修復方案。相反,它阻塞在同步呼叫上,什麼都沒做。
這就是閒置等待問題。同步執行意味著 AI 一次只能做一件事,即使當前操作不需要它的關注。
如何運作
前景 vs. 背景
Claude Code 支援兩種執行模式:
Foreground (blocking):
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Start │────►│ Wait... │────►│ Result │
│ command │ │ (idle) │ │ ready │
└──────────┘ └──────────┘ └──────────┘
Time: ============================|
Background (non-blocking):
┌──────────┐ ┌──────────────────────────────┐
│ Start │────►│ Continue working... │
│ command │ │ Write code, read files, plan │
└──────────┘ │ ... │
│ ◄── Notification: "Done!" │
└──────────────────────────────────┘
Time: ====| (productive work fills the gap)
關鍵區別:在背景模式下,AI 立即取回控制權,可以在操作執行時做其他工作。
背景任務生命週期
每個背景任務遵循三個階段:
┌─────────────────────────────────────────────────────┐
│ Background Task Lifecycle │
│ │
│ Phase 1: LAUNCH │
│ ┌────────────────────────────────────────┐ │
│ │ Tool call with run_in_background=true │ │
│ │ → Process starts in daemon thread │ │
│ │ → AI receives confirmation instantly │ │
│ │ → AI continues with next action │ │
│ └────────────────────────────────────────┘ │
│ │
│ Phase 2: MONITOR │
│ ┌────────────────────────────────────────┐ │
│ │ Background process runs independently │ │
│ │ → stdout/stderr captured │ │
│ │ → Exit code tracked │ │
│ │ → No AI attention required │ │
│ └────────────────────────────────────────┘ │
│ │
│ Phase 3: NOTIFY │
│ ┌────────────────────────────────────────┐ │
│ │ Process completes (success or failure) │ │
│ │ → Result placed in notification queue │ │
│ │ → AI receives notification in next │ │
│ │ turn's context │ │
│ │ → AI can act on the result │ │
│ └────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
啟動背景任務
run_in_background 參數可在 Bash 工具中使用:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "npm test",
"description": "Run full test suite",
"run_in_background": true
}
}
當這個執行時:
- 測試套件在獨立的程序中開始執行
- AI 立即收到確認:「Background task started」
- AI 的下一個動作可以是任何事 — 它不必等待
與前景呼叫(預設)比較:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "npm test",
"description": "Run full test suite"
}
}
這會阻塞直到 npm test 完成。AI 在執行期間無法做任何其他事情。
通知佇列
當背景任務完成時,其結果會進入通知佇列。AI 在隨後的輪次中看到它:
Turn N:
AI launches background task: "npm test"
AI continues: reads files, writes code...
Turn N+1:
[System notification]
Background task completed:
Command: npm test
Exit code: 1
Output: "47 passed, 3 failed
FAIL: src/auth/login.test.ts
FAIL: src/auth/session.test.ts
FAIL: src/api/users.test.ts"
AI: "The test suite found 3 failures. Let me fix them."
通知自然地出現在對話流程中。AI 不需要輪詢或檢查 — 當背景任務完成時它會自動被通知。
什麼適合在背景執行
不是每個命令都適合放在背景。以下是決策框架:
Need the result to decide your next action?
├── YES → Foreground (blocking)
│ Examples:
│ - "cat package.json" (need to read contents now)
│ - "git status" (need to know state before committing)
│ - "ls src/" (need to know what files exist)
│
└── NO → Background (non-blocking)
Examples:
- "npm test" (can write code while tests run)
- "docker build ." (can prepare deployment config while building)
- "pnpm build" (can write documentation while building)
| 操作 | 耗時 | 背景執行? | 原因 |
|---|---|---|---|
cat file.txt | < 1s | 否 | 立即需要結果 |
git diff | < 1s | 否 | 現在就需要看到變更 |
npm test | 10-120s | 是 | 測試執行時可以繼續工作 |
docker build | 30-300s | 是 | 長時間建構,不立即需要結果 |
npm install | 5-30s | 視情況 | 取決於是否立即需要套件 |
pnpm build | 5-60s | 是 | 可以同時準備部署設定 |
eslint . | 5-30s | 是 | 可以在 linting 時繼續寫程式 |
交錯背景和前景工作
真正的威力在於將背景任務與有效的前景工作結合起來:
Timeline:
├── Launch: npm test (background)
├── Read: src/auth/login.ts (foreground, instant)
├── Read: src/auth/session.ts (foreground, instant)
├── Edit: fix suspected bug in login.ts (foreground)
├── [Notification: npm test completed, 3 failures]
├── Analyze: compare failures with the fix just made
├── Edit: fix remaining 2 test failures
└── Launch: npm test (background, verify fixes)
AI 利用測試套件的執行時間做了有用的工作:它讀取了可能出錯的檔案,並在測試結果返回之前就開始修復最明顯的問題。
關鍵洞見
背景任務讓你避免閒置等待 — AI 可以在長時間操作執行時做有用的工作。 這不僅僅是一種優化;它從根本上改變了 AI 處理複雜任務的方式。
沒有背景執行的話,每個長時間操作都會在對話中創造一個空白區。AI 啟動一個建構,閒等 60 秒什麼都不做,然後繼續。這 60 秒本可以用來閱讀文件、撰寫程式碼或規劃下一步。
洞見更深層:背景任務改變了 AI 的規劃策略。當 AI 知道它可以在背景執行測試時,它更願意提早啟動測試(以獲得快速回饋),而不是等到它認為一切都完美了才執行。這導致更迭代、更回饋驅動的工作流程 — 更接近經驗豐富的開發者實際的工作方式。
把它想像成做菜。好的廚師不會站在烤箱前面看烤肉。他們開始烤,然後切蔬菜、準備醬汁、擺餐桌。烤箱會在完成時通知他們。背景任務給了 AI 同樣的交錯操作能力。
實作範例
邊測試邊寫程式
以下是一個利用背景任務的實際工作流程:
User: "Fix the failing tests in the auth module"
AI Plan:
1. Run test suite in background to identify failures
2. While tests run, read the auth module source code
3. When test results arrive, cross-reference with source
4. Fix each failure
5. Re-run tests in background to verify
Execution:
Step 1: Launch tests in background
→ Bash(command="npm test -- --reporter json", run_in_background=true)
→ "Background task started"
Step 2: Read source files (while tests run)
→ Read("src/auth/middleware.ts")
→ Read("src/auth/routes.ts")
→ Read("src/auth/session.ts")
→ (AI now understands the auth module's structure)
Step 3: Test results arrive
→ Notification: 3 tests failed
- login.test.ts: "Expected 200, got 401"
- session.test.ts: "Token expired error"
- users.test.ts: "Missing required field"
Step 4: Fix with full context
→ AI already read the source files, can immediately
correlate failures with code
→ Edit middleware.ts: fix token validation
→ Edit routes.ts: add missing field
Step 5: Verify in background
→ Bash(command="npm test", run_in_background=true)
→ Continue documenting the changes while tests run
背景任務與逾時
長時間執行的任務可以指定逾時來防止失控的程序:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "npm run e2e-test",
"description": "Run end-to-end test suite",
"run_in_background": true,
"timeout": 300000
}
}
timeout 參數(以毫秒為單位)確保背景任務不會無限期執行。如果程序超過逾時,它會被終止,AI 收到逾時通知。
應避免的反模式
Bad: Running a quick command in background
→ Bash(command="cat README.md", run_in_background=true)
→ Overhead of notification queue isn't worth it for <1s operations
Bad: Launching many background tasks that compete for resources
→ 5 parallel "npm test" runs will slow each other down
→ Better: one background test run + foreground analysis
Bad: Launching a background task then immediately waiting for it
→ Bash(command="npm test", run_in_background=true)
→ Bash(command="sleep 30") ← defeats the purpose!
→ Instead: do useful work, let the notification come naturally
前後對比
| 僅前景執行 | 有背景任務 |
|---|---|
| AI 在長時間操作時閒置 | AI 在等待時持續有效工作 |
| 一次一個操作 | 交錯前景和背景工作 |
| 測試只在「準備好」時才執行 | 測試提早執行以獲得快速回饋 |
| 循序工作流程 | 重疊的執行階段 |
| 90 秒測試 = 90 秒什麼都不做 | 90 秒測試 = 90 秒有效寫程式 |
| 建構後部署要等兩次 | 建構在背景執行,同時準備部署設定 |
下一堂課
第 9 堂課介紹 Agent Teams 與通訊 — 多個 Claude Code 實例如何以獨立的上下文視窗協作,通過 JSONL 訊息匯流排進行通訊,處理單一代理無法應付的問題。