Memory Model
The Memory Model is the foundation of Papr Memory, defining how information is structured, stored, and retrieved. It combines vector embeddings with graph relationships to create a rich, contextual memory system.
Core Components
Memory Item
A memory item is the basic unit of information in Papr Memory. It consists of:
{
"id": "mem_abc123",
"content": "Meeting notes from our product roadmap session",
"type": "text",
"metadata": {
"topics": ["product", "planning", "roadmap"],
"hierarchical_structures": "Business/Planning/Product",
"conversationId": "conv-123",
"sourceUrl": "https://meeting-notes.example.com/123",
"workspaceId": "ws_456",
"external_user_id": "user_789",
"createdAt": "2024-03-20T10:00:00Z"
}
}Content Types
Papr Memory supports the following content types as defined in the API specification:
Text (
text):- Standard text content
- Meeting notes
- Chat conversations
- Notes and summaries
- JSON
- Other
Code Snippets (
code_snippet):- Programming code
- Scripts
- Configuration files
- Technical documentation with code examples
- Other
Documents (
document):- PDF files
- Word documents
- Markdown documents
- Text documents
Messages vs Direct Memories
Papr provides two complementary APIs for storing information:
Messages API (/v1/messages)
Best for: Chat applications, conversational AI, dialogue systems
The Messages API is specifically designed for chat/conversation scenarios:
- Session Management: Automatically groups messages by
session_id - Automatic Memory Creation: With
process_messages: true, important messages become searchable memories - Built-in Compression: Long conversations are automatically compressed for efficient LLM context
- Role-Based Storage: Tracks user messages and assistant responses separately
- History Retrieval: Get paginated conversation history
- Context Management: Intelligent summarization for token optimization
# Store a chat message
client.messages.store(
content="I need help with my project",
role="user",
session_id="conv_123",
external_user_id="user_456",
process_messages=True # Creates memories automatically
)
# Get conversation history
history = client.messages.get_history(session_id="conv_123")Direct Memory API (/v1/memory)
Best for: Structured data, explicit knowledge, non-conversational content
The Memory API gives you direct control over what gets stored:
- Explicit Control: You decide exactly what becomes a memory
- Structured Data: Add memories with specific metadata and properties
- Knowledge Graphs: Use
memory_policyto control entity/relationship extraction - Rich Metadata: Attach custom metadata for filtering and organization
- Document Processing: Upload PDFs/Word docs with structured extraction
# Create a memory directly
client.memory.add(
content="Customer Jane prefers dark mode UI",
memory_policy={
"mode": "auto",
"schema_id": "preferences_schema"
}
)When to Use Which?
| Use Case | Recommended API | Why |
|---|---|---|
| Chat applications | Messages API | Automatic session management, compression, history |
| Customer support bots | Messages API | Track conversations, automatic memory creation |
| Meeting notes | Direct Memory | Structured content, explicit metadata |
| Document upload | Direct Memory | Process PDFs/docs with schema-guided extraction |
| User preferences | Direct Memory | Structured data with controlled properties |
| Knowledge base | Direct Memory | Explicit control over what's stored |
| Multi-turn conversations | Messages API | Built-in context management |
Hybrid Approach
Many applications use both APIs:
- Messages API for chat interactions
- Direct Memory API for structured facts
# Chat interaction (Messages API)
client.messages.store(
content="User mentioned they work at Acme Corp",
role="user",
session_id="conv_123"
)
# Explicit fact (Direct Memory API)
client.memory.add(
content="User profile",
memory_policy={"mode": "manual"},
metadata={
"external_user_id": "user_456",
"company": "Acme Corp",
"role": "engineer"
}
)Memory Policy
The memory_policy field controls how knowledge graphs are generated from your content:
Auto Mode
Let AI extract entities and relationships:
memory_policy={
"mode": "auto",
"schema_id": "your_schema", # Optional: guide extraction
"node_constraints": [...] # Optional: control entity creation
}Manual Mode
Specify exact graph structure:
memory_policy={
"mode": "manual",
"nodes": [{"id": "n1", "type": "Person", "properties": {...}}],
"relationships": [{"source": "n1", "target": "n2", "type": "WORKS_FOR"}]
}Access Control
Memory policies support ACL, consent, and risk tracking:
memory_policy={
"mode": "auto",
"consent": "explicit", # explicit, implicit, terms, none
"risk": "sensitive", # none, sensitive, flagged
"acl": {
"read": ["external_user:alice"],
"write": ["external_user:alice"]
}
}See Graph Generation Guide for complete details.
Processing Pipeline
Papr Memory handles all the complex processing for you behind the scenes. As a developer, you simply need to:
- Add Memories: Use the
/v1/memoryAPI to save content to your knowledge base - Search Memories: Use the
/v1/memory/searchAPI to retrieve relevant information
What happens automatically:
Adding Content to Memory
Retrieving Content from Memory
What Papr Handles For You:
1. Content Processing
- Automatic chunking and segmentation
- Format conversion
- Metadata extraction
2. Knowledge Representation
- State-of-the-art vector embeddings
- Automatic relationship discovery
- Context preservation
3. Storage & Indexing
- Optimized vector indexing
- Graph database organization
- Fast retrieval structures
4. Intelligent Search
- Semantic similarity matching
- Multi-hop graph traversal
- Dynamic result reranking
Memory Organization
Vector Storage
Memory items are transformed into high-dimensional vector embeddings, allowing for semantic similarity search. This means you can find relevant information even when exact keywords don't match.
Graph Structure
Memory items are also organized in a knowledge graph with:
- Explicit relationships between memories
- Contextual connections
- Temporal sequencing
- Hierarchical organization
Memory Operations
Creating Memories
# Simple memory creation
memory = client.memory.add(
content="Meeting notes from project kickoff",
type="text"
)
# Memory with rich metadata
memory = client.memory.add(
content="Meeting notes from project kickoff",
type="text",
metadata={
"topics": ["project", "planning", "kickoff"],
"hierarchical_structures": "Projects/Atlas/Meetings",
"conversationId": "conv-123",
"sourceUrl": "https://meeting-notes.example.com/123",
"workspaceId": "ws_456",
"external_user_id": "user_789"
}
)Searching Memories
# Simple search with detailed query
results = client.memory.search(
query="Find the detailed discussion about API rate limiting from our technical design meetings last month. I need information about the proposed limits and any concerns raised by the team.",
enable_agentic_graph=True
)
# Advanced search with parameters
results = client.memory.search(
query="Find all project kickoff meeting notes with action items assigned to the marketing team. Focus on items related to the Q2 product launch.",
max_memories=15,
max_nodes=10,
enable_agentic_graph=True,
external_user_id="user_789"
)Best Practices
Provide Detailed Content
- Be specific and descriptive
- Include relevant context
- Use clear, structured formats
Use Rich Metadata
- Add topics and hierarchical structures
- Include temporal and location information
- Use consistent categorization
Write Detailed Search Queries
- Use 2-3 sentence queries with specific details
- Include context about why you need the information
- Specify time frames when relevant
Enable Response Compression
- Include the
Accept-Encoding: gzipheader - Improves performance with large responses
- Include the
Enable Agentic Graph Search
- Set
enable_agentic_graph=Truefor intelligent, context-aware search - Provides better results for ambiguous or complex queries
- Set