> For the complete documentation index, see [llms.txt](/llms.txt). Every page on this site is also available as markdown at `<path>.md`.

# Tenant

Every runtime is scoped to exactly one tenant. `define_tenant(...)` creates the identity
serialized into `RuntimeSpec`; the Rust runtime (`flowai-runtime`) uses it as the isolation
key for everything it stores and serves.

```python
from flowai_harness import define_tenant

tenant = define_tenant("acme", "v1")

tenant.model_dump(by_alias=True, mode="json")
# {"resourceId": "acme", "version": "v1"}
```

Pick a stable `resource_id` from trusted auth or deployment configuration; do not derive it
from a user prompt.

## What tenancy isolates

`resource_id` namespaces everything the runtime persists or guards:

- **Runtime storage** — the runtime's KV state (references, plans, pending-approval audit
  records, caches) is keyed by tenant, so two tenants sharing one store never read each
  other's entries.
- **References** — reference ids are content hashes salted with the tenant, and every resolve
  checks the stored owner. A handle leaked across tenants resolves to "not found" rather than
  to another tenant's payload.
- **Plans** — plans are stored and loaded per `(tenant, plan_id)`. Cross-tenant loads also
  return "not found", so the existence of another tenant's plan is never disclosed.
- **Requests** — every query is checked against the handle's tenant. There is no per-call
  tenant override; a mismatched request is rejected.
- **Data-environment scope** — if `data_environment` declares a `tenant_id`, runtime
  construction rejects it unless it matches the runtime tenant.

Telemetry and trace events are recorded per runtime handle, and each handle is bound to a
single tenant.

What tenancy does **not** isolate: the topology itself. Agents, prompts, tools, and provider
configuration are properties of the `RuntimeSpec` you build — runtimes created from the same
spec for different tenants run the same agents. Per-tenant behavior belongs in the spec you
construct for that tenant, not in the identity.

## `version` semantics

The second field, `version`, labels the revision of the tenant identity. It must be a
non-empty string and is serialized with the spec, so it shows up wherever the runtime spec is
dumped or inspected. It does not participate in storage keying: changing `"v1"` to `"v2"` does
not repartition or invalidate stored references, plans, or approval records — the tenant still
sees all state keyed by its `resource_id`. Use it to record which revision of your tenant
configuration built a given runtime.

## Tenant is not prompt content

Tenant identity is runtime routing metadata. It is not automatically rendered into system
prompts. Put business vocabulary, domain facts, or operating assumptions in
[`layered_prompt(domain_knowledge=...)`](/docs/concepts/prompts) instead:

```python
domain_knowledge = {
    "entities": ["product", "segment", "channel"],
    "metrics": ["revenue", "margin"],
}
```

This separation keeps tenancy inspectable and security-relevant while keeping prompt content
customer-defined and domain-specific.

## See also

- [Runtime](/docs/concepts/runtime) — `define_runtime(tenant=...)` and the single-tenant handle.
- [`define_tenant` reference](/docs/reference/tenant)
