feat(experimental): add context memory — persistent key-value blocks for agents#1005
feat(experimental): add context memory — persistent key-value blocks for agents#1005mattzcarey wants to merge 2 commits intomainfrom
Conversation
Adds Context Memory as the second tier of the experimental memory system. Context stores labeled text blocks (personality, preferences, tasks) that persist across sessions and can be injected into AI prompts. Key features: - Readonly blocks (SOUL files the AI cannot modify) - maxTokens enforcement via token estimation heuristic - AI tool integration via tools() → ToolSet - System prompt rendering via toString() - Predefined blocks with defaults
|
commit: |
|
Are you imagining a use case where this could work at two levels? It seems like there is a straightforward path to creating something like a |
Summary
Adds Context Memory as the second tier of the experimental memory system (after Session Memory in #991). Context stores labeled text blocks that persist across sessions and can be injected into AI prompts.
Two primary use cases:
Usage
Reading blocks
Writing blocks
AI tool integration
The
tools()method returns aToolSet(from AI SDK) containing anupdate_context_blocktool. The tool description lists all writable blocks. Readonly blocks are excluded from the tool but visible intoString()output withreadonly="true".System prompt rendering
toString()renders all blocks as structured XML:Architecture
Mirrors the Session Memory pattern — wrapper class with business logic over a pure storage provider:
Key design decisions
ContextBlockused everywhere. Provider returnsStoredBlock(Omit<ContextBlock, "tokens">), wrapper adds computedtokensfield viaestimateStringTokens().setBlock()andappendToBlock()throw on readonly blocks regardless of caller.estimateStringTokens()heuristic from Session Memory (hybrid char/word estimate, ~4 chars/token).ContextOptionsare lazily initialized on first read. Existing blocks are preserved.Implementing custom providers
Implement the
ContextProviderinterface (5 methods):No business logic needed — the
Contextwrapper handles readonly, maxTokens, defaults, and token computation.Limitations / reviewer notes
estimateStringTokens()uses ~4 chars/token (conservative). Not exact tokenizer counts. Fine for limits but not precision use cases.tools()returns a singleupdate_context_blocktool for all writable blocks. Could add per-block tools later if needed.setBlockfor initial creation.New files (7)
packages/agents/src/experimental/memory/context/types.ts— typespackages/agents/src/experimental/memory/context/provider.ts—ContextProviderinterfacepackages/agents/src/experimental/memory/context/context.ts—Contextwrapper classpackages/agents/src/experimental/memory/context/providers/agent.ts—AgentContextProvider(DO SQLite)packages/agents/src/experimental/memory/context/index.ts— barrel exportspackages/agents/src/tests/agents/context.ts— test agentspackages/agents/src/tests/experimental/memory/context/provider.test.ts— 20 testsTests
20 tests covering: CRUD, upsert, append, maxTokens enforcement (set + append), readonly enforcement (set + append), predefined blocks with defaults, predefined block re-initialization after clear, toString rendering (with/without readonly), empty state, and persistence across agent lookups.