AgentisProAGENTISPRO RAG ENGINE

Data Isolation

How data is isolated between tenants in AgentisPro RAG Engine

Data Isolation

AgentisPro RAG Engine ensures complete data isolation between tenants at multiple levels.

Isolation Architecture

┌─────────────────────────────────────────────────────────┐
│                    Request Layer                        │
│  API Key → org_id validation → Scope enforcement       │
├─────────────────────────────────────────────────────────┤
│                    Data Layer                           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │   Neo4j     │  │   Vectors   │  │   Storage   │    │
│  │  (Labels)   │  │(Namespaces) │  │  (Prefixes) │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
└─────────────────────────────────────────────────────────┘

Neo4j Graph Isolation

Each organization's data uses unique labels:

// Org A's documents
(:Document:org_acme_corp {id: "doc1", title: "Sales Guide"})
(:Entity:org_acme_corp {name: "Product X"})
 
// Org B's documents - completely separate
(:Document:org_beta_inc {id: "doc1", title: "HR Policy"})
(:Entity:org_beta_inc {name: "Employee"})

Query Isolation

Queries automatically filter by organization label:

// Internal query for acme-corp
MATCH (d:Document:org_acme_corp)
WHERE d.content CONTAINS $query
RETURN d
 
// Cannot access beta_inc data

Vector Store Isolation

Embeddings are stored in namespaces:

# Namespace structure
vectors = {
    "acme-corp": [...embeddings...],
    "beta-inc": [...embeddings...],
}
 
# Search is namespace-scoped
results = vector_store.search(
    query_embedding,
    namespace="acme-corp",  # Only searches acme's vectors
    top_k=10
)

File Storage Isolation

Documents are stored with org-prefixed paths:

/storage/
├── acme-corp/
│   ├── documents/
│   └── cache/
└── beta-inc/
    ├── documents/
    └── cache/

API Key Enforcement

Every API request is validated:

# Middleware validation
async def validate_request(api_key: str, org_id: str):
    key_data = await get_api_key(api_key)
    
    # Check if key has access to requested org
    if org_id not in key_data.allowed_orgs:
        raise HTTPException(403, "Access denied to organization")
    
    # Scope check
    if required_scope not in key_data.scopes:
        raise HTTPException(403, "Insufficient permissions")

Audit Logging

All operations are logged per organization:

{
  "timestamp": "2025-01-28T10:30:00Z",
  "org_id": "acme-corp",
  "user_id": "user-123",
  "operation": "query",
  "details": {
    "query": "sales report Q4",
    "mode": "hybrid",
    "results_count": 5
  }
}

Security Guarantees

ThreatProtection
Cross-tenant data accessLabel/namespace isolation
API key theftScoped to specific orgs
Injection attacksParameterized queries
Data leakageEncrypted at rest

Important: Never share API keys between organizations. Each organization should have its own set of API keys.

On this page