Setting up a new tenant's knowledge base
How to stand up an isolated agent-native knowledge base (the
knowledge-base wiki space) for a new team — one that agents read index-first
and that compounds from their work, fully isolated from other tenants by
Row-Level Security.
For what the KB is and how it operates, read the agent-native knowledge base concept page first; for the read path agents use, see KB retrieval.
The model: a team that needs its own KB = its own tenant
- Tenant = the RLS isolation boundary. A team that needs an isolated KB gets its own tenant.
- Organisation = a sub-entity within a tenant (ADR-005). Orgs in one tenant share the tenant's RLS scope, so they share one KB.
- Therefore: isolated KB ⇒ separate tenant, not just a separate org.
Prerequisite — verify RLS is actually enforced (do this first)
The entire multi-tenant isolation rests on the app connecting to Postgres as a
non-BYPASSRLS role. If the runtime connects as a superuser / BYPASSRLS
role, all RLS is inert — one tenant could read another's data, and per-tenant
KB isolation is illusory.
Before onboarding any team whose KB must be isolated, confirm the runtime connects as a non-bypass role. If it does not, fix that first. Everything below assumes RLS is genuinely enforced.
Setup steps
1. Provision the tenant + org (Directory)
Create the tenant (types: AGENCY / SUPPLIER / PROGRAMME_OFFICE /
PLATFORM_OPERATOR), at least one organisation, and an admin user. This is the
RLS boundary every later step inherits.
2. Create the knowledge-base space (in the new tenant)
Use exactly the slug knowledge-base. That well-known slug is what wires the
coordinator read path and consult file-back to the space. Mark it agent-owned and
give it a description (mirror the platform KB space). One KB space per tenant.
3. Mint tenant-scoped API keys (Settings → API Keys, in the tenant)
The Directory-issued API-key JWT carries tenant_id, so every MCP / pt CLI
call RLS-scopes to this tenant — a key for Team A can never read Team B's KB.
One key per agent/machine; shown once; ~90-day default. See the
MCP server setup.
4. Wire the environment
| Variable | Where | Why |
|---|---|---|
WIKI_BASE_URL | the team's .mcp.json | Registers the wiki MCP tools (search_pages, get_page, ingest, lint, …) on the MCP server. Does not gate query_knowledge_base — that tool is always registered against the PT client. |
WIKI_ZONE_URL | the PT / coordinator runtime | The backend read path for query_knowledge_base and the coordinator KB reader; the wiki-spaces proxy fails closed if it is unset (returns WIKI_BACKEND_NOT_CONFIGURED, never a silent empty). |
CRON_SECRET + DISPATCHER_DATABASE_URL | the wiki runtime (for file-back) | The outbox dispatch-events cron must run for consult file-back to deliver. Use a dispatcher-role DSN. |
5. Set the coordinator profile + initiative (PT)
The coordinator is initiative-scoped. Create the team's initiative and its
coordinator_profile (the conventions the coordinator reasons with). The
platform coordinator service is generic — per-team behaviour lives in this
profile.
6. The per-repo convention layer (in the team's repo)
The platform is generic; convention lives in two places — the per-initiative
coordinator_profile (step 5) and the team's repo:
.mcp.json—PT_BASE_URL,WIKI_BASE_URL,PT_AUTH_TOKEN.- The
consult-the-kbskill — so agents query the KB before implementing and cite what they used. .claude/agents/pt-coordinator.md— copied in, with their initiative ID.
7. Seed the KB (recommended)
A fresh KB is empty. Seed the team's durable canonical knowledge (their
constitution / ADRs / conventions) via ingest_source (human-approved, with
approvedBy), in curated waves — not a raw dump. ADRs and locked decisions
are the best seed material; volatile documents create curation churn. See the
knowledge-base concept page
for what makes a good ingestion candidate.
Verify it works
- Read path: a live consult on the team's initiative returns citations referencing seeded KB pages.
- File-back loop: a successful UNCLASSIFIED consult files back a
synthesis-consult-*page (andevents.deliveriesgrows — proving the dispatcher delivers). - Index health: the space
indexis a small hub-and-spoke, under the coordinator reader cap. - Isolation: a token for this tenant cannot see another tenant's KB (the RLS check from the prerequisite, now proven end to end).
Keep it healthy (curation cadence)
- Daily mechanical lint — automated cron: orphan / broken-crossref / provenance-drift.
- Per-release LLM judgement pass + nomination-queue processing: stale-claim / contradiction findings + ingesting newly-nominated pages.
- See Wiki lint & curation and the
wiki-curatorsubagent.
What is not shared across tenants (yet)
Each tenant's KB is fully isolated. Common knowledge — a shared constitution, platform ADRs, cross-team conventions — is duplicated per tenant today; there is no shared/federated KB. A cross-tenant / platform shared KB is a future enhancement, not a current capability.
Deployment models
| Model | Trade-off |
|---|---|
| (a) Additional tenant, shared instance | Fastest. The team is a tenant with its own KB. Works today — modulo the RLS prerequisite above. |
| (b) Separate Constellation deployment | Heavier, full infra isolation. SaaS / Dedicated-Cloud / On-Prem tiers; each deployment gets its own KB. See Deployment. |