Philipp Hölke

Library

On Treating Agent Memory as an Audit Trail

Logs aren’t understanding. If you can’t ask a system why it made a decision and get a coherent answer, you don’t have an audit trail — you have a write-only database.

A grainy monochrome image — a classical sculpted head in profile with luminous white filaments streaming horizontally out of it across a starry black field, two pale orbs behind.

Prompt-fixing only works because your agents aren’t autonomous yet. Once they run for weeks, audit trails become essential — everyone building agents knows this now.

But most audit solutions stop at “we logged it.” And logs aren’t understanding. If you can’t ask the system why it made a decision and get a coherent answer, you don’t have an audit trail. You have a write-only database.

Currently, that’s fine, because most agentic workflows aren’t long-running yet. They’re usually triggered by some sort of user interaction, a database trigger, a cron job or another workflow in your backend. That means, if something goes wrong or the output of the workflow isn’t satisfactory, we can simply tweak the system prompt and that usually does the trick. But that only works because you’ve built an execution, not a proper reasoning machine.

Once Agents become truly long-running and far more autonomous than what we’re all building at the moment, prompt-fixing isn’t going to work. That’s because long-running Agents have a compounding effect: mistakes are amplified and cause a chain reaction. Past mistakes can’t just be undone, there are consequences for mistakes and wrong actions, just like with humans.

Understanding Agent Decision-Making

When an agent appears to do something simple e.g. “generate documentation”, “summarise this repo”, “plan the next steps”, there’s a lot happening that never surfaces in reasoning models. They inspect inputs, form hypotheses, discard options, skip work they think is redundant.

Those decisions ultimately matter more than the final output, because they shape everything downstream. But in most systems they evaporate immediately. Once the response is produced, the reasoning that led to it is gone.

Any audit platform or framework I’ve ever come across is workflow-oriented and optimised for request-response patterns, not perpetually running agents or agent swarms. So they work fine until a system starts acting autonomously for longer stretches of time.

Capturing the Internal Monologue

While building out Trajan, our autonomous project management framework, I started thinking about how to make otherwise disconnected agentic workflows more cohesive and continuous. One of the reasons for building Trajan was to try out the ergonomics and dev experience of the Elephantasm SDKs for myself during our public alpha.

At face value, there wasn’t a direct use case, as Trajan doesn’t have obvious user-facing LLM functionality yet; certainly none that would have to be long-running. But the idea emerged that Elephantasm’s framework would work just as well for backend-only, internal monologues of the LLMs completing workflows and executing instructions.

The long-term memory system becomes an audit tool, for me to visualise why an Agent called a specific tool, why it reasoned about something in a certain way. Even better, it unifies otherwise fragmented agentic workflows into a single Anima, which means there’s persistence even among unrelated workflows and chains of thought.

How to Set This Up

The key insight is that audit and memory are the same problem. If you’re capturing events for memory formation, you’re also capturing them for audit. The infrastructure serves both purposes.

Here’s the approach I’ve taken with Elephantasm, broken down into the pieces that matter:

1. Structure Events Around Decisions, Not Just Outputs

Most logging captures what happened. For audit to be useful, you need to capture why it happened. That means structuring events to include the reasoning context, not just the result.

When an agent completes a task, I ingest an event that looks something like this:

await memory.ingest_event(
    spirit_id=product.anima_id,
    event_type="doc_generation",
    content={
        "documents_created": ["Architecture.md", "API Reference.md"],
        "documents_skipped": ["README.md"],
        "skip_reasoning": "README existed with recent commits—user content preserved",
        "alternatives_considered": ["Overwrite", "Merge", "Skip"],
        "decision_rationale": "Skip minimises risk of destroying user work",
        "confidence": 0.85,
        "context_files_examined": ["README.md", "package.json", "src/index.ts"]
    },
    importance=0.7
)

The skip_reasoning, alternatives_considered, and decision_rationale fields are what make this auditable. Without them, you just know what was created. With them, you can trace back why the agent made the choices it did.

2. Use Importance Scoring to Prioritise High-Signal Events

Not all events matter equally. A user editing a generated document is a stronger signal than the document being created in the first place — it implies the output wasn’t quite right.

