Skip to content

Tenant Isolation ​

A tenant is the logical boundary for data and access. Depending on your business, a tenant might be a customer organization (Acme_Corp, Bank_Alpha) in a B2B platform, an internal department (HR, Engineering) in an enterprise tool, or an individual user (user_123) in a B2C app.

Zelkor isolates these tenants across the platform. One verified identity scopes the run, the tools, and the trace. The agent cannot choose a different tenant. Another tenant’s rows, vectors, and traces are not reachable from this run.

The core advantage: the agent you already wrote is sandboxed — it can't break out, reach unauthorized data or networks, its prompts are verified, budget controlled, and it is under observation.

  • Community Edition is the self-hosted runtime.
  • Pro adds SSO, team controls (budgets and approvals), and production HA / GitOps.
  • Enterprise adds isolation and compliance on Pro (hardware sandbox, mTLS, retained audit, BAA).

How a tenant identity scopes a run. The agent code never supplies the tenant_id to the tools; it is enforced by the platform.

---
config:
  theme: neutral
---
sequenceDiagram
    participant Client as Client JWT
    box Trust Boundary
        participant Wrap as Agent Worker
        participant MCP as MCP Gateway
        participant Store as Native Store
    end

    Client->>Wrap: POST /run (Bearer token)
    Note over Wrap: JWT verified.<br/>Thread gets tenant_id.
    
    Wrap->>MCP: tools/call (no tenant arg)
    Note over MCP: Tenant identity passed<br/>via headers.
    
    MCP->>Store: execute query
    Note over Store: RLS/filters applied<br/>using tenant_id.
    Store-->>MCP: data
    MCP-->>Wrap: tools/call result
    Wrap-->>Client: response

One Identity Per Run ​

The platform extracts the tenant identity from a verified JWT at the front door. This identity is injected into the agent worker's thread state. The agent code does not parse the token, and it cannot forge a different identity.

No Default Tenant: To ensure strict isolation, Zelkor does not have a "default" or "fallback" tenant. If a request lacks a valid JWT, or if the token is missing the required tenant claim, the platform fails closed and rejects the request. There is no global tenant that can access all data.

Tool Governance ​

When the agent calls a tool via the Model Context Protocol (MCP), it cannot pass a tenant_id argument. If an agent tries to supply one, the tools/call request fails closed. The MCP Gateway receives the tenant identity from the platform's internal headers, ensuring the agent cannot spoof another tenant.

Native Store Filtering ​

Native MCP servers (like Postgres and Qdrant) apply this tenant identity directly to their queries.

  • In Postgres, queries are scoped using Row-Level Security (RLS) or explicit WHERE tenant_id = ... clauses injected by the MCP server.
  • In Qdrant, vector searches include a strict payload filter for the tenant.

Extra MCP backends (Bring Your Own) receive the tenant identity in headers but are responsible for applying their own filters (see Extra Backends).

Langfuse Tracing ​

Every run trace emitted to Langfuse is tagged with the user identity derived from the JWT. Traces are naturally partitioned, and one tenant cannot query or view traces belonging to another.