Skip to main content

C# SDK: Memories

Create, search, update, and delete memories using the Trix .NET SDK.

Overview

The memories resource handles creating, reading, updating, and deleting memory objects. Memories are the core data type in Trix - use them to store any information you want your AI to remember.

// Access via the client
client.Memories

Create Memory

Store a new memory with optional tags, metadata, and space assignment:

CreateMemory.cs
using Trix.Models;

var memory = await client.Memories.CreateAsync(new CreateMemoryRequest
{
    Content = "C# provides static type checking at compile time",
    Type = MemoryType.Text,
    Tags = new List<string> { "csharp", "programming" },
    Metadata = new Dictionary<string, object>
    {
        ["source"] = "documentation",
        ["author"] = "team"
    },
    SpaceId = "space_abc123"  // Optional: assign to space
});

Console.WriteLine($"Created memory: {memory.Id}");
Console.WriteLine($"Content: {memory.Content}");

Create Request Options

PropertyTypeDescription
ContentstringThe memory content (required)
TypeMemoryTypeText, Markdown, Code, Json, Html, Url, Audio
TagsList<string>Tags for categorization
MetadataDictionary<string, object>Custom key-value metadata
SpaceIdstring?Space to store memory in
Priorityint?Priority level (0-100)
ExpiresAtDateTime?Expiration timestamp

List Memories

List memories with filtering and pagination:

ListMemories.cs
// List all memories with pagination
var response = await client.Memories.ListAsync(new ListMemoriesRequest
{
    Limit = 20,
    Offset = 0
});

Console.WriteLine($"Total: {response.Total}");
Console.WriteLine($"Has more: {response.HasMore}");

foreach (var m in response.Data)
{
    Console.WriteLine($"- {m.Content}");
}

// Filter by tags
var tagged = await client.Memories.ListAsync(new ListMemoriesRequest
{
    Tags = new List<string> { "csharp", "programming" },
    SortBy = "createdAt",
    SortOrder = "desc"
});

// Filter by space
var spaceMemories = await client.Memories.ListAsync(new ListMemoriesRequest
{
    SpaceId = "space_abc123",
    Type = MemoryType.Text,
    Limit = 50
});

Async Enumerable

Stream through all memories without manual pagination using await foreach:

IterateMemories.cs
// Automatically handles pagination
await foreach (var memory in client.Memories.ListAllAsync())
{
    Console.WriteLine(memory.Content);
}

// With filters
await foreach (var memory in client.Memories.ListAllAsync(new ListMemoriesRequest
{
    Tags = new List<string> { "important" },
    Type = MemoryType.Text
}))
{
    ProcessMemory(memory);
}

// With cancellation
var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
await foreach (var memory in client.Memories.ListAllAsync(cancellationToken: cts.Token))
{
    if (ShouldStop(memory))
        break;

    await HandleMemory(memory);
}

The ListAllAsync() method returns an IAsyncEnumerable that automatically fetches pages as needed. This is memory-efficient for large datasets.

Get Single Memory

Retrieve a specific memory by ID:

GetMemory.cs
var memory = await client.Memories.GetAsync("mem_xyz789");

Console.WriteLine($"ID: {memory.Id}");
Console.WriteLine($"Content: {memory.Content}");
Console.WriteLine($"Type: {memory.Type}");
Console.WriteLine($"Tags: {string.Join(", ", memory.Tags ?? Array.Empty<string>())}");
Console.WriteLine($"Created: {memory.CreatedAt}");

// Access metadata
if (memory.Metadata != null)
{
    foreach (var (key, value) in memory.Metadata)
    {
        Console.WriteLine($"  {key}: {value}");
    }
}

Update Memory

Update an existing memory's content, tags, or metadata:

UpdateMemory.cs
var updated = await client.Memories.UpdateAsync("mem_xyz789", new UpdateMemoryRequest
{
    Content = "Updated content here",
    Tags = new List<string> { "csharp", "updated" },
    Metadata = new Dictionary<string, object>
    {
        ["lastReviewed"] = DateTime.UtcNow.ToString("O"),
        ["version"] = 2
    }
});

Console.WriteLine($"Updated at: {updated.UpdatedAt}");

Updating content triggers re-embedding. If you only want to update metadata or tags, consider using a metadata-only update to avoid re-embedding costs.

Delete Memory

Permanently delete a memory:

DeleteMemory.cs
await client.Memories.DeleteAsync("mem_xyz789");

// Delete with error handling
try
{
    await client.Memories.DeleteAsync("mem_xyz789");
    Console.WriteLine("Memory deleted successfully");
}
catch (NotFoundException)
{
    Console.WriteLine("Memory not found - already deleted?");
}

Bulk Operations

Perform operations on multiple memories at once for better performance:

Bulk Create

BulkCreate.cs
var result = await client.Memories.BulkCreateAsync(new List<CreateMemoryRequest>
{
    new() { Content = "First memory", Tags = new List<string> { "batch" } },
    new() { Content = "Second memory", Tags = new List<string> { "batch" } },
    new() { Content = "Third memory", Tags = new List<string> { "batch" } }
});

Console.WriteLine($"Created: {result.Success}");
Console.WriteLine($"Failed: {result.Failed}");

if (result.Errors?.Count > 0)
{
    foreach (var error in result.Errors)
    {
        Console.WriteLine($"Error at index {error.Index}: {error.Message}");
    }
}

Bulk Update

BulkUpdate.cs
var updateResult = await client.Memories.BulkUpdateAsync(new List<BulkUpdateItem>
{
    new() { Id = "mem_abc123", Priority = 10 },
    new() { Id = "mem_def456", Tags = new List<string> { "important" } },
    new() { Id = "mem_ghi789", Metadata = new Dictionary<string, object> { ["reviewed"] = true } }
});

Console.WriteLine($"Updated: {updateResult.Success}");

Bulk Delete

BulkDelete.cs
var deleteResult = await client.Memories.BulkDeleteAsync(new List<string>
{
    "mem_abc123",
    "mem_def456",
    "mem_ghi789"
});

Console.WriteLine($"Deleted: {deleteResult.Success}");
Console.WriteLine($"Failed: {deleteResult.Failed}");

Bulk operations are significantly faster than individual operations when working with many memories. Use them when creating, updating, or deleting more than 5-10 memories at once.

Reinforce Relationships

Boost a relationship's strength when it proves useful. This helps the most relevant connections surface in future graph traversals:

Reinforce.cs
// Reinforce a helpful relationship
await client.Relationships.ReinforceAsync("rel_abc123", amount: 0.1);

Memory Type Reference

The Memory object structure:

MemoryType.cs
public class Memory
{
    public string Id { get; set; }
    public string SpaceId { get; set; }
    public MemoryType Type { get; set; }
    public string Content { get; set; }
    public double[]? Embedding { get; set; }
    public List<string>? Tags { get; set; }
    public Dictionary<string, object>? Metadata { get; set; }
    public int Priority { get; set; }
    public double Salience { get; set; }
    public bool IsPrivate { get; set; }
    public double? Score { get; set; }  // Search relevance score
    public DateTime CreatedAt { get; set; }
    public DateTime UpdatedAt { get; set; }
    public DateTime? AccessedAt { get; set; }
}

Paginated Response

PaginatedResponse.cs
public class PaginatedResponse<T>
{
    public List<T> Data { get; set; }
    public int Total { get; set; }
    public int Page { get; set; }
    public int Limit { get; set; }
    public bool HasMore { get; set; }
}

Memory Pinning

Pin important memories to prevent them from being affected by decay or automatic cleanup. Pinned memories are always prioritized in search results.

Pinning.cs
// Pin a memory to mark it as important
await client.Memories.PinAsync("mem_xyz789");

// Unpin a memory
await client.Memories.UnpinAsync("mem_xyz789");

// Check if a memory is pinned
var memory = await client.Memories.GetAsync("mem_xyz789");
Console.WriteLine($"Pinned: {memory.IsPinned}");

// Create a memory as pinned
var pinned = await client.Memories.CreateAsync(new CreateMemoryRequest
{
    Content = "Critical business rule: always validate input",
    IsPinned = true,
    Tags = new List<string> { "rules", "validation" }
});

// List only pinned memories
var pinnedMemories = await client.Memories.ListAsync(new ListMemoriesRequest
{
    Pinned = true
});

foreach (var m in pinnedMemories.Data)
{
    Console.WriteLine($"Pinned: {m.Content.Substring(0, Math.Min(50, m.Content.Length))}...");
}

Use pinning for critical information that should never be forgotten, such as core business rules, important contacts, or key procedures.

Protection Levels

Set protection levels on memories to control how they can be modified or deleted. This provides an extra layer of safety for important data.

Protection.cs
using Trix.Models;

// Set protection level on existing memory
await client.Memories.SetProtectionLevelAsync("mem_xyz789", ProtectionLevel.Hard);

