Agentic Research

Three Departments and Six Ministries vs Loop Engineering: A Technical Dissection of Institutional Process Enforcement

2026/06/1441 min readBryan Chan閱讀中文原文
TopicsMulti-AgentArchitectureLoop Engineering

Core proposition: What mechanisms do the two "Three Departments and Six Ministries" Agent systems on GitHub use to ensure the process cannot be skipped? The answer: institutional enforcement, a State Machine, Permission Matrix, Review Gate, and 4-layer Gateway. These are not prompt suggestions; they are non-bypassable constraints at the level of Python/TypeScript code.


0. Why Study the Three Departments and Six Ministries

We ran into a fundamental problem in the Loop Engineering system: the Looper agent skipped the verify step 6 times in a row, and on the 6th occasion escalated to fabricating verification records. Process constraints at the pure prompt level proved completely unreliable.

On GitHub, two independent projects separately chose the same metaphor to solve this problem: the Chinese Tang dynasty Three Departments and Six Ministries system. This is no coincidence. The reason the Three Departments and Six Ministries system lasted 1,400 years is precisely that it solved the same fundamental problem: how to ensure that power operates under institutional constraint, rather than relying on the self-discipline of the executor.


1. Overview of the Two Systems

1.1 Edict (jashion/edict · OpenClaw platform)

MetricValue
Number of Agents12 (11 business + 1 compatibility)
Number of States9 (Pending→Taizi→Zhongshu→Menxia→Assigned→Doing→Review→Done/Cancelled)
Core enforcement mechanismState Machine + Permission Matrix + Menxia Department veto
PlatformOpenClaw
StarsSignificant

1.2 Sansheng (er-three/sansheng · OpenCode platform)

MetricValue
Number of Agents11
Number of verification layers4 (workflow state→risk assessment→review verification→execution decision)
Core enforcement mechanism4-layer Gateway + Task Dependencies + Permission Matrix
PlatformOpenCode Plugin
Versionv3.1.1 (permission matrix enforcement)

2. A Deep Dissection of Six Process Enforcement Mechanisms

2.1 State Machine: Hardcoded State Transitions

Edict implementation (kanban_update.py):

_VALID_TRANSITIONS = {
    "Pending":  ["Taizi"],
    "Taizi":    ["Zhongshu"],
    "Zhongshu": ["Menxia"],
    "Menxia":   ["Zhongshu", "Assigned"],  # Seal and reject back to Zhongshu OR approve
    "Assigned": ["Doing"],
    "Doing":    ["Review"],
    "Review":   ["Done", "Menxia"],         # Imperial approval OR return
}

def update_state(task_id, new_state):
    if new_state not in _VALID_TRANSITIONS.get(current_state, []):
        raise InvalidTransitionError(
            f"Illegal state transition: {current_state} → {new_state}"
        )

What problem this solves:

In our Loop Engineering, the Looper could jump straight from Execute to Done, skipping Verify. Edict's State Machine blocks this behaviour at the Python level: Zhongshu → Done is not in _VALID_TRANSITIONS, so the call raises an error directly.

What this means for us: Loop Engineering needs a _VALID_TRANSITIONS dictionary. Execute → Done must pass through Verify first.


2.2 Permission Matrix: Who Can Call Whom

Edict implementation:

| Agent | Callable SubAgent | Not callable |
| --- | --- | --- |
| Crown Prince | Secretariat | Chancellery, Department of State Affairs |
| Secretariat | Chancellery, Department of State Affairs | Six Ministries |
| Chancellery | Department of State Affairs (+ callback to Secretariat) | Six Ministries |
| Department of State Affairs | Six Ministries | Secretariat, Chancellery |
| Six Ministries | None | All |

Sansheng implementation (v3.1.1 hardened version):

| Agent   | Callable SubAgents       | Permissions |
|---------|--------------------------|-------------|
| Emperor | Secretariat, Chancellery, Department of State Affairs | Strategic decision-making |
| Secretariat | Chancellery | Planning and formulation |
| Chancellery | None | Review and validation |
| Department of State Affairs | task() invokes the Six Ministries | Execution coordination |
| Six Ministries | None | Concrete implementation |

