What inspired it

I build SLEEPCOACHGAME — a 58-second game that finds the habit stealing your sleep and hands you a fix from an AI coach. It works. People finish a round, learn that their 4pm coffee is the thief, read their fix, and close the tab.

Then nothing happens. The finding was real and the fix was right, and by Thursday it was gone.

That is not a content problem. It is a memory problem. The insight lived in a response body and died with the HTTP connection. An agent that finds your thief habit and forgets it by morning is a very fast oracle and a useless coach. Coaching is what happens on day four.

So I built agentrecall: the game writes what it found to CockroachDB, and an agent acts on that memory every day at 2pm in the player's own timezone.

How it works

When a round ends, the wrong habits that generated the coachline are written to CockroachDB as durable rows against the player's order — not a session, not a cache. The player opts in with her email and her timezone, and that row becomes the agent's standing brief.

The coaching corpus is the other half of the memory. My game already holds a structured table of thief habits and their cause/effect fixes, and I have twenty long-form answer pages written for the same questions. Those get embedded with Amazon Bedrock and stored in CockroachDB with a distributed vector index, so retrieval is semantic rather than a lookup table. The stored habit is embedded too, and the day's nudge is chosen by similarity:

$$\text{sim}(h, c) = \frac{h \cdot c}{\lVert h \rVert \, \lVert c \rVert}$$

where $h$ is the remembered habit vector and $c$ a corpus line. The top matches are handed to Bedrock, which writes that day's message in the product's voice — one habit, one positive fix, never a scolding.

An EventBridge schedule ticks hourly into a Lambda, which asks CockroachDB one question: whose local clock reads 14:00 right now? Those rows are sent by SES. Timezone lives in the memory layer, so the schedule stays a single job no matter how many regions the players are in.

I used the CockroachDB Cloud Managed MCP Server as my operator surface throughout, connected read-only from my editor: what does the agent remember about this order, what did it retrieve, what did it send. Provisioning, the cluster and the schema were driven from the ccloud CLI, scripted and committed so the whole thing stands up from the repo.

What I learned

Vector search inside the operational database changed the design more than I expected. My first version was a dictionary — caffeine maps to the caffeine line. Putting the embeddings next to the transactional rows meant the retrieval and the memory could not drift apart, and it let the corpus grow without touching the agent.

The read-only MCP connection was the other surprise. Being able to interrogate the memory layer conversationally, safely, while the agent was live, is how I found my scheduling bug.

Challenges

Delivery was the first wall. I wanted SMS, and getting a South African origination number cleared was never going to happen in the time I had, so email it is — the reminder is the product, not the transport.

The harder one was resisting a queue. Every instinct said to precompute tomorrow's messages. But a precomputed message is a cache again, and the whole point is that the agent reads its memory at the moment it acts.

Built solo, from Johannesburg.

Look forward to Sweet Deep Sleep that makes You glad to wake up in the morning!

Built With

Share this project:

Updates