Skip to content

Agents and tenants

A tenant is the top-level isolation boundary. Every grant, namespace, object, and API key is scoped to exactly one tenant. Tenants do not share data.

Multi-tenancy is day-one in Pore: every domain table has tenant_id as the leading composite-index column. There is no ambient tenant context — TenantId is a first-class type in the kernel.

For most SaaS applications, a tenant corresponds to a customer workspace.

An agent is a non-human subject that acts on behalf of a user or autonomously. Agents are first-class in Pore:

  • Agent identifiers live under the agent namespace: agent:claude-4-alice.
  • Agents can hold grants directly: (agent:claude-4-alice, editor, document:42).
  • Agents carry a scope mask — a set of named capabilities (e.g. check:read, grant:read) that limits which actions they may be authorized for, independent of the grant graph.
  • Agents are revocable independently of the user they act for via a single killswitch operation.

Agents are registered via the API rather than created implicitly:

POST /v1/agents
{
"external_id": "claude-4-alice",
"display_name": "Claude acting for Alice",
"owner": "user:alice",
"scope": ["check:read", "grant:read"]
}

This creates the agent and reserves its subject identifier. No grants are created automatically. See the API reference for the full request/response shape.

A common pattern is to bind an agent’s authority to a specific user:

(agent:claude-4-alice, member, user:alice)

Then grants made to user:alice flow to the agent via group expansion. When alice’s access changes, the agent’s access changes with it.

DELETE /v1/agents/{external_id}

This deletes the agent row and every grant where the agent is the subject — one call removes all access. It is the operation a security lead reaches for when an agent is behaving badly. Revoking individual grants is also possible for surgical removal, but the killswitch is the authoritative revocation path for compromised agents.