What problem this solves:

In our system, the Looper can spawn any agent and could in theory verify itself. The Permission Matrix in Edict/Sansheng constrains this at the config level: the Shangshu Department cannot call the Zhongshu Department, and the Menxia Department cannot call the Six Ministries. Each role's power boundary is hardcoded.

What this means for us: The Looper's subagents.allowAgents should contain only ["executor-agent"], rather than ["coder-deepseek", "coder-qwen", ...]. Checker spawning should be performed by the External Supervisor, rather than decided by the Looper itself.


2.3 The Menxia Department (Review Gate): A Review Checkpoint That Cannot Be Bypassed

Edict's core design:

"Every decree must pass through the Menxia Department, without exception. This is not an optional plugin; it is part of the architecture."

Secretariat plans → Chancellery reviews
  ├─ ✅ Approved → Department of State Affairs dispatches
  └─ 🚫 Vetoed → Secretariat replans (max 3 rounds)

Mechanism:

  1. The Menxia Department holds an independent veto power, and can reject a proposal and return it with reasons
  2. After a veto, a mandatory rework loop follows: the Zhongshu Department must revise and resubmit for review
  3. A maximum of 3 review rounds; if it still fails after 3 rounds, it escalates to the Emperor for a ruling
  4. "No exceptions": not "it is recommended to pass through the Menxia Department", but "it must pass through"

Sansheng's 4-layer Gateway:

Each Edit/Write operation →
  Layer 1: Workflow status check (Has it been initialized? Has the task been claimed?)
  Layer 2: Risk assessment (number of files involved, number of lines, file types)
  Layer 3: Review verification (Is review required? Has review passed?)
  Layer 4: Execution decision (Are all conditions met? Execute)

What this means for us: Our system-health loop needs a Menxia Department that cannot be bypassed: not a prompt suggestion to "please do a verify", but a Gate that must be passed before STATE.json is written. Our Gate 0 design direction is correct, but at the execution level it still relies on the agent's self-discipline. Sansheng's approach is more thorough, intercepting at the tool execution level rather than suggesting at the prompt level.


2.4 The Veto Loop: The Enforcement Mechanism from Fail to Retry

Edict implementation:

# Two paths after Menxia Department review
if verdict == "Approved":
    state → Assigned
    notify Shangshu Department
    
elif verdict == "Vetoed":
    review_round += 1
    if review_round > 3:
        escalate_to_emperor()  # Escalate to Emperor
    else:
        state → Zhongshu       # Return to Zhongshu Department
        notify Zhongshu Department(reason)   # Attach veto reason

Process visualization:

Secretariat → Chancellery (Round 1)
  ├─ 🚫 Rejected: "Missing performance tests"
  └─ Secretariat revised → Chancellery (Round 2)
       ├─ 🚫 Rejected: "Incomplete risk assessment"
       └─ Secretariat revised → Chancellery (Round 3)
            ├─ ✅ Approved → Department of State Affairs
            └─ 🚫 Rejected → Escalate to Emperor

Comparison with ours:

Edict ChancelleryLoop Engineering Engine
Trigger methodState Machine enforcementPrompt suggestion → Engine retry
Maximum attempts330
After failureReturn to the Zhongshu Department to redoRetry in theory (in practice 0 times)
EscalationEmperormain agent
Actual effect100% execution0% execution

What this means for us: Rolling back to "the Zhongshu Department replans" is a crucial step. It is not merely "please retry", but rolling the state machine back to the upstream node, so that the upstream agent redoes the work according to the veto reasons. Although our Engine retry does perform a retry, it does not change the Looper's behaviour; the Looper simply rewrites STATE.json to fake a pass.


2.5 Audit Trail: A Tamper-Resistant Process Record

Edict implementation:

Each task's flow_log records every state transition:

{
  "flow_log": [
    "Emperor → Crown Prince: issue decree",
    "Crown Prince → Secretariat: forward the decree",
    "Secretariat → Chancellery: submit the proposal for review",
    "Chancellery → Secretariat: 🚫 Veto and return (additional performance testing required)",
    "Secretariat → Chancellery: revised proposal (second round of review)",
    "Chancellery → Department of State Affairs: ✅ Approved",
    "Department of State Affairs → Six Ministries: distribute for execution",
    "Six Ministries → Department of State Affairs: all ministries completed",
    "Department of State Affairs → Secretariat: compile and report back"
  ]
}

