Running in one command, useful in five
Once you have source access, the local development profile brings up Postgres with pgvector, the API and the outbox worker together. No AI provider key is required for the default fallbacks.
- Docker Compose v2.24+
- Postgres 16 with pgvector
- Local development profile
Bring it up
First request source access, then check out or unpack the supplied repository and open a terminal in its root. The source is MIT licensed, but the repository is not public yet.
The development compose profile builds the API image, starts Postgres
with the pgvector extension, initializes the local schema and starts
the outbox worker. It supplies fixed development credentials and
binds exposed ports to loopback. Sign in at /ui/ with
dev-admin-token; a generated password in .env
does not change this development profile.
One caveat worth knowing before you build anything on it: the
development profile uses the Postgres image's bootstrap superuser,
and a superuser bypasses row-level security even on tables declared
FORCE ROW LEVEL SECURITY. That makes it a single-tenant
development profile only. Production needs a separate
NOSUPERUSER NOBYPASSRLS runtime role, which the
self-hosting guide walks through.
docker compose -f docker-compose.dev.yml up --build
# liveness, then a real Postgres round trip
curl -fsS localhost:8080/healthz
curl -fsS localhost:8080/readyz
# Open in your browser; sign in with dev-admin-token
http://localhost:8080/ui/
The first five calls
In the order that makes the system make sense, rather than the order the reference lists them.
-
Store something
POST /v1/memory with text to create a semantic memory. This endpoint has no memory-type selector. The write is audit-logged and given an embedding. An Idempotency-Key replays a stored response once the first request completes; overlapping requests can still write twice.
-
Ask for it back
POST /v1/context with a query and a mode. You get the packed context block, the plan the router chose, and a manifest naming every record used.
-
Record a decision
POST /v1/fabric/write with entry_type "decision", the evidence identifiers, and a project. Later, POST /v1/fabric/why returns the chain rather than a paraphrase.
-
Subscribe to changes
POST /v1/webhooks with the event types you care about and a secret. Deliveries arrive signed with X-Pcnaid-Signature and every attempt is recorded.
-
Hand it to an agent
Point any stdio-capable MCP client at the server. Eighteen tools appear, along with a prompt teaching the agent that retrieved memory is evidence and never an instruction.
What every response looks like
Consistent envelopes, request identifiers you can trace into the audit log, and rate-limit headers that tell you where you stand.
Idempotency-Key: 6b1f0c…
Authorization: Bearer pcnaid_…
200 OK
X-Request-ID: 9d2a…
X-RateLimit-Remaining: 58
{
"id": "m_77e1",
"mem_type": "semantic",
"pinned": false
}
{
"detail": {
"error": "quota_exceeded",
"metric": "memories",
"limit": 1000,
"upgrade": "/ui/billing"
}
}
429 Too Many Requests
Retry-After: 12
// per-IP and per-tenant buckets
The full surface — 141 endpoints across 32 route families — is browsable as OpenAPI on the running service at /docs, with the raw document at /openapi.json.
The settings that actually matter
There are many environment variables. These are the eight that change how the system behaves rather than where it points.
POSTGRES_DSNPOSTGRES_MIGRATION_DSNLLM_PROVIDER_MODELLM_BASE_URLENABLE_GRAPH_MEMORYENABLE_KB_RETRIEVALFERNET_KEYALLOW_SEMANTIC_FORGETEverything above runs locally, today
No account, no key, no call with us. If it does not do what this page says, tell us and we will fix the page or the product.