給 Agent 開發者的 # Harness + Loop Engineering
2026/6/26
ihower @ 生成式 AI 開發者年會
![w:280](harness-qrcode.jpg)

我是誰

**張文鈿**,網路暱稱 *ihower* - 2002 年起從事 Web 軟體開發 - 2005 年 個人部落格 <https://ihower.tw> - 2018 年 自行開業「愛好資訊科技」<https://aihao.tw> - 2023 年 開始經營 **AI Engineer 電子報** - 開源貢獻: [OpenAI Agents SDK](https://github.com/openai/openai-agents-python/pulls?q=is%3Apr+author%3Aihower+) - 我的課程「大語言模型 LLM 應用開發工作坊」<https://aihao.tw/llm>
![w:320](photo3.jpg)

Agenda

1. Recap: 什麼是 Deep Agent
2. **什麼是 Harness Engineering** 🎯
3. **時機 ①: 工具執行內**
4. **時機 ②: request 之間注入**
5. **時機 ③: 單輪結束(stop hook)**
6. **時機 ④: 外層 Loop**
7. 進階: 自我改進的 Harness
8. 收尾: 會過期的 Harness
9. 番外: 自建 Agent 的框架選型
![h:430](blog-list.jpg)
📚 搭配有 9 篇的 blog 系列《給 Agent 開發者的駕馭工程》長篇文章 👉 blog.aihao.tw

👥 預期聽眾

多數談 Harness Engineering 是在講 Claude Code、Codex 來做軟體開發流程。

本場不是這個角度,而是站在「自行開發 AI Agent」的切入點。你要做的可能是 Text-to-SQL Agent、知識庫 RAG Agent,場景各式各樣,用途不一定是軟體開發。

Harness Engineering 可以適用於開發任何場景的 AI Agent

PART 1

Recap:
什麼是 Deep Agent


複習 Agent 1.0 迴圈

w:980 Agent 迴圈: Input → LLM 挑選工具 → Tools → 執行得到 Tool Result → 觀察結果回到 LLM,呼叫工具 N 次後輸出 Output

呼叫工具 N 次、每次都把結果讀回來,直到沒有工具要呼叫才輸出

Agent 2.0 (Deep Agent) 的六項能力

這些能力讓 Agent 應付更大更複雜的任務,技術上都是用到 Function Calling 來實現的

能力 做什麼
Plan & Todos 拆解大任務,依序執行
Filesystem & Bash 操作檔案、執行程式(搭配 sandbox)
Sub-Agent 把耗 token 的任務分給子代理人,隔離 context
Memory 跨 session 記得使用者與專案的長期資訊
Skills 按需動態載入的技能 prompt
更多工具 MCP、Browser、Computer Use
代表產品: Claude CodeCodexGemini CLI、LangChain Deep Agents

Deep Agent 內建能力 ①: Plan & Todos

### 🎯 它解決什麼問題 - 只靠 in-context 規劃,思路容易被中間步驟干擾、遺失 - 改用工具維護外部 todo list,**不會忘記**沒做完的事
### 🔧 技術上怎麼辦到 透過 Function Calling 提供工具: - `TaskCreate` 建立任務項目 - `TaskGet` 取得任務詳情 - `TaskUpdate` 更新任務狀態 - `TaskList` 列出所有任務

Deep Agent 內建能力 ②: Filesystem & Bash

### 🎯 它解決什麼問題 - **Filesystem** 讀寫改檔,**Bash** 執行任意 shell 指令 - 讓 Agent 真的**動手做事**:編譯、跑測試、git、裝套件
### 🔧 技術上怎麼辦到 透過 Function Calling 提供工具: - `Read`/`Edit`/`Write` 讀寫檔案 - `Bash` 執行 CLI 指令 - `Glob`/`Grep` 搜尋檔案

Deep Agent 內建能力 ③: Sub-Agent

### 🎯 它解決什麼問題 - 主 agent 派子代理去研究、查找、驗證 - 子 agent 是**獨立 context** 跑,只回精簡摘要(**context 隔離**) - 可**平行化**:多個子 agent 同時工作
### 🔧 技術上怎麼辦到 透過 Function Calling 提供工具: - 一個叫做 `Agent` 的工具 - 工具內就是**呼叫另一個 Agent** 執行,把子 agent 輸出回傳給主 agent

Deep Agent 內建能力 ④: Memory

### 🎯 它解決什麼問題 - 把**重要資訊存起來**,下次再開 agent,**它還記得** - 例:Claude Code 的 `CLAUDE.md`、Codex 的 `AGENTS.md`、長期 memory 儲存
### 🔧 技術上怎麼辦到 - Agent 一啟動就**預設載入** `AGENTS.md` - 使用者可以自己要求**更新** `AGENTS.md` - 可自行設計記憶行為:記什麼、存在哪些目錄檔案、什麼時候回憶哪些內容

Deep Agent 內建能力 ⑤: Skills

### 🎯 它解決什麼問題 - 為特定任務打包的 **prompt +工具配置+程式碼** - **不全部塞進 context**,用到才載入;寫 markdown 就能新增 - 例:翻譯 skill、寫部落格 skill、處理 PDF skill
### 🔧 技術上怎麼辦到 - 預設 system prompt 只載入 **skills 列表** - 使用者需要某個 skill 時,Agent 才用讀檔工具**載入完整 skill 內容**

Deep Agent 內建能力 ⑥: 更多工具

### 🎯 它解決什麼問題 - **MCP**: 接外部 Slack、Gmail、Notion、自建 API… - **Browser**: 瀏覽網頁、填表單、點按鈕,能上網做事或用網頁驗證自己的產出 - **Computer Use**: 直接操作桌面 GUI(看螢幕、移動滑鼠、敲鍵盤)
### 🔧 技術上怎麼辦到 - Browser 與 Computer Use 需要**多模態模型**:讓 AI 看截圖判斷下一步該點哪裡 - MCP 標準化工具協議

但有能力 ≠ 把事情做好

### ✓ 能力給了你能不能做 能讀檔、跑指令、開子代理、記憶、用工具。
### ? 但是做得對不對 · 做完了沒 這一步的產出對嗎?整個任務做完了沒?怎麼穩定地做好、做完?

PART 2

什麼是
Harness Engineering


「做完了」誰說了算?

- Agent 自信地宣稱完成,但東西是壞的 - 測試沒跑、需求沒做完,它說「已全部完成 ✅」 - 你指出問題,它道歉,然後再犯
### 這不是個案 Anthropic 整理長時間執行 agent 的失敗模式,**第一名就是「過早宣告完成」**。
參考:Anthropic Effective harnesses for long-running agents

什麼是 Harness? ➡️ Agent = Model + Harness

這是網路上常見的定義 **模型以外的一切**(system prompt、工具、編排、hooks)都算 harness。
### 小小吐槽 🤷 這定義有點偷懶 > 就像說「整體 = 核心 + 其他」 這個其他到底是什麼,我們需要**更可以操作的技術拆解**!
定義出自: The Anatomy of an Agent Harness(Viv Trivedy)

首先,harness 不只是技術功能列表

