Day 25 到 Day 27,我們看了三種很不一樣的 Agent Harness。
Claude Code:
完整 Production Coding Harness。
Hermes Agent:
長期存在、會記憶、會排程、跨 Channel 的 Agent。
mini-swe-agent:
把 Harness 壓到最小,只留 Loop、Bash、Budget 與 Eval。
今天要看第四種方向。
它不是單純問:
Harness 應該有多少功能?
而是問:
Harness 本身要怎麼被組裝?
這就是 DeepSeek Harness 最有辨識度的地方。
Awesome Agent Architecture 目前研究的版本固定在:
dsh-v0.1.0-rc.7
在 A3 的 system matrix 裡,它被定位成:
Plugin-first harness: even the loop is a replaceable plugin.
而 companion repo learn-deepseek-harness 把它濃縮成一句更直接的規則:
Everything is a plugin, and every registration is reversible.
這篇的重點不是介紹 DeepSeek Model。
也不是比較 Coding 能力。
而是拆一個非常不同的 Harness 思想:
一般系統談 Plugin,常常是:
Core Agent
+
Optional Plugin A
+
Optional Plugin B
也就是:
Core 先存在,Plugin 只是加功能。
DeepSeek Harness 更激進。
它的核心方向更接近:
Kernel
↓
Plugins register capabilities
↓
Composition becomes the Agent
甚至 Agent Loop 本身也是可替換的一個 Plugin。
這代表:
不是 Core Agent 擁有 Plugins,而是 Plugin Composition 定義了這次 Agent 到底是什麼。
這是理解 dsh 最重要的第一步。
DeepSeek Harness 建在 Cordis 這類 Plugin Runtime 上。
最核心的概念不是:
class Agent
而是:
Context
+
Services
+
Events
+
Effects
+
Plugins
Plugin Mount 時可以:
Plugin Unmount 時,這些 Registration 必須能被撤回。
所以 companion repo 把第一個核心規則定義成:
Every registration is reversible.
想像你有一個 Plugin:
github-tools
它載入時註冊:
如果 Unload 時每個 Plugin 都要自己記得 Cleanup:
remove tool
remove listener
remove prompt
remove service
很容易漏。
漏掉一個 Listener,就可能出現:
所以 DeepSeek Harness 的 Kernel 更接近:
Plugin mount
↓
所有 registration 綁在同一個 lifecycle
Plugin dispose
↓
Runtime 自動 reverse effects
這讓「卸載能力」變成 Framework Property。
不是每個 Plugin 作者的自律。
Hooks 是:
在已知 Lifecycle Event 插入行為。
Plugin Kernel 更廣。
Plugin 可以提供:
所以 Hook 是 Extension Point。
Plugin 是 Composition Unit。
兩者不要混在一起。
一般 Agent 最常保存的是:
messages[]
也就是:
User
Assistant
Tool
Assistant
...
DeepSeek Harness 的設計方向更接近:
Session 先保存完整 Event Log,再從 Log 推導模型要看的 messages[]。
也就是:
Append-only Session Events
↓
deriveMessages()
↓
Model-visible History
這是一個很重要的反轉。
messages[] 不再是 Durable Truth。
它只是一個 Projection。
可以想像 Session 中保存:
turn/start
user/message
step/start
assistant/chunk
assistant/message
tool/call
tool/result
step/end
turn/end
真正 Durable 的是這些 Event。
模型下一輪要看的:
messages[]
由 deriveMessages() 從 Event Log 重新建立。
所以:
Session Log
=
Truth
Model Context
=
Derived View
這和 Day 9 Context Management 的概念非常一致。
Storage 不等於 Context。
如果你直接修改 messages[]:
刪除舊 Tool Result
替換舊 Summary
插入新的 Compaction
很難回答:
原本真正發生過什麼?
Append-only Log 則保留歷史。
你可以:
這對 Long-running Agent 特別重要。
因為:
Context 可以被壓縮,但歷史事實不一定要被銷毀。
DeepSeek Harness 架構中特別值得注意的一個 invariant 是:
如果某個資訊真的影響模型,它應該可以從 Session Log 重建。
也就是概念上:
Model-visible
⇔
Logged
這個原則非常強。
因為它直接改善 Debug:
如果 Agent 做出一個奇怪決策,我們可以問:
它當時到底看到了什麼?
然後從 Log 重新 Projection。
而不是猜某個 Runtime Object 當時長什麼樣。
如果 Log Append-only,那 Context 快滿時怎麼辦?
這就是 DeepSeek Harness Context Management 最有特色的地方。
它不一定要刪掉原始 Event。
可以改:
哪些 Event 被投影到目前 Model Surface。
概念:
Full Log
↓
Surface / Projection
↓
Compact Model View
A3 對 DeepSeek Harness 的整理是:
spill
↓
prune
↓
summary event
歷史 Log 仍然存在。
縮小的是模型當下看到的 View。
這可以用一句話記住:
History is durable. Context is replaceable.
如果你直接:
Old History
↓
Summary
↓
Delete Old History
Summary 一旦漏掉資訊,很難恢復。
如果原始 Log 還在:
Summary
只是目前 View
Raw Events
仍然可以重新讀
就能做到:
代價則是:
這是一個很清楚的 Trade-off。
這是 DeepSeek Harness 和前三個系統差異最大的地方。
一般架構:
Agent Core
內建 Loop
dsh 的方向:
Agent Interface
↓
Default Agent Loop Plugin
也就是 Default Loop 只是某個 Provider。
理論上可以被替換。
這代表:
Loop 不再是產品不可動的中心,而是一個 Capability Implementation。
如果未來要換:
不一定需要 Fork 整個 Harness。
既然:
Log = Truth
那每次 Step 就可以:
Read Log
↓
Derive messages[]
↓
Assemble System Prompt
↓
Resolve Tools
↓
Call Model
這和一般「持有一個 mutable messages list 一路 append」的 Mental Model 很不一樣。
它更接近:
Runtime State 每一輪重新投影成 Model Request。
這正是 Day 11 Prompt Assembly 的極端版本。
DeepSeek Harness 的 Tool Layer 也很值得看。
companion repo 把它整理成:
scoped registry
↓
pre
↓
ask
↓
guard
↓
execute
↓
post
這說明 Tool Call 不只是:
name → function
而是一條 Execution Pipeline。
更重要的是:
Denied 或 Error 的 Tool Call 也應該產生正常 Tool Result。
為什麼?
因為對 Agent 來說:
Permission Denied
也是 Environment Observation。
如果 Runtime 直接 Crash,Loop 無法學到:
這條路不能走。
DeepSeek Harness 的 Tool Scheduler 還有一個很值得研究的細節:
如果某個平行 Tool Call 因為前面的 Exclusive Operation 或 Abort 而沒有真的開始,系統仍可能需要產生一個對應 Result。
為什麼?
因為 Model 已經產生:
tool/call
如果沒有對應:
tool/result
Session Protocol 會留下半個 Interaction。
所以:
Protocol Completeness 有時比「真的有執行」更重要。
即使 Tool 沒跑,也要告訴模型:
這個 Call 被取消 / 未執行。
DeepSeek Harness 對 Tool Scheduling 也提供一個很好的例子。
有些 Tool:
read-only
parallel-safe
可以重疊執行。
有些 Tool:
exclusive
state-mutating
需要形成 Barrier。
所以 Scheduler 不能只是:
asyncio.gather(all_tools)
而要知道:
哪些可以平行,哪些必須序列化。
這和 Day 7 Subagent 的 Parallelism 問題完全一樣。
Parallel 是 Scheduling Decision。
不是「有多個 Call 就一起跑」。
Long-running Agent 常需要接受新資訊:
使用者補充需求
外部 Event
新的 Steering
但如果任何時間都直接插入 Runtime,可能破壞:
DeepSeek Harness 用 Inbox / Step Boundary 的概念處理這件事。
可以理解成:
New Message
↓
Inbox
↓
在安全 Boundary Claim
↓
進入下一個 Step / Turn
也就是:
Interrupt 有入口,但不是任意時刻 Mutation。
DeepSeek Harness 的 Prompt Assembly 還有一個有趣選擇。
Stable Section 可以組成 System Text。
但 Runtime Dynamic State 可以被重新發射成一個 Context Snapshot,而不是把所有東西都永久混進 System Prompt。
這讓不同來源維持比較清楚的身份:
Stable System Policy
Tool Schemas
Dynamic Runtime Context
Session History
這和 Day 11 的核心完全一致:
Prompt 是 Assembly Result,不是一個靜態字串。
DeepSeek Harness 的 Skill 方向也非常符合 Progressive Disclosure。
不是:
所有 Skill Body
全部塞 Context
而是:
Skill Catalog
先讓模型知道有什麼
需要時
Tool Call 載入 Skill Body
也就是:
Discover
↓
Select
↓
Load
這和 Day 8 的 Skill Architecture 對得非常乾淨。
DeepSeek Harness companion repo 特別把 Capability Seam 拆成三個角色:
例如 Filesystem:
Definition
定義 Filesystem Capability
Provider
Local FS / Remote FS / Sandbox FS
Consumer
Model-facing Tool 或其他 Plugin
只有 Interface 不夠。
如果 Consumer 還直接 import 某個 Local Implementation,就沒有真正可替換。
所以真正的 Seam 必須是:
定義、實作、使用者三者分離。
這個 Capability Seam 的價值在 Sandbox / Remote Environment 特別明顯。
如果:
Filesystem
+
Subprocess
都依賴同一個 Execution Provider。
把 Provider 從 Local 換成 Remote Sandbox 後:
File
Shell
PTY
LSP
都可以跟著移動。
不需要每個 Tool 各自寫:
LocalTool
RemoteTool
DockerTool
這是 Plugin-first Architecture 真正的收益。
DeepSeek Harness 的 Job Capability 很適合對照 Day 14。
一旦 Background Job 建立:
job_id
下一個問題不是:
怎麼 Poll?
而是:
誰擁有取消這個 Job 的權限?
如果 Child 建了一個 Job,Parent 是否可以 Cancel?
Session Dispose 時 Job 怎麼辦?
所以 Job Protocol 需要:
這就是 owner-fenced background-work protocol 的價值。
另一個很有 Plugin 味道的設計是 Subagent。
一般 OOP 直覺可能會做:
class ResearchAgent(Agent)
class CodingAgent(Agent)
DeepSeek Harness 更接近:
Delegation Interface
↓
Named Provider Registry
↓
某個 Provider 建立 Child
↓
回傳 Run Handle
也就是 Subagent 是 Capability。
不是固定 Class Hierarchy。
這讓不同 Child Runtime 可以被替換。
前面所有東西最後會在 Composition 層相遇。
例如一個 Agent Preset 可以決定:
所以真正的 Agent 更像:
Composition
=
Plugin Set
+
Config
+
Providers
不是:
One giant Agent class
這是 DeepSeek Harness 和 Claude Code / mini-swe-agent 最不同的 Mental Model。
Companion repo 對 Composition 有一個很值得學的決策:
Patch Layer 對整個 Config Entry List 做 Replacement,而不是偷偷 Deep Merge。
原因是 Deep Merge 很容易產生:
Whole-config Replace 雖然比較明確地要重述 Config,但結果更容易推理:
這一層最後到底產生什麼 Composition?
對 Plugin System 來說,可預測性很重要。
DeepSeek Harness 還有 ACP 這類 Automation / Editor Bridge。
它再次說明:
Agent Core 不應該和某一個 UI 綁死。
外部 Client 可以透過 Protocol:
而 Agent 內部仍然使用同一套:
Session
Agent
Tools
Events
這和 Day 18 Protocol / Day 20 Channels 的邊界一致。
可以簡化成:
| Claude Code | DeepSeek Harness | |
|---|---|---|
| 核心印象 | 完整 Coding Harness | Plugin-first Runtime |
| 組裝方式 | 完整產品內部 Harness | Cordis Plugin Composition |
| Session Mental Model | Interactive coding session | Append-only event-sourced log |
| Loop | Harness 核心的一部分 | 可替換 Agent Loop Provider |
| Context | Reduction / compaction | 從 durable log 投影 Surface |
| 擴充 | Hooks / Tools / MCP / Subagents | Services / Events / Plugins / Providers |
| 最值得學 | Production control surface | Runtime composition and durable truth |
兩個都很完整。
但設計重心不同。
mini-swe-agent:
One loop
One bash tool
One environment
One budget
DeepSeek Harness:
Kernel
+
Plugin Lifecycle
+
Event Log
+
Projection
+
Capability Seams
+
Composition
mini 的問題是:
最少要多少 Harness?
dsh 的問題是:
Harness 變大後,怎麼讓每個部分仍然可替換、可卸載、可重組?
這是兩個完全不同的最佳化方向。
如果只看目錄,你可能會覺得:
這只是很多 Package。
真正有價值的是背後三個 Invariant。
Plugin-first Architecture 也不是免費的。
deriveMessages() 或 Surface Projection 錯。模型仍然會看到錯的世界。到 Day 28,我們已經有四個非常不同的答案:
| System | 最值得學的地方 | 核心問題 |
|---|---|---|
| Claude Code | Full Harness | Model 怎麼安全地碰真實 Repository? |
| Hermes Agent | Memory / Skills / Always-on | Agent 怎麼跨時間長期存在? |
| mini-swe-agent | Minimal Loop / Budget / Eval | 最少多少 Harness 就夠? |
| DeepSeek Harness | Plugin Kernel / Session Log / Composition | Harness 變大後怎麼保持可組裝與可替換? |
這四個系統不是互相取代。
它們其實對應四種不同壓力:
Claude Code
Complex Environment
Hermes
Long Time Horizon
mini-swe-agent
Minimal Research Surface
DeepSeek Harness
Runtime Composition Complexity
這也是為什麼學 Agent Architecture 最有效的方法,不是只追一個 Framework。
而是:
用同一套 Mechanism Lens 去比較不同 Harness,在不同 Failure Mode 下做了什麼取捨。
DeepSeek Harness 最有價值的設計,不是「它用了 Plugin」。
而是它把 Plugin 思想一路推到 Harness 核心:
Loop
Tools
Prompt
Session
Jobs
Subagent
Capability
Composition
都可以透過明確的 Seam 被組裝。
同時,它用 Append-only Session Log 把:
發生過什麼
和:
模型現在看到什麼
分離。
最後可以把整篇壓成一句:
Claude Code 教我們怎麼控制 Agent,Hermes 教我們怎麼讓 Agent 長期存在,mini-swe-agent 教我們怎麼刪掉不必要的 Harness,而 DeepSeek Harness 教我們怎麼讓 Harness 本身可組裝。
完整系列與程式碼範例收錄於 https://github.com/hardness1020/awesome-agent-architecture