Aegis Orchestrator
Guides

Multi-Tenancy Configuration

Configure and isolate multiple tenants using Keycloak realms and OpenBao namespaces.

Multi-Tenancy Configuration

AEGIS is designed as a multi-tenant platform that can serve multiple independent organizations (tenants) from a single infrastructure deployment. This guide details how operators should configure and isolate these tenants using the AEGIS four-layer isolation model.


The Four-Layer Isolation Model

AEGIS enforces tenant isolation at four complementary layers. Each layer must hold independently to ensure a failure in one does not create a cross-tenant data leak.

LayerMechanismImplementation
1. IdentityKeycloak RealmsEach tenant has a dedicated Keycloak realm. TenantId is derived from the JWT issuer URL.
2. AuthorizationSEAL ContextsSecurityContext names are namespaced (e.g., tenant-acme-corp-research).
3. DataPostgreSQL ScopingAll core tables (agents, executions, workflows) are scoped by a tenant_id column.
4. SecretsOpenBao NamespacesEach tenant has a dedicated OpenBao namespace: tenant-{slug}/.

Layer 1: Identity (Keycloak)

AEGIS identifies tenants based on the Keycloak realm slug embedded in the JWT's iss (issuer) claim.

Tenant Kinds

KindKeycloak RealmTenantId
Consumer (Per-User)zaru-consumeru-{user-uuid}
Enterprise Tenanttenant-{slug}{slug}
Platform Operatoraegis-systemaegis-system

Consumer users all authenticate through the shared zaru-consumer Keycloak realm, but each user receives their own dedicated per-user tenant at signup. The tenant slug follows the format u-{uuid} (e.g., u-a1b2c3d4-5678-...). This provides full data isolation between consumer users — agents, workflows, executions, and secrets are scoped to the individual user's tenant rather than a shared pool. The tenant_id is injected into the JWT via a tenant_id protocol mapper on the zaru-consumer realm, and the orchestrator extracts it from this custom claim during identity resolution.

Configuration

To onboard a new tenant, an operator must create a corresponding realm in Keycloak. AEGIS will automatically derive the TenantId from the cryptographically validated JWT issued by that realm.


Layer 2: Authorization (SEAL SecurityContext)

To prevent cross-tenant capability name collisions, all enterprise tenant SecurityContext names must follow a strict naming convention:

Tenant TypePatternExample
Zaru Consumerzaru-{tier}zaru-free, zaru-pro
Enterprisetenant-{slug}-{name}tenant-acme-research
Operatoraegis-system-{name}aegis-system-admin

The AttestationService enforces this convention. A principal from tenant acme cannot request a context named tenant-globex-research.


Layer 3: Data (PostgreSQL)

AEGIS uses a shared schema model where a tenant_id column is added to all aggregate tables.

  • Isolation: Every repository query includes a WHERE tenant_id = $1 clause.
  • Uniqueness: Resources like Agent and Workflow names are unique within a tenant, not globally.
  • Performance: Indexes are applied to (tenant_id, id) and (tenant_id, status) to ensure performant scoped lookups.

Layer 4: Secrets (OpenBao)

Each tenant is assigned a dedicated OpenBao namespace for their credentials, tool API keys, and webhook secrets.

Namespace Pattern

tenant-{slug}/

Policy Enforcement

The AEGIS Orchestrator uses its AppRole to access these namespaces. The CredentialResolver automatically routes secret lookups to the appropriate namespace based on the TenantId of the requesting execution.

# Example secret reference in an agent manifest
spec:
  tools:
    - name: "custom-tool"
      api_key: "secret:custom-api-key" # Automatically looked up in tenant-acme/kv/

Operator Administration

Provisioning a Tenant

Tenant provisioning is handled by the TenantOnboardingService (triggered via the Zaru client admin console or CLI). The sequence is atomic:

  1. Create Keycloak Realm: tenant-{slug}
  2. Create OpenBao Namespace: tenant-{slug}/
  3. Register in AEGIS: Insert record into the tenants table.

Cross-Tenant Admin Access

Platform operators (aegis-system realm) can perform administrative actions on behalf of a tenant using the X-Aegis-Tenant header:

curl -H "X-Aegis-Tenant: acme-corp" \
     -H "Authorization: Bearer <system-admin-jwt>" \
     https://api.aegis.cloud/v1/agents

Every use of this bypass is logged as a TenantEvent::AdminCrossTenantAccess for audit compliance.


Agent Visibility

Agents belong to a tenant. When the system resolves an agent by name or ID for execution, it checks the caller's tenant first. If no match is found, it falls back to platform-provided global agents.

Platform agents — such as the intent pipeline, agent creator, and judge agents — are global and accessible to all tenants automatically. No configuration is required to use them.

CRUD operations (update, delete) are strictly tenant-scoped. You can only modify agents your tenant owns. Attempting to update or delete a global platform agent is rejected regardless of the caller's permissions.


Workflow Scope

Every workflow has a visibility scope that controls which callers can discover and invoke it:

ScopeVisibility
TenantAll members of your organization (or the individual consumer user's per-user tenant)
GlobalAll tenants — reserved for platform builtins

When running a workflow by name (e.g., via aegis workflow run or aegis.workflow.run), the system resolves using narrowest-first: tenant-scoped workflows first, then global builtins.

Platform workflows such as builtin-intent-to-execution are global scope and always available without any additional configuration.

Changing a workflow's scope is an admin operation. Newly registered workflows default to tenant scope.


Quotas and Rate Limits

Tenant-level quotas are configured in the tenants table and can be overridden in node-config.yaml:

tenants:
  overrides:
    - slug: acme-corp
      max_concurrent_executions: 200
      max_agents: 2000
      max_storage_gb: 1000.0

When a quota is exceeded, AEGIS returns 429 Too Many Requests and publishes a TenantQuotaExceeded event to the event bus.

On this page