A persona's state travels with its job, and the trace is the only store¶
agent needs a persona's current beliefs to condition a prompt, its past memories to retrieve from, and it produces
new ones. The architecture's sketch — turn(persona, impression, view) -> Reaction — carries none of that, so the
state had to live somewhere: inside the agent, behind a memory port, or across the boundary.
It travels across the boundary. A turn takes the persona, its presentation and a PersonaState — beliefs, the
persona's own memory events, and the counters that decide reflection — and returns the reaction together with the
new memories and the belief change. The agent itself stores nothing and is a pure function of its inputs. The trace
is the store: memory events, belief snapshots and character-probe results are trace events like any other, and the
runner is their only writer.
The decision is driven by the runner. A study spreads personas across workers, and no worker holds them all. If the agent owned the store, each persona would be pinned to the worker holding its history and a resume would replay a whole trace into memory. With state crossing the boundary, any worker takes any persona, a checkpoint is state that has already been serialised, and rebuilding state from the trace is an independent check on the checkpoint rather than the only way to get it back.
Retrieval stays arithmetic the engine owns: exp(-Δt/τ) · importance · cos(memory, stimulus) over one persona's own
memories, embedded once when written through the existing EmbedPort. Importance comes from a rule — the action
taken and the size of the belief change — except on tier B events, where the model is already being paid for and can
rate it in the same call. A persona's memories are capped, with reflection consolidating older ones into fewer,
higher-importance summaries, so neither the prompt nor the state grows without bound.
Considered options¶
An agent-internal store rebuilt by replay, mirroring world (ADR 0011), was rejected: the world is a single
authority with one writer per run, while persona state is sharded across workers and must be addressable. A
MemoryPort the agent writes through was rejected because it puts persistence back inside the module that owns the
conditioning invariant, and makes deterministic replay harder to test. A memory framework (LangChain, LlamaIndex,
Mem0, Letta) was rejected on the same grounds as provider SDKs (ADR 0021), and more sharply: such a framework owns
prompt assembly and retrieval policy, which is exactly the invariant that decides this engine's validity and cannot
be co-owned. A vector database was rejected at this scale — every search is scoped to one persona's few dozen
memories, which is a dot product, not an index.
Consequences¶
The agent's interface is wider than the architecture's sketch, and FINAL_ARCH.md §5.6 is amended to match. The
runner owns persistence, checkpointing and resume, and gains a determinism check it did not have: state rebuilt by
replaying a trace must equal the checkpoint written during the run. Memory events, belief snapshots and probe
results need trace payloads, which land in jahan/schemas before either the agent or the world branch begins.