Manual Memory Management Guide¶
This guide covers manual memory management operations in the Memory Store (v0.6 features). Learn how to create, search, update, delete, and evolve project knowledge.
Table of Contents¶
- Core Operations
- Adding Memories
- Retrieving Memories
- Updating Memories
- Deleting Memories
- Memory Evolution
- Project Summaries
- Advanced Patterns
- Best Practices
Core Operations¶
Memory Store provides seven core manual operations:
- add_memory - Create new memory
- search_memories - Find memories by query/filters
- get_memory - Retrieve specific memory by ID
- update_memory - Modify existing memory
- delete_memory - Remove memory
- supersede_memory - Create new memory that replaces old one
- get_project_summary - Get project overview
Each operation is available via: - MCP Tools - For AI assistants (Claude Desktop, VSCode) - HTTP API - For web applications - Python Service - For direct integration
Adding Memories¶
Basic Memory Creation¶
MCP Tool:
add_memory(
project_id="my-project",
memory_type="decision",
title="Use JWT for authentication",
content="Decided to use JWT tokens instead of session-based authentication",
reason="Need stateless authentication for mobile clients and microservices",
importance=0.9,
tags=["auth", "security", "architecture"]
)
HTTP API:
curl -X POST http://localhost:8000/api/v1/memory/add \
-H "Content-Type: application/json" \
-d '{
"project_id": "my-project",
"memory_type": "decision",
"title": "Use JWT for authentication",
"content": "Decided to use JWT tokens instead of session-based authentication",
"reason": "Need stateless authentication for mobile clients",
"importance": 0.9,
"tags": ["auth", "security"]
}'
Python Service:
from src.codebase_rag.services.memory import memory_store
result = await memory_store.add_memory(
project_id="my-project",
memory_type="decision",
title="Use JWT for authentication",
content="Decided to use JWT tokens",
reason="Need stateless auth for mobile clients",
importance=0.9,
tags=["auth", "security"]
)
memory_id = result['memory_id']
Response:
{
"success": true,
"memory_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "decision",
"title": "Use JWT for authentication"
}
Memory Types and Examples¶
1. Decision Memory¶
Use For: Architecture choices, technology selections, design decisions
add_memory(
project_id="web-app",
memory_type="decision",
title="Adopt microservices architecture",
content="Transitioning from monolith to microservices for user service, order service, and payment service",
reason="Need independent scaling and deployment. User service has different load patterns than order service",
importance=0.95,
tags=["architecture", "microservices", "scaling"],
related_refs=[
"ref://file/docs/architecture/microservices.md",
"ref://file/services/user-service/README.md"
]
)
2. Preference Memory¶
Use For: Team coding styles, tool preferences
add_memory(
project_id="web-app",
memory_type="preference",
title="Use functional components in React",
content="Team prefers functional components with hooks over class components",
reason="Hooks provide better code reuse and easier testing. Team is more familiar with functional approach",
importance=0.6,
tags=["react", "frontend", "coding-style"]
)
3. Experience Memory¶
Use For: Problems encountered and solutions
add_memory(
project_id="web-app",
memory_type="experience",
title="Redis connection timeout in Docker Compose",
content="Redis connections were timing out when using 'localhost:6379' in Docker environment",
reason="Docker Compose networking requires using service name 'redis:6379' instead of 'localhost'. Docker creates an internal network where services communicate by name",
importance=0.7,
tags=["docker", "redis", "networking", "deployment"],
related_refs=["ref://file/docker-compose.yml#L15"]
)
4. Convention Memory¶
Use For: Team rules, naming standards
add_memory(
project_id="web-app",
memory_type="convention",
title="API endpoints use kebab-case",
content="All REST API endpoints must use kebab-case naming convention. Example: /api/user-profiles instead of /api/userProfiles",
reason="Consistency across API, better readability in URLs",
importance=0.5,
tags=["api", "naming", "conventions"]
)
5. Plan Memory¶
Use For: Future improvements, TODOs
add_memory(
project_id="web-app",
memory_type="plan",
title="Add rate limiting to public API",
content="Plan to implement rate limiting on all public API endpoints. Use Redis-based rate limiter with sliding window algorithm. Limit: 100 requests per minute per IP",
reason="Prevent API abuse and ensure fair usage",
importance=0.6,
tags=["api", "security", "todo", "performance"]
)
6. Note Memory¶
Use For: General information
add_memory(
project_id="web-app",
memory_type="note",
title="Production database backup location",
content="Production PostgreSQL backups are stored in S3 bucket 'prod-db-backups' with 30-day retention. Daily backups run at 2 AM UTC",
reason="Critical operational information for disaster recovery",
importance=0.7,
tags=["operations", "backup", "production"]
)
Advanced: Linking to Code References¶
Use ref:// handles to link memories to specific code:
add_memory(
project_id="api-service",
memory_type="decision",
title="Use dependency injection for services",
content="Implemented dependency injection pattern for all service classes",
reason="Improves testability and reduces coupling",
importance=0.8,
tags=["architecture", "patterns"],
related_refs=[
"ref://file/src/core/container.py",
"ref://file/src/services/user_service.py#L25",
"ref://symbol/UserService",
"ref://symbol/inject_dependencies"
]
)
Supported ref:// formats: - ref://file/path/to/file.py - Link to entire file - ref://file/path/to/file.py#L45 - Link to specific line - ref://symbol/ClassName - Link to class/function - ref://file/path#section - Link to section
Advanced: Custom Metadata¶
Add custom metadata for application-specific needs:
add_memory(
project_id="web-app",
memory_type="decision",
title="Switch to PostgreSQL 15",
content="Upgraded from PostgreSQL 13 to 15",
reason="Better performance and new JSON features",
importance=0.8,
tags=["database", "upgrade"],
metadata={
"migration_date": "2024-11-01",
"downtime": "5 minutes",
"rollback_plan": "restore from backup",
"approved_by": "tech-lead"
}
)
Retrieving Memories¶
Get Specific Memory¶
MCP Tool:
HTTP API:
Python Service:
result = await memory_store.get_memory("550e8400-e29b-41d4-a716-446655440000")
if result['success']:
memory = result['memory']
print(f"Title: {memory['title']}")
print(f"Content: {memory['content']}")
print(f"Related refs: {memory['related_refs']}")
Response:
{
"success": true,
"memory": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "decision",
"title": "Use JWT for authentication",
"content": "Decided to use JWT tokens...",
"reason": "Need stateless authentication...",
"tags": ["auth", "security"],
"importance": 0.9,
"created_at": "2025-11-06T10:00:00Z",
"updated_at": "2025-11-06T10:00:00Z",
"metadata": {},
"related_refs": [
{"type": "File", "path": "src/auth/jwt.py"}
]
}
}
Updating Memories¶
Update Memory Fields¶
MCP Tool:
update_memory(
memory_id="550e8400-e29b-41d4-a716-446655440000",
importance=0.95,
tags=["auth", "security", "critical", "production"]
)
HTTP API:
curl -X PUT http://localhost:8000/api/v1/memory/550e8400-e29b-41d4-a716-446655440000 \
-H "Content-Type: application/json" \
-d '{
"importance": 0.95,
"tags": ["auth", "security", "critical"]
}'
Python Service:
result = await memory_store.update_memory(
memory_id="550e8400-e29b-41d4-a716-446655440000",
title="Use JWT with refresh token rotation",
content="Updated implementation to include refresh token rotation",
importance=0.95,
tags=["auth", "security", "critical"]
)
Updatable Fields: - title - Change the title - content - Update the content - reason - Modify the rationale - tags - Replace tags (not append - provide full list) - importance - Adjust importance score
Note: Only provided fields are updated. Omitted fields remain unchanged.
Common Update Scenarios¶
Increase Importance After Production Issue¶
# Security vulnerability discovered
update_memory(
memory_id=auth_memory_id,
importance=1.0,
tags=["auth", "security", "critical", "vulnerability"]
)
Add Context to Existing Memory¶
# Found additional information
update_memory(
memory_id=redis_memory_id,
content=original_content + "\n\nUpdate: Also affects Redis Sentinel configuration. Must use sentinel service names.",
reason=original_reason + " Additionally, Sentinel failover requires proper service name configuration."
)
Reclassify Memory Importance¶
# Initially thought important, but turned out routine
update_memory(
memory_id=config_memory_id,
importance=0.4 # Downgrade from 0.7
)
Deleting Memories¶
Delete Memory¶
MCP Tool:
HTTP API:
Python Service:
result = await memory_store.delete_memory("550e8400-e29b-41d4-a716-446655440000")
if result['success']:
print("Memory deleted")
else:
print(f"Error: {result['error']}")
Note: This is a hard delete - the memory is permanently removed from the database. For preserving history when decisions change, use supersede_memory instead.
When to Delete vs Supersede¶
Use Delete When: - ❌ Memory was created by mistake - ❌ Information is completely wrong - ❌ Duplicate memory exists - ❌ Memory is obsolete and not worth preserving
Use Supersede When: - ✅ Decision has changed and you want history - ✅ Solution was improved and old approach is deprecated - ✅ Convention evolved and old one should be marked outdated
Memory Evolution¶
Superseding Memories¶
When decisions change, use supersede_memory to preserve history:
MCP Tool:
supersede_memory(
old_memory_id="abc-123-def-456",
new_memory_type="decision",
new_title="Migrate from MySQL to PostgreSQL",
new_content="Migrated from MySQL to PostgreSQL for production database",
new_reason="Need advanced JSON support, full-text search, and better geospatial features",
new_tags=["database", "postgresql", "migration"],
new_importance=0.9
)
HTTP API:
curl -X POST http://localhost:8000/api/v1/memory/supersede \
-H "Content-Type: application/json" \
-d '{
"old_memory_id": "abc-123-def-456",
"new_memory_type": "decision",
"new_title": "Migrate from MySQL to PostgreSQL",
"new_content": "Migrated from MySQL to PostgreSQL",
"new_reason": "Need advanced JSON and full-text search",
"new_importance": 0.9
}'
Python Service:
result = await memory_store.supersede_memory(
old_memory_id="abc-123-def-456",
new_memory_data={
"memory_type": "decision",
"title": "Migrate from MySQL to PostgreSQL",
"content": "Migrated from MySQL to PostgreSQL",
"reason": "Need advanced features",
"tags": ["database", "postgresql"],
"importance": 0.9
}
)
new_memory_id = result['new_memory_id']
old_memory_id = result['old_memory_id']
What Happens: 1. New memory is created with your data 2. SUPERSEDES relationship is created: (new)-[:SUPERSEDES]->(old) 3. Old memory gets superseded_by and superseded_at fields 4. Old memory remains in database but marked as superseded 5. Both memories belong to same project
Evolution Example: Database Decision¶
Phase 1: Original Decision (January)
mysql_memory = add_memory(
project_id="web-app",
memory_type="decision",
title="Use MySQL as primary database",
content="Selected MySQL for application database",
reason="Team familiarity and existing infrastructure",
importance=0.7,
tags=["database", "mysql"]
)
# memory_id: "original-123"
Phase 2: Requirements Change (March)
postgres_v1 = supersede_memory(
old_memory_id="original-123",
new_memory_type="decision",
new_title="Migrate to PostgreSQL",
new_content="Migrating from MySQL to PostgreSQL",
new_reason="Need better JSON support and full-text search",
new_tags=["database", "postgresql", "migration"],
new_importance=0.8
)
# new_memory_id: "update-456"
# "original-123" now marked as superseded
Phase 3: Full Migration Complete (June)
postgres_v2 = supersede_memory(
old_memory_id="update-456",
new_memory_type="decision",
new_title="PostgreSQL 15 in production",
new_content="Completed migration to PostgreSQL 15. All services migrated",
new_reason="Migration successful. Using advanced features: JSONB, GiST indexes, full-text search",
new_tags=["database", "postgresql", "production"],
new_importance=0.9
)
# new_memory_id: "final-789"
# "update-456" now marked as superseded
Result: Complete decision history preserved:
"original-123" (MySQL)
← superseded by "update-456" (PostgreSQL migration)
← superseded by "final-789" (PostgreSQL production)
Project Summaries¶
Get Project Overview¶
MCP Tool:
HTTP API:
Python Service:
result = await memory_store.get_project_summary("web-app")
summary = result['summary']
print(f"Total memories: {summary['total_memories']}")
for memory_type, data in summary['by_type'].items():
print(f"{memory_type}: {data['count']}")
for mem in data['top_memories'][:3]:
print(f" - {mem['title']} (importance: {mem['importance']})")
Response:
{
"success": true,
"summary": {
"project_id": "web-app",
"total_memories": 56,
"by_type": {
"decision": {
"count": 15,
"top_memories": [
{
"id": "...",
"title": "Adopt microservices architecture",
"importance": 0.95
},
{
"id": "...",
"title": "Use JWT for authentication",
"importance": 0.9
}
]
},
"preference": {
"count": 8,
"top_memories": [...]
},
"experience": {
"count": 12,
"top_memories": [...]
},
"convention": {
"count": 6,
"top_memories": [...]
},
"plan": {
"count": 10,
"top_memories": [...]
},
"note": {
"count": 5,
"top_memories": [...]
}
}
}
}
Use Cases: - Onboarding new team members or AI agents - Project health checks - Memory audit and cleanup - Understanding project knowledge distribution
Advanced Patterns¶
Pattern 1: AI Agent Session Workflow¶
# Start of session: Get context
async def start_session(project_id: str, task_area: str):
# 1. Get project overview
summary = await memory_store.get_project_summary(project_id)
print(f"Project has {summary['summary']['total_memories']} memories")
# 2. Search for relevant context
context = await memory_store.search_memories(
project_id=project_id,
query=task_area,
min_importance=0.6
)
# 3. Review top decisions and experiences
for memory in context['memories'][:5]:
print(f"Relevant: {memory['title']}")
return context
# During work: Check conventions
async def check_conventions(project_id: str, area: str):
conventions = await memory_store.search_memories(
project_id=project_id,
memory_type="convention",
tags=[area]
)
return conventions
# End of session: Save learnings
async def save_learnings(project_id: str, new_knowledge: dict):
result = await memory_store.add_memory(
project_id=project_id,
**new_knowledge
)
return result['memory_id']
Pattern 2: Memory Cleanup and Maintenance¶
async def cleanup_low_value_memories(project_id: str):
"""Remove low-importance notes older than 6 months"""
# Search for low-importance notes
old_notes = await memory_store.search_memories(
project_id=project_id,
memory_type="note",
min_importance=0.0,
limit=100
)
from datetime import datetime, timedelta
cutoff_date = datetime.utcnow() - timedelta(days=180)
deleted_count = 0
for memory in old_notes['memories']:
created_at = datetime.fromisoformat(memory['created_at'])
if memory['importance'] < 0.3 and created_at < cutoff_date:
await memory_store.delete_memory(memory['id'])
deleted_count += 1
print(f"Deleted old note: {memory['title']}")
return deleted_count
Pattern 3: Memory Migration Between Projects¶
async def migrate_memory(memory_id: str, from_project: str, to_project: str):
"""Copy memory from one project to another"""
# Get original memory
result = await memory_store.get_memory(memory_id)
memory = result['memory']
# Create copy in new project
new_result = await memory_store.add_memory(
project_id=to_project,
memory_type=memory['type'],
title=f"[Migrated] {memory['title']}",
content=memory['content'],
reason=memory.get('reason'),
tags=memory.get('tags', []) + ['migrated'],
importance=memory.get('importance', 0.5),
metadata={
**memory.get('metadata', {}),
'migrated_from': from_project,
'original_memory_id': memory_id
}
)
return new_result['memory_id']
Pattern 4: Tag-Based Memory Organization¶
async def organize_by_tags(project_id: str):
"""Get memories organized by tag"""
# Get all memories
all_memories = await memory_store.search_memories(
project_id=project_id,
limit=100
)
# Organize by tag
by_tag = {}
for memory in all_memories['memories']:
for tag in memory.get('tags', []):
if tag not in by_tag:
by_tag[tag] = []
by_tag[tag].append({
'id': memory['id'],
'title': memory['title'],
'importance': memory['importance']
})
# Sort tags by memory count
sorted_tags = sorted(
by_tag.items(),
key=lambda x: len(x[1]),
reverse=True
)
print("Top tags:")
for tag, memories in sorted_tags[:10]:
print(f"{tag}: {len(memories)} memories")
return by_tag
Best Practices¶
1. Importance Scoring¶
Be Consistent:
# Critical architecture decision
importance=0.95
# Important feature decision
importance=0.8
# Team preference
importance=0.6
# Minor convention
importance=0.4
# Future plan
importance=0.3
Adjust Over Time:
# Initially seemed important
add_memory(..., importance=0.7)
# Later found to be critical
update_memory(memory_id, importance=0.95)
2. Effective Tagging¶
Use Hierarchical Tags:
tags = [
"auth", # Domain
"security", # Category
"jwt", # Technology
"production", # Environment
"critical" # Status
]
Be Specific:
# ❌ Too vague
tags = ["backend", "code"]
# ✅ Specific and useful
tags = ["auth", "jwt", "refresh-token", "security"]
3. Writing Good Content¶
Include Context:
# ❌ Too brief
content = "Using Redis"
# ✅ Comprehensive
content = """
Implementing Redis as caching layer for user sessions and API responses.
Configuration:
- Redis 7.0 in cluster mode
- 3 master nodes, 3 replicas
- Maxmemory policy: allkeys-lru
- Persistence: RDB + AOF
Cache strategy:
- User sessions: TTL 24h
- API responses: TTL 5min
- Invalidation on data updates
"""
Explain Why:
# ❌ No rationale
reason = "Better performance"
# ✅ Clear rationale
reason = """
Need to reduce database load by 70%. Current response times averaging 500ms,
target is 100ms. Redis provides:
1. Sub-millisecond latency
2. Horizontal scaling
3. Built-in data structures
4. Proven at scale by similar companies
"""
4. Related References¶
Link to Relevant Code:
related_refs = [
"ref://file/src/cache/redis_client.py",
"ref://file/config/redis.yml",
"ref://file/docs/cache-strategy.md"
]
Be Specific:
# ✅ Point to exact implementation
related_refs = [
"ref://file/src/auth/jwt.py#L45", # JWT generation
"ref://symbol/verify_token" # Verification function
]
5. Memory Lifecycle Management¶
Regular Reviews:
# Monthly review
async def monthly_review(project_id: str):
# Check for outdated plans
plans = await memory_store.search_memories(
project_id=project_id,
memory_type="plan",
min_importance=0.0
)
# Review and update or delete completed plans
for plan in plans['memories']:
print(f"Review: {plan['title']}")
# Manual decision: delete, update, or keep
Update on Changes:
# When decision evolves, supersede instead of update
# Preserves history
await memory_store.supersede_memory(old_id, new_data)
Common Patterns¶
Pattern: Feature Development Workflow¶
async def feature_workflow(project_id: str, feature_name: str):
# 1. Check existing decisions
decisions = await memory_store.search_memories(
project_id=project_id,
query=feature_name,
memory_type="decision"
)
# 2. Check conventions
conventions = await memory_store.search_memories(
project_id=project_id,
memory_type="convention"
)
# 3. Check past experiences
experiences = await memory_store.search_memories(
project_id=project_id,
query=feature_name,
memory_type="experience"
)
# 4. Implement feature...
# 5. Save new knowledge
await memory_store.add_memory(
project_id=project_id,
memory_type="decision",
title=f"Implemented {feature_name}",
content="...",
reason="...",
importance=0.7
)
Pattern: Debugging Workflow¶
async def document_bug_fix(project_id: str, bug_description: str, solution: str):
# Save the experience
result = await memory_store.add_memory(
project_id=project_id,
memory_type="experience",
title=f"Bug: {bug_description}",
content=f"Problem: {bug_description}\n\nSolution: {solution}",
reason="Prevent recurrence of this issue",
importance=0.7,
tags=["bug", "debugging"]
)
return result['memory_id']
Troubleshooting¶
Memory Not Found¶
result = await memory_store.get_memory(memory_id)
if not result['success']:
if "not found" in result['error'].lower():
print("Memory doesn't exist or was deleted")
else:
print(f"Error: {result['error']}")
Update Not Applied¶
# Make sure at least one field is provided
result = await memory_store.update_memory(
memory_id=memory_id,
importance=0.9 # At least one field required
)
if not result['success']:
if "No updates" in result['error']:
print("Must provide at least one field to update")
Search Returns No Results¶
# Try broader search
result = await memory_store.search_memories(
project_id=project_id,
query="auth", # Remove filters
limit=100 # Increase limit
)
if result['total_count'] == 0:
print("No memories found for this project")
Next Steps¶
- Search Guide: Learn advanced search strategies in search.md
- Auto-Extraction: Discover automatic memory extraction in extraction.md
- API Reference: Full API documentation at
/api/v1/memory - Examples: See
/examples/memory_usage_example.py