### ❌ 不是這個 Skills、Sub-Agent、Hooks、Filesystem、worktree 這些都只是**手段**,不是 Harness Engineering 的思維核心。
### ✅ 真正的主軸 是如何讓 agent 在**執行過程**能被**約束、檢查、動態修正**

回顧 Prompt、Context、Harness 三層

常被講成一條「演進」之路,但其實技術累加的都會用上,只是各自凸顯一個新的工程焦點:

  核心問題 技術功能
Prompt Engineering 怎麼讓模型這一次答得更好 system prompt、few-shot、evals
Context Engineering 在 context window 限制下選擇該放的資訊 RAG、memory、compaction、tool offload
Harness Engineering 怎麼在執行過程中約束、檢查、動態修正 skills、filesystem、hooks

並沒有「XXX 已死」這回事,後者是基於前者的發展之上,而非取而代之。


Harness 核心策略: 先 generate,再 verify

核心策略就是: 驗證 (verification),廣義的說就是 回饋(feedback)

### 常見失敗 agent 輸出答案 → agent 覺得「看起來沒問題」→ 就停了。
### 解法: generate → verify → fix 模型有自我修正的能力,但我們需要讓 Agent 順利觸發進入「輸出 → 回饋驗證 → 修正」這個流程。
那工程上怎麼確保 verify「真的會發生」?

兩個軸把 harness 拆解

Thoughtworks 用兩個軸拆解 harness 作法: 方向×型態:

  運算式 Computational(確定性、程式工具) 推論式 Inferential(LLM 生成)
前饋 Feedforward
引導器 Guides(行動前引導)
用程式工具產生的 code metadata 與約束:LSP、Codemod/ast-grep、架構規則(ArchUnit 等) system prompt、AGENTS.md、Skills、bootstrap instructions、how-to 文件
回饋 Feedback
感測器 Sensors(行動後修正)
測試、linter、type checker、靜態分析(eslint、semgrep)、pre-commit hook LLM as Judge、AI code review、Review Skills
原文是針對 coding agent 場景,但此框架被我延伸到非 coding agent 上
參考:Birgitta Böckeler(Thoughtworks)Harness engineering for coding agent users

好的 Harness 做兩件事

### 🧭 Guides 前饋 **提高「一次做對」的機率** 文件、skills、範例、架構約束。 軟性引導,做不做最後還是要看 agent
### 📡 Sensors 回饋 **輸出之後,感測提供回饋,引導 Agent 自我修正** 測試、linter、judge、AI review。 用程式自動觸發,不靠 Agent 自覺。
好的 harness 同時做兩件事: 提高「一次做對」的機率,並在出錯時能自我修正。

前饋 Guides

你的 system/developer prompt,要把「什麼是好的結果」以及「驗證流程」寫清楚。 例如 AGENTS.md/CLAUDE.md 都會要求 Agent 要去做驗證

### Claude Code > 「**非常重要**:完成任務時你**必須**執行 lint 和 typecheck(npm run lint、ruff…),確保程式碼正確。」
### Codex > 「如果 AGENTS.md 裡有可程式化的檢查,你**必須**全部執行並盡力驗證通過。即使只是改文件也一樣。」
參考:敏捷三叔公 最小可行 harnessAGENTS.md 該寫什麼

前饋的限制

前饋終究是軟性、機率性的引導

你在 AGENTS.md 寫十遍「一定要驗證」,模型還是有可能跳過 😢


回饋 Sensors: 把 verify 變成自動執行

前饋是軟性引導;回饋則用程式自動執行,不靠模型自覺

這可以插在 Agent lifecycle 的不同位置,來給 Agent 回饋。

本場將深入講解回饋的四個時機點

**① 工具執行內**(Part 3) **② request 之間注入**(Part 4)
**③ 單輪結束 · Stop hook**(Part 5) **④ 外層 Loop**(Part 6)

當然,前饋和回饋缺一不可

### 若只有回饋、沒有前饋 agent 寫 code → 測試失敗 → 改 → 再失敗,跑好幾輪還是超時。 通常不是回饋不夠,是 agent 從頭就不知道「好的執行過程跟結果」該有的樣子。
### 若只有前饋、沒有回饋 Agent 可能跳過驗證流程,可能沒有確實做好驗證。不知道做的對不對、不確定做完了沒
Agent 需要前饋一開始走對方向,也需要回饋負責把關修正。兩者缺一不可。

Harness Engineering:
讓 Agent 依目標持續、正確地動作的工程。

本場將重點講「回饋訊號」:要有東西能判斷做得好不好、做得對不對、做完了沒


回饋的四個時機點

把 agent 的迴圈由內而外拆解,回饋有四個時機點:

時機 多久觸發一次 成本 修正粒度 對應的 hook
① 工具執行內 每次 tool call 毫秒,最便宜 單一動作 Pre/PostToolUse
② request 之間注入 使用者或程式想注入時 趨近零 當前這一輪的方向 無專屬 hook
③ 單輪結束 每一輪 秒級 整輪的產出 Stop hook
④ 外層 Loop 每個 session 分鐘到小時 整個任務 排程/外迴圈

回饋的四個時機 ①②③④

④ 外層 Loop · 每個 session · 分鐘~小時 · 修正整個任務 ③ 一輪 Turn · 秒級 使用者輸入 模型 request 1 🔧 tool calls 模型 request 2 🔧 tool calls 模型 輸出答案 ② request 之間注入 (人 steer 或程式) ① 工具執行內 · 修正單一動作 Stop hook 沒過 → 同份 context 再跑一輪 一輪 (Turn) = 多次「模型 request → tool calls」反覆,直到模型輸出答案 ④ 通過後這個 session 收掉,換上全新 context 再跑一圈

PART 3 · 時機 ①

在工具執行內


Tool Call 裡面

工具呼叫內,有三個可以設計的地方:

### 執行前: 驗證輸入 確定性檢查參數與內容, 擋掉危險或無效的呼叫
### 執行後: 檢查結果 對結果做品質檢查, 必要時就地修復或重試
### 工具回傳值+夾帶指引 tool response 不只回資料,**還夾帶指示與 metadata**,引導 Agent 的下一步

工具輸出不只是 function output,
是你寫給 Agent 的回饋

寫程式習慣把回傳值當「資料」: 查到什麼回什麼,出錯就回傳 error code

但對 Agent 來說,tool response 也是一個對話訊息:
你可以在裡面夾帶指示、更多資訊 metadata,
甚至告訴 Agent 下一步怎麼做。

案例: Text-to-SQL Agent

### 場景 使用者用自然語言問財務數據, Agent 基於 DB schema 產生 SQL 用 `execute_sql(sql_query)` 工具查詢。
### LLM 生成 SQL 的風險 - **幻覺**不存在的表格和欄位 - 生成查詢以外的危險語法 - 忘記**分頁**,回傳爆量資料 - SQL dialect 語法不同
我們會在 system prompt 插入 table schema 說明有哪些 tables/columns,以及各種 SQL 限制,這是前饋要先寫好。

在工具內: 把 SQL 解析成語法樹(AST),做確定性的檢查和改寫

import sqlglot
from sqlglot import exp

tree = sqlglot.parse_one(sql_query, dialect="postgres")

