Skip to content

Memory Management API

🧠 Intelligent Memory System

The Memory Management API provides access to Quantbot's Neo4j-based memory system powered by graphiti-core. This system stores conversation history, extracts entities, and enables contextual memory retrieval for AI agents.

Base URL

All memory management endpoints are prefixed with:

/api/v1/memory/

Authentication

All memory endpoints require authentication. Include the Bearer token in the Authorization header:

Authorization: Bearer <your_jwt_token>

Overview

The Memory API is divided into two main categories:

Ingestion Endpoints (/ingest/)

  • Store messages and entities in memory
  • Manage conversation episodes
  • Delete memory data

Retrieval Endpoints (/retrieve/)

  • Search memories using semantic similarity
  • Retrieve conversation episodes
  • Get contextual memory for conversations

Data Models

Message

{
  "content": "How is Apple stock performing today?",
  "uuid": "msg_123e4567-e89b-12d3-a456-426614174000",
  "name": "User Question",
  "role_type": "user",
  "role": "John Doe",
  "timestamp": "2025-01-15T10:30:00Z",
  "source_description": "Chat interface"
}

FactResult

{
  "uuid": "fact_123e4567-e89b-12d3-a456-426614174000",
  "name": "Apple Stock Analysis",
  "fact": "Apple (AAPL) closed at $185.25, up 2.1% from previous session",
  "valid_at": "2025-01-15T10:30:00Z",
  "invalid_at": null,
  "created_at": "2025-01-15T10:30:00Z",
  "expired_at": null
}

Result

{
  "message": "Messages added to processing queue",
  "success": true
}

Ingestion Endpoints

Add Messages to Memory

Store conversation messages in the memory system for later retrieval.

POST /api/v1/memory/ingest/messages

Request Body

{
  "group_id": "user_123",
  "messages": [
    {
      "content": "What's the latest news on Tesla stock?",
      "uuid": "msg_001",
      "name": "Tesla Inquiry",
      "role_type": "user",
      "role": "John Doe",
      "timestamp": "2025-01-15T10:30:00Z",
      "source_description": "Chat interface"
    },
    {
      "content": "Tesla (TSLA) is currently trading at $248.50, up 1.8% today. Recent news includes their Q4 delivery numbers exceeding expectations.",
      "uuid": "msg_002", 
      "name": "Tesla Analysis",
      "role_type": "assistant",
      "role": "Market Analyst",
      "timestamp": "2025-01-15T10:31:00Z",
      "source_description": "AI Agent Response"
    }
  ]
}

Response

Status Code: 202 Accepted

{
  "message": "Messages added to processing queue",
  "success": true
}

Add Entity Node

Create a new entity node in the memory graph.

POST /api/v1/memory/ingest/entity-node

Request Body

{
  "uuid": "entity_tesla_stock",
  "group_id": "user_123",
  "name": "Tesla Stock (TSLA)",
  "summary": "Electric vehicle company stock with high volatility and growth potential"
}

Response

Status Code: 201 Created

{
  "uuid": "entity_tesla_stock",
  "group_id": "user_123", 
  "name": "Tesla Stock (TSLA)",
  "summary": "Electric vehicle company stock with high volatility and growth potential",
  "created_at": "2025-01-15T10:30:00Z"
}

Delete Entity Edge

Remove a specific entity edge from the memory graph.

DELETE /api/v1/memory/ingest/entity-edge/{uuid}

Path Parameters

Parameter Type Description
uuid string UUID of the entity edge to delete

Response

Status Code: 200 OK

{
  "message": "Entity Edge deleted",
  "success": true
}

Delete User Group Memory

Delete all memory data for a specific user group.

DELETE /api/v1/memory/ingest/group/{group_id}

Path Parameters

Parameter Type Description
group_id string Group ID to delete all memory for

Response

Status Code: 200 OK

{
  "message": "Group deleted",
  "success": true
}

Delete Episode

Remove a specific conversation episode from memory.

DELETE /api/v1/memory/ingest/episode/{uuid}

Path Parameters

Parameter Type Description
uuid string UUID of the episode to delete

Response

Status Code: 200 OK

{
  "message": "Episode deleted",
  "success": true
}

Clear All Data (Admin Only)

⚠️ DANGER: This endpoint clears ALL memory data from the system.

POST /api/v1/memory/ingest/clear

Authentication Required

Authorization: Bearer <superuser_access_token>

Note: Only superuser accounts can access this endpoint.

Response

Status Code: 200 OK

{
  "message": "Graph cleared", 
  "success": true
}

Retrieval Endpoints

Search Memories

Search for relevant memories using semantic similarity.

POST /api/v1/memory/retrieve/search

Request Body

{
  "group_ids": ["user_123"],
  "query": "Tesla stock performance and recent news",
  "max_facts": 10
}

Response

Status Code: 200 OK

