Governed Autonomy: Supervisor-Worker Hierarchies and Stateful Skill Graphs for Complex Agent Systems
How to architect multi-agent systems with role-based tool isolation, governed supervisor-worker hierarchies, and composable stateful skill graphs for reliable, auditable task execution.
Production agent systems constantly face a tension: you want the flexibility of a generative model that can reason across novel situations, but you also need the rigor of deterministic pipelines that enforce rules, respect boundaries, and produce auditable results. A two-layer architecture — one layer governing who can do what, and a second layer governing what happens in what order — is an increasingly practical answer to that tension. Understanding how these layers interact gives you a reusable blueprint for any high-stakes agentic workflow.
The Two Problems That One Agent Can’t Solve
When engineers first build multi-step agent systems, they often start with a single orchestrator that routes tasks, calls tools, and tracks state. This works until the system grows complex enough that three failure modes emerge simultaneously: tool sprawl (any agent can call any tool, making behavior hard to predict), state bleed (intermediate results from one task corrupt context for another), and accountability gaps (no clear record of which agent made which decision).
These are fundamentally different problems. Tool sprawl and accountability are governance problems — they’re about authority and boundaries. State bleed is a workflow problem — it’s about how tasks compose and hand off to each other. Trying to solve both in a single orchestrator leads to a bloated, brittle system. Separating them into two explicit architectural layers produces something much more maintainable.
Layer One: Governed Supervisor-Worker Hierarchy
The first layer addresses governance. A supervisor agent holds decision-making authority: it interprets the high-level objective, decomposes it into subtasks, and dispatches those subtasks to specialized worker agents. Critically, the supervisor does not directly execute domain tools. Workers do.
Role-based tool isolation is the key mechanism. Each worker is instantiated with a fixed, minimal set of tools relevant to its role. A data-retrieval worker gets search and fetch tools. A synthesis worker gets transformation and generation tools. Neither can access the other’s toolset. This isn’t just a safety measure — it’s an architectural contract that makes behavior predictable and testable.
Role-based tool isolation at the worker level lets you unit-test each worker in complete isolation. You can verify that a worker both can use its assigned tools and cannot call tools outside its scope, without spinning up the full supervisor-worker stack.
The supervisor maintains a registry of available workers and their capabilities, expressed as structured metadata rather than free-form descriptions. When a subtask arrives, the supervisor matches it to a worker by capability rather than by asking the LLM to improvise. This keeps routing deterministic and auditable.
┌─────────────────────────────────────────┐ │ SUPERVISOR │ │ ┌──────────────────────────────────┐ │ │ │ Task Decomposition & Routing │ │ │ │ Worker Registry (capabilities) │ │ │ └──────────────┬───────────────────┘ │ └─────────────────┼───────────────────────┘ │ dispatches subtasks ┌─────────┼─────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │Worker A │ │Worker B │ │Worker C │ │[tool1] │ │[tool3] │ │[tool5] │ │[tool2] │ │[tool4] │ │[tool6] │ └─────────┘ └─────────┘ └─────────┘ Role: Fetch Role: Analyze Role: Report
Layer Two: Stateful, Composable Skill Graphs
The second layer addresses workflow. Rather than letting workers invent their own execution sequences, complex domain tasks are encoded as skill graphs: directed graphs where each node represents a discrete, versioned skill and each edge represents a valid transition between skills.
A skill in this sense is more than a tool call. It bundles the LLM prompt template, the tool calls that skill may invoke, the expected output schema, and the success criteria for that step. This bundle is the unit of composition. Because skills are stateful — they receive the outputs of predecessor nodes as structured inputs — the graph enforces a data contract across the entire workflow.
@dataclass
class Skill:
name: str
description: str
prompt_template: str
allowed_tools: list[str]
output_schema: type[BaseModel]
success_criteria: Callable[[BaseModel], bool]
@dataclass
class SkillEdge:
source: str # skill name
target: str # skill name
condition: Callable[[BaseModel], bool] | None # None = unconditional
class SkillGraph:
def __init__(self, skills: list[Skill], edges: list[SkillEdge]):
self.skills = {s.name: s for s in skills}
self.edges = edges
def next_skills(self, current: str, output: BaseModel) -> list[str]:
return [
e.target for e in self.edges
if e.source == current
and (e.condition is None or e.condition(output))
]
Skill graphs also provide natural checkpointing. You can pause execution at any node boundary, serialize graph state to durable storage, and resume from that exact point. This is essential for long-running workflows where partial failures shouldn’t require a full restart.
Human-in-the-Loop Checkpoints as First-Class Nodes
One of the most practically valuable features of the skill graph model is that human review can be modeled as an explicit node type rather than bolted on afterward.
Adding human review as an afterthought — a post-processing step or external webhook — means your agent system treats it as optional infrastructure. Encoding review as a graph node makes it a mandatory contract: the graph cannot advance past that node without a human decision signal.
A HumanCheckpointSkill node pauses graph execution, serializes the current state and the pending decision into a structured review payload, and blocks the next transition until it receives an explicit approval or rejection signal. Rejection can route to a remediation branch; approval advances the main path. This pattern supports compliance requirements and builds operator trust in autonomous systems because every consequential decision has a verifiable human sign-off record.
class HumanCheckpointSkill(Skill):
"""Blocks graph execution until a human decision is received."""
async def execute(self, state: GraphState) -> CheckpointDecision:
payload = self.build_review_payload(state)
review_id = await self.review_queue.submit(payload)
# Long-poll or webhook — blocks until decision arrives
decision = await self.review_queue.await_decision(review_id)
return decision # .approved or .rejected with reason
Putting the Two Layers Together
The two layers are loosely coupled by design. The supervisor-worker governance layer handles task allocation and authority; the skill graph layer handles task execution and state. A worker agent is essentially a skill graph runner: it receives a subtask from the supervisor, identifies the appropriate skill graph for that task type, and executes it to completion (or to a checkpoint that requires escalation back to the supervisor).
This separation has a useful engineering consequence: you can evolve the two layers independently. Adding a new worker role doesn’t require changing existing skill graphs. Revising a skill graph doesn’t require changing the supervisor’s routing logic. The system grows by adding nodes, not by rewriting monolithic orchestrators.
For teams building agents in any domain that combines open-ended reasoning with procedural rigor — legal document processing, financial analysis, medical record review, scientific workflows — this two-layer pattern offers a principled way to get the flexibility of LLMs without sacrificing the predictability that production systems demand.
This article is an AI-generated summary. Read the original paper: Mozi: Governed Autonomy for Drug Discovery LLM Agents .