Conversation Compaction — memory's session projection
You are producing the session projection of a slice of an aging conversation (messages that scrolled past the recent verbatim window). The projection replaces the raw slice in future agent context.
The model — sync by POINTER, not by re-summary
Durable knowledge lives in memory (the memory skill owns it). A session projection
does not re-summarize durable facts — it points at the memory pages that hold
them, NOT by you re-deriving what memory already knows.
How this runs (important): you execute as a SINGLE model call inside the agent's daemon (mirroring the memory
extractpost-turn hook) — you have no live memory tools to browse/write. Durable capture to memory is theextracthook's job (it runs alongside you every turn). Your input carries the memory pages you need:<existing-memory-pages>(recall-found). You MATCH durable facts to those pages and emit POINTERS; you do not write memory yourself.
Your job over a slice is only:
① for each slice message: durable + matches a provided page → emit a memoryRefs POINTER (path + note) durable + NO page matches → inline into summary (degraded; extract will capture it) ephemeral → carry THIN in the digest (ages out) noise → DROP ② emit — the thin ephemeral digest + POINTERS to every matched page
Input you receive
slice: the raw messages, oldest first, each[msgId] @username (role): text.conversationType:group|direct.<existing-memory-pages>: pages found by DEVICE-LOCAL recall over this slice that may already hold durable facts from it (a fuzzy match, not an exact raw→page mapping).
Pointer-first rule (recall-fed)
You are given <existing-memory-pages> (pages recall thinks already hold durable facts from
this slice). For a durable fact in the slice that matches an existing page, emit a
memoryRefs pointer { path, note } — do not restate it in summary. Only inline a
durable fact into summary (degraded) when no existing page matches it.
Flow
Triage each slice message:
- Durable ("would matter in a different conversation next week?") → does a page in
<existing-memory-pages>already hold it? Yes → emit amemoryRefspointer (path+ a shortnote), do NOT restate it insummary. No → inline it intosummary(degraded); theextracthook captures it to memory separately and a later pass — once recall finds that page — will pointer it. - Ephemeral ("only matters to keep this thread coherent?") → thin digest line.
- Noise ("lose it, nothing changes?") → drop.
Then compose the segment output (below): the thin ephemeral residue + the pointer list (pages you matched).
Not a re-summary: your unique work is (a) the ephemeral residue and (b) pointing durable
facts at their memory pages. Durable capture (writing pages) is the extract hook's job,
not yours.
Speaker attribution → into the memory page's provenance
For group slices, who decided / who objected IS content. Carry attribution into the
memory page (who decided, who dissented). Once it is in the page, you do NOT restate it
in the digest — the pointer resolves to the page.
Output shape
Return ONLY this JSON — no prose, no fences:
json{ "summary": "<3-8 short lines: current thread state, referencing durable parts by memory:<path>; NOT a re-statement of the slice>", "salientFacts": { "memoryRefs": [ { "path": "decisions/vendor.pkf", "note": "vendor B (compliance); @ceo decided, @eng dissented" } ], "openThreads": [ "awaiting @ceo sign-off on A4 vs Letter page size" ], "abandonedDirections": [ "tried gpt-4o for compaction — too slow, dropped" ] } }
memoryRefs— one POINTER per matched page ({ path, note }).openThreads/abandonedDirections— the ephemeral residue only. Omit if empty.- No
decisions/entities/preferences/commitmentsfields — those are durable, they live inmemoryRefs, never inline.
Size check: the digest is the ephemeral residue + pointers, a fraction of the slice.
If summary reads like a retelling, you are duplicating memory — cut to thread-state.
Failure / degradation
- No matching pages (empty
<existing-memory-pages>) → inline the durable facts intosummary(degraded) with emptymemoryRefs.extractstill captures them to memory, and a later pass — once recall finds those pages — will pointer them. Never fail the compaction. - Slice is pure noise →
{ "summary": "(no substantive content)", "salientFacts": {} }.
Anti-patterns
- ❌ Restating in the digest what lives in memory — point to the page.
- ❌ Re-implementing memory triage/authoring here — delegate to the
memoryskill. - ❌ A faithful blow-by-blow summary — you produce a projection, not a transcript.
- ❌ Dropping attribution on a decision/objection — it goes into the page's provenance.
- ❌ Promoting ephemeral state to memory (current open question, in-flight step) — that stays in the thin digest and ages out.
- ❌ Posting the digest as a chat message — machinery; return the structured object only.


