Notes from building Engram for the Global AI Hackathon with Qwen Cloud (Track 1: MemoryAgent)
The junk drawer problem
The track brief asked for persistent memory with "timely forgetting" and "recall within limited context windows," and reading it I realized every memory system I'd ever built failed at least two of those. The standard recipe is: embed everything, store everything, retrieve top-k. That's not memory. That's a junk drawer.
It fails in three ways, and each one gets worse the longer the agent runs. It never forgets, so a fact from March comes back with the same confidence as one from this morning, even after the user told you it changed. It grows without limit, and more candidates means worse retrieval precision. And top-k has no concept of a budget, so a few long chunks can eat half your context window before the user's question even arrives.
Human memory deals with all three using a mechanism we usually file under "bug": forgetting. So I spent the hackathon building forgetting as a feature.
How it's wired
At a high level, the browser UI talks to a FastAPI server, which runs the agent loop. Each turn goes through recall (score memories, pack them under a token budget) and optionally consolidation (extract facts, resolve contradictions, run sleep cycles). Everything persistent lives in SQLite. All model calls go out to Qwen Cloud on Alibaba Cloud.
Forgetting as an algorithm
Every memory in Engram carries a stability value S, in hours. Retention follows the same exponential curve Ebbinghaus drew in 1885:
R(t) = exp(-t / S)
The part that makes it useful is reinforcement. When a memory gets retrieved into context, its stability grows:
S' = 1.6 * S + 12h
That's the spaced-repetition update. A memory recalled a handful of times becomes effectively permanent. A memory nobody touches decays toward a threshold, where a "sleep cycle" compresses it: qwen-flash summarizes each faded group into one short gist, archives the originals, and total storage levels off instead of growing forever.
What I like most about this design is that I never had to write a "should we delete this?" heuristic. Usage decides. Relevance is revealed, not predicted.
Beliefs that supersede instead of overwrite
Raw conversation is episodic memory. Durable facts get distilled out of it (one cheap qwen-flash JSON call per turn) into a ledger of (subject, predicate, object) triples, like (user, is allergic to, shellfish).
The interesting case is contradiction. The user says "I moved to Ponta Delgada" and the ledger holds (user, lives in, Lisbon). The model picks a verdict: supersede, coexist, or discard. Superseding is bi-temporal, meaning the old belief isn't deleted. It gets a valid_to timestamp and a pointer to its successor. One indexed query answers "what's true now?", but the full timeline is still there, and every belief links back to the exact message it was learned from. When the agent gives a wrong answer, debugging is following a chain instead of guessing.
Recall as a knapsack
At recall time every belief and episode gets scored:
relevance = 0.60 * similarity + 0.20 * importance + 0.20 * recency
score = relevance * (0.15 + 0.85 * retention)
Retention multiplies the score rather than adding to it, and there's a floor. A faded memory can still wake up on a very strong semantic match (recognition is easier than free recall, same as in humans), but a weak match on a faded memory drops out entirely.
Then a greedy knapsack packs the winners under a hard 1,200-token budget by score per token. A one-line belief usually beats a rambling episode. The memory context stays the same size whether the agent has a day of history or a year.
Did it work?
I ran Engram against a stateless agent using the identical Qwen model, so the only variable was the memory engine. Three sessions separated by simulated weeks (a persisted clock offset shifts every timestamp uniformly, which is also how the demo shows weeks of decay in minutes), then seven questions graded by a qwen-flash judge. Answering with a superseded fact, like the old city, counts as wrong.
Engram scored 7/7, including the belief-revision traps. The baseline scored 0/7. That number sounds damning but it's just structural: a stateless agent cannot remember anything across sessions, which is exactly the point of the comparison. Memory context averaged 318 tokens per question against the 1,200 budget. Everything is reproducible with python -m eval.run_eval.
Qwen Cloud notes from the trenches
Route by cost. qwen3.7-plus, the reasoning model, only writes the agent's replies. All the bookkeeping (fact extraction, contradiction adjudication, summaries, judging) goes to qwen-flash, and those calls outnumber replies about 3 to 1. This one routing decision made the system roughly an order of magnitude cheaper.
The OpenAI-compatible endpoint at dashscope-intl.aliyuncs.com/compatible-mode/v1 meant zero SDK friction. The standard openai package works unchanged.
text-embedding-v4 at 512 dimensions was plenty for memory recall, and it keeps every stored embedding at 2KB.
One thing that surprised me: reasoning models return their thinking in a separate reasoning_content field, and they spend real tokens on it. Budget latency for that on chat turns, and don't use them for JSON extraction. Flash is faster and, honestly, more obedient at returning clean JSON.
What I'd build next
An MCP server wrapping Engram, so any agent, not just mine, can mount a memory that forgets on purpose.
Repo: https://github.com/abdelaalimouid/Engram-v1 (MIT). Built for the Global AI Hackathon Series with Qwen Cloud.

Top comments (0)