# 1. 只允許 SELECT(擋下來)
if not isinstance(tree, exp.Select):
    return "只允許 SELECT 查詢"

# 2. 資料表白名單(擋下來)
for table in tree.find_all(exp.Table):
    if table.name not in ALLOWED_TABLES:
        return f"資料表 {table.name} 不在允許範圍,可用:{ALLOWED_TABLES}"

# 3. 沒 LIMIT 就補安全上限(補強)
if tree.args.get("limit") is None:
    tree = tree.limit(200)

safe_sql = tree.sql(dialect="postgres") # 確保輸出 postgres 語法

工具回饋的設計

驗證沒過時,tool response 的品質決定 Agent 自我修正的能力

### ❌ 爛 error ```text ERROR: column "revenue_growth" does not exist ``` Agent 只能瞎猜重試,越改越歪。
### ✅ 好 error ```text 欄位 revenue_growth 不存在。 financial_metrics table 可用欄位有: revenue, revenue_yoy, gross_margin… 和 revenue_growth 最相似的欄位有 revenue_yoy, revenue_qoq ``` 下一步直接被導正。
每個失敗訊息都是引導模型再次做對的好機會

連「成功」都可以回傳更多狀態資訊

### ❌ 陽春的成功 flag `{"success": true}` 或 `{"count": 0}` - 查詢成功但 0 筆,是真的沒有結果,還是查詢不正確? - 是改了幾筆,也看不出來
### ✅ 回傳更多狀態資訊 把規模與範圍寫清楚: - 影響幾筆、動了哪些欄位或區塊 - 有沒有碰到不該碰的 更多資訊,Agent 才有依據判斷「這次結果合不合理」,是否要修正
錯誤要設計,成功也要設計。一個陽春的成功 flag,也可能是「假完成」的訊號

工具回傳的引導訊息

各種純運算式(Computational)的檢查,回傳的是對應的固定訊息:

def collect_feedback(output, source):
    # 純運算式檢查:規則直接判定,不靠 LLM,沒過就回寫死的固定訊息
    msgs = []
    if count_words(output) > 500:
        msgs.append("摘要超過 500 字,請縮短")
    if missing_required_terms(output):
        msgs.append("漏掉必留的專有名詞,請補回")
    if cosine_similarity(output, source) < 0.8:
        msgs.append("與原文語意偏離,請貼近來源重寫")
    return msgs
### 運算式檢查(固定訊息) 回**事先寫死**的固定字串:又快又穩又可重現。
### 語意 judge(當場生成) 若沒辦法用純運算式的檢查,也可用 LLM 當 judge,附上回饋的 **reasoning** 理由。

設計回傳值的另一個重點: 需要有意識地控制 context window

注意控制別塞滿 context。context 過了某個門檻,模型會變笨(context rot)

別忘了 Context Engineering 的整套策略,各種縮減 context 的技術:

### Context Offloading **硬性工具輸出上限**、**頭尾保留** (切頭切尾)、**卸載到檔案** (只留預覽 + 路徑,有需要 Agent 再打開看)
### 檢索技術 關鍵字、向量檢索、reranker 等,只挑選相關的 context
### Sub-Agent 龐大的中間過程交給 sub-agent 在獨立 context 跑,只回傳結論

案例: 知識庫 RAG Agent

知識庫問答 Agent 會配一個 search_knowledge(query) 工具 (關鍵字搜尋+向量搜尋 等)

工具不只回傳搜尋結果,我們還可以回傳以下資訊,回饋給 Agent 更多資訊:

### 1️⃣ 標註來源與分數 回傳時標上來源和相關度分數,讓 Agent 有依據判斷哪些該引用、哪些該丟
### 2️⃣ 同源就 load 整頁 好幾個 chunk 都來自同一份文件 → 暗示整份相關。**可以指示 Agent 直接把整頁讀回來**,比散落片段好用
### 3️⃣ 看見 top-k 以外的資訊 回傳不只 top-k 搜尋結果,還夾帶整個資料集的統計
參考:Jason Liu Beyond Chunks: Why Context Engineering is the Future of RAG

工具回傳除了 top-k,還夾帶統計與指示

<results query="API timeout issues">
  <ticket id="LIN-1247" status="Done"></ticket>
  <ticket id="LIN-1189" status="Done"></ticket>
</results>
<facets>
  <status_facet> <value name="Done" count="6"/> <value name="Open" count="5"/> </status_facet>
</facets>
<system-instruction>
  回傳的 2 筆全是 Done。facets 顯示另有 5 筆 Open 沒進 top-k,請改用 search(query, status="Open") 追查進行中的問題。
