An on-call agent that answers "no prior incidents" might be telling you the archive is empty. It might also be telling you the embedding call timed out, and most memory stores return both as the same empty list.
I built Throughline in August for the CockroachDB x AWS hackathon on agentic memory. It didn't place. My guess at why is at the end.
Throughline is an incident-response agent with a memory layer you can audit. Memories are typed, and the type sets how fast they decay. "The primary is db-7" is an entity fact with a 14-day half-life. "Restarting the pods did not help" is a rejected hypothesis, and it keeps its value for a year. Most systems throw that second kind away, and it's the cheapest useful thing you can tell someone mid-outage.
Every recall comes back with a receipt: the retrieval path that actually ran, how many candidates were examined, what was excluded and under which rule, and a coverage verdict of COVERED, PARTIAL or UNKNOWN. If the search couldn't run, the verdict is UNKNOWN, and a guard at the boundary makes it an error to report that as "nothing found". Ranking is computed in code. The model (Claude Haiku on Bedrock) writes the answer around the results and never produces the number that ordered them.
One limit, up front. With no cloud keys, recall uses a small local embedder that matches words, not meaning. Ask it a question in French about a memory written in English and it will say it searched the whole workspace and found nothing relevant. That's true: it compared them, and they share no words. The receipt proves the search ran. It can't prove the search was clever. Matching meaning is the hosted embedder's job, and on Bedrock that's Titan.
Vector indexing works on CockroachDB's free Basic tier. On 2026-08-03, on v26.2.1, the cluster setting read true and CREATE VECTOR INDEX completed. I couldn't find that written down anywhere.
My first index, on the embedding column alone, was close to useless. An unfiltered nearest-neighbour query used it. Every query recall actually runs has a filter, though, and WHERE workspace_id = $1 planned as a full scan. The docs do say filters are only accelerated on prefix columns. I hadn't read that as "the planner skips the index entirely". The fix was an index on (workspace_id, is_live, embedding), where is_live is a stored computed column so it can't drift from the eviction timestamp it comes from. The capability probe now reads the query plan instead of trusting that an index exists.
I also wrote a client for CockroachDB's managed MCP server, as a second channel that has to agree with the direct one. It never made it into the running demo, but probing the live server paid off. Every failure I could produce came back as HTTP 200, with the error in the JSON-RPC body and no result. A client written the obvious way, rows ?? [], turns an outage into "that row doesn't exist", the exact failure Throughline exists to catch. And select_query quietly adds LIMIT 25 when you don't give it one.
The bug that nearly poisoned the demo was two vector spaces in one column. I'd seeded the demo rows with the local embedder while recall went through Titan. Cosine similarity across two embedders is noise, and nothing throws. Seeding now refuses an embedder that differs from recall's, and says why.
There were 444 entries and three prizes. The winner, Anchor, was also an on-call agent with an Unknown verdict, and its values are close to mine. Its memory and its actions commit in the same transaction, though, so CockroachDB is the mechanism rather than the storage. I kept my memory layer independent of the database on purpose. That's the right call for a library and the wrong one for a contest that asks what the database does for you. I also never deployed the public demo URL the rules asked for (the AWS deploy was planned and never written), and I offered a test count where the winners offered measured comparisons against a baseline.
The demo is 2:47, silent, with captions.