Hierarchical Agent Supervisors: Designing Deterministic Finite State Machines
Prevent infinite looping and context drift in complex agent systems by decoupling task planning from worker execution through typed state machines.
Netbay Cloud Team
Netbay Engineering
On this page
When software engineers build simple autonomous agents, they frequently rely on an open-ended loop: the model receives a user prompt, calls tools in a while-loop, and stops whenever it decides it is finished. In trivial demonstrations, this looks miraculous. In production enterprise environments, it predictably degrades into infinite loops, context window exhaustion, and unpredictable side effects.
The solution to agentic chaos is the Hierarchical Supervisor Pattern combined with a deterministic Finite State Machine (FSM). By separating high-level task decomposition from low-level tool execution and enforcing formal state transitions, engineering teams can build agents that operate deterministically.
The Hierarchical State Machine Pattern
Rather than allowing a single model to both plan and execute, we divide responsibilities into distinct nodes governed by an FSM:
- Planner / Supervisor: Reviews user goals and decomposes them into a directed acyclic graph (DAG) of discrete tasks.
- Worker Nodes: Specialized sub-agents (e.g., Code Implementer, QA Test Writer, Lint Fixer) that receive narrow context, execute bounded tool calls, and report back.
- Quality Gate: A programmatic state evaluator that verifies whether tests pass and lint standards are met before authorizing transition to the final Commit state.
TypeScript Finite State Machine Implementation
Here is an FSM engine managing agent transitions with typed state checks and max-retry circuit breakers:
type AgentState = 'PLAN' | 'EXECUTE' | 'AUDIT' | 'COMMIT' | 'FAILED';
interface AgentContext {
taskDescription: string;
planSteps: string[];
currentStepIndex: number;
testPassCount: number;
retryAttempts: number;
maxRetries: number;
}
class AgentSupervisorFSM {
private state: AgentState = 'PLAN';
private ctx: AgentContext;
constructor(task: string) {
this.ctx = {
taskDescription: task,
planSteps: [],
currentStepIndex: 0,
testPassCount: 0,
retryAttempts: 0,
maxRetries: 3
};
}
public async transition(event: 'PLAN_READY' | 'STEP_DONE' | 'TEST_PASSED' | 'TEST_FAILED'): Promise<AgentState> {
console.log('[FSM] Current:', this.state, '-> Event:', event);
switch (this.state) {
case 'PLAN':
if (event === 'PLAN_READY') this.state = 'EXECUTE';
break;
case 'EXECUTE':
if (event === 'STEP_DONE') this.state = 'AUDIT';
break;
case 'AUDIT':
if (event === 'TEST_PASSED') {
this.ctx.currentStepIndex++;
this.state = this.ctx.currentStepIndex >= this.ctx.planSteps.length ? 'COMMIT' : 'EXECUTE';
} else if (event === 'TEST_FAILED') {
this.ctx.retryAttempts++;
if (this.ctx.retryAttempts > this.ctx.maxRetries) {
this.state = 'FAILED';
} else {
this.state = 'EXECUTE'; // Loop back to fix defect
}
}
break;
}
return this.state;
}
public getState(): AgentState {
return this.state;
}
}Key Architectural Advantages
- Bounded Blast Radius: If a worker fails, only its local context is discarded; the global plan remains intact.
- Predictable Costs: Hard maximum retry counts prevent infinite token consumption.
- Observability: Every state change generates an audit log entry for production monitoring.
Video Walkthrough on Agent Orchestration
Discover stateful agent design patterns and multi-agent coordination frameworks:
Replacing open-ended agent prompts with typed state machines allows teams to unleash autonomous systems with total confidence in their production behavior.
Run high-reliability AI agent supervisors 24/7 on robust Netbay Cloud VPS instances at netbayhosts.in.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance