Memory Space Operations API
Last Updated: 2026-01-09 | Version: v0.29.0+
This document covers the cortex.memorySpaces.* namespace for managing memory spaces, participants, and access control.
Overview
Memory spaces are the fundamental isolation boundary in Cortex. The cortex.memorySpaces.* API provides explicit management and registration capabilities beyond the implicit creation that happens automatically when you first use a memorySpaceId.
When to use this API:
- Production deployments (explicit registration)
- Analytics and observability needs
- Hive Mode with participant tracking
- Memory space lifecycle management
- Access control and permissions
- Multi-tenant SaaS (automatic
tenantIdisolation via AuthContext)
When you don't need it:
- Quick prototypes (use implicit creation)
- Simple single-agent apps
- When you just want memory to "just work"
Table of Contents
- register() - Register a memory space with metadata
- get() - Retrieve memory space details
- list() - List all memory spaces with pagination
- count() - Count memory spaces
- search() - Search memory spaces by metadata
- update() - Update memory space metadata
- addParticipant() - Add a single participant
- removeParticipant() - Remove a single participant
- updateParticipants() - Add/remove multiple participants (Hive Mode)
- findByParticipant() - Find spaces by participant
- archive() - Mark memory space as inactive
- reactivate() - Reactivate archived space
- delete() - Delete memory space and all data
- getStats() - Get analytics for a memory space
register()
Register a memory space with metadata and participant tracking.
Signature
cortex.memorySpaces.register(
params: RegisterMemorySpaceParams
): Promise<MemorySpace>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | Memory space ID (e.g., "user-123-personal") |
tenantId | string | No | — | Multi-tenancy isolation (auto-injected from AuthContext) |
name | string | No | — | Human-readable name |
type | "personal" | "team" | "project" | "custom" | Yes | — | Organization type |
participants | Array<{ id: string; type: string }> | No | — | For Hive Mode tracking - participant identifier and type ("user", "agent", "tool", etc.) |
metadata | Record<string, unknown> | No | — | Custom metadata |
v0.29.0+: Graph sync is now automatic when CORTEX_GRAPH_SYNC=true. The syncToGraph option has been removed.
Returns
interface MemorySpace {
_id: string;
memorySpaceId: string;
name?: string;
type: "personal" | "team" | "project" | "custom";
tenantId?: string; // Auto-injected from AuthContext for multi-tenancy
participants: Array<{
id: string;
type: string;
joinedAt: number;
}>;
metadata: Record<string, unknown>;
status: "active" | "archived";
createdAt: number;
updatedAt: number;
}
Examples
// Register user's personal memory space
await cortex.memorySpaces.register({
memorySpaceId: "user-123-personal",
name: "Alice's Personal AI Memory",
type: "personal",
participants: [
{ id: "cursor", type: "ai-tool" },
{ id: "claude", type: "ai-tool" },
{ id: "notion-ai", type: "ai-tool" },
],
metadata: {
owner: "user-123",
environment: "production",
},
});
// Register team workspace
await cortex.memorySpaces.register({
memorySpaceId: "team-engineering-workspace",
name: "Engineering Team Workspace",
type: "team",
participants: [
{ id: "code-review-bot", type: "agent" },
{ id: "deployment-bot", type: "agent" },
{ id: "ticket-bot", type: "agent" },
],
metadata: {
team: "engineering",
project: "apollo",
},
});
// Register and sync to graph database
await cortex.memorySpaces.register(
{
memorySpaceId: "finance-agent-space",
name: "Finance Agent Memory",
type: "custom",
participants: [{ id: "finance-agent", type: "agent" }],
},
);
// Graph sync is automatic when CORTEX_GRAPH_SYNC=true (v0.29.0+)
Error Handling
try {
await cortex.memorySpaces.register({
memorySpaceId: "space-123",
type: "personal",
});
} catch (error) {
if (error.code === "MEMORYSPACE_ALREADY_EXISTS") {
console.log("Space already registered");
// Use update() instead
}
}
get()
Retrieve memory space details and metadata.
Signature
cortex.memorySpaces.get(memorySpaceId: string): Promise<MemorySpace | null>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID to retrieve |
Examples
const space = await cortex.memorySpaces.get("user-123-personal");
if (space) {
console.log(space.name); // "Alice's Personal AI Memory"
console.log(space.participants); // [{ id: 'cursor', type: 'ai-tool', joinedAt: 1234567890 }, ...]
console.log(space.type); // 'personal'
}
const space = await cortex.memorySpaces.get("unknown-space");
if (space === null) {
console.log("Memory space does not exist");
// Create it
await cortex.memorySpaces.register({
memorySpaceId: "unknown-space",
type: "personal",
});
}
list()
List memory spaces with filtering, pagination, and sorting.
Signature
cortex.memorySpaces.list(filters?: ListMemorySpacesFilter): Promise<ListMemorySpacesResult>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
type | "personal" | "team" | "project" | "custom" | No | — | Filter by memory space type |
status | "active" | "archived" | No | — | Filter by status |
tenantId | string | No | — | Multi-tenancy filter (auto-injected from AuthContext) |
participant | string | No | — | Filter by participant ID |
limit | number | No | 100 | Maximum number of results |
offset | number | No | 0 | Pagination offset |
sortBy | "createdAt" | "updatedAt" | "name" | No | — | Sort field |
sortOrder | "asc" | "desc" | No | "desc" | Sort direction |
Returns
interface ListMemorySpacesResult {
spaces: MemorySpace[];
total: number;
hasMore: boolean;
offset: number;
}
Examples
const result = await cortex.memorySpaces.list();
console.log(`Found ${result.total} memory spaces`);
result.spaces.forEach((space) => {
console.log(`${space.name} (${space.type})`);
});
// Get all personal spaces
const personal = await cortex.memorySpaces.list({
type: "personal",
status: "active",
});
// Get all team workspaces
const teams = await cortex.memorySpaces.list({
type: "team",
});
// Find all spaces where Cursor participates
const cursorSpaces = await cortex.memorySpaces.list({
participant: "cursor",
});
console.log(`Cursor operates in ${cursorSpaces.total} memory spaces`);
// Get first 20
const page1 = await cortex.memorySpaces.list({ limit: 20, offset: 0 });
// Get next 20
if (page1.hasMore) {
const page2 = await cortex.memorySpaces.list({ limit: 20, offset: 20 });
}
// Sort by name ascending
const sorted = await cortex.memorySpaces.list({
sortBy: "name",
sortOrder: "asc",
});
// Most recently updated first
const recent = await cortex.memorySpaces.list({
sortBy: "updatedAt",
sortOrder: "desc",
});
count()
Count memory spaces matching filter criteria.
Signature
cortex.memorySpaces.count(filter?: {
type?: "personal" | "team" | "project" | "custom";
status?: "active" | "archived";
}): Promise<number>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
type | "personal" | "team" | "project" | "custom" | No | — | Filter by memory space type |
status | "active" | "archived" | No | — | Filter by status |
Examples
// Count all spaces
const total = await cortex.memorySpaces.count();
// Count active personal spaces
const activePersonal = await cortex.memorySpaces.count({
type: "personal",
status: "active",
});
console.log(`${activePersonal} active personal spaces out of ${total} total`);
search()
Search memory spaces by name or metadata.
Signature
cortex.memorySpaces.search(query: string, options?: SearchOptions): Promise<MemorySpace[]>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | — | Search query string |
type | "personal" | "team" | "project" | "custom" | No | — | Filter by memory space type |
status | "active" | "archived" | No | — | Filter by status |
limit | number | No | — | Maximum number of results |
Examples
const results = await cortex.memorySpaces.search("engineering");
// Returns spaces with "engineering" in name or metadata
// [
// { memorySpaceId: 'team-engineering-workspace', name: 'Engineering Team', ... },
// { memorySpaceId: 'project-engineering-docs', name: 'Engineering Docs Project', ... }
// ]
const results = await cortex.memorySpaces.search("alice", {
type: "personal",
status: "active",
limit: 5,
});
update()
Update memory space metadata (not participants - use updateParticipants()).
Signature
cortex.memorySpaces.update(
memorySpaceId: string,
updates: MemorySpaceUpdates
): Promise<MemorySpace>
// Note: syncToGraph option removed in v0.29.0+ - sync is automatic
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID to update |
name | string | No | — | New human-readable name |
metadata | Record<string, unknown> | No | — | Metadata to merge with existing |
status | "active" | "archived" | No | — | New status |
Options:
v0.29.0+: Graph sync is now automatic when CORTEX_GRAPH_SYNC=true. No options parameter needed.
Examples
await cortex.memorySpaces.update("user-123-personal", {
name: "Alice's Updated Personal Space",
});
await cortex.memorySpaces.update("team-engineering-workspace", {
metadata: {
lastReview: Date.now(),
status: "active-development",
},
});
await cortex.memorySpaces.update(
"team-engineering-workspace",
{ name: "Updated Team Space" },
);
// Graph sync is automatic when CORTEX_GRAPH_SYNC=true (v0.29.0+)
addParticipant()
Add a single participant to a memory space.
Signature
cortex.memorySpaces.addParticipant(
memorySpaceId: string,
participant: { id: string; type: string; joinedAt: number }
): Promise<MemorySpace>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID |
participant.id | string | Yes | — | Participant identifier |
participant.type | string | Yes | — | Participant type ("user", "agent", "tool", etc.) |
participant.joinedAt | number | Yes | — | Timestamp when participant joined |
Examples
// User installs new AI tool
await cortex.memorySpaces.addParticipant("user-123-personal", {
id: "github-copilot",
type: "ai-tool",
joinedAt: Date.now(),
});
removeParticipant()
Remove a single participant from a memory space.
Signature
cortex.memorySpaces.removeParticipant(
memorySpaceId: string,
participantId: string
): Promise<MemorySpace>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID |
participantId | string | Yes | — | ID of the participant to remove |
Examples
// User uninstalls tool
await cortex.memorySpaces.removeParticipant("user-123-personal", "old-tool");
// Note: Participant's existing memories remain (audit trail)
// But space no longer lists it as active participant
Removing a participant does not delete their existing memories. The memories remain for audit trail purposes, but the space no longer lists them as an active participant.
updateParticipants()
Add or remove multiple participants from a memory space (Hive Mode).
Signature
cortex.memorySpaces.updateParticipants(
memorySpaceId: string,
updates: ParticipantUpdates
): Promise<MemorySpace>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID |
add | Array<{ id: string; type: string; joinedAt: number }> | No | — | Participants to add |
remove | string[] | No | — | Participant IDs to remove |
Examples
// User installs new AI tools
await cortex.memorySpaces.updateParticipants("user-123-personal", {
add: [
{ id: "github-copilot", type: "ai-tool", joinedAt: Date.now() },
{ id: "windsurf", type: "ai-tool", joinedAt: Date.now() },
],
});
// User uninstalls tools
await cortex.memorySpaces.updateParticipants("user-123-personal", {
remove: ["old-tool-1", "old-tool-2"],
});
// Set exact participant list
await cortex.memorySpaces.updateParticipants("team-workspace", {
remove: ["bot-1", "bot-2"], // Remove old
add: [
{ id: "bot-3", type: "agent", joinedAt: Date.now() },
{ id: "bot-4", type: "agent", joinedAt: Date.now() },
],
});
findByParticipant()
Find all memory spaces where a participant is active.
Signature
cortex.memorySpaces.findByParticipant(participantId: string): Promise<MemorySpace[]>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
participantId | string | Yes | — | The participant ID to search for |
Examples
// Find all spaces where a specific user participates
const userSpaces = await cortex.memorySpaces.findByParticipant("user-123");
console.log(`User is active in ${userSpaces.length} memory spaces`);
userSpaces.forEach((space) => {
console.log(`- ${space.name} (${space.type})`);
});
archive()
Mark memory space as archived (inactive). Data is preserved but space is hidden from default lists.
Signature
cortex.memorySpaces.archive(memorySpaceId: string, options?: ArchiveOptions): Promise<MemorySpace>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID to archive |
reason | string | No | — | Why the space is being archived |
metadata | Record<string, unknown> | No | — | Additional archive metadata |
Examples
// Project complete, archive its memory space
await cortex.memorySpaces.archive("project-apollo", {
reason: "Project completed successfully",
metadata: {
archivedBy: "admin-456",
completedAt: Date.now(),
},
});
// Space still exists, data intact, but marked inactive
const space = await cortex.memorySpaces.get("project-apollo");
console.log(space.status); // 'archived'
// User hasn't logged in for 90 days
await cortex.memorySpaces.archive(`user-${userId}-personal`, {
reason: "User inactive for 90 days",
metadata: {
lastSeen: user.lastSeen,
},
});
reactivate()
Reactivate an archived memory space.
Signature
cortex.memorySpaces.reactivate(memorySpaceId: string): Promise<MemorySpace>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The archived memory space ID to reactivate |
Examples
// User returns, reactivate their space
await cortex.memorySpaces.reactivate(`user-${userId}-personal`);
const space = await cortex.memorySpaces.get(`user-${userId}-personal`);
console.log(space.status); // 'active'
delete()
DESTRUCTIVE: This operation permanently deletes the memory space and ALL associated data. This cannot be undone.
Signature
cortex.memorySpaces.delete(
memorySpaceId: string,
options: DeleteMemorySpaceOptions
): Promise<DeleteMemorySpaceResult>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID to delete |
cascade | boolean | Yes | — | Must be true to proceed with deletion |
reason | string | Yes | — | Why deleting (for audit trail) |
confirmId | string | No | — | Safety check - must match memorySpaceId |
Returns
interface DeleteMemorySpaceResult {
memorySpaceId: string;
deleted: true;
cascade: {
conversationsDeleted: number; // Layer 1a
memoriesDeleted: number; // Layer 2
factsDeleted: number; // Layer 3
totalBytes: number; // Storage freed
};
reason: string;
deletedAt: number;
}
Examples
// User requests data deletion
const result = await cortex.memorySpaces.delete("user-123-personal", {
cascade: true,
reason: "GDPR deletion request from user-123",
confirmId: "user-123-personal", // Safety check
});
console.log(`Deleted ${result.cascade.memoriesDeleted} memories`);
console.log(`Deleted ${result.cascade.conversationsDeleted} conversations`);
console.log(`Deleted ${result.cascade.factsDeleted} facts`);
// Project archived, delete after retention period
await cortex.memorySpaces.delete("project-old-2023", {
cascade: true,
reason: "Data retention policy: 2 years expired",
});
// Without cascade - ERROR
try {
await cortex.memorySpaces.delete("user-123-personal", {
cascade: false, // Must be true
reason: "Test",
});
} catch (error) {
console.error("Must set cascade: true to delete");
}
// With confirmId (extra safety)
await cortex.memorySpaces.delete("production-space", {
cascade: true,
reason: "Migration to new architecture",
confirmId: "production-space", // Must match memorySpaceId
});
getStats()
Get analytics and usage statistics for a memory space.
Signature
cortex.memorySpaces.getStats(
memorySpaceId: string,
options?: GetMemorySpaceStatsOptions
): Promise<MemorySpaceStats>
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
memorySpaceId | string | Yes | — | The memory space ID |
timeWindow | "24h" | "7d" | "30d" | "90d" | "all" | No | "all" | Time window for activity metrics |
includeParticipants | boolean | No | false | Include participant activity breakdown (Hive Mode) |
Returns
interface MemorySpaceStats {
memorySpaceId: string;
// Counts
totalMemories: number;
totalConversations: number;
totalFacts: number;
totalMessages: number;
// Activity (based on timeWindow)
memoriesThisWindow?: number;
conversationsThisWindow?: number;
// Storage
storage: {
conversationsBytes: number;
memoriesBytes: number;
factsBytes: number;
totalBytes: number;
};
// Performance
avgSearchTime?: string; // Average search latency (e.g., "12ms")
// Content Analysis
topTags: string[];
importanceBreakdown: {
critical: number; // 90-100
high: number; // 70-89
medium: number; // 40-69
low: number; // 10-39
trivial: number; // 0-9
};
// Participant Activity (if includeParticipants: true)
participants?: Array<{
participantId: string;
memoriesStored: number;
conversationsStored: number;
factsExtracted: number;
firstActive: number;
lastActive: number;
avgImportance: number;
topTags: string[];
}>;
}
Examples
const stats = await cortex.memorySpaces.getStats("user-123-personal");
console.log(`Total memories: ${stats.totalMemories}`);
console.log(
`Storage used: ${(stats.storage.totalBytes / 1024 / 1024).toFixed(2)} MB`,
);
console.log(`Top tags: ${stats.topTags.join(", ")}`);
// Last 7 days
const weekStats = await cortex.memorySpaces.getStats("user-123-personal", {
timeWindow: "7d",
});
console.log(`Activity this week: ${weekStats.memoriesThisWindow} memories`);
console.log(`Conversations this week: ${weekStats.conversationsThisWindow}`);
const stats = await cortex.memorySpaces.getStats("team-engineering-workspace", {
timeWindow: "7d",
includeParticipants: true,
});
console.log(`Activity this week: ${stats.memoriesThisWindow} memories`);
// Participant breakdown
stats.participants?.forEach((p) => {
console.log(`${p.participantId}:`);
console.log(` - Stored: ${p.memoriesStored} memories`);
console.log(` - Last active: ${new Date(p.lastActive).toISOString()}`);
console.log(` - Avg importance: ${p.avgImportance}`);
});
Common Patterns
Pattern 1: Dynamic Space Creation (SaaS)
// Create memory space per customer on signup
async function onUserSignup(userId: string) {
const memorySpaceId = `customer-${userId}-space`;
await cortex.memorySpaces.register({
memorySpaceId,
name: `Customer ${userId} Memory`,
type: "personal",
metadata: {
customerId: userId,
tier: "free",
signupDate: Date.now(),
},
});
return memorySpaceId;
}
Pattern 2: Team Workspace Management
// Admin creates team workspace
async function createTeamWorkspace(
teamId: string,
teamName: string,
members: string[],
) {
const memorySpaceId = `team-${teamId}-workspace`;
await cortex.memorySpaces.register({
memorySpaceId,
name: `${teamName} Workspace`,
type: "team",
participants: members.map((m) => ({
id: `bot-${m}`,
type: "agent",
})),
metadata: {
teamId,
createdBy: "admin",
members,
},
});
return memorySpaceId;
}
// Add new member
async function addTeamMember(teamId: string, memberId: string) {
await cortex.memorySpaces.addParticipant(`team-${teamId}-workspace`, {
id: `bot-${memberId}`,
type: "agent",
joinedAt: Date.now(),
});
}
Pattern 3: Lifecycle Management
// Complete lifecycle
async function memorySpaceLifecycle(projectId: string) {
const memorySpaceId = `project-${projectId}`;
// 1. Create
await cortex.memorySpaces.register({
memorySpaceId,
type: "project",
metadata: { status: "active" },
});
// 2. Use (implicit in app)
// await cortex.memory.remember({ memorySpaceId, ... });
// 3. Complete project - archive
await cortex.memorySpaces.archive(memorySpaceId, {
reason: "Project completed",
});
// 4. After retention period - delete
await cortex.memorySpaces.delete(memorySpaceId, {
cascade: true,
reason: "Retention period (2 years) expired",
});
}
Pattern 4: Analytics Dashboard
// Build memory space analytics dashboard
async function getMemorySpaceDashboard() {
const result = await cortex.memorySpaces.list({ status: "active" });
const dashboard = await Promise.all(
result.spaces.map(async (space) => {
const stats = await cortex.memorySpaces.getStats(space.memorySpaceId, {
timeWindow: "7d",
includeParticipants: true,
});
return {
name: space.name,
type: space.type,
participants: space.participants.length,
memoriesThisWeek: stats.memoriesThisWindow,
storage: stats.storage.totalBytes,
topParticipant: stats.participants?.[0]?.participantId,
};
}),
);
return dashboard;
}
// Usage
const dashboard = await getMemorySpaceDashboard();
console.table(dashboard);
Best Practices
1. Use Structured IDs
// Good: Structured, searchable
"user-{userId}-personal";
"team-{teamId}-workspace";
"project-{projectId}-memory";
// Avoid: Random, opaque
"abc123";
"temp";
"space1";
2. Always Register in Production
// Development: Implicit is fine
await cortex.memory.remember({ memorySpaceId: "test-space", ... });
// Production: Explicit registration
await cortex.memorySpaces.register({
memorySpaceId: "user-123-personal",
name: "Alice's Personal Space",
type: "personal",
metadata: { environment: "production" },
});
3. Track Participants in Hive Mode
// Good: Clear participant list with types
await cortex.memorySpaces.register({
memorySpaceId: "user-123-personal",
participants: [
{ id: "cursor", type: "ai-tool" },
{ id: "claude", type: "ai-tool" },
{ id: "notion-ai", type: "ai-tool" },
],
});
4. Use Metadata for Organization
// Rich metadata for filtering and search
await cortex.memorySpaces.register({
memorySpaceId: "user-123-personal",
metadata: {
owner: "user-123",
environment: "production",
tier: "pro",
region: "us-west-2",
created: Date.now(),
tags: ["active", "premium"],
},
});
5. Archive Before Delete
Always archive a memory space before deleting it. This provides a grace period for recovery and maintains data integrity during the retention period.
// Recommended: Archive first, delete later
await cortex.memorySpaces.archive(memorySpaceId, { reason: "Inactive" });
// Wait for retention period...
// Then delete
await cortex.memorySpaces.delete(memorySpaceId, {
cascade: true,
reason: "Retention period expired",
});
// Avoid: Direct deletion without archival period
Error Handling
Common Errors
MEMORYSPACE_ALREADY_EXISTS:
try {
await cortex.memorySpaces.register({ memorySpaceId: "user-123-personal", type: "personal" });
} catch (error) {
if (error.message?.includes("MEMORYSPACE_ALREADY_EXISTS")) {
// Use update() instead
await cortex.memorySpaces.update("user-123-personal", { ... });
}
}
MEMORYSPACE_NOT_FOUND:
const space = await cortex.memorySpaces.get("nonexistent-space");
if (space === null) {
// Create it
await cortex.memorySpaces.register({
memorySpaceId: "nonexistent-space",
type: "personal",
});
}
CASCADE_REQUIRED (Delete Prevention):
try {
await cortex.memorySpaces.delete("active-space", {
cascade: false,
reason: "Test",
});
} catch (error) {
if (error.message?.includes("CASCADE_REQUIRED")) {
console.error("Must set cascade: true to delete space with data");
}
}
CONFIRM_ID_MISMATCH:
try {
await cortex.memorySpaces.delete("space-123", {
cascade: true,
reason: "Test",
confirmId: "wrong-id", // Doesn't match
});
} catch (error) {
if (error.message?.includes("CONFIRM_ID_MISMATCH")) {
console.error("confirmId must match memorySpaceId");
}
}
Conclusion
The Memory Space Operations API provides explicit control over memory space lifecycle, participant management, and analytics.
Key Takeaways:
- Registration is optional (implicit creation works)
- Register in production for analytics and tracking
- Use participants for Hive Mode tracking
- Archive before delete (safer)
- Monitor with getStats() for observability
Most important: memorySpaceId is the fundamental isolation boundary. Everything else builds on this.
Questions? Ask in Discussions.