diff --git a/changelog.mdx b/changelog.mdx index 17e7c99..9248ad7 100644 --- a/changelog.mdx +++ b/changelog.mdx @@ -22,6 +22,22 @@ export const STAGE_SELF_MANAGED_M66 = "$0.0001"; usezombie is in **stealth-mode testing** and pre-production. APIs and agent behavior may change between releases without long deprecation windows. Email [usezombie@agentmail.to](mailto:usezombie@agentmail.to) if you want a hand calibrating an agent or to join as a design partner. + + ## `core` memories now survive the hydration window and the entry cap + + Memory selection previously ran on write-recency alone: an identity fact stored once — an owner, a deploy target, a customer's plan — was the first thing both the hydration window and cap eviction discarded once noisier `daily` writes piled up. Both mechanisms are now category-pinned, so the facts an agent marked durable stop being the first casualties of the byte budget and the entry cap. + + ## What's new + + - **Category-pinned hydration** — every `core` entry that fits the hydration byte budget loads before any non-core entry is considered; the remaining budget fills with the newest non-core entries. A `core` fact written in run 1 is still in context at entry 1001. + - **Tiered cap eviction** — at the per-agent entry cap, the coldest non-core rows are deleted first; a `core` row is evicted only when no non-core row remains. + - **Safe default for custom categories** — a category the platform doesn't recognise is windowed by recency, never silently pinned. + - **Deterministic selection** — same entries, same budget, same hydration on every run, so "why does my agent remember X but not Y?" has a checkable answer: X was `core`, Y was windowed. + - **Memory-hygiene guidance** — the [Memory page](/memory) now documents what to store as `core`, why stable keys beat dated ones, and why hoarding everything as `core` defeats the pinning. + + The four memory tools, the wire shapes, the hydration byte budget, and the entry cap are unchanged — only which entries fill the window. + + ## Platform token spend now actually bills diff --git a/memory.mdx b/memory.mdx index 22db7f1..7f41000 100644 --- a/memory.mdx +++ b/memory.mdx @@ -11,7 +11,7 @@ Memory is always on — no setup, no flag. | Category | Scope | Lifetime | Use for | |---|---|---|---| -| `core` | agent | permanent until forgotten | Learned facts about durable entities — customers, accounts, preferences. | +| `core` | agent | durable; evicted last at the entry cap | Learned facts about durable entities — customers, accounts, preferences. | | `daily` | agent | 72h auto-prune | Time-bounded follow-ups, open tickets, scheduled reminders. | | `conversation` | event | dies with the run | Within-run scratch — checkpoint findings during a long incident. | | `workspace` | workspace | durable | Facts shared across every agent in the workspace. | @@ -43,6 +43,23 @@ flowchart LR Store --> End([run closes]) ``` +## What survives — selection and eviction + +Hydration (what an agent sees at run start) and eviction (what the platform deletes at the per-agent entry cap) are both **category-pinned**: `core` wins. + +- **Hydration** fills a fixed byte budget: every `core` entry that fits loads first (newest first), then the newest non-core entries fill the remainder. A `core` fact written once — an owner, a deploy target, a customer's plan — is still in context at entry 1001, even after a noisy month of `daily` writes. +- **Eviction** at the entry cap deletes the coldest non-core entries first. A `core` entry is deleted only when nothing else remains. +- **Custom categories** (and anything the platform doesn't recognise) are windowed by recency — never silently pinned. + +Selection is deterministic — same entries, same budget, same result — so "why does my agent remember X but not Y?" always has a checkable answer: X was `core`; Y was windowed, or too big for the budget. + +Four habits make selection work for you instead of against you: + +1. **Store load-bearing facts as `core`.** If a future event must know it, it's `core`. Everything windowed ages out of hydration. +2. **Reuse stable keys.** Re-storing a key refreshes the entry instead of duplicating it — `deploy_target`, not `deploy_target_jun12`. +3. **Forget what's stale.** `memory_forget` beats letting eviction pick the victim. Hoarding everything as `core` defeats the pinning: an all-`core` set over the cap evicts your coldest `core` facts. +4. **Keep entries small.** The hydration budget is bytes, not entries — snapshot conclusions, not transcripts. + ## Entry format Memory is stored in Postgres but exports as markdown for human review. @@ -93,6 +110,6 @@ The underlying system changed but memory didn't. Steer the agent to call `memory | Symptom | Cause | Fix | |---|---|---| | Recall returns nothing on a known entity | Inconsistent key convention | Use a stable, deterministic key derivation in `SKILL.md` (e.g. `customer_`). | -| Memory grows forever | No pruning on `core` (by design) | Steer the agent to call `memory_forget` on stale keys, or move time-bounded entries to `daily`. | +| Memory grows forever | `core` has no time-based pruning; at the entry cap, coldest `core` entries are evicted when no non-core entries remain | Steer the agent to call `memory_forget` on stale keys, or move time-bounded entries to `daily`. | | `UZ-MEM-003` on store | Memory backend unavailable | Re-run the trigger; if persistent, file an issue. | | `UZ-MEM-001` on store | Memory scope denied (cross-agent access attempt) | Memory is per-agent. Use `workspace`-category writes if you need to share facts across agents. |