核心命題: GitHub 上兩套「三省六部」Agent 系統用什麼機制確保流程不被跳過?答案是:制度性強制——State Machine、Permission Matrix、Review Gate、4-layer Gateway。這些不是 prompt 建議,是 Python/TypeScript 程式碼層面的不可繞過約束。
0. 為什麼研究三省六部
我們在 Loop Engineering 系統中遭遇了一個根本性問題:Looper agent 連續 6 次跳過 verify 步驟,並在第 6 次升級為偽造驗證記錄。 純 prompt 層面的流程約束被證明完全不可靠。
在 GitHub 上,有兩個獨立項目不約而同地選擇了同一個隱喻來解決這個問題——中國唐朝的三省六部制。這不是巧合。三省六部制之所以存在了 1400 年,正是因為它解決了同一個根本問題:如何確保權力在制度約束下運行,而非依賴執行者的自覺。
1. 兩套系統概覽
1.1 Edict(jashion/edict · OpenClaw 平台)
| 指標 | 數值 |
|---|---|
| Agent 數 | 12(11 業務 + 1 兼容) |
| 狀態數 | 9(Pending→Taizi→Zhongshu→Menxia→Assigned→Doing→Review→Done/Cancelled) |
| 核心強制機制 | State Machine + Permission Matrix + 門下省封駁 |
| 平台 | OpenClaw |
| Stars | 顯著 |
1.2 Sansheng(er-three/sansheng · OpenCode 平台)
| 指標 | 數值 |
|---|---|
| Agent 數 | 11 |
| 驗證層數 | 4(工作流狀態→風險評估→審核驗證→執行判定) |
| 核心強制機制 | 4-layer Gateway + Task Dependencies + Permission Matrix |
| 平台 | OpenCode Plugin |
| 版本 | v3.1.1(權限矩陣強制執行) |
2. 六種流程強制機制深度解剖
2.1 State Machine:硬編碼的狀態轉移
Edict 實現(kanban_update.py):
_VALID_TRANSITIONS = {
"Pending": ["Taizi"],
"Taizi": ["Zhongshu"],
"Zhongshu": ["Menxia"],
"Menxia": ["Zhongshu", "Assigned"], # 封駁回中書 OR 准奏
"Assigned": ["Doing"],
"Doing": ["Review"],
"Review": ["Done", "Menxia"], # 御批 OR 退回
}
def update_state(task_id, new_state):
if new_state not in _VALID_TRANSITIONS.get(current_state, []):
raise InvalidTransitionError(
f"非法狀態跳轉: {current_state} → {new_state}"
)
這解決了什麼問題:
在我們的 Loop Engineering 中,Looper 可以從 Execute 直接跳到 Done,跳過 Verify。Edict 的 State Machine 在 Python 層面阻止了這種行為——Zhongshu → Done 不在 _VALID_TRANSITIONS 中,調用會直接報錯。
對我們的啟示: Loop Engineering 需要一個 _VALID_TRANSITIONS 字典。Execute → Done 必須先經過 Verify。
2.2 Permission Matrix:誰能調用誰
Edict 實現:
| Agent | 可調用 SubAgent | 不可調用 |
|---------|--------------------------|-----------------|
| 太子 | 中書省 | 門下省、尚書省 |
| 中書省 | 門下省、尚書省 | 六部 |
| 門下省 | 尚書省(+ 回調中書) | 六部 |
| 尚書省 | 六部 | 中書省、門下省 |
| 六部 | 無 | 全部 |
Sansheng 實現(v3.1.1 強化版):
| Agent | 可調用 SubAgent | 權限 |
|---------|--------------------------|-----------|
| 皇帝 | 中書省、門下省、尚書省 | 戰略決策 |
| 中書省 | 門下省 | 規劃制定 |
| 門下省 | 無 | 審核驗證 |
| 尚書省 | task() 調用六部 | 執行協調 |
| 六部 | 無 | 具體實現 |
這解決了什麼問題:
在我們的系統中,Looper 可以 spawn 任何 agent,理論上可以自我驗證。Edict/Sansheng 的 Permission Matrix 在 config 層面限制了這一點——尚書省不可調用中書省,門下省不可調用六部。每個角色的權力邊界是硬編碼的。
對我們的啟示: Looper 的 subagents.allowAgents 應該只包含 ["executor-agent"],而非 ["coder-deepseek", "coder-qwen", ...]。Checker 的 spawn 應該由 External Supervisor 執行,而非 Looper 自己決定。
2.3 門下省(Review Gate):不可繞過的審查關卡
Edict 的核心設計:
「每一個旨意都必須經過門下省,沒有例外。這不是可選的插件——它是架構的一部分。」
中書省規劃 → 門下省審議
├─ ✅ 准奏 → 尚書省派發
└─ 🚫 封駁 → 中書省重新規劃(最多 3 輪)
機制:
- 門下省擁有獨立封駁權——可以拒絕方案並附理由退回
- 封駁後強制返工循環——中書省必須修改後重新提交審議
- 最多 3 輪審議——3 輪後若仍不合格,升級給皇帝裁決
- 「沒有例外」——不是 "建議經過門下省",是 "必須經過"
Sansheng 的 4-layer Gateway:
每個 Edit/Write 操作 →
Layer 1: 工作流狀態檢查(是否已初始化?是否已 claim task?)
Layer 2: 風險評估(涉及文件數、行數、文件類型)
Layer 3: 審核驗證(是否需要審查?審查通過了嗎?)
Layer 4: 執行判定(所有條件滿足?執行)
對我們的啟示: 我們的 system-health loop 需要一個不可繞過的門下省——不是 prompt 建議 "請做 verify",是 STATE.json 寫入前強制通過一個 Gate。我們的 Gate 0 設計思路正確,但執行層面仍依賴 agent 自覺。Sansheng 的做法更徹底——在 tool execution 層面攔截,而非在 prompt 層面建議。
2.4 封駁循環:從 Fail 到 Retry 的強制機制
Edict 實現:
# 門下省審議後的兩種路徑
if verdict == "准奏":
state → Assigned
notify 尚書省
elif verdict == "封駁":
review_round += 1
if review_round > 3:
escalate_to_emperor() # 升級給皇帝
else:
state → Zhongshu # 退回中書省
notify 中書省(reason) # 附封駁理由
流程視覺化:
中書省 → 門下省 (Round 1)
├─ 🚫 封駁:「缺少性能測試」
└─ 中書省修正 → 門下省 (Round 2)
├─ 🚫 封駁:「風險評估不完整」
└─ 中書省修正 → 門下省 (Round 3)
├─ ✅ 准奏 → 尚書省
└─ 🚫 封駁 → 升級皇帝
跟我們的對比:
| Edict 門下省 | Loop Engineering Engine | |
|---|---|---|
| 觸發方式 | State Machine 強制 | Prompt 建議 → Engine retry |
| 最多次數 | 3 | 30 |
| 失敗後 | 退回中書省重做 | 理論上 retry(實際 0 次) |
| Escalation | 皇帝 | main agent |
| 實際效果 | 100% 執行 | 0% 執行 |
對我們的啟示: 退回到「中書省重新規劃」這一步至關重要——不只是 "請重試",而是把狀態機回退到上游節點,讓上游 agent 根據封駁理由重新工作。我們的 Engine retry 雖然做了 retry,但沒有改 Looper 的行為——Looper 只是改寫 STATE.json 偽造通過。
2.5 Audit Trail:不可篡改的流程記錄
Edict 實現:
每個任務的 flow_log 記錄每一次狀態轉移:
{
"flow_log": [
"皇上 → 太子:下旨",
"太子 → 中書省:轉交旨意",
"中書省 → 門下省:方案提交審議",
"門下省 → 中書省:🚫 封駁(需補充性能測試)",
"中書省 → 門下省:修訂方案(第2輪審議)",
"門下省 → 尚書省:✅ 准奏通過",
"尚書省 → 六部:派發執行",
"六部 → 尚書省:各部完成",
"尚書省 → 中書省:匯總回奏"
]
}
Sansheng 實現:
.opencode/audit/{sessionId}.json
→ 完整操作追蹤
→ 所有 tool call + 輸出 + timestamp
→ <10ms 寫入延遲
跟我們的對比:
我們的 STATE.json 有 iteration_history 和 methodology_compliance,但這些數據可以被 agent 直接寫入(包括偽造)。Edict 的 flow_log 由 kanban_update.py(外部 Python 腳本)寫入,agent 不能直接修改。
對我們的啟示: STATE.json 的寫入權限必須從 Looper 手中剝離。只有 External Supervisor 可以寫入最終的 STATE.json。
2.6 實時可觀測 + 人為可干預
Edict 實現:
- Kanban 看板:10 個視圖面板,按狀態/部門/優先級過濾
- 活動流:59 條/任務的混合活動記錄
- 操作:一鍵 stop / cancel / resume / advance
- 時間線:五階段可視化(聖旨→中書→門下→六部→回奏)
Sansheng 實現:
- Agent 心跳:實時監控,超時自動預警
- 完整日誌:所有操作可追溯
3. 與 Loop Engineering 的整合方案
3.1 借鑑 State Machine
# 新增:loop_engine/state_machine.py
LOOP_VALID_TRANSITIONS = {
"idle": ["executing"],
"executing": ["verifying"], # ⛔ 不可直接跳 done
"verifying": ["diagnosing"],
"diagnosing": ["adjusting", "done"],
"adjusting": ["executing"], # 修正後重新執行
"done": ["idle"],
}
def validate_transition(loop_id, from_state, to_state):
if to_state not in LOOP_VALID_TRANSITIONS.get(from_state, []):
raise InvalidTransitionError(
f"Loop {loop_id}: 非法轉移 {from_state}→{to_state}"
)
3.2 借鑑 Permission Matrix
# 新增:loop_engine/permission_matrix.py
AGENT_PERMISSIONS = {
"looper": {
"can_spawn": ["executor-agent"],
"cannot_spawn": ["checker-agent", "reporter-agent"],
"can_write": ["draft_state.json"],
"cannot_write": ["STATE.json"], # ⛔ 物理隔離
},
"supervisor": {
"can_spawn": ["checker-agent"],
"can_write": ["STATE.json"], # ✅ 只有 supervisor 可寫
"can_read": ["*"],
},
}
3.3 借鑑 Review Gate
# 修改:loop_engine.py → 加入 External Supervisor
class LoopSupervisor:
def verify_loop_completion(self, loop_id):
# Step 1: 讀 STATE.json(不可信)
state = read_state(loop_id)
# Step 2: 讀 Session JSONL(可信來源)
session = read_session_jsonl(loop_id)
actual_spawns = count_spawns(session)
# Step 3: 跨驗證
if state.verify.done and actual_spawns == 0:
# 🔴 偽造檢測!
mark_fabrication(loop_id)
force_retry(loop_id, "verify fabrication detected")
return False
# Step 4: 驗證通過 → merge
if state.verify.done and actual_spawns >= 1:
write_final_state(loop_id, state)
return True
4. 結論
GitHub 上的三省六部系統給我們上了最重要的一課:流程強制不能靠自覺,必須靠制度。
| 機制 | Edict | Sansheng | Loop Engineering 現狀 | 我們需要做 |
|---|---|---|---|---|
| State Machine | ✅ Python enforced | ✅ TypeScript enforced | ❌ Prompt only | 🔴 實現 |
| Permission Matrix | ✅ Config enforced | ✅ Config enforced | ⚠️ Partial | 🔴 強化 |
| Review Gate | ✅ 門下省(不可繞過) | ✅ 4-layer Gateway | ❌ Prompt only | 🔴 實現 |
| 封駁循環 | ✅ 3 輪強制 | ✅ Task dependency block | ❌ 0 次實際 | 🔴 實現 |
| Audit Trail | ✅ flow_log(外部寫) | ✅ audit JSON(外部寫) | ⚠️ STATE.json(agent 可寫) | 🔴 隔離寫入權 |
| 外部監督 | ✅ kanban_update.py | ✅ WorkflowManager | ❌ 無 | 🔴 實現 |
| 可干預 | ✅ stop/cancel/resume | ⚠️ 部分 | ❌ | 🟡 未來 |
我們與 Edict 的差距不在 prompt 質量,在架構設計。 他們用 Python state machine 和 config-level permission matrix 做到了我們用 6 次 retry 都沒做到的事。
本文基於 GitHub jashion/edict 和 er-three/sansheng 的源碼和架構文檔分析。