{
  "facts": [
    {
      "uuid": "fact_001",
      "name": "Tesla Stock Analysis",
      "fact": "Tesla (TSLA) closed at $248.50, up 1.8% today",
      "valid_at": "2025-01-15T10:30:00Z",
      "invalid_at": null,
      "created_at": "2025-01-15T10:30:00Z",
      "expired_at": null
    },
    {
      "uuid": "fact_002", 
      "name": "Tesla Q4 Deliveries",
      "fact": "Tesla reported Q4 deliveries of 484,507 vehicles, exceeding analyst expectations",
      "valid_at": "2025-01-15T09:00:00Z",
      "invalid_at": null,
      "created_at": "2025-01-15T09:00:00Z",
      "expired_at": null
    }
  ]
}

Get Entity Edge

Retrieve a specific entity edge by UUID.

GET /api/v1/memory/retrieve/entity-edge/{uuid}

Path Parameters

Parameter Type Description
uuid string UUID of the entity edge to retrieve

Response

Status Code: 200 OK

{
  "uuid": "edge_001",
  "source_uuid": "entity_tesla",
  "target_uuid": "entity_stock_market",
  "relationship": "TRADES_IN",
  "created_at": "2025-01-15T10:30:00Z"
}

Get Episodes

Retrieve recent conversation episodes for a user group.

GET /api/v1/memory/retrieve/episodes/{group_id}?last_n={count}

Path Parameters

Parameter Type Description
group_id string Group ID to retrieve episodes for

Query Parameters

Parameter Type Required Description
last_n integer Yes Number of recent episodes to retrieve

Response

Status Code: 200 OK

[
  {
    "uuid": "episode_001",
    "name": "Tesla Stock Discussion",
    "created_at": "2025-01-15T10:30:00Z",
    "messages": [
      {
        "content": "What's the latest on Tesla?",
        "role_type": "user",
        "timestamp": "2025-01-15T10:30:00Z"
      }
    ]
  }
]

Get Contextual Memory

Get relevant memory context based on conversation messages.

POST /api/v1/memory/retrieve/get-memory

Request Body

{
  "group_id": "user_123",
  "max_facts": 10,
  "center_node_uuid": "entity_tesla_stock",
  "messages": [
    {
      "content": "How has Tesla been performing lately?",
      "role_type": "user",
      "role": "John Doe",
      "timestamp": "2025-01-15T10:30:00Z"
    }
  ]
}

Response

Status Code: 200 OK

{
  "facts": [
    {
      "uuid": "fact_001",
      "name": "Tesla Recent Performance",
      "fact": "Tesla stock has gained 15% over the past month following strong delivery numbers",
      "valid_at": "2025-01-15T10:30:00Z",
      "invalid_at": null,
      "created_at": "2025-01-15T10:30:00Z",
      "expired_at": null
    }
  ]
}

Memory System Architecture

User Isolation

  • Group-based separation: Each user has a unique group_id
  • Data isolation: Users can only access their own memory data
  • Privacy protection: No cross-user memory access

Memory Types

  1. Episodic Memory: Conversation history and temporal context
  2. Entity Memory: Knowledge about financial instruments, companies, concepts
  3. Relationship Memory: Connections between entities and facts

Search & Retrieval

  • Semantic similarity: Uses embeddings for intelligent memory search
  • Temporal awareness: Considers recency and relevance of memories
  • Context-aware: Retrieves memories relevant to current conversation

Integration Examples

Python Example

import requests
from datetime import datetime
from typing import List, Dict, Any

