核心洞見: 把 Agent Skill Document 當作神經網絡的權重來訓練——用 rollout 做前向傳播、reflect 做反向傳播、bounded edits 做梯度更新、held-out gate 做驗證集。
源碼規模: ~16,000 LOC(核心引擎 11,215 + Sleep 引擎 5,114)
實驗結果: 52/52 全勝,GPT-5.5 平均 +23.5 分提升
1. 引言:Agent Skills 的進化困境
今天的 AI Agent 靠什麼變聰明?答案很矛盾——靠人手寫的 prompt。
我們花了無數時間 fine-tune 模型權重,卻把 Agent 的行為規則交給「一次性 LLM 生成」或「無控制的自我修改」來決定。更糟糕的是,這些 skill document 幾乎沒有品質保證:改了可能變好,也可能變差,甚至完全崩潰。沒有人做 validation gate,沒有人控制 edit budget,沒有人保證收斂。
SkillOpt 的答案很簡單:把 skill document 當作神經網絡的權重來訓練。
這個由 Microsoft Research 發表的框架,是已知第一個系統性的、可控的文字空間 Agent Skill 優化器。它不碰模型權重(frozen agent),只在文字空間中通過 rollout → reflect → bounded edit → held-out gate 的循環來訓練 skill document。部署時零推理開銷——產出的只是一個緊湊的 best_skill.md(300-2,000 tokens)。
2. 核心洞見:Deep Learning 類比
SkillOpt 的整個設計圍繞著一個核心類比——把 skill document 當作神經網絡的權重來訓練,這不是表面的修辭,而是架構級的設計決策。一旦理解了這個映射,你就知道怎麼調參數、怎麼解讀收斂曲線、怎麼診斷優化失敗。
| 深度學習概念 | SkillOpt 對應 | 說明 |
|---|---|---|
| 模型權重 | Skill document (.md) | 被優化的對象 |
| 前向傳播 | Rollout | Target 用當前 skill 執行任務 |
| 損失函數 | Task evaluator | 評分任務執行品質 |
| 反向傳播 | Reflect | Optimizer 分析失敗 → 產生 edit patches |
| 梯度 | Edit patches | 對 skill 的具體修改建議 |
| 梯度聚合 | Patch aggregation | 合併語義相似的 edits |
| 梯度裁剪 | Edit selection (clip) | 限制每步最大 edit 數量 |
| 學習率 | learning_rate (edit budget) |
控制每次更新幅度 |
| LR Scheduler | lr_scheduler |
衰減策略:cosine / linear / constant |
| SGD 步驟 | Skill update | 將選中的 patches 應用到文件 |
| 驗證集 | Selection split | Gate 在驗證集上檢查是否進步 |
| Early Stopping | Gate patience | 拒絕不進步的更新 |
| Momentum | Slow update | Epoch 邊界的縱向比較 |
| Meta-learning | Meta skill | 跨 epoch 的優化器策略記憶 |
| Batch size | batch_size |
每步採樣的任務數量 |
實驗驗證的遷移規則:
✅ Cosine schedule > constant — 與 DL 中一致,cosine annealing 幫助收斂
✅ Moderate LR (4-16) > 極高/極低 — 太少 edits = 學太慢,太多 = 噪音
✅ Slow update 有效 — 縱向比較防止跨 epoch 災難性遺忘
✅ Meta skill 改善 reflection — Optimizer 受益於跨 epoch 策略筆記
⚠️ Batch size ≠ better — 更大 rollout 批次有 diminishing returns(受限於 API 成本)
⚠️ 更多 epochs ≠ better — Skills 比神經網絡收斂更快(2-4 epochs 通常足夠)
3. 訓練循環:六階段詳解
SkillOpt 的訓練循環是 Epoch → Step 的雙層結構:
for epoch in epochs:
for step in steps:
1. Rollout — Target 執行任務(前向傳播)
2. Reflect — Optimizer 分析軌跡(反向傳播)
3. Aggregate — 合併語義相似 patches
4. Select — 排序 + 裁剪 edits(梯度裁剪)
5. Update — 應用 patches 到 skill doc(參數更新)
6. Gate — 驗證集檢查(validation)
Epoch Boundary:
Slow Update — 縱向比較 + 防止災難性遺忘
Meta Skill — 跨 epoch 策略記憶
3.1 Rollout(前向傳播)
Target model 使用當前 skill document 作為 prompt 來執行任務批次。每個任務產生一個軌跡(trajectory)和一個分數(score)。
# 類比:neural network 的 forward pass
predictions = model(input, skill_document)
scores = evaluate(predictions, ground_truth)
Rollout 支援三種執行環境(harness):
- Direct chat:直接通過 API 調用,適用於 QA 類 benchmark
- Codex CLI:透過 Codex agentic loop 執行
- Claude Code CLI:透過 Claude Code agentic loop 執行
源碼:skillopt/envs/<benchmark>/rollout.py
3.2 Reflect(反向傳播)— 最關鍵的創新
不是簡單地讓 LLM 看一眼失敗就隨便改。SkillOpt 的 reflect 有三層設計:
層 1:Minibatch trajectory analysis
失敗軌跡以 minibatch(大小 M)為單位進行分析,而非逐個分析。這類似於 minibatch SGD vs per-sample SGD——批次分析能捕捉系統性模式而非個別噪音。
層 2:Error + Success 雙分析
同時分析失敗和成功案例。Optimizer 不僅知道「哪裡錯了」,還知道「什麼做法是對的」。
層 3:Skill-aware reflection(v0.1+)
區分兩種失敗類型:
- SKILL_DEFECT:skill 本身的缺陷 → 修改 skill body
- EXECUTION_LAPSE:執行失誤 → 只在 appendix 中記錄提醒(不修改 body)
# 類比:neural network 的 backward pass
gradients = loss.backward() # → edit patches
源碼:skillopt/gradient/reflect.py — run_minibatch_reflect() · skillopt/optimizer/skill_aware.py
3.3 Aggregate(梯度聚合)
語義相似的 edit patches 被層次化合併(hierarchical merge),避免重複的 edits 浪費 edit budget。
源碼:skillopt/gradient/aggregate.py
3.4 Select:文字學習率與梯度裁剪
這是最能體現「文字版深度學習」的設計。
文字學習率(Textual Learning Rate)不是一個浮點數,而是一個整數 N:每步最多應用 N 個 edits。lr_scheduler 控制這個 N 隨訓練進程如何衰減:
| Scheduler | 行為 |
|---|---|
| cosine | 前期探索(高 LR),後期收斂(低 LR) |
| linear | 線性衰減 |
| constant | 固定 budget |
| autonomous | Optimizer 自己決定下一步 LR |
當 edit 數量超過 budget 時,rank_and_select() 調用 optimizer LLM 按重要性排序,只保留 top-L edits。
# 類比:gradient clipping
selected = top_k(edits, k=learning_rate)
源碼:skillopt/optimizer/clip.py — rank_and_select() · skillopt/optimizer/scheduler.py
3.5 Update(參數更新)
選中的 edits 應用到 skill document。三種操作:
| Edit Op | 說明 |
|---|---|
ADD |
在末尾追加一條規則/步驟 |
DELETE |
按精確匹配刪除一行 |
REPLACE |
按精確匹配替換一行 |
關鍵約束:bounded edits only。不允許添加全新章節(防止 catastrophic forgetting),不允許刪除整個段落。
Skill document 有一個 protected region(<!-- SLOW_UPDATE --> 標記)。Edit 引擎會跳過 protected region 內的任何修改。
源碼:skillopt/optimizer/skill.py — apply_edit()
3.6 Gate(驗證門控)— SkillOpt 的靈魂
這是 SkillOpt 與所有其他 skill 優化方法最根本的區別。
候選 skill 必須在 held-out selection split 上嚴格提升分數,才會被接受。 不接受「差不多」、「可能更好」——必須是嚴格改進。
三種 gate metric:
| Metric | 說明 | 適用場景 |
|---|---|---|
hard |
精確匹配準確率 | 答案明確的任務 |
soft |
F1 / partial credit | 開放式任務 |
mixed |
(1-w)×hard + w×soft |
平衡兩者 |
被拒絕的 edits 不會被丟棄——它們作為**負反饋(rejected-edit buffer)**傳遞給下一輪的 optimizer。
源碼:skillopt/evaluation/gate.py
Epoch Boundary:Slow Update & Meta Skill
Slow Update(類似 Momentum):
- 同時 rollout 上一個 epoch 的 skill 和當前 skill 在相同樣本上
- 分類為:improved / regressed / persistent_fail / stable_success
- 生成高層次指導注入 protected region
- 防止「改好了 A 但弄壞了 B」的災難性遺忘
Meta Skill(類似 Meta-learning):
- 累積跨 epoch 的策略記憶
- Optimizer 在未來 reflection 時獲得跨 epoch 的上下文
4. 源碼架構總覽
skillopt/ # 核心引擎(~11,215 LOC)
├── gradient/
│ ├── reflect.py # 反向傳播:error/success 分析 → edit patches
│ └── aggregate.py # 梯度聚合:層次化合併相似 patches
├── optimizer/
│ ├── clip.py # 梯度裁剪:LLM 排序 + top-L 選擇
│ ├── skill.py # 參數更新:apply_edit / protected region
│ ├── scheduler.py # LR scheduler:cosine/linear/constant/auto
│ ├── slow_update.py # Momentum:epoch 邊界縱向比較
│ ├── meta_skill.py # Meta-learning:跨 epoch 策略記憶
│ ├── skill_aware.py # Skill-aware reflection
│ └── appendix.py # Protected appendix 管理
├── evaluation/
│ └── gate.py # 驗證門控:accept/reject 決策
├── model/
│ ├── azure_openai.py # Azure OpenAI backend
│ ├── claude_backend.py # Claude (Anthropic) backend
│ ├── codex_backend.py # Codex CLI backend
│ ├── qwen_backend.py # Qwen (vLLM) backend
│ ├── minimax_backend.py # MiniMax backend
│ └── router.py # 模型路由
├── envs/ # 6 個 benchmark
│ ├── searchqa/ # 搜索引擎 QA
│ ├── spreadsheetbench/ # 試算表任務
│ ├── livemathematicianbench/ # 數學推理
│ ├── alfworld/ # 具身 AI 任務
│ ├── officeqa/ # 辦公場景 QA
│ └── docvqa/ # 文檔視覺 QA
├── prompts/ # 分析 prompt 模板
└── configs/ # YAML 配置(支援繼承)
skillopt_sleep/ # Sleep 引擎(~5,114 LOC)
├── cycle.py # 主循環(harvest→mine→replay→consolidate)
├── consolidate.py # 核心優化邏輯
├── replay.py # 任務重播
├── mine.py # 任務挖掘
├── backend.py # Backend 協議
├── config.py # 配置加載
├── types.py # TaskRecord / EditRecord / ReplayResult
└── experiments/ # 實驗腳本 + 基準測試
核心函數速查:
| 函數 | 文件 | 用途 |
|---|---|---|
load_config |
config.py |
加載 YAML 配置(支援繼承 + key=value override) |
run_minibatch_reflect |
gradient/reflect.py |
對軌跡 minibatch 運行 error/success 分析 |
merge_patches |
gradient/aggregate.py |
層次化合併語義相似 patches |
rank_and_select |
optimizer/clip.py |
LLM 排序 edits + 裁剪到 LR budget |
build_scheduler |
optimizer/scheduler.py |
構建 LR scheduler(cosine/linear/constant/auto) |
apply_patch |
optimizer/skill.py |
將 edits 應用到 skill document |
evaluate_gate |
evaluation/gate.py |
純 accept/reject 決策 |
run_slow_update |
optimizer/slow_update.py |
產生 epoch 邊界縱向指導 |
5. 關鍵設計決策深度分析
5.1 為什麼是「文字空間」而非「權重空間」?
Fine-tuning 有幾個根本問題:
- 成本:每次改進需要 GPU hours + 數據準備
- 不可解釋:不知道模型學到了什麼
- 不可遷移:一個模型的 fine-tune 結果無法給另一個模型用
- 不可迭代:無法在部署後持續改進
SkillOpt 的文字空間方案:零推理開銷、完全可解釋(產出就是 Markdown)、跨模型可遷移、可持續迭代。
5.2 為什麼需要 Optimizer/Target 分離?
用一個**強模型(optimizer)來為弱模型(target)**寫 skill。
實驗證明這不是簡單的「蒸餾」。即使是 matched target-as-optimizer 的設定(用同一個模型既當 target 又當 optimizer),在 bounded/validated 的約束下也能發現有用的 edits。Optimizer 的角色是分析者而非替代者。
5.3 Rejected-edit Buffer 的妙用
被 gate 拒絕的 edits 不是垃圾——它們是有結構的負反饋。下一輪的 optimizer 會看到「這些方向被試過但沒用」,從而避免重複犯錯。這類似於 RL 中的 negative reward shaping。
5.4 Protected Region 機制
Skill document 中的 <!-- SLOW_UPDATE --> 區塊是 epoch 級別的指導(類似於 momentum term),不會被 step 級別的 edits 修改。這確保了長期學習信號不會被短期噪音淹沒。
6. SkillOpt-Sleep:部署時的進化引擎
SkillOpt 解決了「如何在 benchmark 上訓練 skill」。但現實中,你的 coding agent 每天在用自己的 skill 處理真實任務。SkillOpt-Sleep 把同樣的訓練紀律應用到你自己的日常使用。
6.1 一個「夜晚」的流程
harvest 你的 session transcripts
→ mine 重複任務模式
→ replay offline(baseline vs candidate)
→ reflect on failures
→ bounded edits
→ GATE on held-out tasks(你的真實任務)
→ stage proposal
→ (你) adopt
6.2 三層數據劃分
| Split | 來源 | 用途 |
|---|---|---|
| train | 真實任務 + 可選的 "dreamed" 變體 | Optimizer 學習 |
| val (selection) | 僅真實任務,held-out | Gate:嚴格驗證 |
| test | 僅真實任務,從未見過 | 最終效果報告 |
你可以想像額外的訓練例子來穩健地學習規則,但規則仍然在真實的、未見過的任務上被評判。
6.3 可控的開關
| 開關 | 預設 | 說明 |
|---|---|---|
--gate on|off |
on |
嚴格 held-out gate vs 貪婪模式 |
--rollouts-k K |
1 |
多軌跡對比反射(K≥3 極大提升信號品質) |
--preferences "..." |
— | 你的個人規則(作為 prior 引導 optimizer) |
--optimizer-model |
— | 用強模型優化 → 弱模型受益 |
--budget-tokens N |
— | 控制每晚 API 花費 |
--auto-adopt |
off | 自動應用 vs 手動審核 |
6.4 已驗證效果
- gbrain-evals
skillopt-v1:缺陷 skill 在 held-out 上 0.00 → 1.00(4 seeds, real tool-use loop) - 跨模型遷移:在一個模型上優化的 skill 能提升另一個模型
- 跨 runtime 遷移:Codex ↔ Claude Code 之間 skill 遷移有效
- Gate 正確阻擋回歸:有害 edits 被系統性地攔截
7. OpenClaw 整合實戰
SkillOpt-Sleep 在 2026-06-15 合併了 OpenClaw plugin(PR #59),我們是第一時間安裝的用戶之一。
7.1 架構
plugins/openclaw/
├── run_sleep.py # 主入口
├── skillopt_sleep_openclaw.py # DeepSeek + Ollama backend
├── slash_sleep.py # /sleep 斜槓指令
├── run_sleep_cron.sh # cron 包裝
├── config.json # 引擎配置
├── SKILL.md # OpenClaw skill manifest
└── tests/ # held-out test sets
├── research-cron-tasks.json
├── devops-tasks.json
└── wiki-tasks.json
7.2 Backend 設計
OpenClawDeepSeekBackend 實現了三個核心方法:
attempt(task, skill, memory):用 DeepSeek V4 Pro 執行任務,返回 responsejudge(task, response):Hard score(精確匹配)+ Soft score(LLM judge 按 rubric 評分)reflect(failures, successes, skill, memory):分析失敗/成功軌跡 → 產生 bounded edit proposals
7.3 成本
使用 DeepSeek V4 Pro 作為 optimizer,每夜 $0.02($0.59/月,~$7.18/年)。
7.4 Cron 設定
# 每日凌晨 3:00 HKT 自動運行
0 3 * * * cd ~/.openclaw/workspace/skills/skillopt-sleep && \
bash run_sleep_cron.sh >> ~/.skillopt-sleep/logs/nightly.log 2>&1
8. 實驗結果精華
8.1 主要結果
在 6 個 benchmark × 7 個 target model × 3 個 execution harness = 52 個 cells 上,SkillOpt 是最佳或並列最佳,擊敗所有競爭者(human、one-shot LLM、Trace2Skill、TextGrad、GEPA、EvoSkill)。
8.2 GPT-5.5 上的提升
| Harness | 提升幅度 |
|---|---|
| Direct Chat | +23.5 分 |
| Codex Agentic Loop | +24.8 分 |
| Claude Code | +19.1 分 |
8.3 消融實驗關鍵發現
| 消融項 | 影響 |
|---|---|
| 移除 Gate | 效能大幅下降(證明 held-out validation 的必要性) |
| 移除 Rejected Buffer | 重複犯相同錯誤 |
| 移除 Slow Update | 災難性遺忘,前期進步在後期消失 |
| 用 Target 自身做 Optimizer | 仍然有效(不是單純的蒸餾) |
| Cosine > Constant LR | 與 DL 中的經驗一致 |
8.4 遷移實驗
- 跨模型遷移:在一個模型上訓練的 skill 轉移到另一個模型時仍有效
- 跨 harness 遷移:Codex skill → Claude Code 有效,反之亦然
- 跨 benchmark 遷移:在一個 benchmark 上訓練的 skill 能遷移到相近 benchmark
9. 對 Agent 開發者的啟示
9.1 Skill ≠ Prompt
SkillOpt 告訴我們一個重要的事實:好的 skill 不是寫出來的,是訓練出來的。 就像你不會手寫神經網絡的權重,你也不應該手寫複雜的 agent skill。你需要一個優化循環。
9.2 Validation Gate 是必需品
沒有 gate 的自我修改 = 隨機漫步。你今天改了 skill,明天不知道是變好還是變壞。Gate 提供了唯一的品質保證。
9.3 Bounded Edits > Unbounded Rewrites
允許 optimizer 重寫整個 skill document 會導致災難性遺忘。Bounded edits(每次只改幾個特定位置)是穩定學習的關鍵。
9.4 Optimizer/Target 分離有價值
用強模型分析和用弱模型執行是互補的。這意味著你不需要為每個模型都訓練 skill——用一個強 optimizer 訓練的 skill 可以幫助所有 target model。
10. 未來展望
SkillOpt 代表了 Agent 工程的一個新範式轉向:
- 從「寫 prompt」到「訓練 prompt」
- 從「一次性生成」到「迭代優化」
- 從「無品質保證」到「held-out validation」
但還有很長的路要走:
- Multi-skill coordination:如何協調多個 skill 之間的交互?
- Online learning:如何在部署中持續在線學習?
- Skill composition:如何組合多個 skill 來解決複雜任務?
- Safety constraints:如何在優化過程中保持安全約束?
對 OpenClaw 生態而言,SkillOpt-Sleep 是最直接的價值點——它讓我們現有的 agent skill 系統獲得持續的、有品質保證的自我進化能力。
本文基於對 SkillOpt v0.1.0 源碼的完整分析(~16,000 LOC),以及實際在 Mac Studio + DeepSeek V4 Pro 環境上的部署測試。
參考資料:論文 arXiv 2605.23904 · GitHub microsoft/SkillOpt · 項目頁面 · PyPI: pip install skillopt