// Protection levels:
// - ProtectionLevel.None: No protection (default)
// - ProtectionLevel.Soft: Requires confirmation for deletion
// - ProtectionLevel.Hard: Cannot be deleted without removing protection first

// Create memory with protection
var protectedMemory = await client.Memories.CreateAsync(new CreateMemoryRequest
{
    Content = "Legal compliance requirement: retain for 7 years",
    ProtectionLevel = ProtectionLevel.Hard,
    Tags = new List<string> { "legal", "compliance" }
});

// Check protection level
var memory = await client.Memories.GetAsync("mem_xyz789");
Console.WriteLine($"Protection: {memory.ProtectionLevel}");

// Remove protection before deletion
await client.Memories.SetProtectionLevelAsync("mem_xyz789", ProtectionLevel.None);
await client.Memories.DeleteAsync("mem_xyz789");

Protection Level Reference

LevelDescriptionUse Case
ProtectionLevel.NoneNo protection, can be freely modified or deletedRegular memories
ProtectionLevel.SoftDeletion requires explicit confirmationImportant but occasionally updated data
ProtectionLevel.HardCannot be deleted without first removing protectionCritical data, compliance requirements

Soft Delete & Restore

Soft delete moves memories to a recoverable state instead of permanently deleting them. This allows you to restore accidentally deleted memories.

SoftDelete.cs
// Soft delete a memory (recoverable)
await client.Memories.SoftDeleteAsync("mem_xyz789");

// Memory is now in "deleted" state but can be restored
var deleted = await client.Memories.GetAsync("mem_xyz789");
Console.WriteLine($"Deleted at: {deleted.DeletedAt}");

// Restore a soft-deleted memory
await client.Memories.RestoreAsync("mem_xyz789");

// Memory is now active again
var restored = await client.Memories.GetAsync("mem_xyz789");
Console.WriteLine("Status: active");

// List soft-deleted memories
var deletedMemories = await client.Memories.ListAsync(new ListMemoriesRequest
{
    IncludeDeleted = true
});

foreach (var m in deletedMemories.Data)
{
    Console.WriteLine($"Deleted: {m.Content.Substring(0, Math.Min(50, m.Content.Length))}... at {m.DeletedAt}");
}

// Permanently delete
await client.Memories.DeleteAsync("mem_xyz789");

Soft-deleted memories are automatically purged after 30 days by default. Configure the retention period in your space settings.

Topic Extraction

Extract and search by topics to organize and discover related memories. Topics are automatically extracted or can be manually assigned.

Topics.cs
// Get topics for a specific memory
var topics = await client.Memories.GetTopicsAsync("mem_xyz789");
foreach (var topic in topics)
{
    Console.WriteLine($"Topic: {topic.Name} (relevance: {topic.Relevance:F2}, category: {topic.Category})");
}

// Search memories by topic
var results = await client.Memories.SearchByTopicAsync("machine learning", limit: 20);
foreach (var memory in results)
{
    Console.WriteLine($"- {memory.Content.Substring(0, Math.Min(50, memory.Content.Length))}...");
}

// Combine with text search
var combined = await client.Memories.ListAsync(new ListMemoriesRequest
{
    Q = "dependency injection",
    Mode = SearchMode.Hybrid
});

// Manually tag a memory with topics
await client.Memories.UpdateAsync("mem_xyz789", new UpdateMemoryRequest
{
    Tags = new List<string> { "software architecture", "best practices" }
});

Quality Scores & Enrichment

Assess memory quality and enrich memories with additional metadata, summaries, and extracted information.

Quality Scores

Quality.cs
// Get quality score for a memory
var score = await client.Memories.GetQualityScoreAsync("mem_xyz789");
Console.WriteLine($"Quality score: {score:F2}");

// List memories filtered by quality
var highQuality = await client.Memories.ListAsync(new ListMemoriesRequest
{
    MinQuality = 0.7,
    Limit = 50
});

// List high-quality memories
foreach (var m in highQuality.Data)
{
    Console.WriteLine($"High quality: {m.Content.Substring(0, Math.Min(50, m.Content.Length))}...");
}

Memory Enrichment

Enrichment.cs
using Trix.Models;

// Enrich a memory with additional data
var result = await client.Memories.EnrichAsync("mem_xyz789", new EnrichMemoryOptions
{
    Operations = new List<EnrichmentOperation>
    {
        EnrichmentOperation.Topics,
        EnrichmentOperation.Summary,
        EnrichmentOperation.Entities
    }
});