</system-instruction>
### `` 揭露隱藏資料 告訴 Agent:符合的不只你看到這 2 筆,還有 5 筆 Open 沒進 top-k </div>
### `` 額外的指示 直接在工具輸出裡告訴 Agent 下一步該怎麼搜 </div> </div> --- ## 語意 judge: 把回饋交給另一個模型 呼叫另一個模型做 review,把回饋當 tool response 帶回來。從主迴圈看,這仍是一次普通的 tool call。 ```python @function_tool async def consult_model(question, files, model): """遇到難題、想確認方向、或要 review 產出時呼叫, 交給另一個模型給獨立回饋。""" ... ``` 例如: RAG Agent 生成答案後,用另一個模型檢查有沒有幻覺。 --- ## 案例: Claude Code + Codex plugin 這種做法在 coding agent 上也蠻常見
`/codex:review`: Claude 把本地 git 改動交給 **Codex(GPT)** 做 code review,並說明「只做 review、不准順手改」。一個寫 code、一個分析審查。
這是人工觸發,也可以寫進前饋規則,說明「在流程中何時、遇到哪類情況就呼叫」 --- ## 工具層 Harness 的設計原則
### 1️⃣ 能確定性檢查最好 例如 SQL 語法驗證用 SQLGlot,又快又穩
### 2️⃣ 語意判斷才用 LLM Judge 細緻品質好不好沒有確定性 assert 可寫, 使用 LLM judge 補規則型檢查的不足
### 3️⃣ 回饋最好可行動 錯誤訊息要附「該怎麼辦」,不是只丟一個程式 error code。
### 4️⃣ 延遲預算內完成 工具層回饋在 tool call 內發生,要注意 latency,別拖慢整個迴圈。
--- PART 4 · 時機 ② # 兩次 model request 之間,
把訊息注入執行中的 agent --- ## 這個時機在哪:兩次 model request 之間 一輪 (Turn) 不是「一問一答」,而是「模型 request → tool calls → 模型 request → …」反覆,直到輸出答案。注入就發生在這個迴圈內部、**還沒輸出答案前**: 一輪 Turn (agent 還在進行中) ↓ 在這裡注入訊息 (人 steer 或程式) 模型 request 1 🔧 tool calls 模型 request 2 🔧 tool calls 模型 輸出答案 (還沒到) 注入發生在每個「tool calls → 下一個 model request」之間 (圖中標記處) agent 還沒到「輸出答案」這一步,就把新訊息插進這一輪
不是等 agent 執行完才注入(那是時機③單輪結束),而是在它還在迴圈中間、還沒輸出答案時就插進去。來源可以是人 (steer),也可以是程式。
--- ## 同一個注入點,兩種用途 Agent 還在反覆呼叫工具、還沒輸出答案時,就把新訊息插進去,馬上影響它接下來的動作
### 🧑 用途一: 人中途 steer 使用者就主動輸入一段話介入,叫做 **steering** 轉向/引導。 在 **Codex、Claude Code** 這類互動式 coding agent 最常見,是內建功能。
### ⚙️ 用途二: 程式注入 例如背景工具程式跑完送回結果、外部事件 (webhook、告警) 要讓 agent 知道。 目前**較少框架實作**,少數像 **Pydantic AI** 做成通用機制。
--- ## 只能在 requests 之間: 這是 API 後端的限制 已經發出 tool calls 但還沒拿到結果,這時若添加 user message 回傳,API 會錯誤
### ❌ 不合法 assistant 發了 tool calls → 還沒等到所有工具結果 → 直接加 user message 回傳。下一個 request 送出就 400。
### ✅ 合法 assistant 發了 tool calls → **每個 call 的結果都補齊** → 再加 user message → 下一個 request。
OpenAI、Anthropic 模型發出的每一個 tool call 都必須先補上對應結果,中間不能插別的訊息。所以必須等當前 tool 全部執行完、湊成 API 合法狀態,才能在下一個 model request 之前注入你的訊息。
--- ## 用途一: 人中途 steer 最常見的用途是人主動介入。steering 和 interrupt 都是 **Codex、Claude Code** 的內建功能。這跟 human-in-the-loop 不一樣:
### 🛑 Human-in-the-loop 你**刻意設計一個等待點**,讓 agent 跑到那裡停下來問你 (最典型: 執行某工具前先請使用者確認)。 是 **agent 停下來問你**。
### 🧭 Steering agent **沒有等待點、也不打算停**,是你在它還在執行時主動輸入 (通常因為「需求變了」)。 是**你主動介入**。
--- ## 當用戶中途輸入訊息時,還可以細分兩種: steering 與 interrupt
### 🧭 不中斷: steering 訊息先排進佇列,等當前 tool calls 結果到齊、正要發下一個 model request 前才注入。 agent 沒中斷,只是下一步多了你的訊息,**已建立的 context 全部保留**。
### 🛑 強制中斷: interrupt 取消正在執行的工具,沒答完的 tool call 硬塞 `tool_result`,內容是固定字串 `aborted` ,維持對話 API 合法。
--- ## 用途二: 程式注入 用途常見有:
### 🔧 背景工具結果 長時間工具在背景跑完,把結果送回 agent。
### 📡 外部事件 webhook、錯誤告警、聊天平台訊息主動送進來。
有提供這個注入點的框架不多: OpenAI Agents SDK、Google ADK 都沒有。少數例外是 Pydantic AI v1.101.0(2026 年 5 月)的 enqueue,兩種模式: asap(盡快插入,就是這篇的時機點)與 when_idle(整輪結束後才插入)。
--- ## 背景工具結果怎麼送回 agent 它分兩步:
### 第一步: 當工具被呼叫時 tool call 後不等跑完,馬上回 `tool_result`,內容是固定的:
Tool 'X' is running in background (task N). You will receive the result automatically when it completes.
### 第二步: 當背景任務完成時 只能用 user message 插入:
Background tool 'X' (task N) completed. Result: …
注意不能用 `tool_result` 訊息了,因為 API 的 tool call 跟 tool result 是一對一配對的。
--- PART 5 · 時機 ③ # 單輪結束的
Goal 與 Outcomes --- ## 單輪結束的時機 ③ Agent 連續呼叫工具後,最後輸出文字答案時 ④ 外層 Loop · 每個 session · 分鐘~小時 · 修正整個任務 ③ 一輪 Turn · 秒級 使用者輸入 模型 request 1 🔧 tool calls 模型 request 2 🔧 tool calls 模型 輸出答案 ② request 之間注入 (人 steer 或程式) ① 工具執行內 · 修正單一動作 Stop hook 沒過 → 同份 context 再跑一輪 一輪 (Turn) = 多次「模型 request → tool calls」反覆,直到模型輸出答案 ④ 通過後這個 session 收掉,換上全新 context 再跑一圈 --- ## 設計 Goal 可驗證的停止條件,強迫模型自動再一輪
給 Agent 一個目標: - 希望的**最終狀態**是什麼 - 用什麼**證據**驗證 - 有哪些**限制**要遵守 讓 Agent 持續修正,直到通過為止。 這是 Codex 和 Claude Code 的內建功能。
### 核心精神 > 不能因為「模型**覺得**大概做完了」 > 就算數。 完成與否,要對著**停止條件**驗證, 沒過就繼續做。
--- ## Goal 合約模板 好的 Goal 不一定是更長的 prompt,而是一份**精簡的契約**: ```text /goal ← 期望的最終狀態 verified by ← 用什麼證據驗證 while preserving . ← 同時要保住什麼 Use <allowed inputs, tools, boundaries>. ← 允許的工具與邊界 Between iterations, . If blocked or no valid paths remain, . ```
範例:「將 p95 latency 降到 120ms 以下,用壓力測試做驗證,並保持測試套件都要通過」
🤖 **讓 AI 幫你寫**:任務夠清楚時,直接 `Help me turn this into a strong /goal: <任務描述>` </div> --- ## 不適合用 Goal 的時候
### ❌ 完成條件模糊 - 「把這個變得**更好**」 - 「**重構**這段程式碼」 沒有可靠的完成條件,
### ✅ 先定義,再開工 - 預期的**最終狀態** - 驗證用的**測試** - 要保住的**限制** 定義不出來?那問題不在工具, 在你還不知道自己要什麼。
--- ## 使用者的角色轉變: turn → round
藏在 Goal 背後的,是交付物的轉變: - 你交付的不再是一句 **prompt**,而是一份「**目標 + 邊界**」的契約 - 然後讓 Agent 持續去跑: **prompt → 判斷完成沒 → 再 prompt** 讓 agent 繼續做 - 思考單位,從「一次對話 **turn**」換成「一輪工作 **round/loop**」
### 那這迴圈怎麼判斷「做完了沒」? 有各種不同實作,讓我幫你分析。
--- ## 深入研究三種產品實作,沿著「驗證的 Judge 有多獨立」來看
### Codex 的 Goal 由**主模型自我審計**,自己呼叫 `update_goal` 宣告
### Claude Code 的 Gooal 每輪結束,交給獨立的 **Haiku** 小模型裁決
### Claude Managed Agents 的 Outcome 由獨立的 grader agent 拿 rubric 評分標準,去檢查產出物做驗收
--- ## 實作一: Codex /goal,沒有裁判的自我審計 Codex 沒有第二個模型在做判定,是自我審計
### Agent loop 像是確定性狀態機 - 當判斷完成時,主模型呼叫 `update_goal(complete)`更新狀態 - 如果狀態還是 Active,就重新注入同一份 continuation.md prompt 強迫 Agent 繼續跑下一輪
### 判定者就是主模型自己 - 完成 = 模型呼叫 `update_goal(complete)` - Agent 帶著完整的對話紀錄和推理脈絡繼續下一輪
--- ## Codex /goal:自我審計迴圈 update_goal(complete) ✅ 注入 continuation.md 每輪同一份合約 prompt 主 agent 跑一輪 推理 + 工具呼叫 自我審計 達成目標? 否: 沒呼叫 update_goal → thread idle 且 goal.status = Active → 再注入 判定者就是主 agent 自己, 全程沒有第二個模型 --- ## Codex 怎麼防「過早宣告完成」 判定權在主模型手上,Codex 用 prompt 要求以「當前 worktree 與外部狀態」去自查
### Tool description update_goal 的 description 寫好寫滿: > Set status to `complete` **only when the objective has actually been achieved** and no required work remains.
### 每輪注入的 Continuation prompt 要求模型逐項找證據: > "treat completion as **unproven** and verify it against the actual current state" > "The audit must **prove** completion, not merely fail to find obvious remaining work" 每輪注入的 prompt 都一樣 (只有 Budget 數字不同)
--- ## 別只看名字,要看實作
### 流傳的誤解 有些技術文章寫: Codex 的 Goal「用一個獨立小模型每回合評分」
### 翻原始碼跟文件才知道 沒有第二個 model、沒有額外的 grader
harness 的實作細節,不能靠幻覺想像那是怎麼做的
--- ## 實作二: Claude Code 的 Goal,獨立 Haiku 讀刪減 transcript Claude Code 把判定交給**另一個模型**。當主迴圈(Opus)輸出答案時,harness 不交還控制權,而是發一個 request 把整段對話交給一個獨立小模型來審計 (類似 fork): ```text Based on the conversation transcript above, has the following stopping condition been satisfied? Answer based on transcript evidence only. ```
⚠️ 注意: 這只會看對話紀錄,審計是不會呼叫工具打開檔案、實際檢查 artifact 產出物
--- ## Claude Code /goal 的三個細節
### 獨立的小模型 預設 **Haiku**,用另一份 system prompt
### transcript 是重組副本 保留對話紀錄、工具呼叫紀錄,**移除** thinking、移除整包 claudeMd 環境、tool metadata 等
### structured output 回覆 `{ok, reason, impossible}`,包括回饋理由,以及是否不可能辦到(此時應該放行,避免無窮迴圈卡死)。
### 判「是」 目標完成,把最後答案輸出給你
### 判「否」 擋下,把 Haiku 寫的 `reason` 注入主 agent,強迫跑下一輪
--- ## Claude Code /goal:Haiku 裁判流程 主 agent 跑一輪 (Opus) 自認達成, 要結束 Stop hook 攔下結束 複製刪減版 transcript (剝除 thinking) 獨立 Haiku 裁判 另一個模型, 只讀 transcript ok: true ok: false 目標完成, 交還控制 ✅ goal 達成 reason 注入回主 thread 針對性診斷 → 主 agent 繼續下一輪 --- ## 判「沒完成」之後,兩家差在哪 | | Codex /goal | Claude Code /goal | |---|---|---| | **回饋形式** | 重播同一份 continuation.md,只有 budget 數字在動 | Haiku 寫的針對性診斷,指出 transcript 缺了什麼 | | **下一步依據** | 環境證據(測試失敗、compile error等)+自己保留的 reasoning | 外部裁判指出缺口 | | **成本代價** | 每輪多累積一份 prompt,但會有 prompt cache | 每輪多一次 Haiku call,主 thread 只增加一小段 reason | | **失效模式** | 模型有盲點時無外部視角打破,可能連錯好幾輪 | Haiku 誤判:會被自信的收尾語言騙過 | --- ## 實作三: Claude Managed Agents 的 Outcome
第三種最為獨立,獨立 Agent 拿著 rubric 操作 artifact 做檢查: - Grader 在**全新 context window**:只拿 rubric 與產出物,**看不到主 agent 的推理與敘事** - 不只「看」:而是有工具操作,可以像真實使用者**實際操作** artifact 產出物,開檔、點 UI、打 API、查 DB 等 - Rubric **逐條可評分**;沒過就帶著**逐條缺失**進下一輪 - `max_iterations` 預設 3、最多 20
### Rubric 評分條件 範例 ```markdown # Outcome: 研究報告完成 - [ ] 涵蓋 7 項必查數據,各附來源 - [ ] 每個引用 [n] 連到有效 URL, 且原文逐字支持該主張 - [ ] 財務數字出自 10-K / 10-Q 正式文件 ```
--- ## Outcome:獨立 grader 操作 artifact 主 agent (generator) artifact (檔案 / app) 獨立 grader agent 全新 context + rubric 產出 拿 rubric 操作 點 UI / 打 API / 查 DB satisfied needs_revision 交付 ✅ 逐條缺失回饋 主 agent 再改一輪 裁判完全獨立: 不看 transcript, 直接對成品逐條驗收 --- ## 相比自評,獨立驗收是最準確的
### Agent 會自我吹捧 要 agent 評自己做的東西,它傾向**自信地稱讚**,哪怕在人眼中品質明顯普通。 而且 context 裡的錯誤推理會**不斷累積**,前面說服了自己「方向對」,後面就一路錯下去。
### 問題在於「誰來批判」 同一個 agent 較難對自己的產出下得了手,換一個全新 context 獨立評審,比較容易做出準確的 Judge。
「調出一個挑剔的獨立 evaluator,比教會 agent 自我批判容易得多。」
--- ## 學界研究表示: 越獨立、越會動手,判定越可信
### 自我評審 - **純自我修正**: 缺乏外部回饋時容易失敗 - **只讀文字的 judge**: 偵測假性完成(false success)能力有限,容易被「自信的收尾語言」帶著走
### 獨立評審 - **環境/執行回饋**: 看測試與執行結果,不看語言宣稱 - **rubric 分解**: 把驗收拆成逐條標準 - **Agent-as-a-Judge**: 能讀檔、跑指令的裁判,可靠度接近人類
越往獨立、越會實際操作的那端,判定越可信。
--- ## 三種實作的總比較 | | Codex 的 Goal | Claude Code 的 Goal | Claude Managed Agents Outcomes | |---|---|---|---| | **誰來判定** | **主模型自我審計** | 獨立的 Haiku | 全新 context 的 grader agent | | **harness 角色** | 不判斷,閒置時重播合約 prompt | 每輪結束送 transcript 裁決 | 自動配置 grader 評估迴圈 | | **看什麼證據** | 自己 context 裡的一切(含 reasoning) | **刪減版 transcript** | **只看 artifact,實際操作驗收** | | **怎麼宣告完成** | 主模型呼叫 `update_goal` | yes/no +診斷 reason | rubric 逐條 pass/fail | | **沒完成時的回饋** | 沒有診斷,只重播同一份模板 | 一段針對性診斷,指出缺什麼 | 逐條列出缺失,最具體 |
獨立性: Codex Goal < Claude Code goal < Managed Agents Outcomes
--- ## 但是對工程師來說,一切都有 tradeoff: 成本和獨立性的代價 獨立性換來可靠度,但要付出代價。差別不只是「單次評估多少錢」,也要看「錯誤多久才被發現」 | | 獨立性/可靠度 | 單次評估成本 | 錯誤多久被發現 | |---|---|---|---| | **Codex 自我審計** | 低:主模型自評 | 趨近零:只查狀態 | 靠模型自己就先發現 | | **Claude Code Haiku** | 中:獨立小模型讀 transcript | 小:約 1-2 秒 | 每 turn 一次 | | **Outcome grader** | 高:獨立 agent 操作 artifact | 高:數十倍、約 8 分鐘 | 整個 iteration 做完才抓到 |
越獨立越可靠,但需要用到更多 tokens 來分析,錯誤也是在整個流程中越晚被發現,導致總成本較貴也較慢
--- ## OpenAI Codex goal 為什麼不用獨立裁判?
### 有兩層可以裁判: - **harness 層**: 用獨立裁判,就像 Claude 作法 - **模型層**: 要靠模型本身的驗證、自我審計能力行不行
### 我個人推測 - 我推測 OpenAI 有特別加強 update_goal 的 post-training 模型訓練,強化模型自我審計的能力 - **比較節省執行 tokens 的總成本**
兩家方向不同: OpenAI 偏向加強模型訓練 goal、把自評 prompt 寫好。Claude 則用 harness 層的獨立裁判來做。
--- ## 如果是自行開發 agent,該怎麼選
### 自我審計(Codex 式) 調教難度較高。高度依賴模型的自律,一般模型容易過早宣告完成。 適合: 重視 Latency 和成本的中短任務。
### Transcript 裁判(Claude Code 式) 折衷做法。小模型判 transcript,好實作、好評估(輸入輸出都是文字)。 適合:中程任務,在 transcript 中就能看到可信的證明。
### 獨立 verify(Outcome 式) 效果最好,但成本最高、latency 是最大弱點。每次驗收要把 artifact 跑起來操作。 適合:長時間、以交付物為終點,價值高到值得花評估開銷。
--- ## 綜合案例: 使用者訪談 Agent,結合兩家的做法
需求: 按訪綱逐題訪問用戶 挑戰: 但什麼時候該換下一題?這題問夠了沒? 模型會偏向「覺得差不多了就想往下走」,跟第二篇的**過早宣告完成**是同一個問題,只是這裏是「這**一題**問完了沒」。
### 我的做法 - 借 **Claude Code** 的 transcript judge 把關「這題問夠了沒」 - 借 **Codex** 每輪重新注入 prompt 的做法,讓訪談持續往前
--- ## 借 Claude Code 的做法: 提供換題工具,裡面做 transcript judge agent 想跳下一題時,呼叫 `switch_next_question_workflow` 工具,裡面是一個獨立 Judge 審核: ```python @function_tool async def switch_next_question_workflow(reason: str, user_requested_next: bool) -> str: """當你判斷目前這題已取得足夠答案、或使用者要求跳題時呼叫。""" # 真正的判定在 server 端,工具只是把請求轉過去 ... ```
prompt 寫說:「回傳 Y/已切換才代表進到下一題」、「回傳 N 你 MUST 繼續聚焦同一題,換問法追問」
--- ## Judge 看什麼: 每題有不同的 rubric,根據逐字稿判斷 不同題目有不同的完成標準(rubric),用小模型根據逐字稿來判斷:
```python QUESTION_WORKFLOW = [ { "title": "最近一次使用情境", "completion_criteria": "需含最近一次使用的具體情境," "至少提到使用的功能與當時任務。" }, { "title": "替代方案", "completion_criteria": "需提到至少一個替代方案," "最好指出最常用者與原因。" }, # …其餘題目 ] ```
```text You are a user interview quality reviewer. Use only the transcript below. Do not infer facts that are not in the transcript. Current question: {question} Completion criteria: {completion_criteria} Transcript: {transcript} Return exactly one character: Y if complete. N if not. ```
--- ## 沒過時的回傳值: 還是要可行動 Judge 回 N 時,工具不是只回一個 false,而是回一段**可行動的指令**,順便附上這是第幾次被退: ```text N: 仍停留在第 1 題「最近一次使用情境」。這是第一次追問。 請換一種問法追問目前這題,不要切換題目。 ``` --- ## 借 Codex 的做法: time_control 每輪注入動態狀態 每輪推動 agent 往對的方向走: 「現在過幾分鐘了、第幾題了」的狀態也傳給 Agent ```text 已過 7 分鐘 / 共 15 分鐘 第 2 / 5 題: 題目.... ```
每輪動態注入當下狀態,提醒目前在哪一題,以及用這個訊號調節奏:時間充裕就從容追問,時間不夠了就加速減少追問。
--- ## 訪談 Agent:time_control 推進度,Judge 把關 time_control: 每輪注入動態狀態 (時間 / 題號) Codex 式 · 前饋: 給模型它自己算不出的當下狀態 訪談 agent 跑一輪 逐題問答 · 判斷這題問夠了沒 獨立 Judge · 只讀 transcript + 該題 rubric Claude Code 式 · 回饋: 把關「這題能不能換」 進到下一題 ✅ harness 推進到下一題 留在本題, 換問法追問 回傳可行動指令 + 第幾次被退 影響何時換題 想換題: 呼叫 switch 工具 Y: 切換 N: 留本題 下一輪 退 3 次 / 使用者喊跳 → 強制放行 time_control 推進度, Judge 把關: 一前一後讓限時訪談問得深又跑得完 --- PART 6 · 時機 ④ # 外層 Outer Loop --- ## Agent 輸出一輪完整答案之後 ④ 外層 Harness ④ 外層 Loop · 每個 session · 分鐘~小時 · 修正整個任務 ③ 一輪 Turn · 秒級 使用者輸入 模型 request 1 🔧 tool calls 模型 request 2 🔧 tool calls 模型 輸出答案 ② request 之間注入 (人 steer 或程式) ① 工具執行內 · 修正單一動作 Stop hook 沒過 → 同份 context 再跑一輪 一輪 (Turn) = 多次「模型 request → tool calls」反覆,直到模型輸出答案 ④ 通過後這個 session 收掉,換上全新 context 再跑一圈 --- ## 為什麼需要外層迴圈?
### 三種情況 - **① 單一 context 能力有限**: 大任務得拆段,每段用乾淨 context 重新開始、表現不受前一段影響(塞滿、失敗推理污染、Goal 跨不過 session) - **② 是另一個不相關的新任務**: 本來就該各自開乾淨 context,並管理多條平行的 agent - **③ 要由外部事件自動觸發**: webhook、新郵件、排程、CI 失敗一來就啟動
### 共同的解法 需要一個在單輪 agent 之外的工程迴圈,也就是 **外層 harness** 它決定何時觸發、每件事開獨立 agent、多條 agent 怎麼協調。 進度不靠 context 記憶,會寫到檔案系統共享。
--- ## 思路: 設計提示 Agent 的迴圈
這一層最近在社群很熱門: - 龍蝦爸 Peter Steinberger:「你不該再去提示 agent,你該**設計提示 agent 的迴圈**」講了好幾個月 - Claude 的 Boris Cherny、Andrej Karpathy 大神也講過類似的話 - 最近出現 **loop engineering** 新詞
### 具體來說 其實就是強調 Outer loop (Outer harness) 這一層,讓我們看具體實作案例,拆解給你看
參考: Peter Steinberger: You should be designing loops that prompt your agents.
--- ## 外層 Loop 的三種實作案例
### 🔁 Ralph **bash 蠻力重跑** 每圈全新 context,同一份 prompt 反覆送進去直到做完
### 🎼 OpenAI Symphony **看板協調器** 專案管理工具當控制平面,每張開啟的 ticket 配一個 agent
### ⏰ 自動排程 **定時觸發** 時間到就跑一輪;依 context 是否沿用,再分「獨立」與「heartbeat」兩種
--- ## Ralph:最笨也最有名的 Loop ```bash while :; do cat PROMPT.md | claude-code done ``` - 一個 bash 無窮迴圈,每圈把同一份 prompt 再送進去一次 - **每一圈都是全新的 context**:每圈歸零,只從固定幾份檔案重新讀起 - **完成才跳出**:當 AI 認為所有任務都完成,輸出 `COMPLETE` 代表完成,就脫離無窮迴圈
出處: ghuntley.com/ralph(2025 就有了)
--- ## 跨圈記憶: 進度全靠外部狀態 Ralph 拆成三個檔案:
### 📜 git history 完成的工作就是 commit, 新 agent 開圈先看歷史
### 📝 progress.txt 每圈追加學到的事: 陷阱、模式、決策
### ☑️ prd.json 任務清單與 `passes` 狀態: 每圈挑最高優先且未完成的
**ralph 的每一圈**: 讀 prd.json/progress.txt → 挑最高優先尚未完成的 story → 只實作這一個 → 跑 typecheck 和測試 → 過了 commit 標記完成 → learning 追加進 progress.txt → 下一圈。
--- ## Ralph:一圈的樣子 每圈結束 → context 整個丟掉, 開全新一圈 prompt.md 每圈用同一份 全新 context 的 agent 乾淨的 context, 跑一圈 挑一個 story 做 過 typecheck/測試才 commit 檔案狀態 (跨圈不丟) git history · progress.txt · prd.json ① 開圈先讀 ② commit、 記下學到的 --- ## Claude Code 的 ralph-wiggum Plugin: 別只看名字,要看內部實作 名字叫 Ralph,但讀完 code,它的機制跟原版不同:
### 原版 Ralph bash 外迴圈,**每圈整個重來**:全新 context、靠檔案傳遞進度。是「**換新 context**」的設計。
### ralph-wiggum plugin 用 **Stop hook** 在**同一個 session** 內攔住結束,進行完成判定。
「同一條 thread 延續」+「完成與否主模型自己決定」= 其實是 Codex /goal 作法,而不是原版 Ralph。
--- ## 對 Ralph 的批評
- **無狀態重跑**: prompt 每圈不變,progress.txt 只是軟性筆記、缺結構化記憶 - **暴力跑,收斂困難**: 弱模型的權宜之計,靠大量 token 硬做、可能把關不足 - **執行成本**: 可能卡住一直耗 token
心得: 驗證 (goal) 應該在內層 harness 就要做好,而不能只靠外層一直重跑。只依靠外層既耗 token,也很難對大範圍做好驗證。
--- ## OpenAI Symphony: 把專案管理系統變成 Agent 控制系統 OpenAI 開源的 harness 外層系統(以Spec形式): 以任務為中心,將 Linear 當做控制平面,每張開啟的 ticket 都有一個 agent 在自己工作區跑(有新 ticket 就派工)
### 專案看板就是狀態機 - ticket 狀態驅動:進 Todo 派 agent、進 Rework 帶 review 重做、進終態收掉 - 任務 DAG:沒被 block 的就開 agents 平行跑 - agent 自己開 ticket、交付 **proof of work** 成果(CI、review、示範影片等)
### 人管理的是「工作」,不是 code - 有些 ticket 純調查分析,從頭到尾不碰 codebase - Agent 的目標不只是「寫完 code」,而是要「說服人類把這段程式碼合併」
--- ## Symphony:看板就是狀態機 🎼 Symphony: 看板當控制平面, 每張開啟的 ticket 都配一個 agent 在自己的 workspace 跑 Todo In Progress Review Done TICKET-12 待派工 TICKET-13 待派工 TICKET-9 🤖 agent A 實作中 TICKET-10 🤖 agent B 實作中 TICKET-7 PR + 證明影片, 等人審 TICKET-3 ✓ merged ticket 狀態由左往右流動 = 狀態機; 沒被 block 的各配一個 agent 平行跑 --- ## 自動排程(cron): 最輕量、最通用的觸發
設定觸發條件,條件一到就自動把一段 prompt 丟出去跑一輪。 Claude Code、Codex 都已**內建**(`/loop`、Routines、Automations),設定就能用,是最容易上手的。
### 觸發的節奏 - **定時**: cron 排程,時間到就跑 - **動態**: 讓 agent 自己決定下次何時跑 - **事件**: webhook、新郵件、CI 失敗才觸發
例如 ```text /loop 5m 檢查 deploy 狀態,失敗就修 ← 固定間隔 /loop 盯著 CI,紅了就處理 ← 動態間隔:模型自己決定 ``` --- ## 設計重點: 要不要沿用 context ?
### 每次獨立 context 每次開**全新的 agent**。乾淨 context、進度靠外部狀態。 例如 Codex 的 standalone automation 模式 、Claude Code 的 Routines 功能
### 沿用 context: Heartbeat 把 prompt 打到**同一個長駐 session**。記憶連續、反應快,但 context 會持續變大。 例如 Codex 的 thread automation 模式、Claude Code 的 in-session `/loop`功能
--- ## 兩種觸發:獨立 context vs heartbeat cron 觸發 時間到就跑 開新的 回同一條 每次獨立 context (cron + headless / 雲端排程) t1 全新 run 乾淨的 context t2 全新 run 乾淨的 context t3 全新 run 乾淨的 context 各自了結, 結果送出後 context 就丟掉; 進度靠外部狀態傳遞 Heartbeat: 沿用 context (/loop · thread automation) t1 t2 t3 同一條 session 一直活著 context 每次都更長 → --- ## Loop 和 Goal 可以一起用 | | 管什麼 | 回答的問題 | |---|---|---| | **外層 Loop** | scheduling 排程 | **什麼時候**跑、多久跑一次 | | **Goal** | termination 終止 | 做到**什麼程度**才能停 |
### 作法一 排程內的 Agent 就直接用上 Goal 把事情做完
### 作法二 在排程內,把工作丟到某個 queue 就結束。另外有真正做事帶 goal 的 Agent 去執行
--- ## 案例: 龍蝦爸爸的 Loop 自動維護 Repo Steinberger 開源的 maintainer-orchestrator skill 每隔 5 分鐘醒來執行
### 🕰️ Cron + Orchestrator 協調分配任務 - orchestrator 本身只當**控制平面**:定時檢查、派工、監控、需要時問人決策 - 每 5 分鐘 **heartbeat** 醒來讀各 worker 現況 - 實作全部下放給平行跑的 **worker thread**;worker **不准再往下委派**
### 🗂️ 先過一道 triage 分類 github-project-triage 把進來的 queue 分三類: - **Autonomous**:可重現、有界、可驗證 → 直接派工 - **Needs owner**:產品決策、安全、缺權限 - **Defer/close**:過期、重複 → 附證據處置
出處:@steipete(2026/6),skills 開源於 agent-scripts
--- ## 外層 Loop 核心三個問題
### 1️⃣ 怎麼被觸發 固定 cron、動態間隔,還是事件(webhook、新郵件、CI 失敗、看板多一張 ticket)?
### 2️⃣ 醒來看什麼 要讀哪些 context 之外的狀態,才知道進度到哪、有沒有新工作? 例如 Ralph 讀 git/progress.txt、Symphony 讀專案看板等等
### 3️⃣ 結果送去哪 開 PR、寄一封簡報、丟進 triage 收件匣,還是安靜歸檔?
--- ![w:860 loopcraft: 由內到外五層巢狀迴圈,從 token 到開放探索](loopcraft.png)
出自 Shawn "swyx" Wang 電子報,其中 loop engineering 最想強調的是第 ④ 層 MetaLoop(生迴圈的迴圈)
--- PART 7 · 進階 # 自我改進的
Harness --- ## 把「改 harness」這件事交給 agent
**連 harness 本身,都讓 agent 自己改。** 讓 agent 根據自己跑出來的 trace 與 eval,回頭改自己的 harness,包括 system prompt, skills 甚至 code 。
自我改進不是讓 agent 想改什麼就改什麼 需要在 eval、trace、版本控制、regression test 的限制下,提出可驗證的變更。 不然,「自我改進」和「把 harness 改壞」就分不出來了。
### 📡 方法一: 讀 Production Traces
### 🔧 方法二: 用 Agent 當優化器改 code
### 📚 方法三: Self-Improving 改 Skills
💡 詳見 blog.aihao.tw 文章: 自我改進 Harness, Meta-Harness 與爬坡
--- PART 8 · 收尾 # 會過期的 Harness

