What are Clusters?
Clusters are named groupings that help organize related memories within a space. Unlike spaces (which provide access isolation), clusters are flexible labels that memories can belong to. A single memory can belong to multiple clusters.
- Memories can belong to multiple clusters
- Flexible, tag-like organization
- No access control implications
- Can be auto-assigned by Trix
- Memories belong to one space only
- Strict organizational boundaries
- API key scoping for access control
- Multi-tenant isolation
Creating Clusters
import { Trix } from '@trixdb/client';
const trix = new Trix({ apiKey: process.env.TRIX_API_KEY });
// Create a cluster
// NOTE: TypeScript SDK accepts name, description, memoryIds, spaceId, metadata — no 'color' field yet.
const cluster = await trix.clusters.create({
name: 'learning-progress',
description: 'Track user learning milestones',
spaceId: '<space-uuid>',
});
console.log(cluster.id);
console.log(cluster.name);Adding Memories to Clusters
When Creating Memories
Assign clusters at creation time:
const memory = await trix.memories.create({
content: 'Completed React tutorial',
clusters: ['learning-progress', 'frontend']
});
console.log(memory.clusters);Adding Existing Memories
Add memories to clusters after creation:
await trix.memories.addToClusters('mem_abc123', {
clusters: ['learning-progress', 'important']
});
await trix.memories.removeFromCluster('mem_abc123', 'learning-progress');
await trix.memories.update('mem_abc123', {
clusters: ['new-cluster-1', 'new-cluster-2']
});Automatic Clustering
Trix can automatically assign memories to clusters based on semantic similarity. Enable auto-clustering to let Trix organize memories as they're created.
await trix.spaces.update('user_123', {
autoClustering: {
enabled: true,
minSimilarity: 0.75,
maxClusters: 3,
createNew: true
}
});
const memory = await trix.memories.create({
content: 'User likes hiking and outdoor activities',
autoCluster: true
});
console.log(memory.clusters);
console.log(memory.clusterScores);Auto-clustering uses embeddings to find semantically similar clusters. New clusters are created when no existing cluster matches above the threshold.
Filtering by Cluster
Search for memories within specific clusters:
const result = await trix.memories.list({
q: 'what has the user learned?',
cluster: 'learning-progress'
});
const result2 = await trix.memories.list({
q: 'user activity',
clusters: ['learning-progress', 'feedback', 'support']
});
const result3 = await trix.memories.list({
q: 'important information',
excludeClusters: ['archived', 'deprecated']
});When multiple clusters are specified, memories belonging to any of the clusters are returned (OR logic).
Managing Clusters
List Clusters
const { data: clusters } = await trix.clusters.list();
clusters.forEach(c => {
console.log(`${c.name}: ${c.memoryCount} memories`);
});
const spaceClusters = await trix.clusters.list({
spaceId: 'user_123'
});Get Cluster Details
const cluster = await trix.clusters.get('cls_abc123');
console.log({
name: cluster.name,
description: cluster.description,
memoryCount: cluster.memoryCount,
createdAt: cluster.createdAt,
lastMemoryAt: cluster.lastMemoryAt
});Update Cluster
await trix.clusters.update('cls_abc123', {
name: 'updated-name',
description: 'New description',
color: '#FF5733'
});Delete Cluster
await trix.clusters.delete('cls_abc123');
await trix.clusters.delete('cls_abc123', {
deleteMemories: true
});Deleting a cluster does not delete the memories in it by default. The memories remain and can still be searched or added to other clusters.
Bulk Operations
Perform operations on many memories at once:
await trix.clusters.addMatching('cls_abc123', {
q: 'project alpha',
spaceId: 'work'
});
await trix.clusters.moveMemories({
from: 'old-cluster',
to: 'new-cluster',
deleteFromSource: true
});
await trix.clusters.merge({
sources: ['cluster-1', 'cluster-2'],
target: 'merged-cluster',
deleteSources: true
});Cluster Statistics
Get insights about cluster usage:
const stats = await trix.clusters.stats();
console.log({
totalClusters: stats.total,
totalMemoriesInClusters: stats.memoriesCount,
averageMemoriesPerCluster: stats.average,
largestCluster: stats.largest,
emptyClusters: stats.empty
});
const clusterStats = await trix.clusters.stats('cls_abc123');
console.log({
memoryCount: clusterStats.memoryCount,
avgMemoryLength: clusterStats.avgContentLength,
topEntities: clusterStats.topEntities,
recentActivity: clusterStats.lastWeekCount
});Common Use Cases
| Use Case | Example Clusters | Description |
|---|---|---|
| Topic Organization | work, personal, hobbies | Group memories by subject area |
| Project Management | project-alpha, q1-goals | Track information by project or initiative |
| Content Type | preferences, feedback, questions | Categorize by type of information |
| Priority | critical, important, nice-to-have | Tag by urgency or importance |
| Workflow Status | pending-review, approved, archived | Track processing status |
| Source Tracking | email, chat, meeting | Identify where information came from |
Multi-scale Clustering
Trix supports brain-inspired multi-scale clustering that organizes memories at different levels of abstraction. This allows you to navigate your memory space from high-level overviews down to specific details.
Understanding Scales
Multi-scale clustering creates three hierarchical levels of organization:
| Scale | Cluster Size | Description | Best For |
|---|---|---|---|
fine | min 5 memories | Small, highly specific clusters | Precise recall, specific topics, detailed context |
medium | min 10 memories | Balanced clusters for general themes | General exploration, balanced context, default searches |
coarse | min 25 memories | Large, abstract category clusters | High-level overview, navigation, categorization |
Scale Use Cases
- Finding specific conversations or events
- Precise technical topics (e.g., "React hooks usage")
- Individual project discussions
- Detailed preference categories
- General topic exploration
- Broad project categories
- Default search context
- Balanced detail/breadth tradeoff
- Dashboard overviews
- Memory space navigation
- High-level categorization
- Understanding knowledge domains
List Clusters at Specific Scale
import { Trix } from '@trixdb/client';
const trix = new Trix({ apiKey: process.env.TRIX_API_KEY });
const fineClusters = await trix.clusters.list({
scale: 'fine',
spaceId: 'user_123'
});
console.log(`Found ${fineClusters.data.length} fine clusters`);
fineClusters.data.forEach(c => {
console.log(`- ${c.name}: ${c.memoryCount} memories`);
});
const mediumClusters = await trix.clusters.list({
scale: 'medium',
spaceId: 'user_123'
});
const coarseClusters = await trix.clusters.list({
scale: 'coarse',
spaceId: 'user_123'
});Get Cluster with Scale Parameter
const cluster = await trix.clusters.get('cls_abc123', {
scale: 'fine'
});
console.log({
name: cluster.name,
scale: cluster.scale,
memoryCount: cluster.memoryCount,
parentCluster: cluster.parent,
childClusters: cluster.children
});
const fineCluster = await trix.clusters.get('react-state-management', { scale: 'fine' });
const mediumCluster = await trix.clusters.get('react-development', { scale: 'medium' });
const coarseCluster = await trix.clusters.get('frontend', { scale: 'coarse' });
console.log(fineCluster.parent === mediumCluster.id);
console.log(mediumCluster.parent === coarseCluster.id);Search with Cluster Scale Filter
const result = await trix.memories.list({
q: 'how to handle state?',
cluster_scale: 'medium',
spaceId: 'user_123'
});
result.data.forEach(m => {
console.log(`[${m.cluster_name}] ${m.content}`);
});
const fineResult = await trix.memories.list({
q: 'how to handle state?',
cluster_scale: 'fine',
spaceId: 'user_123'
});
const coarseResult = await trix.memories.list({
q: 'how to handle state?',
cluster_scale: 'coarse',
spaceId: 'user_123'
});Get Cluster Hierarchy
const hierarchy = await trix.clusters.getHierarchy('cls_abc123');
console.log({
fine: hierarchy.fine,
medium: hierarchy.medium,
coarse: hierarchy.coarse
});
const topLevel = await trix.clusters.list({
scale: 'coarse',
spaceId: 'user_123'
});
for (const coarseCluster of topLevel.data) {
console.log(`=== ${coarseCluster.name} ===`);
const mediumClusters = await trix.clusters.list({
scale: 'medium',
parent: coarseCluster.id
});
for (const mediumCluster of mediumClusters.data) {
console.log(` ${mediumCluster.name}`);
const fineClusters = await trix.clusters.list({
scale: 'fine',
parent: mediumCluster.id
});
for (const fineCluster of fineClusters.data) {
console.log(` - ${fineCluster.name} (${fineCluster.memoryCount})`);
}
}
}Multi-scale clustering is automatically maintained by Trix. When you add new memories, they are assigned to clusters at all three scales based on semantic similarity. The hierarchy is continuously updated as your memory space evolves.
Practical Applications
| Application | Recommended Scale | Why |
|---|---|---|
| RAG context retrieval | fine or medium | Specific context for accurate responses |
| User dashboard | coarse | High-level overview of knowledge areas |
| Topic exploration | medium | Balance between breadth and specificity |
| Conversation context | fine | Precise details for ongoing discussions |
| Knowledge graph visualization | All scales | Drill-down navigation from overview to detail |
| Content organization | medium to coarse | Manageable categories for manual review |
Best Practices
- Use descriptive names: Cluster names should clearly indicate what type of memories they contain.
- Don't over-cluster: Start with broad categories and add specificity as needed. Too many clusters reduce their usefulness.
- Combine with tags: Use clusters for primary organization and memory tags for secondary attributes.
- Enable auto-clustering: Let Trix help organize memories automatically, especially in high-volume scenarios.
- Review periodically: Check cluster statistics to identify empty or underused clusters that could be consolidated.
- Scope to spaces: Keep clusters within a space to avoid cross-user organization confusion.
- Leverage multi-scale: Use coarse clusters for navigation and fine clusters for precise retrieval in RAG applications.
Naming Conventions
// Good: Clear, descriptive names
'user-preferences'
'project-roadmap'
'customer-feedback'
'weekly-standup-notes'
// Avoid: Vague or overlapping names
'misc'
'stuff'
'data'
'important' // Too subjective