VigIA: Deterministic State Machine for LLM Orchestration
LLMs are probabilistic engines. Forcing them to manage application state or business logic leads to hallucination spirals. VigIA takes state management away from the LLM, demoting it to a purely functional heuristic parser bounded by a strict, deterministic Finite State Machine (FSM) built in .NET 10 (Native AOT).
If the LLM hallucinates a requirement, violates a Domain-Driven Design (DDD) boundary, or if the user evades providing business rules, the .NET Orchestrator intercepts the payload, discards the mutation, rolls back the chat history, and issues a [NACK] (Negative Acknowledgment).
(Demo: The Judge agent intercepting user evasion, the FSM issuing a Cognitive Strike, and forcing the user to provide strict domain rules).
1. The Homelab Context
This architecture was developed and stress-tested on Ubuntu 24.04 LTS with a local RTX 5090 running Gemma 4. It is designed for zero-latency local inference, proving that enterprise-grade deterministic orchestration can run entirely on edge hardware without relying on external, rate-limited APIs.
2. The Technical Problem: State Corruption
Standard LLM agents (like LangChain wrappers) suffer from State Corruption. When an LLM fails to generate a valid JSON or hallucinates a business rule, the failure is appended to the chat history. In the next turn, the LLM reads its own garbage output, assumes it as ground truth, and spirals into an unrecoverable state.
Furthermore, LLMs suffer from Sycophancy. If a business user asks for a "Stock Reservation" system but provides no specific rules, the LLM will hallucinate a textbook CRUD response just to appease the user, silently bypassing critical domain invariants like Reservation TTL (Time-To-Live) and cancellation release triggers.
3. The Solution: FSM Interceptor & Snapshot Rollbacks
VigIA solves this through a strict architectural pipeline (VigiaAgentOrchestrator):
- Structured State Vector (SSV): Chat history is purged of state. Global context is maintained via an immutable
StructuredStateVector. Only successfully resolved Aggregate Roots are injected into the prompt, preventing context window poisoning. - Deterministic Cross-Validation (
InvariantEnforcer): The LLM's JSON output is never trusted. It is routed through a strict validation layer. It doesn't just check syntax; it enforces DDD invariants. Does the payload have an Actor and an Action? Does it contain exhaustive Gherkin criteria (at least one Happy Path and one Edge Case)? If not, the transition is aborted. - Snapshot Rollbacks (
ChatHistoryManager): When theInvariantEnforcerreturns a failure (via a strictResult<T, E>monad), the FSM performs a snapshot rollback. The LLM is punished with a "Cognitive Strike" prompt detailing its exact structural error, but its previous hallucination is erased from the chat history. - The 3-Strike[NACK] Rule: If the user evades questions (detected by the Judge agent) or the Synthesizer LLM fails to pass the
InvariantEnforcer3 consecutive times, the FSM triggers aHard Blockand halts the system.
4. Why .NET 10 Native AOT? (The Engineering)
VigIA is not a Python script relying on mutable dictionaries. It is a compiled, memory-safe binary designed for production orchestration.
- Zero Reflection: JSON serialization is handled entirely by C# Source Generators (
OrchestrationJsonContext). - Memory Safety: The SSV relies on
readonly record structsandImmutableDictionary. State transitions generate mathematically distinct vectors, preventing memory leaks during long elicitation sessions. - Monadic Error Handling: Exceptions are not used for control flow in the hot path. The
Result<T, E>monad guarantees that the Orchestrator handles every possible LLM failure deterministically at compile-time.
5. Architecture Blueprint
Vigia.RequirementsMaster.slnx/
│
├── src/Vigia.Core.Domain/
│ # 🛡️ LAYER 1: The Deterministic Core. Zero dependencies.
│ ├── Aggregates/ # ArtifactRequirement, SystemBlueprint.
│ ├── Exceptions/ # DomainAmbiguityException, RejectionReason.
│ ├── Monads/ # Result<T, E> forcing compile-time NACK handling.
│ ├── StateVectors/ # StructuredStateVector (SSV) immutable snapshots.
│ └── ValueObjects/ # SystemId, ArtifactId, VectorVersion.
│
├── src/Vigia.Agent.Orchestration/
│ # 🧠 LAYER 2 & 3: Cognitive auditing and FSM state-shift management.
│ ├── Commands/ # CommandInterceptor (e.g., /approve handling).
│ ├── CrossValidation/ # InvariantEnforcer and strict Payload schemas.
│ ├── FSM/ # Pure functional mapping: f(SSV, Payload) -> State | NACK.
│ ├── History/ # ChatHistoryManager (Snapshot & Rollback mechanics).
│ ├── Ports/ # ILlmInferenceEngine interface.
│ ├── Prompts/ # CognitivePrompts, VigiaBasePrompt, VigiaJudgePrompt.
│ └── Serialization/ # OrchestrationJsonContext (SourceGen for AOT).
│
├── src/Vigia.Infrastructure.LLM/
│ # 🔌 LAYER 4: Infrastructure and Inference.
│ ├── Configuration/ # LlmSettings.
│ └── Engines/ # LocalInferenceClient (vLLM/OpenAI compatible) + Strict Schemas.
│
├── src/Vigia.LiveTest/
│ # 🖥️ PRESENTATION: The interactive FSM REPL console.
│ ├── Presentation/ # ReplOrchestrator, VigiaConsoleTerminal.
│ └── appsettings.json # SystemBlueprint injection.
│
└── tests/Vigia.Tests.Unit/
# 🧪 VALIDATION SUITE: Mathematical proof of state immutability.
6. Execution Flow: The Inventory System Test Case
VigIA is driven by a SystemBlueprint. In this repository, we provide a real-world test case: an Inventory Management System. The FSM forces the LLM and the User to sequentially resolve 5 artifacts: CategoryManagement, ProductManagement, InboundStock, ManualStockAdjustment, and finally, the ultimate Sycophancy Trap: StockReservation.
- The Judge (Sensing): User input is first evaluated by a Judge LLM (Temperature 0.0). It checks for
IsDomainDrift,IsEvasion, orIsMalice. If true -> NACK. - The Synthesizer (Elicitation): If approved, the Synthesizer LLM evaluates if the data is complete. If missing -> Emits
Type: Question. - The FSM Interceptor: Once the LLM emits a
Deliverable, the .NET FSM validates the Gherkin scenarios, Actor, Action, and Domain Rules. - Sign-Off: The FSM locks the state and requires the user to type
/approve.
7. Running VigIA Locally
Prerequisites
- .NET 10 SDK (Preview)
- A local LLM inference server (vLLM, LM Studio, Ollama) exposing an OpenAI-compatible API.
Setup
- Clone the repository.
- Edit
src/Vigia.LiveTest/appsettings.jsonto point to your local LLM endpoint:
"LlmSettings": { "Endpoint": "http://localhost:8000/v1", "ModelId": "gemma-4-local", "ApiKey": "empty" }
- Run the REPL Terminal:
cd src/Vigia.LiveTest
dotnet run -c Release8. Background & Research
This architecture evolved from our initial academic research: "VIGÍA 4+1: Mitigating LLM Sycophancy and Normative Bias in Requirements Engineering via Deterministic Agentic Orchestration" (March 2026).
While the original paper utilized Command-R as the baseline model, this repository represents the production-grade evolution of the framework. It has been migrated to .NET 10 Native AOT, refactored with Monadic state handling, and optimized to orchestrate superior reasoning models like Gemma 4.
Built with rigorous engineering. No hype. Just state machines.






















