Back to KB
Difficulty
Intermediate
Read Time
10 min

Models shouldn't have execution authority. Why we built a deterministic FSM runtime for AI agents.

By Codcompass Team··10 min read

Decoupling Intent from Execution: A Deterministic Control Plane for Stateful AI Agents

Current Situation Analysis

The prevailing architecture in modern AI agent frameworks delegates execution authority directly to probabilistic models. This pattern works adequately for read-only operations like log summarization, documentation retrieval, or web search. However, the moment an agent is granted write access to external systems—payment processors, relational databases, cloud infrastructure, or PII repositories—the architecture introduces catastrophic failure modes.

The industry consistently overlooks this vulnerability because engineering efforts are heavily concentrated on model benchmarking. Teams optimize for reasoning depth, context window size, and instruction-following accuracy while treating the control plane as a trivial routing layer. This creates a fundamental mismatch: stochastic generators are being asked to serve as deterministic executors.

When an LLM outputs a JSON payload that directly triggers a database mutation or API call, the system assumes the model's output is trustworthy intent. In reality, it is unverified instruction data. Prompt injection, tool misuse, and non-deterministic state corruption become trivial to exploit. Dynamic dispatch patterns (prompt -> JSON -> dynamic evaluation -> side-effect) lack compile-time guarantees, leaving the blast radius unbounded. Production environments handling financial transactions or regulated data cannot afford this architectural debt. The solution is not to build "smarter" models, but to strip execution authority from the model entirely and route all state mutations through a deterministic control layer.

WOW Moment: Key Findings

Shifting from dynamic dispatch to a deterministic finite state machine (FSM) runtime fundamentally alters the security posture of AI agents. The following comparison illustrates the operational divergence between traditional agent loops and a capability-gated FSM architecture:

ApproachBlast Radius ControlAudit Trail IntegrityReplay SafetyAttack Surface (ReDoS/Injection)Compliance Overhead
Dynamic DispatchUnbounded (model decides)Fragile (post-hoc logging)High risk (no idempotency keys)Large (eval/regex/loops enabled)High (manual redaction breaks chains)
Deterministic FSMStrict (compile-time capability snapshot)Cryptographic (hash-chained envelopes)Zero (absorbing terminal states)Minimal (AST-only policy evaluation)Low (tombstone-based redaction)

This finding matters because it decouples planning from execution. The model remains responsible for generating intent and selecting next steps, but the runtime enforces whether that intent can actually mutate state. By constraining the execution graph to a finite, verifiable structure known ahead of time, organizations can safely deploy agents into production environments handling sensitive operations. The runtime does not attempt to make the model trustworthy; it assumes all model output is untrusted intent and applies strict deterministic semantics before any side-effect occurs.

Core Solution

Building a deterministic control plane requires replacing dynamic evaluation with a compile-time verified execution graph. The architecture rests on five interconnected components: capability gating, AST-based policy evaluation, idempotent execution adapters, cryptographic hash chaining, and absorbing terminal states.

Step 1: Compile-Time Capability Snapshot

Instead of allowing the model to invoke arbitrary tools at runtime, the system registers a fixed capability matrix during initialization. Each state transition is explicitly mapped to allowed operations. The runtime validates every proposed action against this snapshot before execution.

interface CapabilitySnapshot {
  readonly allowedTools: Record<string, boolean>;
  readonly maxPayloadSize: number;
  readonly targetEnvironments: string[];
}

class CapabilityGate {
  constructor(private readonly snapshot: CapabilitySnapshot) {}

  validate(action: string, payload: unknown): boolean {
    if (!this.snapshot.allowedTools[action]) {
      throw new SecurityViolation(`Unauthorized tool invocation: ${action}`);
    }
    if (JSON.stringify(payload).length > this.snapshot.maxPayloadSize) {
      throw new SecurityViolation('Payload exceeds compile-time size limit');
 

🎉 Mid-Year Sale — Unlock Full Article

Base plan from just $4.99/mo or $49/yr

Sign in to read the full article and unlock all 635+ tutorials.

Sign In / Register — Start Free Trial

7-day free trial · Cancel anytime · 30-day money-back