Model-Harness-Fit

--- ## 模型一升級,harness 會怎樣?
### 🔗 沒有一套 harness 適用所有模型 - 同一套 harness 換個模型,效果**不一樣** - 小模型要更複雜精巧的 harness,大模型需要的 harness 可以較輕薄
### ⏳ harness 會過期 模型每次變強,某些當初**補強它的元件**就不再有用,該被移除。 每次升級時可以檢查之前的 prompt 約束、workflow 還有必要嗎?
> Terminal-Bench 2.0 排行榜排的不是「模型」,而是「**harness + 模型**」的配對。同一個模型配不同 harness,分數差好幾個百分點,差距甚至大過一個模型世代的升級。 --- ## 設計 Harness 架構時,應考慮模型升級
### ⏳ 會過期 **各種 harness 做法與補強措施** Bitter Lesson: 能隨算力擴大的通用方法,終究勝過手工規則。很多會隨更強的模型逐步不再需要。
### ♾️ 不會過期 **定義「什麼叫做好」+ 驗證** 就算模型強到能完美自我驗證,它驗證的,仍然是一個「由你定義的目標」。定義什麼是「好」,是無論模型多強都得自己做的核心。 Harness 應該設計得**容易替換元件、更容易測量性能**: 模型一變強,你才拆得掉。
💡 詳見 blog.aihao.tw 文章: 會過期的 Harness, Model-Harness-Fit 與 Bitter Lesson
--- PART 9 · 動手做 # 自建 Agent 的
框架選型 --- ## 該從哪個開發框架開始?
### 路線一: 從功能完整的 Deep Agent 開始 **起點高**: 一開始就有能跑的 agent,但相對不好改。 **✅ 優點**: 馬上能跑;harness 原廠針對自家模型調過。 **⚠️ 缺點**: 會帶用不到的 context/工具;可控性/可維護性受限;常綁特定供應商。
### 路線二: 從基礎構建 **起點低**: 要自己接的多,但彈性與可控性好,能一步步朝想要的設計走。 **✅ 優點**: 完全可控,貼著任務分布拿掉無關 context/工具;model 無關、好換供應商、好控成本。 **⚠️ 缺點**: 前期工程量較大。
--- ## 框架舉例
### 路線一: 全套 Deep Agent - [Codex SDK / app server](https://developers.openai.com/codex/sdk/))Apache 2.0 開源,可用 ChatGPT 訂閱帳號登入 - [Claude Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview)(Anthropic)核心閉源,第三方只能用 API key - [LangChain deepagents](https://github.com/langchain-ai/deepagents) MIT 開源
### 路線二: 從基礎構建(opinionated 高 → 低) - [AWS Strands Agents](https://strandsagents.com/) - [Google ADK](https://adk.dev/) - [Microsoft Agent Framework](https://github.com/microsoft/agent-framework) - [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/) - [Pydantic AI](https://ai.pydantic.dev/) - [LangGraph](https://github.com/langchain-ai/langgraph)
--- ## 那到底該選哪個?
### 🔹 特定情境/規模大 特定情境,或使用者多 → **從基礎構建**。貼近單一任務分布的 vertical agent 更有效率: token 成本低、延遲低,也能換供應商、精算成本。
### 🔹 自用/內部開發 要打造團隊用的 harness 與 outer loop → **從現成 deep agent**。 要的本來就是強的通用開發 agent,原廠已調好內層,先有能跑的東西、疊上 outer loop 最快。
### 🔹 想用訂閱帳號 要讓使用者帶自己的 ChatGPT 帳號 → **看 Codex SDK 或 Codex app server**。 支援訂閱帳號登入,不必 API key 計費;Claude Agent SDK 第三方只能用 API key。
💡 詳見 blog.aihao.tw 文章: 自建 Agent 的框架選型: 全套 Deep Agent 還是從基礎構建?
--- CONCLUSION # 總結

Takeaways

--- ## 給 Agent 開發者的駕馭工程 系列九篇 1. **Part 1**|六項 Deep Agent 能力 2. **Part 2**|Harness = 在**執行迴圈**裡約束、檢查、修正;agent 要**回饋迴路**,不是完美 prompt 3. **Part 3 · 時機①**|**工具裡**閉合最小迴圈: 驗證、改寫、回傳值夾帶指示 4. **Part 4 · 時機②**|**request 之間注入**: 人 steer/interrupt,或程式注入背景工具結果 5. **Part 5 · 時機③**|**單輪結束**驗收 Goal/Outcomes;三種 judge 不同實作分析 6. **Part 6 · 時機④**|**外層 Loop** 跨 session: Ralph/Symphony/cron,**把自己移出迴圈** 7. **Part 7 · 進階**|讓 agent **自己改自己的 harness** 8. **Part 8 · 收尾**|Harness **綁模型、會過期**;不過期的是 **Eval 與 Judge** 9. **Part 9 · 番外**|框架兩條路:**全套 Deep Agent/從基礎構建**
📚 歡迎到 blog.aihao.tw 看全篇內容。
--- Thank You # 謝謝,請多指教 🙏
- 個人部落格 <https://ihower.tw> - Facebook [ihower](https://www.facebook.com/ihower) - Threads [@ihower](https://www.threads.net/@ihower) - Twitter [@ihower](https://twitter.com/ihower)