Skip to content

Core Concepts

Understanding DialogueDB's core concepts will help you build better conversational applications. This guide covers the fundamental building blocks: dialogues, messages, threads, state, and memory.

Dialogues

A dialogue is a conversation session containing a series of messages. Think of it as a container for a complete conversation between users and AI assistants.

Dialogue Properties

typescript
{
  id: string;              // Unique identifier (user-provided or auto-generated)
  namespace?: string;      // Namespace - part of the resource's identity (required on all ops if set)
  threadOf?: string;       // Parent dialogue if this is a thread
  requestId: string;       // Request tracking ID
  status: "active" | "ended" | "archived";
  tags: string[];          // Custom tags for organization
  totalMessages: number;   // Count of messages in this dialogue
  threadCount: number;     // Number of child threads
  lastMessageCreated: string;  // Timestamp of most recent message
  metadata: object;        // Custom metadata
  metadataLength?: number; // Size of metadata
  metadataSHA256?: string; // Metadata hash
  created: string;         // Creation timestamp (ISO 8601)
  modified: string;        // Last modification timestamp (ISO 8601)
  state: object;           // Custom state data
  messages?: Message[];    // Array of message objects (when included)
}

Dialogue Lifecycle

  1. Created: New dialogue initialized
  2. Active: Accepting new messages
  3. Ended: Conversation marked as complete
  4. Deleted: Permanently removed (messages remain)

Creating Dialogues

bash
# Simple dialogue
curl -X POST https://api.dialoguedb.com/api/v1/dialogue \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": {
      "role": "user",
      "content": "Hello!"
    }
  }'

# Dialogue with metadata
curl -X POST https://api.dialoguedb.com/api/v1/dialogue \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "metadata": {
      "userId": "user_123",
      "channel": "web",
      "sessionId": "session_abc"
    },
    "tags": ["customer-support", "billing-question"],
    "message": {
      "role": "user",
      "content": "I have a billing question"
    }
  }'
typescript
// Simple dialogue
const response = await fetch('https://api.dialoguedb.com/api/v1/dialogue', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    message: {
      role: 'user',
      content: 'Hello!'
    }
  })
});

const dialogue = await response.json();

// Dialogue with metadata
const response2 = await fetch('https://api.dialoguedb.com/api/v1/dialogue', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    metadata: {
      userId: 'user_123',
      channel: 'web',
      sessionId: 'session_abc'
    },
    tags: ['customer-support', 'billing-question'],
    message: {
      role: 'user',
      content: 'I have a billing question'
    }
  })
});

const dialogue2 = await response2.json();
python
import requests

# Simple dialogue
response = requests.post(
    "https://api.dialoguedb.com/api/v1/dialogue",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "message": {
            "role": "user",
            "content": "Hello!"
        }
    }
)

dialogue = response.json()

# Dialogue with metadata
response = requests.post(
    "https://api.dialoguedb.com/api/v1/dialogue",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "metadata": {
            "userId": "user_123",
            "channel": "web",
            "sessionId": "session_abc"
        },
        "tags": ["customer-support", "billing-question"],
        "message": {
            "role": "user",
            "content": "I have a billing question"
        }
    }
)

dialogue = response.json()
typescript
// Simple dialogue
const dialogue = await db.createDialogue({
  messages: [{
    role: 'user',
    content: 'Hello!'
  }]
});

// Dialogue with metadata
const dialogue = await db.createDialogue({
  metadata: {
    userId: 'user_123',
    channel: 'web',
    sessionId: 'session_abc'
  },
  tags: ['customer-support', 'billing-question'],
  messages: [{
    role: 'user',
    content: 'I have a billing question'
  }]
});

If you create a dialogue with a namespace, you must pass the same namespace on every subsequent operation - see Namespace.

Messages

Messages are the individual exchanges within a dialogue. Each message represents a single turn in the conversation.

Message Properties

typescript
{
  id: string;              // Unique identifier (user-provided or auto-generated)
  dialogueId: string;      // Parent dialogue ID
  namespace?: string;      // Inherited from dialogue - required on all ops if set
  role: string;  // "user", "assistant", "system" by convention - custom roles allowed
  content: string | object | object[];    // Message content (flexible shape)
  name?: string;           // Optional name for the speaker
  metadata: object;        // Custom metadata
  tags: string[];          // Custom tags
  created: string;         // Creation timestamp (ISO 8601)
}

