Blog/Article

Compressing agent memory only works on long memories

We compressed 589 production agent memories into a structured format. 37% of them came out larger than they went in. Here is the break-even length nobody mentions.

August 11, 20263 min read

Agent memory has a fixed ceiling. Every session, an AI employee loads its history into a context
window, and that window does not grow. Once it fills, the oldest memories stop being loaded. The
agent has not forgotten them exactly, but it can no longer see them, which amounts to the same thing
when you are the person re-explaining a decision for the fourth time.

The obvious fix is to make each memory smaller. We built a pipeline that rewrites prose memories
into a compact structured record, ran it across our production corpus, and measured what actually
happened. The headline result was not the one we expected.

The format

A memory starts life as prose, because that is how an extraction model writes it:

The client prefers timely responses and has requested that observations during the research phase
be surfaced as they happen rather than batched into a weekly summary.

The compressed form encodes the same fact as a typed record with a metadata header:

@Astrid>client . #prf #consultative_sales +luxury <- $f:0.71 $t:2026-04 +stale
Consultative sales fit, luxury segment, surface observations live not batched.

The header carries who the memory is about, its kind, its tags, a confidence score and a date stamp.
Everything after it is the fact itself. A legend line at the top of the file teaches the reading
model the grammar once, so it does not need to be repeated per record.

What we measured

We ran this across 997 stored memories. 589 have been through the pipeline so far. Comparing the
original prose against the compressed record, character for character:

Slice

Memories

Saving

All compressed memories

589

17.8%

Memories longer than 400 characters

20

70.9%

Memories that got larger

218

negative

That third row is the interesting one. 37% of the memories we compressed came out bigger than they
went in.

Why compression can cost you

The metadata header is a fixed cost of roughly 60 to 90 characters. It buys real things: the reading
model gets typed, dated, confidence-scored facts instead of undifferentiated prose, and it can filter
and rank them without a second pass.

But a fixed cost only pays for itself if there is enough prose to condense. Our average memory is 191
characters. Compressing one produces a 157-character record, of which the header is most of the
budget. The memories that grew averaged 129 characters going in. The ones that shrank averaged 228.

There is a break-even length, and a large part of our corpus sits below it.

The correction

Compression is not a property you apply to a corpus. It is a trade against a fixed overhead, and it
only wins where the input is long enough to amortize that overhead. The right behaviour is to
compress selectively above the break-even point and leave short memories as prose, which is what the
sync already does for anything the pipeline has not touched.

The 71% figure on long memories is the real result, and it is worth having. An agent that writes
detailed notes gets most of that context back. An agent that writes terse ones was already efficient
and has nothing to gain.

Two things that were straightforwardly good

The pipeline writes a Merkle root over each batch of compressed blocks into the synced workspace
file. That means an agent's memory file can be checked for truncation or tampering without reading it
back from the database, which turned out to be more useful than the compression itself during
debugging.

Routing the work through a task alias that injects the format grammar server side also removed a
50MB dependency and moved the calls onto free tier models. Compression costs nothing to run, which is
why running it on memories that do not benefit was easy to miss.

What we would tell someone building this

Measure the delta per record, not in aggregate, and plot it against input length. Our aggregate
number was a positive 17.8%, which looks like a win and hides the fact that more than a third of the
corpus moved the wrong way. The break-even length is the number that matters, and you cannot see it
from an average.

Read the release notes at https://opvs.ai/changelog.

Subscribe to our newsletter for blog updates and original content