Install & infrastructure
Set up the desktop host.
For: operators and developers setting up a machine
This is the Layer 1 install — the local half of Cardinal that runs on the operator's laptop. It is engagement-neutral: the same desktop setup serves any engagement. By the end you will have the AI host, the agent corpus, the local message bus, and your credentials in place — ready to point at an engagement (Layer 2 / 3) and spawn the ring (bootstrap).
The simple path
Don't want to run every step by hand? Install Scout — a desktop app that runs AI models locally and can drive your machine — open a session on the computer you're setting up, and give it the prompt below. Scout works through the whole Layer 1 install, pausing only for the interactive sign-ins, and reports back when the smoke tests are green.
Paste this to Scout:
You are setting up the Cardinal desktop host — the "Layer 1" local environment — on this Windows machine. Work through these steps in order, pause to let me complete any interactive sign-in, and finish with a short pass/fail summary. Never write a secret into a file that could be synced or committed. 1. Prerequisites — check for, and help me install if missing: Python 3, PostgreSQL 13+ (listening on localhost:5432), the Azure CLI, and the GitHub CLI. Confirm each is on PATH. 2. Corpus — restore the agent corpus to ~/.copilot using the corpus-sync skill in "pull" mode against the engagement's Azure Blob mirror, then show me a status diff so I can confirm it is complete. 3. Local message bus — create the local Postgres database and schema that back the inter-agent message bus (the scout-bus skill's one-time setup). 4. Authenticate, in this exact order, pausing for me at each interactive prompt: (1) Azure CLI, (2) GitHub CLI, (3) Microsoft 365, (4) the MCP servers, (5) the database access bridge (DAB). Each step depends on the one before it. 5. Smoke tests — run the read-only smoke tests and confirm all pass: cloud identity resolves, each MCP server responds, DAB can read, the corpus is present, and the message bus accepts a registration. 6. Report — tell me what passed and what failed. If anything failed, stop, name the single next action, and do not spawn any agents on a broken substrate. When everything is green, tell me I'm ready to provision Azure (only if I'm not using a shared environment) and then to bootstrap the ring.
Prefer to understand or troubleshoot each step yourself? The full manual walkthrough is below.
What you're building
The desktop host holds four things: the AI host and its long-lived agent sessions, the corpus (skills, role briefs, workflows, engagement packs), a small local Postgres backing the inter-agent message bus, and a set of MCP servers that connect the agents to the database and other systems. None of it carries customer data at rest beyond what the agents are actively working on.
flowchart TB
subgraph laptop ["💻 YOUR LAPTOP — Layer 1"]
direction TB
subgraph runtime ["🚀 Runtime"]
direction LR
HOST["🤖 AI host
long-lived sessions"]:::local
MCP["🔌 MCP servers
DAB · ADO · …"]:::local
end
subgraph data ["📂 On-disk"]
direction LR
CORPUS["📚 Corpus
~/.copilot"]:::local
BUS[("🗄️ Local Postgres
message bus")]:::local
end
CACHE["🔐 Encrypted credential cache
secrets · keys · tokens"]:::secure
end
AZURE(["☁️ Shared Azure substrate
Layer 2"]):::azure
HOST <--> MCP
HOST <--> CORPUS
HOST <--> BUS
MCP --> CACHE
MCP == managed identity · keyless ==> AZURE
CORPUS <== corpus-sync ==> AZURE
style laptop fill:#fdf5f7,stroke:#b11f4b,stroke-width:2px,color:#7a1132
style runtime fill:#fcfbf8,stroke:#b1b1b1,stroke-dasharray:3 3
style data fill:#fcfbf8,stroke:#b1b1b1,stroke-dasharray:3 3
classDef local fill:#fce4ec,stroke:#b11f4b,stroke-width:2px,color:#7a1132
classDef secure fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#78350f
classDef azure fill:#dbeafe,stroke:#0078d4,stroke-width:2.5px,color:#003966
1 · Prerequisites
Software
- A desktop AI host (the application the agents run inside)
- A code editor and a terminal (PowerShell)
- Python 3 (for the message-bus helper scripts)
- A local PostgreSQL 13+ instance listening on localhost
- The Azure CLI and GitHub CLI for authentication
Access
- An operator identity in the engagement's tenant
- Permission to read the corpus storage account (Layer 2)
- Permission to reach the shared Key Vault and database
- Membership of the engagement's allow-list (for the web app, later)
~/.copilot. Everything Cardinal's desktop side needs — skills, role briefs,
workflows, engagement packs, and configuration — lives beneath it.
2 · Restore the corpus
The corpus is the agents' operating manual: their skills, their role briefs, the workflow definitions, and the per-engagement packs. It is mirrored to Azure Blob storage so a fresh machine can be brought up — or recovered — by pulling it down.
What's in the corpus
- Skills — the Markdown capabilities the agents run
- Role briefs — each agent's mission, mode, reads/writes, limits
- Workflows — which roles a workflow spawns, and how
- Engagement packs — the per-engagement configuration overlay
- MCP server registry — how the agents reach the database and other systems
Sync modes
The corpus-sync skill is two-way against the Blob mirror:
pull— bring the latest corpus down (first-run + recovery)push— publish local changes upstatus— show the local-vs-remote diffrestore— point-in-time restore from a previous version
Conflicts use ETag / If-Match semantics; the operator resolves unresolvable diffs explicitly. Blob versioning + a 14-day soft-delete window give point-in-time restore.
3 · Start the local message bus
Agents never message each other directly — they talk over a local, Postgres-backed message bus. Each agent session registers itself, runs a small listener that wakes it when a message arrives, and drains its inbox on each wake. The bus is a local database; it holds no customer data.
What it provides
- Addressable sessions (by identity, handle, or role)
- Wake-on-message, so a sleeping agent responds without a human
- An audit trail of who sent what to whom
One-time setup
- Create the bus database + schema in your local Postgres
- Each agent session registers on first run
- Each session spawns its listener and ends its turn; the host wakes it on inbound
4 · Authenticate — in order
Authentication has a canonical order, because each step depends on the one before it. Do them in sequence; the interactive sign-ins are the slow part (budget ~30 minutes the first time).
| # | Sign in to… | Why it's in this order |
|---|---|---|
| 1 | Azure CLI | Establishes your cloud identity; everything downstream borrows from it. |
| 2 | GitHub CLI | Repo access for code and corpus operations. |
| 3 | Microsoft 365 | Mail / calendar / chat access for the scouts and comms. |
| 4 | MCP servers | Each tool server authenticates using the identities established above. |
| 5 | Database access bridge (DAB) | Comes last — it depends on the cloud identity and the MCP layer being live. |
5 · Run the smoke tests
Before spawning any agents, confirm the plumbing. The smoke tests are lightweight, read-only probes — each one an unambiguous pass/fail in a few seconds — that verify every authentication step took.
What they check
- The cloud identity resolves
- Each MCP server responds
- The database access bridge can read
- The corpus is present and complete
- The local message bus accepts a registration
Run via the smoke-tests skill, covered in bootstrap.
If one fails
- Stop — don't spawn agents on a broken substrate
- Re-run the failing auth step (usually an expired interactive sign-in)
- Re-run the smoke tests until all pass
- Only then proceed to bootstrap