Content accepts any shape: plain strings, structured objects, or arrays of content blocks. This lets you store tool calls, multi-part messages, and provider-specific formats directly without serializing to a string. See the Messages API for detailed examples.

Working with streaming LLMs

DialogueDB stores complete messages - it doesn't proxy or generate LLM responses. Stream from your LLM provider as usual, then call saveMessage() with the full response after the stream finishes. See Working with Streaming LLMs for a complete example.

Message Roles

DialogueDB supports three message roles:

User - Messages from end users

typescript
{
  role: 'user',
  content: 'What is the weather today?'
}

Assistant - Responses from AI assistants

typescript
{
  role: 'assistant',
  content: 'The current weather is sunny with a high of 75°F.'
}

System - System prompts and instructions

typescript
{
  role: 'system',
  content: 'You are a helpful weather assistant. Provide accurate and friendly weather information.'
}

Message Storage

Messages are automatically stored and optimized for fast retrieval. The system handles storage transparently - you don't need to do anything special.

Creating Messages

bash
# Add a message to an existing dialogue
curl -X POST https://api.dialoguedb.com/api/v1/message \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dialogueId": "DIALOGUE_ID",
    "role": "user",
    "content": "Can you explain quantum computing?"
  }'

# Message with metadata
curl -X POST https://api.dialoguedb.com/api/v1/message \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dialogueId": "DIALOGUE_ID",
    "role": "assistant",
    "content": "Quantum computing uses quantum mechanics...",
    "metadata": {
      "model": "gpt-4",
      "tokensUsed": 250,
      "temperature": 0.7
    }
  }'
typescript
// Add a message to an existing dialogue
const response = await fetch('https://api.dialoguedb.com/api/v1/message', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    dialogueId: 'DIALOGUE_ID',
    role: 'user',
    content: 'Can you explain quantum computing?'
  })
});

const message = await response.json();

// Message with metadata
const response2 = await fetch('https://api.dialoguedb.com/api/v1/message', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    dialogueId: 'DIALOGUE_ID',
    role: 'assistant',
    content: 'Quantum computing uses quantum mechanics...',
    metadata: {
      model: 'gpt-4',
      tokensUsed: 250,
      temperature: 0.7
    }
  })
});

const message2 = await response2.json();
python
import requests

# Add a message to an existing dialogue
response = requests.post(
    "https://api.dialoguedb.com/api/v1/message",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "dialogueId": "DIALOGUE_ID",
        "role": "user",
        "content": "Can you explain quantum computing?"
    }
)

message = response.json()

# Message with metadata
response = requests.post(
    "https://api.dialoguedb.com/api/v1/message",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "dialogueId": "DIALOGUE_ID",
        "role": "assistant",
        "content": "Quantum computing uses quantum mechanics...",
        "metadata": {
            "model": "gpt-4",
            "tokensUsed": 250,
            "temperature": 0.7
        }
    }
)

message = response.json()
typescript
// Add a message to an existing dialogue
const message = await dialogue.saveMessage({
  role: 'user',
  content: 'Can you explain quantum computing?'
});

// Message with metadata
const message = await dialogue.saveMessage({
  role: 'assistant',
  content: 'Quantum computing uses quantum mechanics...',
  metadata: {
    model: 'gpt-4',
    tokensUsed: 250,
    temperature: 0.7
  }
});

Retrieving Messages

bash
# Get messages with pagination
curl -X GET "https://api.dialoguedb.com/api/v1/messages?dialogueId=DIALOGUE_ID&limit=20" \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"

# Get specific message
curl -X GET https://api.dialoguedb.com/api/v1/message/MESSAGE_ID \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"
typescript
// Get messages with pagination
const response = await fetch(
  'https://api.dialoguedb.com/api/v1/messages?dialogueId=DIALOGUE_ID&limit=20',
  {
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
    }
  }
);

const { items: messages, next } = await response.json();

// Load next page using the cursor
if (next) {
  const nextResponse = await fetch(
    `https://api.dialoguedb.com/api/v1/messages?dialogueId=DIALOGUE_ID&limit=20&next=${next}`,
    {
      headers: {
        'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
      }
    }
  );

  const { items: moreMessages } = await nextResponse.json();
}
python
import requests

