Skip to content

feat(memory): add TTL and auto-expiration for memory entries#1109

Open
mvanhorn wants to merge 3 commits intovolcengine:mainfrom
mvanhorn:osc/1027-memory-ttl-expiration
Open

feat(memory): add TTL and auto-expiration for memory entries#1109
mvanhorn wants to merge 3 commits intovolcengine:mainfrom
mvanhorn:osc/1027-memory-ttl-expiration

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

Problem Statement

OpenViking stores memories indefinitely. Over time, stale context accumulates and degrades retrieval quality. Users in #1027 and #269 have asked for memory forgetting and deletion.

Proposed Solution

Add an optional expires_at field to MemoryData. When set, expired memories are excluded from retrieval results. TTL defaults are configurable per memory type in ov.conf, with per-memory overrides via metadata.

Evidence

Source Evidence Engagement
#1027 Memory forgetting/overwrite requested open
#269 Individual memory deletion gap @qin-ctx acknowledged
MemAware benchmark RAG memory fails on stale context 10 upvotes, 27 comments
Memory drift Multi-agent workflows accumulate stale state 16 comments

Stale memory is a known failure mode in RAG-based agent systems. TTL provides a minimal, backward-compatible mechanism to address it.

Changes

  • MemoryData.expires_at: Optional datetime field, None = never expires
  • MemoryData.is_expired(): timezone-aware check against UTC now
  • MemoryConfig: default_ttl, ttl_by_type config fields, parse_ttl() static method ('7d', '24h', '30m' format)
  • MemoryExtractor.create_memory(): computes expires_at from config with per-memory metadata override
  • HierarchicalRetriever.retrieve(): filters expired entries before returning results

Testing

8 unit tests covering:

  • is_expired() with no/future/past expiration
  • parse_ttl() with valid and invalid inputs
  • Backward compatibility (no expires_at = works normally)
tests/unit/session/test_memory_ttl.py ........  [100%]
8 passed

Screenshots

TTL Demo

Implementation Notes

  • Mirrors the existing PathLock.is_lock_stale() expiration pattern already in the codebase
  • Handles timezone-naive datetimes by assuming UTC (consistent with parse_iso_datetime)
  • Per-memory override: metadata={"ttl": "7d"} in add_message
  • Expired entries are filtered after scoring in retrieve(), so they don't affect result count

Relates to #1027, #269

This contribution was developed with AI assistance (Codex).

Feature Area

Session Management

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 31, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions
Copy link
Copy Markdown

Failed to generate code suggestions for PR

@qin-ctx qin-ctx requested a review from chenjw March 31, 2026 08:06
@qin-ctx
Copy link
Copy Markdown
Collaborator

qin-ctx commented Mar 31, 2026

/review

@github-actions
Copy link
Copy Markdown

Preparing review...

mvanhorn and others added 3 commits March 31, 2026 05:56
Add an optional expires_at field to MemoryData and implement
expiration checking during memory retrieval. Expired memories
are excluded from search results.

- MemoryData.expires_at: Optional datetime, None = never expires
- MemoryData.is_expired(): timezone-aware expiration check
- MemoryConfig: default_ttl, ttl_by_type, parse_ttl() for
  config-driven TTL ('7d', '24h', '30m' format)
- MemoryExtractor.create_memory(): computes expires_at from
  config with per-memory metadata override
- HierarchicalRetriever: filters expired entries before return

Relates to volcengine#1027, volcengine#269

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mvanhorn mvanhorn force-pushed the osc/1027-memory-ttl-expiration branch from 5a2ba0f to a4acc2e Compare March 31, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

4 participants