Console.WriteLine($"Memory: {result.MemoryId}");
Console.WriteLine($"Operations: {string.Join(", ", result.Operations)}");

// Results are keyed by operation name
foreach (var (op, value) in result.Results)
{
    Console.WriteLine($"{op}: {value}");
}

// Trigger an async enrichment via the Enrichments resource
var triggered = await client.Enrichments.TriggerAsync("mem_xyz789");

Enrichment Operations

OperationDescription
EnrichmentOperation.TopicsExtract topic labels from content
EnrichmentOperation.SummaryGenerate a concise summary
EnrichmentOperation.EntitiesExtract named entities (people, places, organizations)
EnrichmentOperation.QualityCalculate a quality score for the memory

Multi-scale Clusters

Access memory clusters at different granularity levels to understand how memories are organized and find related content.

Clusters.cs
using Trix.Models;

// List clusters at different scales
var fineClusters = await client.Clusters.ListAsync(new ListClustersRequest
{
    Scale = ClusterScale.Fine
});
var mediumClusters = await client.Clusters.ListAsync(new ListClustersRequest
{
    Scale = ClusterScale.Medium
});
var coarseClusters = await client.Clusters.ListAsync(new ListClustersRequest
{
    Scale = ClusterScale.Coarse
});

Console.WriteLine($"Fine clusters: {fineClusters.Data.Count}");
Console.WriteLine($"Medium clusters: {mediumClusters.Data.Count}");
Console.WriteLine($"Coarse clusters: {coarseClusters.Data.Count}");

// Get cluster details
foreach (var cluster in fineClusters.Data.Take(5))
{
    Console.WriteLine($"Cluster: {cluster.Name}");
    Console.WriteLine($"  Memories: {cluster.MemoryIds?.Count ?? 0}");
}

// Fetch a cluster with its memory objects hydrated
var withMemories = await client.Clusters.GetAsync(
    "cluster_abc123",
    new GetClusterOptions { IncludeMemories = true }
);

foreach (var mem in withMemories.Memories ?? new List<Memory>())
{
    Console.WriteLine($"  - {mem.Content}");
}

Cluster Scales

ScaleDescriptionTypical Use
ClusterScale.FineMany small, tightly related clustersFinding very similar memories
ClusterScale.MediumBalanced clusteringGeneral organization (default)
ClusterScale.CoarseFew large, broadly related clustersHigh-level categorization

Advanced List & Create Options

The list and create methods support additional parameters for fine-grained control over memory management.

Advanced List Options

AdvancedList.cs
// List with all advanced filters
var memories = await client.Memories.ListAsync(new ListMemoriesRequest
{
    Q = "search query",                    // Text search
    Mode = SearchMode.Hybrid,              // Search mode
    Tags = new List<string> { "important" },  // Filter by tags
    SpaceId = "space_abc123",              // Filter by space
    Pinned = true,                         // Only pinned memories
    Protected = true,                      // Only protected memories
    MinQuality = 0.7,                      // Minimum quality score
    IncludeDeleted = false,                // Include soft-deleted
    SessionId = "sess_abc123",             // Filter by session
    Limit = 50,
    Offset = 0
});

// Iterate with advanced filters
await foreach (var memory in client.Memories.ListAllAsync(new ListMemoriesRequest
{
    Pinned = true,
    MinQuality = 0.8
}))
{
    Console.WriteLine($"High-quality pinned: {memory.Content.Substring(0, Math.Min(50, memory.Content.Length))}...");
}

Advanced Create Options

AdvancedCreate.cs
// Create with all options
var memory = await client.Memories.CreateAsync(new CreateMemoryRequest
{
    Content = "Important business rule documentation",
    Type = MemoryType.Markdown,
    Tags = new List<string> { "rules", "documentation" },
    Metadata = new Dictionary<string, object>
    {
        ["author"] = "admin",
        ["department"] = "engineering"
    },
    SpaceId = "space_abc123",
    Priority = 9,
    IsPinned = true,                       // Pin on creation
    ProtectionLevel = ProtectionLevel.Soft,   // Set protection
    ExpiresAt = DateTime.Parse("2025-12-31T23:59:59Z")  // Expiration date
});

Console.WriteLine($"Created: {memory.Id}");
Console.WriteLine($"Pinned: {memory.IsPinned}");
Console.WriteLine($"Protection: {memory.ProtectionLevel}");

Next Steps