class QuantbotMemoryClient:
    def __init__(self, base_url: str, access_token: str):
        self.base_url = base_url
        self.headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }

    def add_messages(self, group_id: str, messages: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Add messages to memory"""
        response = requests.post(
            f"{self.base_url}/api/v1/memory/ingest/messages",
            headers=self.headers,
            json={
                "group_id": group_id,
                "messages": messages
            }
        )
        response.raise_for_status()
        return response.json()

    def search_memories(self, group_ids: List[str], query: str, max_facts: int = 10) -> Dict[str, Any]:
        """Search for relevant memories"""
        response = requests.post(
            f"{self.base_url}/api/v1/memory/retrieve/search",
            headers=self.headers,
            json={
                "group_ids": group_ids,
                "query": query,
                "max_facts": max_facts
            }
        )
        response.raise_for_status()
        return response.json()

    def get_contextual_memory(self, group_id: str, messages: List[Dict[str, Any]], max_facts: int = 10) -> Dict[str, Any]:
        """Get contextual memory for conversation"""
        response = requests.post(
            f"{self.base_url}/api/v1/memory/retrieve/get-memory",
            headers=self.headers,
            json={
                "group_id": group_id,
                "max_facts": max_facts,
                "center_node_uuid": None,
                "messages": messages
            }
        )
        response.raise_for_status()
        return response.json()

# Usage
client = QuantbotMemoryClient("http://localhost:8000", "your_access_token")

# Add conversation to memory
messages = [
    {
        "content": "What's Apple's current stock price?",
        "role_type": "user",
        "role": "John",
        "timestamp": datetime.now().isoformat()
    },
    {
        "content": "Apple (AAPL) is currently trading at $185.25, up 2.1% today.",
        "role_type": "assistant", 
        "role": "Market Analyst",
        "timestamp": datetime.now().isoformat()
    }
]

result = client.add_messages("user_123", messages)
print("✅ Messages added to memory")

# Search for relevant memories
search_results = client.search_memories(["user_123"], "Apple stock price today")
print(f"Found {len(search_results['facts'])} relevant memories")

# Get contextual memory for new conversation
context = client.get_contextual_memory("user_123", [
    {
        "content": "How has Apple been performing recently?",
        "role_type": "user",
        "role": "John",
        "timestamp": datetime.now().isoformat()
    }
])
print(f"Retrieved {len(context['facts'])} relevant facts for context")

JavaScript/TypeScript Example

interface Message {
  content: string;
  uuid?: string;
  name?: string;
  role_type: 'user' | 'assistant' | 'system';
  role?: string;
  timestamp: string;
  source_description?: string;
}

interface FactResult {
  uuid: string;
  name: string;
  fact: string;
  valid_at: string | null;
  invalid_at: string | null;
  created_at: string;
  expired_at: string | null;
}

class QuantbotMemoryAPI {
  constructor(private baseURL: string, private accessToken: string) {}

  private get headers() {
    return {
      'Authorization': `Bearer ${this.accessToken}`,
      'Content-Type': 'application/json'
    };
  }

  async addMessages(groupId: string, messages: Message[]): Promise<{message: string, success: boolean}> {
    const response = await fetch(`${this.baseURL}/api/v1/memory/ingest/messages`, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        group_id: groupId,
        messages
      })
    });

    if (!response.ok) {
      throw new Error(`Failed to add messages: ${response.statusText}`);
    }

    return await response.json();
  }

  async searchMemories(groupIds: string[], query: string, maxFacts: number = 10): Promise<{facts: FactResult[]}> {
    const response = await fetch(`${this.baseURL}/api/v1/memory/retrieve/search`, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        group_ids: groupIds,
        query,
        max_facts: maxFacts
      })
    });

    if (!response.ok) {
      throw new Error(`Failed to search memories: ${response.statusText}`);
    }

    return await response.json();
  }

  async getContextualMemory(groupId: string, messages: Message[], maxFacts: number = 10): Promise<{facts: FactResult[]}> {
    const response = await fetch(`${this.baseURL}/api/v1/memory/retrieve/get-memory`, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        group_id: groupId,
        max_facts: maxFacts,
        center_node_uuid: null,
        messages
      })
    });

    if (!response.ok) {
      throw new Error(`Failed to get contextual memory: ${response.statusText}`);
    }

    return await response.json();
  }

  async deleteGroup(groupId: string): Promise<{message: string, success: boolean}> {
    const response = await fetch(`${this.baseURL}/api/v1/memory/ingest/group/${groupId}`, {
      method: 'DELETE',
      headers: this.headers
    });

    if (!response.ok) {
      throw new Error(`Failed to delete group: ${response.statusText}`);
    }

    return await response.json();
  }
}

// Usage
const memoryAPI = new QuantbotMemoryAPI('http://localhost:8000', 'your_access_token');

// Store conversation in memory
const messages: Message[] = [
  {
    content: "What's the latest on Tesla stock?",
    role_type: "user",
    role: "Investor",
    timestamp: new Date().toISOString()
  }
];

memoryAPI.addMessages('user_123', messages)
  .then(result => console.log('✅ Messages stored:', result.message))
  .catch(error => console.error('❌ Error:', error));

// Search for relevant information
memoryAPI.searchMemories(['user_123'], 'Tesla stock price performance')
  .then(results => console.log(`Found ${results.facts.length} relevant memories`))
  .catch(error => console.error('❌ Search error:', error));

Security Considerations

Data Privacy

  • All memory data is isolated by user group
  • Users cannot access other users' memories
  • Admin-only endpoints require superuser privileges

Data Retention

  • Configure memory retention policies via environment variables
  • Episodes can be manually deleted when no longer needed
  • Group deletion removes all user memory data

Performance

  • Message ingestion is asynchronous for better performance
  • Search operations use efficient vector similarity algorithms
  • Caching is implemented for frequently accessed memories

Error Handling

Common Error Responses

401 Unauthorized - Invalid or missing authentication

{
  "detail": "Could not validate credentials"
}

403 Forbidden - Insufficient permissions (admin endpoints)

{
  "detail": "Not enough permissions"
}

404 Not Found - Entity or episode not found

{
  "detail": "Entity edge not found"
}

422 Unprocessable Entity - Invalid request data

{
  "detail": [
    {
      "loc": ["body", "group_id"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Configuration

Environment Variables

The memory system can be configured using these environment variables:

# Neo4j Connection
NEO4J_URI=bolt://neo4j:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=your_password

# Memory Settings
MEMORY_MAX_EPISODES_PER_USER=10000
MEMORY_RETENTION_DAYS=365
MEMORY_SIMILARITY_THRESHOLD=0.7
DISABLE_MEMORY=false

# Security
MEMORY_ENABLE_ENCRYPTION=true
MEMORY_ISOLATION_STRICT=true

For more details on configuration, see the Installation Guide.