# Get messages with pagination
response = requests.get(
    "https://api.dialoguedb.com/api/v1/messages",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    params={"dialogueId": "DIALOGUE_ID", "limit": 20}
)

data = response.json()
messages = data["items"]

# Load next page using the cursor
if data.get("next"):
    response = requests.get(
        "https://api.dialoguedb.com/api/v1/messages",
        headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
        params={"dialogueId": "DIALOGUE_ID", "limit": 20, "next": data["next"]}
    )

    more_messages = response.json()["items"]
typescript
// Get messages with pagination
const messages = await dialogue.loadMessages({ limit: 20 });

// Load next page (SDK manages the cursor internally)
if (dialogue.hasMoreMessages) {
  const more = await dialogue.loadMessages({ limit: 20, next: true });
}

// Get specific message
const message = await dialogue.getMessage(messageId);

If the parent dialogue has a namespace, pass it when listing or retrieving messages too - see Namespace.

Threads

Threads are dialogues that are organizationally linked to a parent dialogue. Think of them as sub-conversations or related processes grouped under a main dialogue, rather than traditional conversational branches.

Understanding Threads

A thread is a full dialogue with its own messages, state, and lifecycle - but it references a parent dialogue via the threadOf field. This creates an organizational hierarchy without affecting the content or independence of either dialogue.

Key characteristics:

  • Threads are complete, independent dialogues
  • Used primarily for grouping and organization
  • Each thread has its own message history
  • Parent dialogue tracks threadCount automatically
  • Threads can be listed by their parent

Thread Use Cases

  • Agent activities: Sub-tasks or tool executions related to a main conversation
  • Parallel reasoning: Multiple AI thought processes for a single query
  • Tool call logs: Detailed execution traces grouped under the main dialogue
  • Internal processes: System operations associated with a user conversation
  • Work breakdown: Decomposing a complex request into sub-dialogues
  • Related conversations: Grouping follow-up discussions under an original inquiry

Creating Threads

bash
# Create a thread linked to a parent dialogue
curl -X POST https://api.dialoguedb.com/api/v1/dialogue \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "threadOf": "PARENT_DIALOGUE_ID",
    "metadata": { "purpose": "tool-call" },
    "tags": ["fetch_weather_data"]
  }'

# Add a message to the thread
curl -X POST https://api.dialoguedb.com/api/v1/message \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dialogueId": "THREAD_ID",
    "role": "system",
    "content": "Executing tool call: fetch_weather_data"
  }'
typescript
// Create a thread linked to a parent dialogue
const response = await fetch('https://api.dialoguedb.com/api/v1/dialogue', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    threadOf: 'PARENT_DIALOGUE_ID',
    metadata: { purpose: 'tool-call' },
    tags: ['fetch_weather_data']
  })
});

const thread = await response.json();

// Add messages to the thread
await fetch('https://api.dialoguedb.com/api/v1/message', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    dialogueId: thread.id,
    role: 'system',
    content: 'Executing tool call: fetch_weather_data'
  })
});

await fetch('https://api.dialoguedb.com/api/v1/message', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    dialogueId: thread.id,
    role: 'assistant',
    content: 'Weather data retrieved successfully'
  })
});
python
import requests

# Create a thread linked to a parent dialogue
response = requests.post(
    "https://api.dialoguedb.com/api/v1/dialogue",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "threadOf": "PARENT_DIALOGUE_ID",
        "metadata": {"purpose": "tool-call"},
        "tags": ["fetch_weather_data"]
    }
)

thread = response.json()

# Add messages to the thread
requests.post(
    "https://api.dialoguedb.com/api/v1/message",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "dialogueId": thread["id"],
        "role": "system",
        "content": "Executing tool call: fetch_weather_data"
    }
)

requests.post(
    "https://api.dialoguedb.com/api/v1/message",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "dialogueId": thread["id"],
        "role": "assistant",
        "content": "Weather data retrieved successfully"
    }
)
typescript
// Create a thread linked to a parent dialogue
const thread = await dialogue.createThread({
  metadata: { purpose: 'tool-call' },
  tags: ['fetch_weather_data']
});

// Add messages after creation - createThread does not accept messages
await thread.saveMessage({
  role: 'system',
  content: 'Executing tool call: fetch_weather_data'
});

// The thread is a full dialogue with its own messages
await thread.saveMessage({
  role: 'assistant',
  content: 'Weather data retrieved successfully'
});

// Parent dialogue automatically tracks threadCount
const parent = await db.getDialogue('dlg_abc123');
console.log(`Parent has ${parent.threadCount} threads`);

Listing Threads

typescript
// Get all threads of a dialogue
const threads = await dialogue.getThreads();

console.log(`Found ${threads.length} threads`);

// Each thread is a full dialogue
threads.forEach(thread => {
  console.log(`Thread ${thread.id}: ${thread.totalMessages} messages`);
});

Thread Hierarchy Example

Main Dialogue (ID: dlg_abc123)
├── User: "Analyze this code and suggest improvements"
├── Assistant: "I'll analyze the code using multiple approaches..."

├── Thread: Code Quality Analysis (threadOf: dlg_abc123)
│   ├── System: "Running static analysis..."
│   └── Assistant: "Found 5 issues..."

├── Thread: Performance Analysis (threadOf: dlg_abc123)
│   ├── System: "Profiling execution..."
│   └── Assistant: "Identified 3 bottlenecks..."

└── Thread: Security Scan (threadOf: dlg_abc123)
    ├── System: "Scanning for vulnerabilities..."
    └── Assistant: "No critical issues found..."

In this example, the main dialogue contains the user conversation, while threads capture parallel analysis processes.

Threads vs. Namespace

Don't confuse threads with namespace:

FeatureThreadsNamespace
PurposeOrganizational hierarchyUser/tenant isolation
RelationshipParent-child linkFlat grouping
Use CaseSub-processes of a dialogueMulti-tenant data separation
VisibilityListed via parent IDQueried by namespace value

Use threads when: You need to group related dialogues under a parent conversation

Use namespace when: You need to isolate dialogues by user, tenant, or organization

State

State allows you to attach custom data to dialogues. Use state to persist conversation context, user preferences, or application-specific information.

State Use Cases

  • Conversation context: Store current topic, intent, or stage
  • User preferences: Remember user settings across messages
  • Application data: Store form data, shopping cart, etc.
  • Session information: Track authentication, permissions

Managing State

bash
# Create dialogue with initial state
curl -X POST https://api.dialoguedb.com/api/v1/dialogue \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": {
      "currentTopic": "weather",
      "location": "San Francisco",
      "userPreference": "celsius"
    },
    "message": {
      "role": "user",
      "content": "What'\''s the temperature?"
    }
  }'

# Update state
curl -X PUT https://api.dialoguedb.com/api/v1/dialogue/DIALOGUE_ID/state \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "currentTopic": "weather",
    "location": "New York",
    "userPreference": "fahrenheit"
  }'
typescript
// Create dialogue with initial state
const response = await fetch('https://api.dialoguedb.com/api/v1/dialogue', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    state: {
      currentTopic: 'weather',
      location: 'San Francisco',
      userPreference: 'celsius'
    },
    message: {
      role: 'user',
      content: "What's the temperature?"
    }
  })
});

const dialogue = await response.json();

// Update state
await fetch(`https://api.dialoguedb.com/api/v1/dialogue/${dialogue.id}/state`, {
  method: 'PUT',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    currentTopic: 'weather',
    location: 'New York',
    userPreference: 'fahrenheit'
  })
});
python
import requests

# Create dialogue with initial state
response = requests.post(
    "https://api.dialoguedb.com/api/v1/dialogue",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "state": {
            "currentTopic": "weather",
            "location": "San Francisco",
            "userPreference": "celsius"
        },
        "message": {
            "role": "user",
            "content": "What's the temperature?"
        }
    }
)

dialogue = response.json()

# Update state
requests.put(
    f"https://api.dialoguedb.com/api/v1/dialogue/{dialogue['id']}/state",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "currentTopic": "weather",
        "location": "New York",
        "userPreference": "fahrenheit"
    }
)
typescript
// Create dialogue with initial state
const dialogue = await db.createDialogue({
  state: {
    currentTopic: 'weather',
    location: 'San Francisco',
    userPreference: 'celsius'
  },
  messages: [{
    role: 'user',
    content: 'What\'s the temperature?'
  }]
});

// Update state
await dialogue.saveState({
  currentTopic: 'weather',
  location: 'New York', // Updated
  userPreference: 'fahrenheit' // Updated
});

