cd /news/artificial-intelligence/i-built-an-ai-memory-agent-that-forg… · home topics artificial-intelligence article
[ARTICLE · art-66069] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=↑ positive

I Built an AI Memory Agent That Forgets on Purpose — Then Spent Two Days Proving It Actually Works

A developer built Synapse, an AI memory agent with intentional forgetting, for the Global AI Hackathon Series with Qwen Cloud. The system uses decay math, contradiction detection, and consolidation to outperform naive vector storage, and was benchmarked against the naive approach to prove its effectiveness.

read5 min views2 publishedJul 20, 2026

Every "AI memory agent" I looked at before starting this does the same trick: embed every message, dump it in a vector database, retrieve the top-k most similar chunks at query time. That's not memory. That's a search index. It never forgets anything, it treats "nice weather today" with the same weight as "I'm allergic to penicillin," and it gets slower and dumber the longer it runs because retrieval gets noisier with every near-duplicate you never clean up.

For the Global AI Hackathon Series with Qwen Cloud (Track 1: MemoryAgent), the brief asked for three specific things: efficient storage and retrieval, timely forgetting of outdated information, and recalling critical memories within a limited context window. That middle one is the one almost nobody builds, because naive vector storage has no concept of "outdated." So I built it — real decay math, real consolidation, real contradiction detection — and then benchmarked it against the naive approach to prove it actually works, instead of just claiming it does.

This is the story of building that, on Qwen Cloud, in about two days, including the parts that broke.

Every memory Synapse stores gets a salience

score that changes over time:

salience(t) = importance_score * recall_boost(recall_count) * exp(-lambda * hours_since_last_recall)
recall_boost(n) = 1 + log(1 + n)
lambda = ln(2) / half_life_hours

Two things matter here. First, importance_score

isn't a keyword heuristic — it's a real structured-output call to Qwen at write time, scoring the memory on explicit signals ("remember this"), decision-relevance (is this the kind of fact that should change future behavior?), and specificity. Second, the half-life isn't a single global constant. Episodic details — what you mentioned on a random Tuesday — decay in about 72 hours unless reinforced. Semantic facts — stable preferences, "I'm vegetarian" — decay over 30 days. That asymmetry is the whole point: the system should forget what you talked about, not what you told it matters.

On top of decay, a background "sleep pass" does two more things a naive vector store can't:

Every LLM call in this project — chat replies, importance scoring, memory extraction, contradiction judgment, cluster summarization, and even the benchmark's own LLM-as-judge scoring — goes to a real Qwen Cloud endpoint. No mocked responses, anywhere, including in the benchmark. That was a hard rule I set for myself: if a mechanism didn't work for real, I'd cut the claim rather than fake the output.

Getting there wasn't instant. Qwen Cloud's OpenAI-compatible endpoint is workspace-specific — not the generic host you'd expect, but a ws-<workspace-id>.<region>.maas.aliyuncs.com

URL you have to find on your own console's API-key page. Past that, qwen-max

/qwen3.7-plus

handled chat, scoring, extraction, and consolidation, and text-embedding-v3

handled every embedding call for retrieval and clustering.

One thing that genuinely surprised me: switching to a faster chat model (qwen3.6-flash

) to speed up the benchmark run occasionally returned malformed JSON on structured-output calls — an empty {}

where a real score should've been. Rather than paper over it with a fallback default, I built a retry wrapper that specifically re-prompts on shape failure, not just network failure:

def _chat_json_retrying(system_prompt, user_prompt, validate, temperature=0.2, max_attempts=3):
    for attempt in range(max_attempts):
        result = _chat_json(system_prompt, user_prompt, temperature)
        if validate(result):
            return result
    raise ValueError("Qwen returned an invalid shape after retries")

Small thing, but it's the difference between a benchmark that silently produces garbage numbers and one that fails loudly when something's actually wrong.

Here's the one I'm most honest about. The consolidation pass is supposed to compare timestamps to figure out which of two contradicting memories is newer. I ran the full benchmark — 110 turns across a simulated 40-day conversation — using a fabricated now

value passed through the code so I could compress 40 days into one script run instead of waiting 40 real days.

Except one function wasn't using that fabricated time. It was quietly falling back to datetime.now()

— real wall-clock time — when deciding which memory was "newer." Every memory in the simulation, regardless of its fictional in-conversation date, actually got written at roughly the same real moment. So the timestamp comparison the contradiction check depended on was comparing noise, not the actual simulated chronology.

I found it by directly querying the database after the benchmark run showed a backwards result — the system confidently answering with a stale fact instead of the current one. Not a vague "accuracy could be better," a specific, traceable bug. I fixed it by threading the simulated now

explicitly through every function that touches timestamps, instead of letting anything default to real time, and wrote a regression test that reproduces the exact failure:

def test_stale_fact_loses_even_when_inserted_after_correct_one():
    ...

I built a second agent — same Qwen models, same embeddings, the only difference being zero decay, zero consolidation, zero pruning — and ran both through the identical conversation. Real results:

That last one is worth sitting with. I could have cherry-picked the two metrics that make the project look great and left it there. Instead I dug into why Synapse lost on raw recall, and found two specific, fixable causes: a similarity pre-filter gate that was rejecting a real contradiction phrased in different words (measured similarity as low as 0.59 against a 0.75 gate), and a re-ranking formula where a frequently-recalled generic fact could out-rank a less-reinforced but more relevant one. I fixed both, verified the fixes with targeted regression tests and a live end-to-end test against the deployed app, and documented all of it — including that I didn't have time to re-run the full multi-hour benchmark against the fixed code before the deadline.

A chart you can trust is worth more than a chart that flatters you.

Synapse is live on Alibaba Cloud ECS, the code is public and MIT-licensed, and the full honest writeup — including the bugs, the fixes, and the numbers before and after — is in the repo.

Repo: github.com/Boweii22/Synapse

Live demo: http://8.208.98.93

Demo video: youtu.be/0SXzcWqlZog

Built for Track 1 (MemoryAgent) of the Global AI Hackathon Series with Qwen Cloud.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @qwen cloud 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-built-an-ai-memory…] indexed:0 read:5min 2026-07-20 ·