iT邦幫忙

3

別把 agent harness 當普通 adapter:你換掉的是整個執行語意

  • 分享至 

  • xImage
  •  

很多團隊第一次把 agent 接進產品時,會很自然地先做一層 adapter。

今天接 Claude Code,明天接 Codex,後天再接另一個 cloud agent。上層都叫 runTask(),輸入一段 prompt,最後拿回 stream、檔案修改或執行結果。看起來很乾淨。

這個想法本身沒錯。錯的是把 agent harness 當成 model provider 的親戚。

換 model provider,通常是在換推理能力、價格、latency、context window、tool calling 格式。這些都會影響產品,但邊界還算清楚。

換 harness 就麻煩多了。

你換掉的不是「誰回答問題」,而是「一段任務到底怎麼在環境裡被執行」。這句話如果沒先講清楚,後面會出事。

Provider abstraction 和 harness abstraction 是兩件事

Model provider abstraction 處理的是 model call。它的問題比較像「我要怎麼把不同模型的輸入輸出整理成同一種產品介面」。

你可能會統一這些東西:

  • messages 格式
  • system prompt
  • tool schema
  • reasoning effort
  • streaming event
  • token usage
  • retry policy

這層抽象的目標很清楚:產品不要被單一模型 API 綁死。今天換 provider,理想上大部分產品邏輯不用重寫。

Harness abstraction 處理的是另一層問題:agent 拿到任務之後,怎麼操作環境。這裡開始就不是單純的 request / response。

它關心的東西通常長這樣:

  • 可以讀哪些檔案?
  • 可以寫哪些目錄?
  • 可以呼叫哪些工具?
  • 需要使用者 approval 嗎?
  • session 能不能 resume?
  • sandbox 是誰提供的?
  • timeout 後怎麼清理?
  • partial output 算成功還是失敗?
  • telemetry 會留下哪些欄位?

這些不是包在 model call 外面的雜項。這些就是產品行為本身。

如果 abstraction 只把不同 harness 包成同一個 function signature,卻沒有定義 runtime contract,那只是把風險藏到比較漂亮的 API 後面。

Harness 擁有的東西,比你想的多

現在的 coding agent 已經不是「模型加幾個工具」。那個階段很快就過去了。

一個完整 harness 可能會管理 skills、sandbox、session、permission flow、runtime config、sub-agent、context compaction,甚至負責把工作切成多個可恢復的步驟。它也可能決定哪些檔案能被讀、哪些命令要 approval、哪些 artifact 會留下來。

所以「支援 Codex / Claude Code / Pi」不應該被理解成單純的 provider list。

假設你的產品有一個內部 automation:

input issue
  -> run agent
  -> edit repo
  -> open PR
  -> attach evidence

上層介面可以都叫 runAgent()。但底下的語意可能完全不同。

有的 harness 預設會要求互動式 permission,有的比較像 cloud automation,事前給定 tool scopes 後就自己跑。

有的 session 可以恢復,有的只留下 log。有的 sandbox 是平台承諾,有的只是你在執行環境裡自己約定。

同一個 prompt,在不同 harness 裡不一定代表同一個操作權限。這才是最容易被 adapter 掩蓋的地方。

一致 API 不等於一致安全語意

我會把這句話寫在 agent platform 的設計文件第一頁:一致 API 不等於一致安全語意。

一致 API 很有價值。它讓產品可以替換 harness、做 A/B test、按任務類型選不同 runner,也讓團隊不用在業務邏輯裡塞滿 provider-specific code。

但一致 API 也最容易製造錯覺:上層看起來一樣,底層就真的一樣。

不會。

例如 tools: ["git", "shell", "browser"] 這種設定,看起來很直覺。可是不同 harness 對這些工具的定義可能不一樣:

  • shell 是否能碰 network?
  • git push 是否需要 approval?
  • browser 是乾淨 profile,還是使用者已登入的 Chrome?
  • 檔案寫入失敗時,是丟 exception、回傳 partial result,還是寫 state note?
  • timeout 之後,背景 process 會不會被收掉?

如果這些問題沒有答案,你其實沒有 adapter。你只有一個會讓大家誤會的轉接頭,而且誤會會在事故發生時才爆開。

最小 runtime contract 要先寫

我比較建議反過來做:先寫 contract,再接 adapter。這很不性感,但它會省掉很多後面的猜謎。

不用一開始就做很重的規格書。先把最小共同契約寫清楚:

契約項目 要回答的問題
Filesystem boundary 可讀、可寫、禁止碰的路徑各是什麼?
Tool allowlist 每個工具能做什麼?哪些工具需要 approval?
Approval policy denied tool、使用者拒絕、approval timeout 時怎麼處理?
Session lifetime session 什麼時候建立、何時銷毀、能不能 resume?
Timeout / retry timeout 後是否重試?重試會不會重複副作用?
Artifact retention prompt、diff、log、screenshot、evidence 存在哪裡?
Telemetry fields 最少要留下哪些欄位才能除錯和稽核?
Cleanup behavior partial file、背景 process、dirty workspace 怎麼收尾?

這張表不漂亮,但很有用。它逼你承認一件事:agent harness 的抽象邊界不是 TypeScript interface,而是整個執行現場。

如果 adapter 寫完後,這張表還是空的,表示整合還沒完成。你只是把第一個 happy path 跑通。

用 production-agent primitives 當檢查表

現在一些 agent SDK 已經開始把 runtime 相關能力放到檯面上,例如 typed runtime context、scoped tools context、tool approvals、durable workflow、timeout、sandbox、telemetry。這些功能不該只被看成新玩具,也不用急著包裝成「最佳實踐」。

我會把它們當成一份檢查表。

你可以問:

  1. 每次 agent run 是否有明確的 runtime context,而不是散落在 prompt 裡?
  2. tool context 是否有 scope,還是所有工具共享一包全域狀態?
  3. approval 是產品流程的一部分,還是只靠 terminal 裡臨時按 y?
  4. durable workflow 是否真的能恢復,還是只是把 log 留長一點?
  5. timeout 發生時,使用者看到的是明確失敗,還是一個永遠 pending 的任務?
  6. telemetry 能不能重建「誰讓 agent 在什麼權限下做了什麼」?

這裡要小心一點:有些 harness package 和 API 還在 experimental 或 canary 階段,不適合被寫成穩定教學照抄進 production。比較務實的用法,是拿它們提醒自己哪些 runtime 問題不能省。

程式碼會變,契約問題不會。

抽象漏水的地方,要故意測

Agent harness 的整合測試,不應該只測「可以成功產生一個 PR」。

那太順了,也太危險。

我會至少補這些不太討喜、但很接近真實事故的測試:

  1. denied tool:agent 嘗試使用未授權工具時,任務要怎麼失敗?
  2. approval rejected:使用者拒絕 approval 後,是否停止並留下可理解的原因?
  3. dirty workspace:開始前或執行中出現未提交變更,agent 能不能避免覆蓋?
  4. timeout:長任務被切斷後,session、process、partial output 是否清乾淨?
  5. partial artifact:只產生一半的檔案,系統會不會誤判成功?
  6. resume:同一個 session 恢復後,會不會重複執行已完成的副作用?
  7. telemetry gap:錯誤發生後,log 是否足夠判斷是哪個工具、哪個權限、哪個 sandbox 出問題?

這些測試很無聊。可是 agent runtime 最常出事的地方,本來就不是 demo 裡那條順路。

真正的差異會出現在拒絕、卡住、中斷、重試、清理失敗的時候。你如果沒有故意測它,等於把最危險的分支交給運氣。

Cloud agent 讓治理問題更明顯

企業環境裡,這件事會更尖銳。

以前你可以說「公司開了 Copilot」或「公司禁了某個 AI 工具」。這種講法現在太粗,粗到會誤導決策。

同一個品牌底下可能有 IDE client、CLI、cloud agent、app automation、issue trigger。它們支援的 settings、tool scopes、approval 行為、資料流向不一定相同。某個設定在互動式 client 有效,不代表 cloud automation 也用同一套語意。

所以治理不是問「AI 有沒有開」。治理要問:

  • 哪個 client?
  • 哪個 runtime?
  • 哪個 trigger?
  • 哪些 tools?
  • 哪些 repository?
  • 哪些 policy key?
  • 哪些 audit events?

這聽起來像管理問題,其實是工程問題,而且是很實際的那種。

當 issue 可以觸發 agent,agent 可以改 metadata、開 PR、推 branch,ticket template、repo permission、tool scope、approval gate、telemetry pipeline 就會黏在一起。你不能只在 UI 上放一個「Enable AI」開關,然後假裝 runtime 差異不存在。

Adoption checklist

如果明天要在產品裡支援可替換的 agent harness,我會先做這幾件事:

  1. 先寫最小 runtime contract。
  2. 把每個 harness 對 contract 的支援程度列成 matrix。
  3. 明確標出不能抽象的行為,例如互動式 permission、cloud-only tool scope、session resume 限制。
  4. 對 denied tool、timeout、dirty workspace、partial output、session cleanup 做整合測試。
  5. 把 telemetry schema 固定下來,至少能追到 run id、session id、tool call、approval result、sandbox id、artifact path。
  6. 讓 adapter 回傳結構化 failure,而不是只丟一段人類可讀文字。
  7. 先跑在非 production repo,確認 cleanup 和 evidence retention 可信,再放大權限。

這些事情做完,adapter 才比較像 adapter。

不然你只是把不同 agent 都塞進同一個按鈕,然後希望它們在最糟的時候剛好表現一致。

Swappable harness 的價值,不是讓你忘記 runtime。

它真正逼你的,是把 runtime 語意寫清楚。寫清楚之後,產品才知道自己到底在替換什麼,也知道哪些東西根本不該被抽象掉。

Source notes


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言