Inspiration

I use AI a lot.

I use models like ChatGPT and Claude for long, complicated work — sometimes for hours, across entire projects. After using AI this heavily, I started noticing something that kept bothering me.

The more intensive the work became, the less certain the model seemed to be about its own history.

I would ask about a decision we had made earlier, something we had established much earlier in a conversation, or why I had chosen a particular approach. Sometimes the model would contradict itself. Sometimes it would reconstruct what it thought happened. Sometimes it would confidently give me an answer that didn't match what we had actually established.

And I kept thinking: if I'm going to use AI for years, what happens to all of this context?

If I have an important conversation with an AI today and come back months or years later, I should be able to ask what happened and have some reason to believe the memory I'm retrieving is actually the memory that was recorded.

That was the idea behind VeriMemory.

When I saw the CockroachDB × AWS hackathon and saw that it was focused on agentic memory, it immediately clicked. I had already experienced the problem myself. Now I had the opportunity to build a solution.

But I didn't want to build another system that simply stores conversations and retrieves them later.

I wanted to answer a more fundamental question:

«Can an AI agent know that the memory it retrieved is actually the memory that was recorded?»


What it does

I built VeriMemory as a tamper-evident memory layer for AI agents.

I store agent memories as a cryptographically chained event ledger on CockroachDB. Every event is bound to its own contents and to the event before it.

The core relationship is:

[ \text{payload_hash} = \operatorname{SHA256}(\operatorname{canonical_json}(\text{payload})) ]

[ \text{chain_hash} = \operatorname{SHA256}(\text{prev_hash} ,|, \text{payload_hash} ,|, \text{seq}) ]

When an event is modified, deleted, or reordered, the expected chain relationship breaks and VeriMemory can identify where the break first occurs.

But detection alone wasn't enough for me.

The important behavior is what happens after detection.

Before my agent uses memory, VeriMemory verifies the chain. If verification succeeds, my agent can retrieve and reason from the memory.

If verification fails, the affected events are never loaded into the model's context.

My agent refuses to answer from memory it cannot verify.

I designed the demo to make this deliberately obvious:

  1. I ask the agent a question → memory verifies → Trust Score: 100%
  2. I search the memory semantically.
  3. I modify an event directly with raw SQL, bypassing my application.
  4. I ask the same question again.
  5. VeriMemory detects the broken chain → Trust Score: 0% → Answer: REFUSED

The refusal is structural, not simply a prompt telling the model not to trust the data.

How I built it

I used CockroachDB as the core persistent memory layer.

I use Distributed Vector Indexing to perform semantic retrieval over the same events protected by my integrity chain. My events contain their payload, cryptographic hashes, metadata, and 1024-dimensional embeddings.

I integrated the CockroachDB Cloud Managed MCP Server as my agent's read path.

My agent uses a dedicated "verimemory_mcp_ro" database identity with SELECT-only privileges. Through MCP, my agent can query its history and verify its memory, but it cannot directly modify the database.

I deliberately separated the write path from the agent's read path.

I use AWS Lambda for ingestion and the controlled API operations. I compute hashes server-side, so callers cannot simply submit their own integrity values.

I use Amazon Bedrock for my production AI and embedding path. I use Amazon Titan Embed Text V2 for the 1024-dimensional embeddings stored in CockroachDB.

My architecture therefore separates my agent's read and write capabilities:

                     AI Agent
                   /          \
              Read              Write
               |                  |
              MCP              Lambda
               |                  |
               v                  v
          +---------------------------+
          |       CockroachDB         |
          |                           |
          | Events                    |
          | Vector Index              |
          | Verification Log          |
          +---------------------------+
                     ^
                     |
                 Bedrock
              AI / embeddings

I made this separation intentional: my agent can read and verify its history, but it does not hold credentials that can rewrite its own past.

I also built the system so that my tamper demonstration bypasses the application entirely. I use a raw SQL "UPDATE" to change an event directly in CockroachDB. VeriMemory then detects the corruption when it replays the chain.