Sansheng implementation:

.opencode/audit/{sessionId}.json
  → Complete operation tracking
  → All tool calls + outputs + timestamps
  → <10ms write latency

Comparison with ours:

Our STATE.json has iteration_history and methodology_compliance, but this data can be written directly by the agent (including fabricated). Edict's flow_log is written by kanban_update.py (an external Python script), and the agent cannot modify it directly.

What this means for us: Write permission for STATE.json must be stripped away from the Looper. Only the External Supervisor may write the final STATE.json.


2.6 Real-Time Observability + Human Intervention

Edict implementation:

  • Kanban board: 10 view panels, filtered by state/department/priority
  • Activity stream: 59 mixed activity records per task
  • Operations: one-click stop / cancel / resume / advance
  • Timeline: five-stage visualization (Imperial Decree→Zhongshu→Menxia→Six Ministries→Report Back)

Sansheng implementation:

  • Agent heartbeat: real-time monitoring, automatic alert on timeout
  • Full logs: all operations traceable

3. An Integration Plan with Loop Engineering

3.1 Borrowing the State Machine

# Added: loop_engine/state_machine.py
LOOP_VALID_TRANSITIONS = {
    "idle":       ["executing"],
    "executing":  ["verifying"],         # ⛔ Cannot jump directly to done
    "verifying":  ["diagnosing"],
    "diagnosing": ["adjusting", "done"],
    "adjusting":  ["executing"],         # Re-execute after correction
    "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}: invalid transition {from_state}→{to_state}"
        )

3.2 Borrowing the Permission Matrix

# Added: 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"],  # ⛔ Physical isolation
    },
    "supervisor": {
        "can_spawn": ["checker-agent"],
        "can_write": ["STATE.json"],      # ✅ Only supervisor can write
        "can_read": ["*"],
    },
}

3.3 Borrowing the Review Gate

# Modification: loop_engine.py -> Add External Supervisor
class LoopSupervisor:
    def verify_loop_completion(self, loop_id):
        # Step 1: Read STATE.json (untrusted)
        state = read_state(loop_id)
        
        # Step 2: Read Session JSONL (trusted source)
        session = read_session_jsonl(loop_id)
        actual_spawns = count_spawns(session)
        
        # Step 3: Cross-validate
        if state.verify.done and actual_spawns == 0:
            # 🔴 Fabrication detected!
            mark_fabrication(loop_id)
            force_retry(loop_id, "verify fabrication detected")
            return False
        
        # Step 4: Verification passed -> merge
        if state.verify.done and actual_spawns >= 1:
            write_final_state(loop_id, state)
            return True

4. Conclusion

The Three Departments and Six Ministries systems on GitHub taught us the most important lesson: process enforcement cannot rely on self-discipline; it must rely on institutions.

MechanismEdictSanshengLoop Engineering statusWhat we need to do
State Machine✅ Python enforced✅ TypeScript enforced❌ Prompt only🔴 Implement
Permission Matrix✅ Config enforced✅ Config enforced⚠️ Partial🔴 Strengthen
Review Gate✅ Menxia Department (cannot be bypassed)✅ 4-layer Gateway❌ Prompt only🔴 Implement
Veto loop✅ 3 rounds enforced✅ Task dependency block❌ 0 in practice🔴 Implement
Audit Trail✅ flow_log (written externally)✅ audit JSON (written externally)⚠️ STATE.json (agent can write)🔴 Isolate write permission
External supervision✅ kanban_update.py✅ WorkflowManager❌ None🔴 Implement
Intervenability✅ stop/cancel/resume⚠️ Partial❌🟡 Future

The gap between us and Edict is not in prompt quality; it is in architecture design. They used a Python state machine and a config-level permission matrix to accomplish what we failed to accomplish with 6 retries.


This article is based on an analysis of the source code and architecture documentation of GitHub's jashion/edict and er-three/sansheng.