OpenViking Session Management: How AI Agents Build Long-Term Memory Automatically
Problem: AI Agents Forget Everything
When I built my first conversational AI agent, I quickly ran into a frustrating problem: every session was a blank slate. The agent would ask the same questions repeatedly, forget my preferences, and make the same mistakes over and over.
The core issues were:
- Session isolation: No learning across conversations
- Repeated preferences: Users must restate their preferences every time
- Repeated mistakes: Agent errors persist without correction
OpenViking solves this with automatic memory extraction that builds long-term context from every conversation.
Purpose: Automatic Memory Learning
OpenViking’s session management provides:
- Automatic extraction: No manual memory management required
- Six structured categories: Organized, searchable memories
- Self-iteration: The agent gets smarter with every use
Let me show you how it works.
Session Lifecycle: The Foundation
The session is the core unit of conversation in OpenViking. Here’s the basic lifecycle:
from openviking import OpenVikingfrom openviking.message import TextPart
client = OpenViking()
# Create sessionsession = client.session(session_id="chat_001")
# Interactsession.add_message("user", [TextPart("I prefer dark mode for all UI elements")])session.add_message("assistant", [TextPart("Noted, I'll use dark theme for your projects...")])
# Commit: triggers compression + memory extractionresult = session.commit()The commit() call is where the magic happens. It triggers:
- Conversation compression
- Archive creation with L0/L1 summaries
- LLM-based memory extraction
- Memory directory updates
Session API Overview
The session API is intentionally minimal:
| Method | Description |
|---|---|
add_message(role, parts) | Add a message to the session |
used(contexts, skill) | Record which contexts/skills were used |
commit() | Commit session: archive + memory extraction |
Message Structure
Each message has a structured format:
from dataclasses import dataclassfrom datetime import datetimefrom typing import List
@dataclassclass Message: id: str # msg_{UUID} role: str # "user" | "assistant" parts: List[Part] # TextPart, ContextPart, ToolPart created_at: datetimeThe parts list can contain different types:
TextPart: Plain text contentContextPart: Referenced contextToolPart: Tool call results
The Six Memory Categories
OpenViking organizes memories into six distinct categories:
| Category | Owner | Description | Mergeable |
|---|---|---|---|
| profile | user | User identity and attributes | Yes |
| preferences | user | User preferences and choices | Yes |
| entities | user | Entities like people and projects | Yes |
| events | user | Events and decisions | No |
| cases | agent | Problem + solution pairs | No |
| patterns | agent | Reusable patterns | Yes |
This categorization serves several purposes:
- Searchability: Find memories by type
- Conflict resolution: Different merge strategies per category
- Ownership clarity: User vs agent memories are separate
Memory Extraction Flow
When you call commit(), OpenViking runs a sophisticated extraction pipeline:
Messages → LLM Extract → Candidate Memories ↓Vector Pre-filter → Find Similar Memories ↓LLM Dedup Decision → Create/Merge/Skip ↓Write to AGFS → VectorizeThe deduplication logic is particularly clever:
| Level | Decision | Description |
|---|---|---|
| Candidate | skip | Duplicate found, do nothing |
| Candidate | create | New memory, create it |
| Candidate | none | Resolve existing instead |
| Item | merge | Merge into existing memory |
| Item | delete | Delete conflicting memory |
This prevents memory bloat while ensuring important information is preserved.
Compression Strategy
Auto-archiving happens automatically on commit():
- Increment the compression_index
- Copy messages to archive directory
- Generate structured summary using LLM
- Clear current messages list
The summary format is structured for easy retrieval:
# Session Summary
**One-line overview**: [Topic]: [Intent] | [Result] | [Status]
## AnalysisKey steps list
## Primary Request and IntentUser's core goal
## Key ConceptsKey technical concepts
## Pending TasksUnfinished tasksThis L0 summary can be further compressed into L1 overviews for long-running sessions.
Storage Structure
OpenViking uses a virtual filesystem (AGFS) for storage:
viking://session/{session_id}/├── messages.jsonl # Current messages├── .abstract.md # Current abstract├── .overview.md # Current overview├── history/│ ├── archive_001/│ │ ├── messages.jsonl│ │ ├── .abstract.md│ │ └── .overview.md│ └── archive_NNN/└── tools/
viking://user/memories/├── profile.md # User profile├── preferences/├── entities/└── events/
viking://agent/memories/├── cases/└── patterns/This structure allows:
- Session isolation: Each session has its own namespace
- Memory persistence: User and agent memories persist across sessions
- Efficient retrieval: Vector search over memory directories
Practical Example: Memory Learning in Action
Let me show you a complete example of how memories are learned and retrieved:
from openviking import OpenVikingfrom openviking.message import TextPart, ContextPart
client = OpenViking()
# First session - user mentions preferencesession = client.session("user_123")session.add_message("user", [ TextPart("I prefer using TypeScript over JavaScript for all new projects")])session.add_message("assistant", [ TextPart("I'll use TypeScript for your project examples going forward.")])session.commit() # Extracts preference memory
# Later session - preference is rememberedsession2 = client.session("user_123")results = client.find( "coding preferences", target_uri="viking://user/memories/")# Returns: user prefers TypeScript
# The agent can now use this contextsession2.add_message("user", [ TextPart("Create a new API endpoint for user authentication")])# Agent automatically uses TypeScript based on stored preferenceThe key insight is that the second session has access to the preference learned in the first session—without any manual configuration.
Recording Context and Skill Usage
OpenViking also tracks what resources were used during a session:
# Record which contexts were usedsession.used(contexts=[ "viking://resources/docs/api.md", "viking://user/memories/preferences/coding.md"])
# Record skill usagesession.used(skill={ "uri": "viking://agent/skills/search-code", "input": "find authentication code", "output": "found 3 files", "success": True})This usage tracking enables:
- Context relevance scoring: Learn which contexts are most useful
- Skill optimization: Identify successful skill patterns
- Debugging: Understand agent decision paths
How This Compares to Other Approaches
I’ve tried several memory solutions for AI agents:
| Approach | Problem |
|---|---|
| No memory | Every session starts fresh |
| Manual memory | Developer must explicitly store and retrieve |
| Full history | Context window overflow, expensive |
| RAG only | No structured learning, just retrieval |
OpenViking’s approach combines the best of all worlds:
- Automatic: No manual memory management
- Structured: Six categories with clear semantics
- Efficient: Compression keeps context manageable
- Intelligent: LLM-powered deduplication
When to Use OpenViking Session Management
This approach is ideal when:
- You need agents that learn user preferences over time
- Sessions span multiple conversations
- You want automatic knowledge accumulation
- Memory deduplication is important
It may be overkill for:
- Single-session chatbots
- Stateless API integrations
- Simple Q&A systems
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments