Multi-tenant AI systems serve multiple customers (tenants) from shared infrastructure. Each tenant needs its own safety policies, its own audit trail, and a guarantee that their data is isolated from other tenants. This guide covers multi-tenant patterns with Authensor.
Each tenant needs:
Store policies per tenant in the control plane:
// When evaluating an action, load the tenant's policy
const guard = createGuard({
controlPlane: 'https://control-plane.internal',
apiKey: tenantApiKey,
tenantId: tenant.id,
});
The control plane serves the correct policy based on the tenant ID. Tenants can customize their policies within the boundaries set by the platform.
In multi-tenant systems, policies typically have two layers:
Platform policy: Rules that apply to all tenants. These enforce platform-wide safety requirements that tenants cannot override.
Tenant policy: Rules specific to each tenant. These customize behavior within the platform's boundaries.
# Platform policy (cannot be overridden)
rules:
- tool: "system.*"
action: block
reason: "System tools are blocked for all tenants"
- tool: "shell.execute"
action: block
reason: "Shell access is disabled"
# Tenant policy (customizable)
rules:
- tool: "email.send"
action: allow
when:
args.to:
endsWith: "@tenant-a.com"
- tool: "email.send"
action: escalate
reason: "External emails need approval"
The platform policy is evaluated first. If it blocks the action, the tenant policy is not consulted. If the platform policy allows, the tenant policy is evaluated.
Receipts are tagged with the tenant ID:
const decision = guard('file.read', { path: '/data/report.csv' });
// decision.receipt.tenantId === 'tenant_abc'
Query receipts by tenant:
curl https://control-plane/api/receipts?tenant_id=tenant_abc
The API enforces tenant isolation: a request authenticated with Tenant A's API key cannot access Tenant B's receipts.
Policy rules prevent agents from accessing other tenants' resources:
- tool: "database.query"
action: block
when:
args.query:
not:
contains: "tenant_id = '${context.tenantId}'"
reason: "Queries must include tenant_id filter"
Sentinel maintains separate baselines per tenant. An anomaly in Tenant A's agent does not trigger alerts for Tenant B. Configure per-tenant alert routing:
sentinel: {
onAlert: (alert) => {
const tenant = getTenant(alert.tenantId);
notifyTenantAdmin(tenant, alert);
}
}
Multi-tenant deployments need to handle policy lookups efficiently. Cache policies per tenant with a short TTL. The control plane supports policy versioning so cached policies can be invalidated when updated.
Explore more guides on AI agent safety, prompt injection, and building secure systems.
View All Guides