Conversation
Lets memory entries optionally start with a YAML frontmatter block: --- type: preference valid_until: 2026-12-31 --- <body> Reader-side only — no schema or writer-side changes: - Backward-compatible: entries without frontmatter render identically, on-disk format is unchanged, char-budget bookkeeping still measures the full on-disk entry (so writers can't silently free budget by adding metadata). - The block is stripped from what gets injected into the system prompt, so the model sees a clean body. - Entries with 'valid_until' in the past are prefixed with a '[STALE — expired YYYY-MM-DD]' marker at render time, giving the model a visible signal to deprioritise time-bound facts (e.g. travel dates, expired credentials, one-off project state) without the writer having to scrub them first. - Malformed YAML / scalar frontmatter / non-mapping payloads degrade to plain-text rendering — memory must keep working even when an agent writes a slightly broken header. Recognised keys today: type, created_at, last_used_at, source, valid_until, supersedes, evidence. Unknown keys are preserved on disk and ignored at render time, leaving room to layer additional behaviour (decay, supersession, provenance display) in follow-ups. Tests cover frontmatter parsing, date coercion, staleness logic, prompt-render stripping, the STALE marker, legacy-entry preservation, and the usage-counter invariant.
|
Status / gentle ping — opened 2026-05-08, sitting without review. This is a typed-memory MVP that addresses a recurring class of bug: stale facts (travel dates, sprint preferences, one-off project settings) keep getting injected into the system prompt long after they stopped being true. The PR adds optional YAML frontmatter so an entry can carry Re: failing CI — none of the failures are caused by this diff:
Happy to rebase on current main if a fresh CI pass would help. Would value @teknium1 / @alt-glitch eyes on whether the frontmatter shape and scope semantics match what you'd want from a typed-memory first pass. |
|
Status ping (15 days, no review yet) — branch still |
Why
Memory entries today are flat strings. There's no built-in way for the agent to mark an entry as time-bound (a travel date, a sprint-scoped preference, a one-off project setting), so stale facts keep getting injected into the system prompt long after they stopped being true. The discussion in #10771 has been pushing toward typed memory entries with frontmatter (
type/created_at/last_used_at/source/valid_until/supersedes/evidence); related work in #17380 is tightening the boundary between compaction summaries and durable memory along the same direction.This PR is the smallest useful slice in that direction.
What
Reader-side only — no schema changes, no writer-side changes, no migration.
An entry may now optionally start with a YAML frontmatter block:
When present, it's stripped at render time so the model sees a clean body. When
valid_untilis in the past, the rendered entry gets a[STALE — expired YYYY-MM-DD]prefix so the model has a visible signal to deprioritise the entry without the writer having to scrub it first.Recognised keys today:
type,created_at,last_used_at,source,valid_until,supersedes,evidence. Unknown keys are preserved on disk and ignored at render time — that leaves room to layer additional behaviour (decay weighting, supersession resolution, provenance display) in follow-up PRs without re-litigating the format.Why this shape
memorytool's OpenAI function-calling schema is untouched. An agent that wants typed entries simply writes the frontmatter block in the existingcontentargument; an agent that doesn't, never sees it.metadataparameter onadd/replace), it can encode into the same on-disk format this reader already understands.Test coverage
22 new tests in
tests/tools/test_memory_tool.py:---\nfoo\n---),---appearing later in body, unknown-key preservationdatepassthrough, ISO date string, ISO datetime string withZ, garbage/None/int/emptyvalid_until, future date, past date, today (fresh), yesterday (stale)Existing tests (33 in
test_memory_tool.py+ sibling memory tests intests/agent/andtests/tools/) continue to pass — 147 / 147 across the relevant suite locally.Follow-ups (out of scope here)
metadataparameter onadd/replace(separate PR — easier to review when the read path is in)prune_stale(target, before=...)administrative APIlast_used_atupdates on memory-read paths_success_responseso tool callers see the full structure, not just the bodyHappy to split, reshape, or rebase — whatever works best with the typed-memory direction in #10771 and the compaction-isolation work in #17380.