Back to all posts

State Management Without the Mess: Deterministic Agent Memory for Long-Running Systems

Thu Apr 16 2026 • Birat Gautam
Agentic AIState ManagementProduction SystemsEvent SourcingCompliance

Difficulty: Advanced

Why semantic memory is not enough

Vector search is great for recall.

It is not great for auditability.

When you need to explain why an agent made a decision a month ago, semantic similarity is not enough. You need the exact sequence of facts, corrections, and state transitions that led to the action.

flowchart LR
  A[Observed event] --> B[Append to immutable log]
  B --> C[Update derived state]
  C --> D[Retrieve for decision]
  D --> E[Decision recorded]

The log is the source of truth. The derived state is the convenience layer.

What usually goes wrong

Vector databases are mutable in ways that are hard to reason about.

That is fine for chat memory. It is risky for systems that make business, legal, or operational decisions.

Event sourcing is the better default

Store facts as events, not just as current summaries.

from dataclasses import dataclass
from datetime import datetime
from enum import Enum


class FactType(Enum):
    OBSERVATION = "observation"
    INFERENCE = "inference"
    CORRECTION = "correction"
    RETRACTION = "retraction"


@dataclass
class MemoryEvent:
    event_id: str
    timestamp: datetime
    fact_type: FactType
    content: str
    source: str
    confidence: float
    reasoning: str
    model_version: str
    superseded_by: str | None = None

This makes memory inspectable and replayable.

A memory system should answer one question

What did the agent know at decision time?

That requires an immutable log plus a derived view.

class EventSourcedMemory:
    def append(self, event: MemoryEvent) -> None:
        self.events.append(event)
        self._persist(event)
        self._update_state(event)

    def reconstruct(self, decision_timestamp: datetime) -> list[MemoryEvent]:
        return [
            event for event in self.events
            if event.timestamp <= decision_timestamp
        ]

If a correction arrives later, do not delete the old fact. Mark it as superseded.

Why this matters in production

Event logs give you:

timeline
  title Memory lineage
  2026-04-01 : observation recorded
  2026-04-03 : correction appended
  2026-04-04 : derived state updated
  2026-04-10 : decision replayed for audit

That kind of reconstruction is what makes long-running systems supportable.

Keep vector search as a cache

You can still use embeddings.

Just do not treat them as authoritative.

That separation gives you speed without losing history.

Practical rule

If a system can influence decisions, its memory should be reconstructible.

For mission-critical agents, deterministic memory is not a luxury feature. It is the minimum structure required to trust the system later.

Related Posts