跳轉到主要內容
這個單元解決什麼問題同一個模型,包在不同的執行外殼裡,行為天差地別。Harness 是 agent 的執行外殼:工具集、權限邊界、記憶、迴圈控制、觀測、kill switch。模型決定能力天花板,harness 決定你實際拿到幾成,以及它穩不穩、能不能重現、出事會不會收不住。本單元拆開 harness 的組成要素與設計判準,讓你在選用或自建 agent 系統時有一套明確的評估框架,而不是靠試錯撞出能動的配置。

學習目標

  • 用自己的話說清楚「模型」與「harness」的分界,並舉出混淆兩者時會產生的具體問題。
  • 列舉一個健全 harness 的六個組成要素,並對照現有工具或自建系統評估其完整性。
  • 設計合理的安全邊界:approval gate、sandbox 隔離、heartbeat 死人開關、kill switch,並知道各自在哪種情境下不可省略。
  • 說明為何「可重現」比「聰明」更重要,並指出讓 agent 行為可重現的最小觀測配置。

1. 什麼是 harness:模型決定天花板,harness 決定你拿到幾成

先看一個對照。同一個 Claude 模型,你可以用兩種方式驅動它:一種是自己寫一個裸迴圈,丟 prompt、收回應、把模型要的工具呼叫手動執行、結果再貼回去,沒有權限檢查、沒有步數上限、沒有任何日誌;另一種是跑 Claude Code,同一個模型,但外面包了權限規則、sandbox、hook、session 持久化、可中斷的迴圈。兩者產出的穩定度、可重現度、安全度差一個數量級。差的不是模型,是 harness Anthropic 把 agentic 系統的基礎積木描述為「一個被檢索、工具、記憶等能力增強過的 LLM」(augmented LLM)[1]。這句話點出分界:
  • 模型管的是:推理、生成、決定「下一步要呼叫哪個工具、要記住什麼、要查什麼」。
  • harness 管的是:工具實際怎麼被執行、權限邊界在哪、狀態怎麼持久化、迴圈何時停、出了異常誰來踩剎車、整個過程留不留得下軌跡。
Claude Agent SDK 文件對這個外殼的定義更直接:驅動 Claude Code 的那層執行迴圈本身就是一個 harness(the agent harness that powers Claude Code),它「gather context → take action → verify work → repeat」,而 SDK 把這個迴圈交給開發者直接掌控工具、權限、成本上限與輸出,而不是藏在抽象層後面 [2]。 最常見的混淆是把 system prompt 當成 harness 的全部。System prompt 屬於 L1/L2(怎麼問、視窗裡放什麼,見 01-301-4),它能影響模型的傾向,但它管不到執行層:它擋不住一個危險的 rm -rf,不會在第 50 步無限重試時喊停,也不會在 agent 卡死時終止 process。這些是 harness 的職責。把兩者混為一談,結果就是你以為「寫好提示詞就安全了」,而真正的安全與穩定性空白被整個忽略。
一句話記住分界模型負責「想做什麼」,harness 負責「能做什麼、做到哪、出事怎麼辦」。前者你靠選模型與寫提示,後者你靠設計外殼。本單元只談後者。

2. 一個健全 harness 的六個組成要素

評估任何 agent 系統(不管是現成工具還是自建),對著這六個要素逐項檢查,缺哪個一清二楚。前四個對應 Anthropic 的 augmented LLM 與 agent loop,後兩個是把它放進生產環境必須補上的。 要素一:工具集與權限邊界。 工具的形狀直接影響模型的決策品質。Anthropic 建議把工具介面(agent-computer interface, ACI)當成人機介面(HCI)一樣慎重設計,投入同等心力:給模型足夠的 token 思考再動手、用接近自然網路文本的格式、消除容易出錯的格式負擔 [1]。形狀之外是邊界:每個工具能碰到的檔案、網域、指令範圍,決定了出錯時的爆炸半徑(blast radius)。最小權限原則在 agent 場景比傳統系統更關鍵,因為決策者是一個會即興發揮的模型,不是行為固定可預期的程式。 要素二:記憶與狀態。 分三層,各有適用場景與污染風險:
  • 短期(對話上下文):session 內的對話歷史。Claude Agent SDK 明確指出 context window 在 session 內只增不減,system prompt、工具定義、對話、工具輸入輸出全部累積 [2],這正是 01-4 講的 context rot 來源。
  • 工作記憶(session 內的結構化狀態):把中間結果存成 key-value 或摘要,而不是讓它漂在對話裡被稀釋。
  • 長期(跨 session 持久化)CLAUDE.md、記憶檔這類跨 session 載入的內容(見 04-1)。風險最高的也是這層,因為被污染的記憶會在未來的 session 安靜地重新組裝。