This is how I’ve designed Elephantasm’s importance weighting:

EVENT_IMPORTANCE = {
    "doc_generation": 0.6,      # Baseline—stuff happened
    "doc_edit": 0.7,            # User effort = implicit feedback
    "doc_regeneration": 0.8,    # Dissatisfaction signal
    "user_feedback": 0.9,       # Explicit feedback = highest signal
    "analysis_completed": 0.5,  # Context, but less actionable
}

When recalling memories later, Elephantasm uses a four-factor scoring algorithm: importance, confidence, recency, and decay. High-importance events surface more readily during recall, which means the audit trail naturally emphasises what matters.

3. Unify Fragmented Workflows Into a Single Entity

Most agent architectures have multiple specialised agents: one for analysis, one for generation, one for planning, etc. They run independently, often without shared state.

The fix is to funnel all of them into the same memory entity. In Elephantasm, that entity is called an Anima. Each product or project gets one Anima, and every agent workflow — regardless of what it does — ingests events into that same Anima.

DocumentOrchestrator  ──┐
CodebaseAnalyzer      ──┼──→  Spirit (per product)  ──→  Unified Memory
FeedbackInterpreter   ──┘

This means the Anima accumulates a coherent history across all agent activity for that product. When you ask “why did it skip the README?”, the answer is part of the product’s full cognitive history, alongside analysis results, user feedback, and everything else, rather than being siloed in some doc-generation log.

4. Make the Audit Trail Queryable, Not Just Browsable

This is where most audit systems fall short. They give you logs you can search, dashboards you can filter, maybe a graph you can click through. But they don’t let you ask questions.

The reason Elephantasm stores events as the foundation for a memory system (rather than just a log) is that memories can be recalled semantically. Instead of grepping for “README” in your logs, you can query:

memories = await memory.recall(
    spirit_id=product.anima_id,
    query="decisions about skipping or preserving existing files",
    limit=10
)

This returns the relevant events, ranked by the four-factor score, with enough context to understand what happened and why. The audit trail becomes conversational — you ask questions in natural language and get grounded, specific answers.

5. Let the System Distill Its Own Patterns

Raw events are useful for debugging specific incidents. But for understanding systemic behaviour (e.g. is the agent learning? drifting? accumulating bad habits?) you need a higher level of abstraction.

Elephantasm handles this through its Dreamer function: a background process that periodically reviews accumulated events, extracts patterns, and distills them into Lessons. Lessons are more abstract than individual events (“this tech stack benefits from architecture docs”) and eventually consolidate into Knowledge (“FastAPI + Next.js monorepos need API reference documentation”).

This hierarchy (Events → Memories → Lessons → Knowledge) means the audit trail isn’t just a record of what happened, but a structured account of what the system has learned, which you can inspect, challenge, or correct.

A System That Understands Its Own Past

One unexpected (but very cool) consequence of this approach is that debugging becomes conversational. Instead of reading logs or dashboards, you can ask the system directly:

  • Why did you skip this?
  • What made you think this already existed?
  • Have you made this decision before?
  • What would have changed your mind?

Those questions only work if the past still exists in a form the system can reason over. Without Events, there’s nothing to point to. With them, the answers are grounded and specific. This is the difference between an agent that acts and one that can account for itself.

Why This Matters Long-Term

Without an audit trail of reasoning, there’s no way to tell whether the system is learning, drifting, or just accumulating noise. Events solve that. Not by making agents smarter, but by making their behaviour legible. And legibility turns out to be a prerequisite for trust, both human trust and system-internal trust, when agents start learning from their own past.

I started out thinking this was about observability, but actually it’s more about authorship: a system that can explain why it did something is participating in its own narrative. Instead of producing outputs, it’s maintaining a coherent account of how it arrived there.

That doesn’t make agents infallible, but it does make them understandable. And in systems that are meant to stick around, that matters more than people realise.

If you’re building long-running agents and want to try this approach, Elephantasm is in public alpha. I’d be curious to hear how others are thinking about agent audit, especially if you’ve tried different memory architectures or have opinions on the Events → Lessons → Knowledge hierarchy.