Appearance
Core Concepts
Understanding DialogueDB's core concepts will help you build better conversational applications. This guide covers the fundamental building blocks: dialogues, messages, threads, and state.
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)
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
- Created: New dialogue initialized
- Active: Accepting new messages
- Ended: Conversation marked as complete
- Deleted: Permanently removed (messages remain)
Creating Dialogues
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'
}]
});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
role: "user" | "assistant" | "system"; // Message role
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.
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
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
typescript
// Get messages with pagination
const messages = await dialogue.loadMessages({
limit: 50,
next: paginationToken // From previous request
});
// Get specific message
const message = await dialogue.getMessage(messageId);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
threadCountautomatically - 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
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:
| Feature | Threads | Namespace |
|---|---|---|
| Purpose | Organizational hierarchy | User/tenant isolation |
| Relationship | Parent-child link | Flat grouping |
| Use Case | Sub-processes of a dialogue | Multi-tenant data separation |
| Visibility | Listed via parent ID | Queried 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
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 stateState 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
Dialogue Actions
DialogueDB provides actions to manage dialogue lifecycle:
End Conversation
Mark a dialogue as complete:
typescript
await dialogue.end();bash
curl -X POST https://api.dialoguedb.com/dialogue/DIALOGUE_ID/end \
-H "Authorization: Bearer DIALOGUE_DB_API_KEY"Use when:
- User closes the conversation
- AI completes a task
- Session expires
Compact Conversation
Summarize a long conversation to reduce token usage:
bash
# Compact a dialogue (REST API only — not yet available in SDK)
curl -X POST https://api.dialoguedb.com/dialogue/DIALOGUE_ID/compact \
-H "Authorization: Bearer DIALOGUE_DB_API_KEY"This generates a summary while preserving the full message history. Useful for:
- Long-running conversations
- Reducing LLM context size
- Maintaining conversation continuity
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
});
}
// Same pattern for messages
const messages = await dialogue.loadMessages({
limit: 50,
next: paginationToken
});Namespace (Advanced)
Namespace is an optional property for custom grouping and isolation of dialogues, messages, and memories. It provides a flexible way to organize your data beyond the built-in project structure.
Understanding Namespace
Namespace is a user-defined string that you can use to group and filter resources:
typescript
// Create dialogue with namespace
const dialogue = await db.createDialogue({
namespace: 'user_789',
messages: [{
role: 'user',
content: 'Hello'
}]
});
// List dialogues by namespace
const { items } = await db.listDialogues({
namespace: 'user_789'
});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
- Custom categorization: Any domain-specific grouping needs
Namespace Examples
Multi-tenant SaaS:
typescript
// Each organization has isolated data
await db.createDialogue({
namespace: `org_${organizationId}`,
message: { role: 'user', content: 'Help request' }
});
// Query only this organization's dialogues
const { items: orgDialogues } = await db.listDialogues({
namespace: `org_${organizationId}`
});User-specific conversations:
typescript
// Store user ID in namespace
await db.createDialogue({
namespace: `user_${userId}`,
message: { role: 'user', content: 'Question' }
});
// List all conversations for this user
const { items: userDialogues } = await db.listDialogues({
namespace: `user_${userId}`
});Memory isolation by user:
typescript
// Store user-specific memory
await db.createMemory({
namespace: `user_${userId}`,
value: 'Prefers dark mode',
label: 'UI Preference'
});
// Search only this user's memories
const memories = await db.searchMemories('preferences', {
namespace: `user_${userId}`
});Namespace Best Practices
Do:
- Use consistent naming conventions (e.g.,
user_${id},org_${id}) - Keep namespace values meaningful and predictable
- Use namespace for cross-dialogue grouping
- Combine with metadata for additional context
Don't:
- Put sensitive data in namespace (it's not encrypted)
- Use extremely long namespace strings (keep under 128 characters)
- Treat namespace as authentication (use proper API key scoping)
Namespace vs. Other Features
| Feature | Purpose | Scope |
|---|---|---|
| Namespace | Custom grouping | User-defined, filterable |
| Project | Top-level isolation | API key scoped |
| Thread | Parent-child linking | Hierarchical relationship |
| Metadata | Arbitrary key-values | Resource-specific |
| Tags | Categorization | Simple labels |
Identifiers
All resources in DialogueDB have unique identifiers:
- Dialogues: User-provided or auto-generated (e.g.,
01KACE6RAZKQ93354SF18CJHHCormy-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
- Use Cases & Patterns - Common conversation patterns
- API Reference - Detailed endpoint documentation
- Best Practices - Optimization strategies