// Or set state property and save
dialogue.state = { currentTopic: 'weather', location: 'New York' };
await dialogue.save();

// Retrieve dialogue with state
const d = await db.getDialogue(dialogueId);
console.log(d.state); // Access state

State Best Practices

Do:

  • Keep state small and focused
  • Use state for session-specific data
  • Update state as conversation progresses

Don't:

  • Store large objects in state
  • Use state for message history (use messages instead)
  • Store sensitive data without encryption

Memory

Memories are persistent, searchable pieces of information that live independently of any dialogue. Unlike state (scoped to a single dialogue) or messages (conversation turns), memories persist across all dialogues and can be found via semantic search.

Use memories for anything that should be recalled later: user preferences, facts, context that spans conversations.

Memory vs. State vs. Messages

FeatureMemoryStateMessages
LifespanIndefinite (until deleted)Per-dialoguePer-dialogue
SearchSemantic searchNot searchableSemantic search
UpdatesTags onlyMerged on updateImmutable
ScopeGlobal or namespaceDialogue-specificDialogue-specific
Use caseLong-term facts & preferencesSession contextConversation turns

Memory Properties

typescript
{
  id: string;              // Unique identifier (custom or auto-generated)
  value: any;              // The stored value (string, number, boolean, object, or array)
  namespace?: string;      // Optional namespace for isolation
  label?: string;          // Human-readable label
  description?: string;    // Description of this memory
  tags: string[];          // Categorization tags
  metadata: object;        // Custom metadata (immutable after creation)
  created: string;         // Creation timestamp (ISO 8601)
  modified: string;        // Last modification timestamp (ISO 8601)
}

Creating and Searching Memories

bash
# Store a memory
curl -X POST https://api.dialoguedb.com/api/v1/memory \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "value": "User prefers dark mode and metric units",
    "namespace": "user_456",
    "tags": ["preferences"],
    "label": "Display Settings"
  }'

# Search memories by meaning
curl -X POST https://api.dialoguedb.com/api/v1/search \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "display settings",
    "object": "memory",
    "namespace": "user_456"
  }'
typescript
// Store a memory
const response = await fetch('https://api.dialoguedb.com/api/v1/memory', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    value: 'User prefers dark mode and metric units',
    namespace: 'user_456',
    tags: ['preferences'],
    label: 'Display Settings'
  })
});

const memory = await response.json();

// Search memories by meaning
const searchResponse = await fetch('https://api.dialoguedb.com/api/v1/search', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query: 'display settings',
    object: 'memory',
    namespace: 'user_456'
  })
});

const results = await searchResponse.json();
python
import requests

# Store a memory
response = requests.post(
    "https://api.dialoguedb.com/api/v1/memory",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "value": "User prefers dark mode and metric units",
        "namespace": "user_456",
        "tags": ["preferences"],
        "label": "Display Settings"
    }
)

memory = response.json()

# Search memories by meaning
response = requests.post(
    "https://api.dialoguedb.com/api/v1/search",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "query": "display settings",
        "object": "memory",
        "namespace": "user_456"
    }
)

results = response.json()
typescript
// Store a memory
const memory = await db.createMemory({
  value: 'User prefers dark mode and metric units',
  namespace: 'user_456',
  tags: ['preferences'],
  label: 'Display Settings'
});

// Search memories by meaning
const memories = await db.searchMemories('display settings', {
  namespace: 'user_456'
});

Retrieving and Deleting Memories

bash
# Get a memory by ID
curl -X GET "https://api.dialoguedb.com/api/v1/memory/mem_abc123?namespace=user_456" \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"

# Delete a memory
curl -X DELETE "https://api.dialoguedb.com/api/v1/memory/mem_abc123?namespace=user_456" \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"
typescript
// Get a memory by ID
const response = await fetch(
  `https://api.dialoguedb.com/api/v1/memory/${memoryId}?namespace=user_456`,
  { headers: { 'Authorization': 'Bearer DIALOGUE_DB_API_KEY' } }
);

const memory = await response.json();

// Delete a memory
await fetch(
  `https://api.dialoguedb.com/api/v1/memory/${memoryId}?namespace=user_456`,
  {
    method: 'DELETE',
    headers: { 'Authorization': 'Bearer DIALOGUE_DB_API_KEY' }
  }
);
python
import requests

