Isolation Boundaries
Understanding Cortex's multi-layered isolation model for security, privacy, and compliance.
Overview
Cortex provides four layers of isolation that work together to ensure data security, enable multi-tenancy, and maintain privacy boundaries:
tenantId • Multi-tenant SaaS separation • Auto-injected via AuthContext
memorySpaceId • Fundamental data boundary • Hive or Collaboration Mode
userId • GDPR compliance • Enables cascade deletion
participantId • Hive Mode attribution • Audit trail
Each layer serves a distinct purpose and can be used independently or combined.
1. Tenant Isolation (Multi-Tenant SaaS)
Complete data separation for SaaS platforms serving multiple organizations.
const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
tenantId: "customer-acme", // All operations scoped to this tenant
userId: "user-123",
}),
});
// All operations automatically include tenantId
await cortex.memory.remember({
memorySpaceId: "user-123-personal",
// tenantId: "customer-acme" ← Auto-injected!
userMessage: "Hello",
agentResponse: "Hi!",
userId: "user-123",
userName: "Alice",
});
- Tenant A cannot query Tenant B's data
- Tenant A cannot access Tenant B's memory spaces
- GDPR deletion respects tenant boundaries
- Complete isolation at database level
2. Memory Space Isolation
Core data isolation boundary for organizing memories, conversations, and facts.
| Feature | Hive Mode | Collaboration Mode |
|---|---|---|
| Spaces | One shared space | Separate spaces per agent |
| Data Access | All participants see all data | Agents only see their own |
| Cross-Access | Automatic | Via A2A or Context Chains |
| Use Case | Personal AI tools | Enterprise workflows |
All AI tools share user's personal space:
const memorySpaceId = "user-123-personal";
// Cursor stores
await cortex.memory.remember({
memorySpaceId,
participantId: "cursor",
userMessage: "I prefer TypeScript",
agentResponse: "Noted!",
userId: "user-123",
userName: "Alice",
});
// Claude reads same space — sees Cursor's memories
const memories = await cortex.memory.search(memorySpaceId, "preferences");
Each agent has separate space:
// Finance agent stores in its own space
await cortex.memory.remember({
memorySpaceId: "finance-agent-space",
userMessage: "Approve budget",
agentResponse: "Approved",
userId: "user-123",
userName: "CFO",
});
// Communication via A2A (dual-write to both spaces)
await cortex.a2a.send({
from: "finance-agent",
to: "hr-agent",
message: "Budget approved",
});
3. User Data Isolation (GDPR)
Link data to users via userId to enable cascade deletion across ALL layers with a single API call.
// Link data to user
await cortex.memory.remember({
memorySpaceId: "support-bot-space",
userId: "user-123", // ← GDPR link
userMessage: "My account issue",
agentResponse: "Let me help",
userName: "Alice",
});
// One API call deletes from ALL layers
const result = await cortex.users.delete("user-123", {
cascade: true,
verify: true,
});
Deleted from: Conversations • Memories • Facts • Sessions • User Profile
4. Participant Tracking
participantId tracks which tool stored data. It does NOT isolate data — all participants can still see all memories in the space.
// Track which tool stored what
await cortex.memory.remember({
memorySpaceId: "shared-space",
participantId: "cursor", // Attribution
userMessage: "User message",
agentResponse: "Response",
userId: "user-123",
userName: "Alice",
});
// Filter by participant for debugging
const cursorMemories = await cortex.memory.list({
memorySpaceId: "shared-space",
participantId: "cursor",
});
Isolation Matrix
How each data type is scoped by isolation layer:
| Data Type | tenantId | memorySpaceId | userId | participantId |
|---|---|---|---|---|
| Conversations | ✅ | ✅ | Optional | Optional |
| Vector Memories | ✅ | ✅ | Optional | Optional |
| Facts | ✅ | ✅ | Optional | Optional |
| User Profiles | ✅ | Shared | N/A | N/A |
| Immutable Store | ✅ | Shared | Optional | N/A |
| Mutable Store | ✅ | Shared | Optional | N/A |
Best Practices
const cortex = new Cortex({
auth: createAuthContext({
tenantId: req.tenant.id, // REQUIRED for multi-tenant
userId: req.user.id,
}),
});
await cortex.memory.remember({
memorySpaceId: "bot-space",
userId: "user-123", // Required for cascade deletion
// ...
});
await cortex.memory.remember({
memorySpaceId: "shared-space",
participantId: "my-bot", // Track attribution
// ...
});