📌 本文重點
- 本地 Agent 痛點在於行為難以持續優化與自動化
- autoswarm 透過 reflect → rewrite → evaluate → write-back 形成閉環
- skills.yaml + 驗證集讓 Agent 行為像「可訓練參數」持續調整
- 先從可量化任務(coding/CLI/FAQ)導入 autoswarm 成效最佳
本地 Agent 最大的痛點不是「模型不夠強」,而是行為難以持續調整:你改了一堆 prompt、skills,效果好壞全憑體感,難以複製、更難自動化。autoswarm 類的自我優化流程,把這件事工程化:讓 Agent 自己從對話紀錄學習、反思、改寫技能檔,並用驗證集嚴格篩選只留下「真有幫助」的改動。
💡 關鍵: autoswarm 把「調 prompt 靠手感」變成「技能檔可度量、可回滾的工程流程」。
換句話說,你不再手動調 prompt,而是給 Agent 一套 reflect → rewrite → evaluate → write-back 的閉環,讓本地 coding 助手、CLI 助手、企業 FAQ agent 在你睡覺時自己變強。
重點說明
1. autoswarm 關鍵架構:從對話到技能檔
典型 autoswarm 流程可以拆成四個模組,每個都可以獨立嵌進現有系統:
- 對話記錄收集(logs)
- 來源:真實使用對話、benchmark(如
TerminalBench)、內部工單。 -
形式:
(task, context, agent_action, outcome),最好能標註success/fail或score。 -
反思(reflect)
- 用一個「較強或同級」的 LLM 對失敗例子做事後檢討。
-
產出:錯誤原因、改進方向、需要修改的 skill 名稱/段落。
-
技能候選改寫(rewrite)
- 以
skills.yaml內容為條件,請 LLM 產生有界改動:新增/刪除/替換特定節點,而不是整檔轟掉重寫。 -
借鏡
SkillOpt:每個改動要有 diff 形式 與 rationale,方便審核與回滾。 -
驗證集評估 + 寫回(evaluate & write-back)
- 對每個候選 skills 版本,跑一輪驗證集,計算 明確的 success metric(accuracy、任務完成率、延遲等)。
- 只有 嚴格提升 才寫回主線
skills.yaml,其餘丟棄;可選擇保留失敗改動作為「負樣本」提示未來避免。
💡 關鍵: 整體流程等同「技能檔梯度下降」,用驗證集決定每次改寫是否保留。
整體就是一個離線/準線上的 技能檔梯度下降:技能檔被當成可訓練參數,用反覆試錯 + 驗證集擇優更新。
2. skills.yaml schema 與 success metric 設計
要讓 autoswarm 好養,技能檔要易於定位、易於局部修改。一個實用的 YAML schema 可以長這樣:
version: 3
meta:
agent_name: local_cli_helper
description: "CLI + coding local agent"
skills:
- id: shell_exec
type: tool
trigger: ["terminal", "bash", "cli"]
prompt: |
你是一個嚴謹的 CLI 助手。只執行使用者要求的指令:
- 先用自然語言解釋你要做什麼
- 再給出具體指令
- 不要執行具有破壞性的指令(rm -rf 等)
guardrails:
forbidden_patterns:
- "rm -rf /"
- ":(){ :|:& };:"
- id: code_edit
type: coding
languages: ["python", "bash"]
prompt: |
你是一個本地 code 編輯助手:
- 優先最小改動
- 保留原有註解
- 回傳可直接貼上的 patch
- id: faq_lookup
type: retrieval
index: "internal_faq.jsonl"
prompt: |
你是企業 FAQ 助理,回答時:
- 引用文件來源 id
- 若找不到答案,要明確說明而不是亂猜
幾個關鍵點:
- id 必須穩定:autoswarm 透過
id來定位要改哪個 skill。 - 把行為拆成多個 skill,而不是一個 mega prompt,讓 autoswarm 有「局部調參」的空間。
- 為每個 skill 準備可計算的 success metric,例如:
- coding:測試通過數 / 單元測試覆蓋率提升。
- CLI:命令
exit code == 0且輸出包含 expected pattern。 - FAQ:答案包含
ground truth片段、或人工標註score。
💡 關鍵: 每個 skill 綁一個可量化 metric,才能自動決定「這次改寫有沒有真的變好」。
3. 驗證集與回放:怎麼自動化
關鍵是把「我覺得好」變成可計算的 pass/fail:
- 來源:
- 基準測試(
TerminalBench、內部腳本集)。 - 真的使用者對話 + 事後標註(成功:
1、失敗:0)。 -
半自動生成:用模型自己產
task,再請另一模型打分。 -
回放機制:
- 對每個驗證樣本
(input, expected),在新skills.yaml下跑一次 Agent,產生output。 - 用簡單的 scorer 函數 計算分數,例如:
- coding:跑
pytest,看全部通過比例。 - CLI:比對
stdout是否包含關鍵字,exit code是否為0。 - FAQ:用一個 judge LLM(或傳統 NLP 指標)評估是否回答到點。
- coding:跑
這層其實就是一個小型 harness:把「模型+skills」包成可測試的函式,對照 Deepseek 提出的觀點,就是那層讓 LLM 變成 Agent 的 runtime code。
4. 如何嵌進現有本地 Agent(MCP/子代理/skills-based)
不需要重寫整個 Agent,只要插入兩個 hook:
- log hook:在 MCP server、子代理 router 或 skills selector 前後,記錄輸入、選到的
skill、輸出、評分。 - offline autoswarm worker:定期(例如每天)跑反思-重寫-評估 loop,更新一個新的
skills_version,下次重啟 agent 或熱更新時載入。
常見集成方式:
- MCP:把
skills.yaml當作 MCP tool 的配置,autoswarm 只負責改 YAML,MCP server 本身不改。 - 多代理框架(如
revfactory/harness):autoswarm 對每個 agent 的 skill 檔做優化,讓「meta-agent」負責決定何時切版本。 - 傳統 skills-based 系統:把原本寫死在程式碼裡的 prompt 抽到 YAML,才能用 autoswarm 自動調參。
實作範例:最小可行 autoswarm(Python + YAML + Ollama)
下面是一個極簡版的 autoswarm:針對單一 skill(faq_lookup),用對話紀錄做反思、改寫 YAML,然後用驗證集評估是否接受改動。
1. 專案結構
project/
skills.yaml
logs.jsonl # 真實對話紀錄
val_set.jsonl # 驗證集
autoswarm.py
skills.yaml 示意(只保留 FAQ skill):
skills:
- id: faq_lookup
type: retrieval
prompt: |
你是 FAQ 助理,只能根據提供的文件回答。
若找不到答案,就回答「找不到」。
2. Python:反思 → 重寫 → 評估 loop
# autoswarm.py
import json, copy, subprocess, textwrap
from pathlib import Path
import yaml
SKILLS_PATH = Path("skills.yaml")
VAL_PATH = Path("val_set.jsonl")
LOGS_PATH = Path("logs.jsonl")
# --- 基礎調用 Ollama ---
def call_ollama(prompt: str, model="llama3.1") -> str:
res = subprocess.run(
["ollama", "run", model],
input=prompt.encode("utf-8"),
stdout=subprocess.PIPE,
check=True,
)
return res.stdout.decode("utf-8").strip()
# --- Step 1: 從失敗 log 產生改進建議 ---
def load_failed_examples(limit=5):
examples = []
with LOGS_PATH.open() as f:
for line in f:
obj = json.loads(line)
if obj.get("success") is False:
examples.append(obj)
if len(examples) >= limit:
break
return examples
def reflect_on_failures(examples):
prompt = """你是資深 prompt engineer。以下是 FAQ agent 的失敗案例:
{cases}
目前 FAQ skill 的行為描述較弱,請提出如何修改 skill prompt 才能避免這些錯誤。
輸出格式:
- mistakes: 一段文字說明主要錯誤
- patch: 改寫後的完整 prompt 內容(繁體中文)
"""
cases_txt = "\n\n".join(
[
f"[CASE]\nquestion: {c['input']}\nwrong_answer: {c['output']}\nexpected: {c['expected']}"
for c in examples
]
)
resp = call_ollama(prompt.format(cases=cases_txt))
return resp
# --- Step 2: 產生候選 skills 版本 ---
def generate_candidate_skills():
skills = yaml.safe_load(SKILLS_PATH.read_text())
base_skills = copy.deepcopy(skills)
failed = load_failed_examples()
if not failed:
print("no failed examples; skip")
return None
reflection = reflect_on_failures(failed)
# 簡化處理:從 LLM 回應中用標記擷取 patch 區塊
if "patch:" in reflection:
patch = reflection.split("patch:", 1)[1].strip()
else:
patch = reflection
# 套用到 faq_lookup
for s in base_skills["skills"]:
if s["id"] == "faq_lookup":
s["prompt"] = patch
return base_skills
# --- Step 3: 評估一個 skills 版本 ---
def run_agent(question: str, skills_obj) -> str:
faq_skill = next(s for s in skills_obj["skills"] if s["id"] == "faq_lookup")
sys_prompt = faq_skill["prompt"]
full_prompt = textwrap.dedent(f"""
系統指令:
{sys_prompt}
使用者問題:{question}
請直接回答。
""")
return call_ollama(full_prompt)
def score_skills(skills_obj) -> float:
total, ok = 0, 0
with VAL_PATH.open() as f:
for line in f:
obj = json.loads(line)
question = obj["input"]
expected = obj["expected"]
out = run_agent(question, skills_obj)
total += 1
if expected.strip() in out:
ok += 1
return ok / total if total else 0.0
# --- 主流程 ---
def main():
current_skills = yaml.safe_load(SKILLS_PATH.read_text())
base_score = score_skills(current_skills)
print("base_score:", base_score)
cand = generate_candidate_skills()
if cand is None:
return
cand_score = score_skills(cand)
print("candidate_score:", cand_score)
if cand_score > base_score:
backup = SKILLS_PATH.with_suffix(".bak.yaml")
backup.write_text(SKILLS_PATH.read_text())
SKILLS_PATH.write_text(yaml.dump(cand, allow_unicode=True))
print("updated skills.yaml (backup saved)")
else:
print("candidate rejected; no improvement")
if __name__ == "__main__":
main()
這個最小範例已經包含核心閉環:
- 反思:
reflect_on_failures用 LLM 分析失敗案例。 - 重寫:
generate_candidate_skills產出新的 FAQ skill prompt。 - 評估:
score_skills在驗證集上打分。 - 寫回 + 回滾:只有 score 提升才覆蓋
skills.yaml,並保留.bak方便回滾。
你可以把 run_agent 換成實際的 MCP 調用、子代理 router,整套邏輯依然成立。
建議與注意事項
1. 避免過度擬合驗證集
問題:skills 慢慢只會在 val_set 上變強,實戰反而變差。
建議:
- 拆
train / val / live三層: train:用來產生候選改動。val:只決定是否接受改動。live:真實流量,週期性抽樣評估是否「線上變好」。- 定期替換驗證集樣本,避免被「背題」。
2. 技能檔膨脹與行為漂移
問題:LLM 每輪都喜歡加條款、加例外,skills.yaml 越寫越厚,最後誰也看不懂。
建議:
- 為 autoswarm 的 rewrite prompt 加上硬性約束:字數上限、禁止新增無根據規則。
- 定期跑「壓縮輪」:請模型把冗長 skill 壓縮成短版,再用同一驗證集確認不降分。
- 每個 skill 保持一個簡短的 design doc(目的、scope、anti-goals),避免 autoswarm 把 skill「學壞」。
3. 無標準答案任務的侷限
在開放式對話、創作任務上,很難定義客觀 success metric。
可以考慮:
- 使用一個獨立 judge 模型,給
1–5分,才算作 metric。 - 只對「明確可評」技能開 autoswarm(如 coding、CLI、FAQ),聊天維持手動設計。
- 針對負面行為(安全、合規)單獨設計 守門驗證集,只要出現就直接拒絕 candidate。
4. 版本控制與回滾策略
- 版本號:在
skills.yaml加version欄位,每次 autoswarm 成功更新+1。 - Git 管理:把 skills 連同 autoswarm logs 一起
commit,方便bisect。 - 多版本 AB 測試:對企業內部 Agent,可同時跑兩個 skills 版本,對比使用者滿意度或工單解決率。
實際好處總結:
- 對本地 coding 助手:用單元測試當驗證集,讓 Agent 自動學會你的專案風格與工具鏈。
- 對 CLI 助手:從錯誤指令和 crash log 中反覆學習,逐步降低「爆炸指令」風險。
- 對企業 FAQ/ops agent:用真實工單與 FAQ 命中率做閉環,減少大家輪流調 prompt 的人工成本。
核心心態是:把 skills.yaml 當成模型參數來訓練,而不是只在 README 裡手動修改的一段文案。有了 autoswarm loop,你的本地 Agent 就能在既有硬體上持續「自我優化」,而不是每天重訓一個新模型。
🚀 你現在可以做的事
- 把現有 Agent 的系統 prompt 抽成
skills.yaml,為每個skill補上穩定id與對應 metric- 寫一個最小版
autoswarm.py,先針對單一 skill(例如faq_lookup)跑 reflect → rewrite → evaluate loop- 準備一小批驗證集(10–20 筆即可起步),接上 CI 或排程,讓 skills 每天自動小幅優化