要素三:迴圈與終止條件。 Agent 迴圈(gather context → take action → verify → repeat)若沒有明確出口,輕則燒 token,重則失控。Anthropic 直接點明:執行時 agent 要在每一步從環境取得 ground truth(工具呼叫結果、程式執行結果)來評估進度,並要有內建的 stopping conditions(例如迭代次數上限)來「maintain control」[1]。三個出口缺一不可:明確的成功判定、最大步數上限、異常跳出路徑。 要素四:觀測與日誌。 沒有觀測,除錯等於翻盲盒。每次工具呼叫至少要留:timestamp、工具名、輸入摘要、碰到的檔案、approval 狀態(放行或攔下)、token 估算。這是要素六(可重現)的前提,第 4 節展開。 要素五:安全邊界。 approval gate、sandbox 隔離、kill switch。這是把 agent 從「我自己跑跑看」推到「無人值守也敢開」的關鍵差距,第 3 節展開。 要素六:可重現。 能不能在事後重建「它上次到底做了什麼」。包含 session 的可回放(至少保留 tool call 序列)與可續跑(Claude Agent SDK 用 session_id resume,恢復讀過的檔案、做過的分析與動作 [2])。第 4 節展開。
對照你手邊的工具做一次盤點拿 Claude Code 當例子套這六項:工具集與權限(settings.jsonpermissions)、記憶(session 上下文 + CLAUDE.md + 記憶檔)、迴圈終止(任務完成判定 + 你隨時可中斷)、觀測(transcript + hook 日誌)、安全邊界(permissions + sandbox + hook gate)、可重現(session resume)。六項都有對應,這就是它比裸 API 迴圈穩的原因。換成你自建的 agent,逐項問「這個我有嗎」,第一個答不出來的,就是它最先會出問題的地方。

3. 安全邊界:approval gate、sandbox、heartbeat、kill switch

這四樣是 harness 設計最容易被偷懶跳過的部分,因為跳過它們時系統「看起來也能跑」。問題在出事那一刻才暴露,而那時通常已經來不及。 Approval gate(審批閘門)。 哪些動作自動放行、哪些必須人工確認。判準只有一條:這個動作造成的傷害可逆嗎? 讀檔案、跑測試這類可逆動作可以放行;刪檔、git push、網路 egress、寫入 repo 以外的路徑這類不可逆或外部可見的動作,應該攔下確認。Claude Code 的 permissions 把規則分三類 allow / ask / deny,評估順序是 deny → ask → allow,第一條命中的規則勝出,所以 deny 永遠優先(截至 2026-05)[3]。
{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(~/.ssh/**)",
      "Bash(curl:*)"
    ],
    "ask": [
      "Bash(git push:*)",
      "Write(~/**)"
    ]
  }
}
審批邊界設太寬或太窄都是錯太寬(什麼都自動放行,或直接 --dangerously-skip-permissions)等於沒有安全邊界,在無人值守或處理外部內容時尤其危險。太窄(每一步都要你確認)讓 agent 喪失自主性的意義,你不如自己做。對著「可逆性」這條判準分流,而不是憑感覺一律放行或一律攔。
Sandbox 隔離。 不信任的工作(外部 repo、附件處理、大量網路爬取)應在容器或 devcontainer 內跑,網路出口預設封閉。要注意 sandbox 與 permissions 是互補的兩層,不是二選一:permissions 控制「哪些工具、哪些檔案與網域可碰」,作用於所有工具;sandbox 是 OS 層級的強制隔離,限制 Bash 指令及其子 process 的檔案系統與網路存取(截至 2026-05)[3]。Anthropic 對 agent 上生產線的建議是「在 sandbox 環境充分測試,搭配適當的 guardrails」,因為 agent 成本更高、錯誤會複合放大 [1]。一行起手的最小隔離:
# 一次性審查不信任的 repo:無網路、不掛載家目錄
docker run -it --rm -v "$(pwd)":/workspace -w /workspace --network=none node:20 bash
Heartbeat(死人開關)與 kill switch。 無人值守的長迴圈需要心跳機制:agent 每隔一段時間寫一次心跳,supervisor 超時沒收到就終止。關鍵設計是不要依賴被監看的 process 自己回報停止(它可能正是卡死的那個),由外部 supervisor 判定並動手。終止時要送訊號給整個 process group,不是只殺父 process,否則子 process 會變孤兒繼續跑。下面這個最小 supervisor 同時示範了 heartbeat 與 process group kill:
#!/usr/bin/env bash
# supervisor.sh:監看 agent 心跳,逾時則終止整個 process group
HEARTBEAT_FILE="/tmp/agent.heartbeat"
TIMEOUT=90            # 逾 90 秒無心跳視為卡死
CHECK_INTERVAL=30

setsid ./run_agent.sh &     # setsid 讓 agent 自成一個 process group
AGENT_PGID=$!

while kill -0 "$AGENT_PGID" 2>/dev/null; do
    sleep "$CHECK_INTERVAL"
    last=$(stat -c %Y "$HEARTBEAT_FILE" 2>/dev/null || echo 0)
    now=$(date +%s)
    if (( now - last > TIMEOUT )); then
        echo "[supervisor] 心跳逾時,終止 process group $AGENT_PGID" >&2
        kill -TERM -"$AGENT_PGID"   # PGID 前的負號:對整個 group 送訊號
        exit 1
    fi
done
agent 端只需在迴圈每一步寫一次心跳(date +%s > /tmp/agent.heartbeat)。這套機制的價值不在平常,在它真的卡死的那一次。
此處只給設計判準,威脅模型留給 03-3本節談的是 harness 該有哪些安全機制與設計取捨。具體的攻擊面分析(prompt injection、供應鏈、記憶污染、相關 CVE)屬於威脅模型範疇,集中在 03-3 展開,這裡不重複。

4. 觀測與可重現:為什麼「可重現」比「聰明」更值得追

一個能偶爾給出驚艷結果但每次都不一樣的 agent,工程價值低於一個穩定產出 80 分的 agent。理由很實際:無法重現的行為無法改進,也無法向利害關係人舉證。「它上次就是這樣做的」不是工程答案,是運氣報告。 讓行為可重現,需要兩件事:
  • 觀測(事後能看見發生了什麼)。 最小配置就是第 2 節要素四那組結構化日誌欄位。重點是用 structured log(JSON 一行一筆)而不是完整 transcript,前者便宜、可查詢、夠用,後者貴且難搜。觀測還有一個被低估的用途:異常模式辨識。被劫持或失控的執行,通常在 tool call trace 上先出現異常訊號(突然讀一堆 .env、對外連不該連的網域),早於你人肉察覺。
  • 可回放與可續跑(事後能重建狀態)。 Claude Agent SDK 的 session 機制讓你抓住 session_id 後可以 resume,恢復先前讀過的檔案、做過的分析與採取的動作 [2]。至少要保留 tool call 序列,不需要完整 token 流。
一行 tool call 日誌長這樣 一個 agent 跑完,這種日誌一行一筆累積起來,就是它的完整行為軌跡。出事時你不是翻幾千行對話找線索,而是 grep approval=blockedgrep .env 直接定位異常。這就是 structured log 比 transcript 值錢的地方。
{"ts":"2026-06-01T10:32:11Z","session":"a1b2","tool":"Bash",
 "input":"npm test","files":[],"approval":"approved","tokens":420}

5. 成熟的 harness 長什麼樣:從「能跑」到「設計良善」

「能跑起來」和「設計良善的 harness」之間的差距,攤成一張對照表最清楚:
面向能跑起來(勉強動)設計良善的 harness
權限全開,或 --dangerously-skip-permissionsdeny 高危動作、ask 不可逆動作、其餘 allow
隔離直接在主機與個人帳號上跑不信任工作進 sandbox / 容器,網路預設封閉
迴圈無步數上限,靠人盯著喊停明確成功條件 + 最大步數 + 逾時退出
記憶全塞進對話視窗短期 / 工作 / 長期分層,跨 session 持久化
觀測出事翻聊天記錄每次 tool call 結構化日誌,可回放
急停關掉終端機視窗kill process group + 審計紀錄 + heartbeat
兩個具體的參照點放在 Part V,建議讀完本單元後對照看,把抽象判準對到真實程式碼(兩單元目前為骨架,尚在展開中):
  • OpenClaw:看它的工具集設計與 approval gate 怎麼實作,對應本單元要素一與第 3 節。
  • Hermes-Agent:看它的記憶分層與迴圈終止條件怎麼設計,對應要素二與要素三。

6. 概念階梯定位:harness 是最外層的 L4

把工程四層由淺至深排好(見 01-301-401-5),harness 是最外面那層:
L1 Prompt engineering   ── 單次請求怎麼寫
L2 Context engineering  ── 視窗裡該有什麼
L3 Workflow engineering ── 多步驟用什麼結構串
L4 Harness engineering  ── 讓整套穩定運轉的外殼(本單元)
L4 承載前三層的輸出,並決定它們能不能穩定落地。一個常見的失衡:把 L3 的 workflow 編排做到極致(漂亮的 DAG、對抗式驗證、收斂迴圈),卻不在 L4 設 kill switch 與權限邊界,等於裝了賽車引擎卻沒裝剎車。反過來,harness 再完整也救不回爛 prompt 與爛 context,L4 放大前三層的設計品質,不替它們補課。
四層一起看才完整遇到「agent 表現不穩」的問題,先定位是哪一層:產出品質飄(多半是 L1/L2)、多步流程結果不一致(L3)、會做出危險或收不住的動作(L4)。把問題歸對層,才不會在 prompt 上反覆調整,根本原因卻在 harness 沒兜底。

工具對照

把 harness 各要素對到主流 agent 系統,你會發現概念一致、名稱不同(截至 2026-05,精確機制與設定路徑以各官方文件為準):
要素Anthropic Claude(主範本)OpenAIGoogle自建(裸 SDK / 框架)
工具集與 ACIClaude Code 工具 + MCP;Agent SDK 自訂工具 [2]Agents SDK function toolsGemini API function calling自訂 function schema
權限 / approval gatesettings.jsonpermissions(deny→ask→allow)[3]Agents SDK guardrails / tool_use 審批需確認原始出處自行實作審批層
迴圈終止任務完成判定;Stop hook 收斂哨兵Agents SDK max_turns 上限需確認原始出處自行設步數 / 逾時上限
記憶與狀態session 上下文 + CLAUDE.md + 記憶檔Agents SDK sessions需確認原始出處自管 state store
觀測transcript + hook 日誌Agents SDK tracing需確認原始出處自接 logging / OpenTelemetry
sandbox / 隔離OS 層 sandbox(限 Bash 子 process)[3]需確認原始出處需確認原始出處容器 / devcontainer
對照表只給座標,不給細節各 cell 的精確名稱、版本與設定路徑屬快變動事實,無法確認者標「需確認原始出處」,以各官方文件為準。本表末欄以「自建」取代慣用對照欄的 GitHub Copilot 與 Cursor,因為這兩者目前不提供對等的可程式化 agent harness 層;harness engineering 的對照點本來就是「現成工具」對「自己搭」。本表用途是讓你知道「同一個 harness 要素在你的工具叫什麼」,深入設定見 Part II 與 Part IV。

動手做

兩個練習,一個盤點、一個動手補上最常缺的那塊。
  1. 對六要素審核你現有的 agent 設定。 拿你正在用的系統(Claude Code 的 .claude/settings.json、或你自建的 agent),對著第 2 節六要素逐項打勾:工具集與權限、記憶與狀態、迴圈終止、觀測、安全邊界、可重現。第一個打不了勾的,寫下「它在什麼場景會第一個出問題」。多數人會發現缺的是觀測或 kill switch,因為平常不需要,需要時已經晚了。
  2. 為一個無人值守迴圈補上 heartbeat。 拿第 3 節的 supervisor.sh 當骨架,改成監看你自己的 agent:決定合理的 TIMEOUT(略大於單步最慢的正常耗時)、在 agent 迴圈每步加一行寫心跳、用 setsid 讓它自成 process group。驗證方式:故意讓 agent 卡在一個無窮迴圈,確認 supervisor 在 TIMEOUT 後真的把整個 group 收掉,而不是留下孤兒 process。

常見誤區

反模式清單
  • 把 harness 等同於 system prompt:system prompt 屬於 L1/L2,管不到執行層的權限、終止與觀測。提示詞寫得再好,也擋不住一個沒有 deny 規則的 rm
  • 審批邊界設太寬或太窄:太寬等於沒有安全邊界,太窄讓 agent 每步卡住失去意義。判準是動作的可逆性,不是憑感覺。
  • 沒有終止條件的迴圈:不設成功判定、最大步數與逾時,最常見的結果是無限重試燒 token,而不是優雅完成。
  • 沒有觀測就上線:出事才發現沒有日誌可查,只能翻對話記錄猜。structured log 要在平常就開著,不是出事後才補。
  • kill switch 只殺父 process:不送訊號給整個 process group,子 process 變孤兒繼續跑。緊急停止要能真的全部停下。
  • 依賴被監看的 process 自報停止:卡死的那個 process 沒辦法可靠地回報自己卡死了。死人開關必須由外部 supervisor 判定。

自我檢核

通過本單元的標準
  1. 你能不能用一句話講清楚「模型」與「harness」各自管什麼?混淆它們時,你踩過或看過哪個具體問題?
  2. 把第 2 節六要素套到你現在用的 agent 工具上,哪幾項是缺的?缺的那項在什麼場景會第一個出問題?
  3. 你的 approval 邊界是按「動作可逆性」分流,還是一律放行 / 一律攔?舉一個你會放行、一個你會攔下的動作。
  4. 你的無人值守迴圈有沒有 heartbeat 與 process group 等級的 kill switch?終止訊號送給的是父 process 還是整個 group?
  5. 如果現在要你重建 agent 上一次執行「到底做了什麼」,你手上的觀測資料夠不夠?不夠的話缺哪一塊?

來源與延伸閱讀

事實主張依官方文件,快變動項標註截至 2026-05;採 IEEE 編號制。
  • [1] E. Schluntz and B. Zhang, “Building Effective Agents,” Anthropic Engineering, Dec. 19, 2024.(augmented LLM 作為基礎積木 = LLM + retrieval + tools + memory;agent 每步取得 environment ground truth;stopping conditions 維持控制;ACI 應如 HCI 般慎重設計;production 需 sandboxed testing + guardrails)https://www.anthropic.com/engineering/building-effective-agents(截至 2026-05)
  • [2] Anthropic, “How the agent loop works,” Claude Agent SDK Docs.(gather context → take action → verify work → repeat;驅動 Claude Code 的 harness 可驅動其他 agent;context 在 session 內累積不重置;session_id resume 恢復完整 context)https://code.claude.com/docs/en/agent-sdk/agent-loop(截至 2026-05)
  • [3] Anthropic, “Configure permissions,” Claude Code Docs.(permissions 的 allow / ask / deny;評估順序 deny → ask → allow first-match-wins;sandbox 為 OS 層強制、只作用於 Bash 及子 process;permissions 與 sandboxing 互補的 defense-in-depth)https://code.claude.com/docs/en/permissions(截至 2026-05)
  • 銜接:01-4 記憶分層與 context rot 的成因、01-5 harness 兜底的 workflow 編排、03-3 安全邊界背後的威脅模型與攻擊面、04-1 長期記憶的設計、04-6 用 hook 實作確定性的 approval gate 與收斂哨兵、05-105-2 兩個開源 harness 的實際設計。