# Get a memory by ID
response = requests.get(
    f"https://api.dialoguedb.com/api/v1/memory/{memory_id}",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    params={"namespace": "user_456"}
)

memory = response.json()

# Delete a memory
requests.delete(
    f"https://api.dialoguedb.com/api/v1/memory/{memory_id}",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    params={"namespace": "user_456"}
)
typescript
// Get a memory by ID
const memory = await db.getMemory('mem_abc123', { namespace: 'user_456' });

// Delete a memory
await db.deleteMemory('mem_abc123', { namespace: 'user_456' });

Memory Use Cases

  • User preferences: Store settings that persist across conversations
  • Facts and knowledge: Remember information mentioned in past dialogues
  • Entity data: Structured data about users, products, relationships
  • Feature flags: Per-user or per-namespace configuration

Memory Best Practices

Do:

  • Use namespace to scope memories by user or tenant
  • Use custom IDs for predictable access (e.g., user_${id}_preferences)
  • Use tags for categorization and organization
  • Use search to find memories by meaning, not just exact keys

Don't:

  • Store conversation history in memories (use messages)
  • Store temporary session data in memories (use state)
  • Store large blobs - memories are indexed for search

TIP

For complete Memory API details, see the Memory API Reference. For SDK methods, see the Memory & Search SDK Reference.

Dialogue Actions

DialogueDB provides actions to manage dialogue lifecycle:

End Conversation

Mark a dialogue as complete:

typescript
await dialogue.end();
typescript
await fetch(`https://api.dialoguedb.com/api/v1/dialogue/${dialogueId}/end`, {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
  }
});
python
import requests

response = requests.post(
    f"https://api.dialoguedb.com/api/v1/dialogue/{dialogue_id}/end",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"}
)
bash
curl -X POST https://api.dialoguedb.com/api/v1/dialogue/DIALOGUE_ID/end \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"

Use when:

  • User closes the conversation
  • AI completes a task
  • Session expires

Pagination

When retrieving large datasets, use pagination:

typescript
// Initial request
const { items, next } = await db.listDialogues({
  limit: 20
});

// Next page
if (next) {
  const { items: moreItems, next: nextToken } = await db.listDialogues({
    limit: 20,
    next: next
  });
}

// Messages use SDK-managed pagination (next: true, not a cursor string)
const messages = await dialogue.loadMessages({ limit: 20 });
if (dialogue.hasMoreMessages) {
  const more = await dialogue.loadMessages({ limit: 20, next: true });
}

Namespace

Namespace is an optional property for grouping and isolating dialogues, messages, and memories within a project. It's the recommended way to scope data by user, tenant, or any other boundary.

How It Works

Set namespace when creating a resource. If you create a dialogue with a namespace, pass the same namespace when operating on that dialogue, its messages, and its state.

Namespace rules: Letters, numbers, underscores, and hyphens only. Must start and end with a letter or number. No dots, colons, or slashes.

bash
# Create dialogue with namespace
curl -X POST https://api.dialoguedb.com/api/v1/dialogue \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "user_789",
    "message": {
      "role": "user",
      "content": "Hello"
    }
  }'

# Get it back - pass the same namespace
curl -X GET "https://api.dialoguedb.com/api/v1/dialogue/DIALOGUE_ID?namespace=user_789" \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"

# List dialogues filtered by namespace
curl -X GET "https://api.dialoguedb.com/api/v1/dialogue?namespace=user_789" \
  -H "Authorization: Bearer DIALOGUE_DB_API_KEY"
typescript
// Create dialogue with namespace
const response = await fetch('https://api.dialoguedb.com/api/v1/dialogue', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer DIALOGUE_DB_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    namespace: 'user_789',
    message: {
      role: 'user',
      content: 'Hello'
    }
  })
});

const dialogue = await response.json();

// Get it back - pass the same namespace
const getResponse = await fetch(
  `https://api.dialoguedb.com/api/v1/dialogue/${dialogue.id}?namespace=user_789`,
  {
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
    }
  }
);

const found = await getResponse.json();

// List dialogues filtered by namespace
const listResponse = await fetch(
  'https://api.dialoguedb.com/api/v1/dialogue?namespace=user_789',
  {
    headers: {
      'Authorization': 'Bearer DIALOGUE_DB_API_KEY'
    }
  }
);

const { items } = await listResponse.json();
python
import requests