I built the cryptographic core, Lambda handlers, MCP configuration, database schema and migrations, trust-gating logic, recovery logic, semantic search, CLI and web demo, deployment tooling, and automated tests as parts of the same system.

Challenges I ran into

The hardest part wasn't calculating a SHA-256 hash.

The difficult part was making the trust decision actually affect my agent.

It would have been easy for me to build a system that detects corruption, displays a warning, and then still sends the corrupted memory to the model.

That wasn't good enough.

I needed verification to happen before retrieval, so that a failed verification meant my model genuinely had nothing untrusted to reason from.

I also had to think carefully about database permissions.

The append-only property couldn't just be a promise made by my Python code. I needed the database roles to enforce it. My Lambda runtime therefore has "SELECT + INSERT" privileges but no "UPDATE" or "DELETE", while my MCP identity is "SELECT"-only.

Another challenge was making vector search and integrity verification work together. A semantically relevant result isn't useful if the underlying memory cannot be trusted, so I made search trust-gated as well.

I also had to deal with the practical complexity of integrating CockroachDB, MCP, AWS Lambda, Amazon Bedrock, vector embeddings, database migrations, deployment configuration, and a cryptographic verification layer into one working system.

Accomplishments that I'm proud of

The biggest accomplishment I'm proud of is that the core security property works end-to-end.

I can write a memory, retrieve it semantically, verify its integrity, deliberately tamper with the underlying database using raw SQL, and have the system detect the modification without relying on the attacker using my API.

More importantly, the corrupted memory doesn't simply receive a warning.

I withhold it from the model.

I'm also proud of the least-privilege architecture.

My agent's MCP identity cannot modify its own history. My Lambda runtime cannot update or delete existing events. My database permissions enforce these boundaries rather than leaving them entirely to application logic.

I built a trust timeline that makes the consequences of a broken chain visible:

✓ Event 0 verified ✓ Event 1 verified ✓ Event 2 verified ✗ Event 3 corrupted ⚠ Event 4 untrusted ⚠ Event 5 untrusted

I'm also proud that I was honest about the limitations of my system. VeriMemory proves integrity, not truth. A false event that was legitimately recorded will still have a valid chain.

That distinction is important to me because I don't want to claim that cryptography can solve a problem it can't.

What I learned

I learned that memory and trustworthy memory are two different problems.

Storing information is relatively easy. Retrieving it is easy too.

The difficult question is whether an AI agent should be allowed to trust what it retrieved.

Building VeriMemory forced me to understand AI agents, CockroachDB, MCP, vector search, AWS Lambda, Amazon Bedrock, cryptographic hashing, database permissions, and retrieval-time trust enforcement as one system.

I also learned that security properties are much stronger when I enforce them at multiple layers.

My cryptographic chain detects changes.

My CockroachDB permissions restrict who can make changes.

MCP gives my agent a controlled read interface.

My retrieval layer prevents unverified memories from reaching the model.

And my reasoning layer refuses to continue when the memory cannot be trusted.

Most importantly, I learned not to overclaim what cryptography provides.

A hash chain can tell me that recorded data has been altered. It cannot tell me whether the original data was true.

That distinction shaped the entire project.

What's next for VeriMemory

My current system detects tampering by verifying the chain stored in CockroachDB.

My next step is making the chain itself harder to rewrite.

An attacker with sufficient database privileges could theoretically rewrite an entire chain from the point of tampering onward and produce a new internally consistent history. VeriMemory currently documents this limitation rather than pretending the hash chain solves it.

I want to introduce external integrity anchoring — periodically publishing trusted "chain_hash" checkpoints somewhere the database attacker cannot modify.

I also want to explore cryptographic signatures backed by a key-management system so that VeriMemory can prove not only that a memory has not changed, but also which trusted writer originally recorded it.

Longer term, I want VeriMemory to become a reusable integrity layer for persistent AI agents — something that can sit underneath an agent's memory system and answer a simple question before the agent acts:

«Can I trust the memory I'm about to use?»

If the answer is no, I want the agent to know that — and stop.

Built With

Share this project:

Updates

Submission history