打開原始碼才發現:三個 Agent 框架,三種截然不同的設計哲學
打開原始碼才發現:三個 Agent 框架,三種截然不同的設計哲學
這個系列從今天開始。我打算借助 AI 工具輔助,直接從原始碼讀起——deepagents、openclaw、hermes-agent 三個 open source Agent 框架,邊讀邊整理成筆記,帶著你一起拆。你可能以為這三個框架做的是差不多的事——不就是 LLM + tools + loop?但打開原始碼之後才發現,它們對「Agent 到底要長什麼樣」這個問題,給的答案幾乎完全不重疊。
同樣叫 Agent 框架,deepagents 的作者在意的是「怎麼讓開發者用最少的程式碼把 Agent 嵌進自己的系統」;openclaw 在意的是「怎麼讓一個 Agent 24 小時跑在你的 WhatsApp 裡而不壞掉」;hermes-agent 的作者想的是「怎麼讓 Agent 在幫你做事的同時,收集訓練資料來訓練更好的模型」。三個完全不同的問題,所以設計出三個完全不同的架構。
這篇是這個系列的第一篇,我想先用這三個框架的比較,勾出幾個值得深挖的設計問題。後續的文章會逐一深入。
讀完這篇,你會理解:
- 為什麼同樣叫「Subagent」,deepagents 和 openclaw 的實作幾乎是兩件不同的事
- 從三個框架的架構選擇中,可以問出哪六個 Agent 系統設計的核心問題
- 什麼場景適合哪個框架——不是哪個比較好,而是你在解什麼問題
這篇不是框架使用教學,也不是「最佳實踐清單」。是從設計決策的角度,試著解釋這些框架為什麼長那個樣子。
三個框架,三種定位
先快速認識三個主角。
deepagents 是 LangChain AI 做的,定位是 SDK——你的 Python 應用裡需要一個 Agent,create_deep_agent() 一行叫起來,其他的它幫你想好。架構核心是一層 Middleware Stack,上面跑 LangGraph。選它,通常是因為你已經在 Python 生態裡,需要最快把 Agent 接進去。
openclaw 是社群專案,定位是個人助理平台。它連接了 20+ 個通訊頻道(WhatsApp、Telegram、Slack、Discord…),讓你的 Agent 常駐在這些平台,隨時待命。架構核心是 Channel Gateway → Session → embedded runner 這個三層結構。選它,通常是因為你想要一個「一直在線」的助理,而不是一個「被程式呼叫的服務」。
hermes-agent 是 NousResearch 做的,定位更接近研究工具。它支援 6 種執行環境(local、Docker、SSH、Modal…),有一個可插拔的 Context Engine,最特別的是有個完整的學習閉環:每次完成任務,就把 trajectory 存成 ShareGPT 格式,可以直接接到 Atropos RL 環境訓練模型。選它,通常是因為你在做 Agent 研究,或是需要在沒有標準環境的機器上跑 Agent。
用一張表快速對比:
| 維度 | deepagents | openclaw | hermes-agent |
|---|---|---|---|
| 定位 | SDK 工具箱 | 個人助理平台 | 自我進化代理 |
| 語言 | Python | TypeScript/Node | Python |
| 核心模式 | Middleware Stack + LangGraph | Gateway → Session → runner | AIAgent + 學習迴圈 |
| 主要用途 | 嵌入自己的系統 | 24/7 多平台助理 | 研究 + 自主代理 |
| LLM 彈性 | LangChain 任意 Model | 20+ Provider,自動輪換 | OpenAI-compat 任意端點 |
架構長什麼樣:三張圖看清楚
文字描述還是太抽象,直接看架構圖。
這三個框架本質上都在做同一件事:Harness Engineering——為 LLM 搭建工具鏈、狀態管理與執行控制,讓 LLM 從「回答問題的服務」變成「能完成複雜任務的 Agent」。差別在於,每個框架對「Harness 應該長什麼樣」的判斷,各自走了截然不同的路。
deepagents:Middleware Stack → LangGraph
create_deep_agent()
│
Middleware Stack(有序疊加)
┌─────────────────────────────┐
│ TodoListMiddleware │ ← write_todos 工具
│ FilesystemMiddleware │ ← read/write/edit/glob/grep
│ SubAgentMiddleware │ ← task() 工具
│ SummarizationMiddleware │ ← 自動 context 壓縮
│ SkillsMiddleware │ ← 載入 SKILL.md
│ MemoryMiddleware │ ← AGENTS.md 記憶
│ HumanInTheLoopMiddleware │ ← 中斷點審批
└─────────────────────────────┘
│
CompiledStateGraph(LangGraph)
│ 透過 checkpointer 持久化
SQLite / Redis / Postgres
每一層 Middleware 做一件事,組合起來就是一個完整的 Agent。這個架構的核心假設是:Agent 的能力應該是可以插拔的,而不是焊死在一個大型 class 裡。
openclaw:Gateway → Session → Embedded Runner
用戶輸入(WhatsApp / Telegram / Slack / CLI...)
│
Channel Gateway(20+ 平台)
│
Session Router(agent-scope, session-key)
│
pi-embedded-runner(核心 LLM 執行引擎)
│ ← 多 Provider,自動 failover
Model(Anthropic / OpenAI / Google / OpenRouter...)
│
Tool Execution Layer
┌────────────────────────────────────────┐
│ Canvas / CronJob / TTS / ImageGen │
│ WebSearch / WebFetch / PDF │
│ Sessions-Spawn / Subagents │
└────────────────────────────────────────┘
│
Context Compaction(自動壓縮)
openclaw 的架構核心假設是:用戶和 Agent 的互動發生在各種平台上,框架要負責把這些入口統一起來。Gateway 層讓 Agent 邏輯和通訊頻道完全解耦,你換一個平台不需要動 Agent 本身。
hermes-agent:AIAgent + 學習迴圈
用戶輸入(CLI / Telegram / Discord / Slack...)
│
AIAgent.run_conversation()
│
ContextEngine(pluggable)
┌──────────────────────────────┐
│ CompressorEngine(預設) │ ← 達到 threshold 自動壓縮
│ LCM Engine(可替換) │ ← 外部 plugin
└──────────────────────────────┘
│
MemoryManager(檔案型記憶 + 外部 provider)
│
LLM Call(OpenAI-compat API)
│
Tool Execution(40+ 工具)
│
執行環境(6 種 Backend)
local / Docker / SSH / Daytona / Singularity / Modal
│
學習迴圈:Trajectory 儲存
→ ShareGPT 格式 → batch_runner → Atropos RL
hermes-agent 的架構核心假設是:Agent 不只是一個執行工具的服務,它應該在執行的過程中不斷學習。這個假設決定了它從 ContextEngine 到 Trajectory 儲存的整條設計鏈。
同樣叫 Subagent,差多少?
讓我用一個具體的設計問題來讓差距變得具體:當主 Agent 需要派一個子任務給另一個 Agent,這個「Subagent」應該是什麼?
在 deepagents 裡,Subagent 有三種型態,但最基本的一種是這樣的:
SubAgent(
name="researcher",
description="專門負責查資料的子代理",
system_prompt="你是一個研究員,負責..."
)
本質上,它是一個宣告式的工具定義。主 Agent 呼叫它,就像呼叫一個 function。呼叫完,結果回來,任務結束。這個設計的優點是簡單、可預測、容易測試。代價是:如果子任務需要跑很長時間、需要暫停後繼續、或是父 Agent 中途 crash 了,這個模型就不好處理。
openclaw 的設計思路完全不同。它有一個 Subagent Registry,記錄系統裡每個子代理的狀態:
subagent-registry
├── 每個子代理的 session-key
├── spawn / complete / error 狀態追蹤
├── depth limit(防止 A→B→C→... 無限遞迴)
└── orphan-recovery(父代理 crash → 子代理自動清理)
在 openclaw 的世界裡,Subagent 不是一次性的 function call,而是一個有生命週期的實體——它會被創建、被引導、會等待、會完成,如果父代理突然消失,它也能被正確回收。這個設計的代價是複雜,但它解決的問題是真實的:當 Agent 要長時間跑在用戶的手機上,「父代理掛掉子代理繼續消耗資源」這件事必須被處理。
這不是哪個設計比較好。是兩個框架在解不同的問題,然後做了不同的選擇。
比較之後,六個值得深挖的設計問題
讀完這三個框架,我整理出六個設計概念,覺得是 Agent 系統裡最值得花時間理解的。
1. Middleware Stack(deepagents)
deepagents 的 Agent 是由一層 Middleware Stack 組成的,每個 Middleware 負責一件事:
FilesystemMiddleware → 增加檔案操作工具
MemoryMiddleware → 把記憶注入 system prompt
SummarizationMiddleware → 監控 context,超過 threshold 就壓縮
HumanInTheLoopMiddleware → 插入人工審批的中斷點
這個模式就是 Harness Engineering 的核心體現——用一層可組合的中介層,替 LLM 建立工具使用能力、記憶管理和執行控制,而不是把這些邏輯全部混入 Agent 本身。設計洞見是:Agent 的能力不應該是一個大型 class,而是一組正交關切點的有序組合。每個 Middleware 可以單獨測試、單獨替換,整個 stack 的行為由組合決定。這和 HTTP server 的 middleware 模式(Express.js、FastAPI)是同一個概念,但用在 LLM Agent 上。
2. Pluggable Context Engine(hermes-agent)
hermes-agent 把 context 壓縮策略抽成一個獨立的介面:
class ContextEngine(ABC):
threshold_percent: float # 何時觸發壓縮
protect_first_n: int # 保護最初 N 輪(設定 context)
protect_last_n: int # 保護最後 N 輪(工作 context)
def should_compress(self) -> bool: ...
def compress(self, messages) -> messages: ...
def get_extra_tools(self) -> list: ... # Engine 可以注入工具!
這個設計的洞見是:不同任務需要不同的 context 管理策略。短任務不壓縮;長研究任務做摘要壓縮;複雜的多步驟任務可能需要結構化壓縮。把這個策略硬編碼進 Agent,等於把一個本來應該可以調整的旋鈕焊死了。
3. Session Registry + 孤兒恢復(openclaw)
前面已經提到了。核心問題是:子代理不是一次性呼叫,當它的生命週期比父代理還長,你需要一個中央狀態表來追蹤它。openclaw 的 orphan-recovery 機制,就是在處理這個邊界情況——在常駐型 Agent 系統裡,這個邊界早晚會遇到。
4. Memory Fencing(hermes-agent)
hermes-agent 把 memory 注入對話的方式是這樣的:
<memory-context>
[System note: The following is recalled memory context, NOT new user input.]
你喜歡 Python 勝過 JavaScript。
上次我們討論了 K8s networking 問題。
</memory-context>
為什麼要加這個 XML fence?因為如果你直接把記憶內容插進 user message,LLM 很可能把它解讀成「用戶剛剛說的話」,混淆對話脈絡。fence 加上明確的 system note,讓 LLM 知道這段是背景記憶,不是新指令。看起來是小細節,但在長期運行的 Agent 裡,這個邊界如果不清楚,對話脈絡很容易開始亂掉。
5. Auth Profile Rotation(openclaw)
openclaw 有一個 auth-profile 機制,讓你預設多組 API key,然後自動輪換:
auth-profiles(多個 API key)
→ failover(自動切換壞掉的 key)
→ cooldown(限流後冷卻計時)
→ model-fallback(找下一個可用 model)
這個設計解決的是 24/7 助理的可用性問題——當你的 Agent 要隨時在線,你不能允許因為單一 API key 被限流就讓整個服務掛掉。這是一個在「週末 demo」場景完全不需要想的問題,但在「長期運行的個人助理」場景裡是剛需。
6. Trajectory → RL 閉環(hermes-agent)
hermes-agent 最與眾不同的設計:
用戶使用 → Trajectory 自動儲存(ShareGPT 格式)
↓
batch_runner(批次生成訓練資料)
↓
Atropos RL 環境(強化學習)
↓
訓練更好的 tool-calling 模型
↓
用戶使用更好的 hermes → ...
hermes-agent 不只是一個 Agent 框架,它同時是一台資料收集機器。每一次用戶和 Agent 的互動,都在餵養下一代模型的訓練管道。這個設計的前提是 NousResearch 本身在做模型訓練——對一般的 Agent 開發者來說,這個閉環不一定能直接拿來用,但「把 Agent 的執行軌跡當作可利用的訓練資料」這個思維,值得記住。
適用場景速查
不同框架解不同的問題,選錯了再怎麼調也只是在解決本不應該存在的問題。
| 你的情境 | 最適合 | 關鍵理由 |
|---|---|---|
| 要把 Agent 能力嵌入現有的 Python 後端服務 | deepagents | 純 SDK,不需要重構現有架構,直接接 FastAPI / Flask |
| 任務跑到一半需要人工確認,或要在多次對話之間保留執行狀態 | deepagents | LangGraph checkpointer 持久化狀態,HumanInTheLoopMiddleware 插入審批點 |
| 想要一個隨時待命的個人助理,同時接管多個通訊平台 | openclaw | 20+ 頻道接入,Session 常駐,隨時觸發 |
| Agent 要 24/7 跑,不能因為某個 Provider 限流就中斷 | openclaw | Auth profile rotation 自動切換 API key 和 model |
| 在做 Agent 研究,需要把執行軌跡拿來訓練或分析 | hermes-agent | Trajectory 自動存為 ShareGPT 格式,直通 Atropos RL 訓練環境 |
| Agent 要能跨環境部署(本機、Docker、SSH、Serverless 都有) | hermes-agent | 6 種執行 backend,Modal serverless 支援按需喚起 |
這個系列要做什麼
我打算把這三個框架的設計決策,一個一個拆開來看。不是要寫使用教學,也不是要比較哪個框架更好。是想回答一個問題:當你在設計自己的 Agent 系統,面對某一個具體的架構問題,那些認真做過的人是怎麼想的?
上面六個設計概念,每一個背後都有不止一種可能的做法。deepagents 的 Middleware Stack 為什麼要這樣疊?hermes-agent 的 Pluggable Context Engine 在什麼情況下才值得這樣設計?openclaw 的 multi-agent 生命週期管理複雜到這個程度,真的是必要的嗎?
這些問題,後續的文章會一篇一篇回來回答。
結語:三個框架,三個對「Agent 是什麼」的不同回答。在讀懂這些差異之前,很難真正知道自己要設計的是哪一種東西。