# Create dialogue with namespace
response = requests.post(
    "https://api.dialoguedb.com/api/v1/dialogue",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    json={
        "namespace": "user_789",
        "message": {
            "role": "user",
            "content": "Hello"
        }
    }
)

dialogue = response.json()

# Get it back - pass the same namespace
response = requests.get(
    f"https://api.dialoguedb.com/api/v1/dialogue/{dialogue['id']}",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    params={"namespace": "user_789"}
)

found = response.json()

# List dialogues filtered by namespace
response = requests.get(
    "https://api.dialoguedb.com/api/v1/dialogue",
    headers={"Authorization": "Bearer DIALOGUE_DB_API_KEY"},
    params={"namespace": "user_789"}
)

items = response.json()["items"]
typescript
// Create dialogue with namespace
const dialogue = await db.createDialogue({
  namespace: 'user_789',
  messages: [{
    role: 'user',
    content: 'Hello'
  }]
});

// Get it back - pass the same namespace
const found = await db.getDialogue(dialogue.id, { namespace: 'user_789' });

// List dialogues filtered by namespace
const { items } = await db.listDialogues({
  namespace: 'user_789'
});

Namespace Required on All Operations

If you create a resource with a namespace, you must pass the same namespace on every subsequent operation - get, update, delete, and list. Omitting it returns a not-found error (DIALOGUE_NOT_FOUND, MEMORY_NOT_FOUND, etc.) even though the resource exists.

typescript
// Created with namespace
const dialogue = await db.createDialogue({ namespace: 'tenant-a', ... });

// Must include namespace to retrieve
await db.getDialogue(dialogue.id, { namespace: 'tenant-a' }); // works
await db.getDialogue(dialogue.id); // DIALOGUE_NOT_FOUND

This applies to dialogues, messages, memories, and state. If you're getting unexpected not-found errors, check whether the resource was created with a namespace.

Namespace Use Cases

  • User isolation: Scope conversations by user ID for multi-user apps
  • Tenant separation: Isolate data by organization in B2B applications
  • Environment segmentation: Separate dev/staging/prod data
  • Feature flagging: Group dialogues by feature or experiment

Namespace Examples

Multi-tenant SaaS:

typescript
const ns = `org_${organizationId}`;

// Create
await db.createDialogue({
  namespace: ns,
  message: { role: 'user', content: 'Help request' }
});

// List
const { items } = await db.listDialogues({ namespace: ns });

// Get
const dialogue = await db.getDialogue(dialogueId, { namespace: ns });

User-specific memories:

typescript
const ns = `user_${userId}`;

// Store
await db.createMemory({
  namespace: ns,
  value: 'Prefers dark mode',
  label: 'UI Preference'
});

// Retrieve
const memory = await db.getMemory(memoryId, { namespace: ns });

// Search
const memories = await db.searchMemories('preferences', {
  namespace: ns
});

Namespace Best Practices

Do:

  • Use consistent naming conventions (e.g., user_${id}, org_${id})
  • Keep namespace values meaningful and predictable
  • Always store and pass the namespace alongside the resource ID

Don't:

  • Put sensitive data in namespace (it's not encrypted)
  • Use extremely long namespace strings (max 64 characters)
  • Treat namespace as authentication (use proper API key scoping)
  • Mix namespaced and non-namespaced resources if you can avoid it

Namespace vs. Other Features

FeaturePurposeScope
NamespaceGrouping and isolationUser-defined, required on all operations if set
ProjectTop-level isolationAPI key scoped
ThreadParent-child linkingHierarchical relationship
MetadataArbitrary key-valuesResource-specific
TagsCategorizationSimple labels

Identifiers

All resources in DialogueDB have unique identifiers:

  • Dialogues: User-provided or auto-generated (e.g., 01KACE6RAZKQ93354SF18CJHHC or my-custom-id)
  • Messages: User-provided or auto-generated (e.g., 01KAD7FYPBVZBF5J1KVVR9NR8S)
  • Memories: Custom keys or auto-generated
  • Projects: e.g., 01KAD6R34620P1C5J0M2KRMGRG

Auto-generated IDs are:

  • Globally unique: No collisions across your account
  • Time-sortable: IDs contain timestamp information for natural ordering
  • URL-safe: Can be used directly in API paths

Custom IDs must be unique within a project and can be 1-64 characters.

Next Steps

Built with DialogueDB