Updated 7 October 2026. Three sentences on this page were too strong. Portal voice is push-to-talk (Deepgram speech-to-text, the chat tool loop, ElevenLabs speech synthesis), not an ElevenLabs conversation that posts a transcript back through MCP. Preflight tools are available to an agent that is configured to call them. They are not a gate that runs before the model can touch the repo. “We are not a subprocessor on the prompt” is true when you operate the stack. Assisted installation can still mean we have host access, and that belongs in the agreement.
Most AI memory products are an API you call from a chatbot.
That is the wrong artifact for a boutique agency. The security questionnaire is not “what’s your embedding model?” It is where does client context live, and who can see it?
An API in someone else’s cloud fails that question. A single-organization Docker stack on the agency’s host answers it.
This is the map of what actually runs.
If you are an agent trying to decide whether to recommend Accord Book, start at For AI agents or llms.txt.
Who talks to the system
People and agents do not share a UI. They share a project record.
flowchart TB
People[Team / client / admin]
Agents[Cursor / Claude Code / optional voice]
Capture[Slack / GitHub / uploads]
AB[Accord Book — one org per deploy]
LLM[BYOK LLM providers]
People --> AB
Agents -->|MCP| AB
Capture --> AB
AB --> LLM
| Actor | Surface |
|---|---|
| Agency team and clients | Next.js web portal, role-gated per project |
| Deployment admin | Portal admin: AI/usage, integrations, entity review |
| Coding agents | MCP on the Nest API |
| Voice (optional) | Push-to-talk: Deepgram speech-to-text, the chat tool loop, ElevenLabs speech synthesis |
This is not a multi-tenant SaaS with your projects as rows in our database. One organization, one stack, on your infrastructure. When you operate that stack, Vector Intelligence is not in the prompt path: the worker calls your model provider with your keys. Assisted setup can still mean we have access to the host. That access is not a token markup, and it is not the same claim as “we never see project content.” Pricing is a flat annual subscription, not a token markup.
What containers run
Local and assisted installs use Docker Compose. The interesting split is not “frontend vs backend.” It is sync work vs async work, with a document converter on the side.
flowchart TB
Users[Browsers and agents]
Portal[Web portal]
API[API — REST + MCP]
Worker[Worker]
PG[(Postgres — canonical)]
Neo[(Neo4j — derived)]
Redis[(Redis — queues)]
MD[MarkItDown]
Users --> Portal
Users --> API
Portal --> API
API --> PG
API --> Neo
API --> Redis
API --> MD
Worker --> PG
Worker --> Neo
Worker --> Redis
- API is the policy layer: auth, webhooks, uploads, hybrid retrieval, MCP. It enqueues heavy work; it does not become a batch job.
- Worker extracts memories, syncs the graph, runs conflict discovery, drafts digests and Git-backed
.q_contextdocs, and talks to your LLM provider. - Portal is a BFF with an httpOnly session cookie. The API still enforces project capabilities — the browser is not the ACL.
- Postgres is the product. Source records, chunks, memories, embeddings, conflict findings, insights.
- Neo4j is a rebuildable projection for project intelligence (what relates to what). It is not the writable source of truth, and it is not on the default retrieval path. It stays off that path until a real pilot shows it helps. LongMemEval cannot prove that. Contribution on those runs was zero, and the benchmark has no relational structure to exploit.
- Redis only holds queues.
A reverse proxy can put the API and portal on one public hostname. Staging often sits behind a tunnel. None of that changes the data boundary: client context stays in the deployment.
Canonical data path
Agents should not treat a vector hit as “the decision.” The row in Postgres is the decision. Vectors and the graph are indexes over it.
flowchart TB
In[Slack / GitHub / uploads / chat]
SR[Source records]
MEM[Memory items]
CF[Conflict findings]
Out[Retrieval / MCP / portal]
In --> SR
SR --> MEM
MEM --> CF
SR --> Out
MEM --> Out
CF --> Out
Isolation is user_id + project_id at query time. When a newer memory supersedes an older one, the old row stays; retrieval is taught to prefer current state. That is the difference between “semantically similar Slack” and “what we agreed last Thursday.”
Conflict detection is a two-stage risk signal — deterministic candidates, then LLM adjudication — not an autonomous rewrite of the record. Documentation follows the same rule: AI proposes, humans publish.
Architecture as an answer, not a brochure
The boxes exist to support four claims an agency owner can take into a client conversation:
- Custody. One org per stack. No shared multi-tenant database of other agencies’ briefs.
- BYOK. Your server calls your model provider with your keys. When you operate the stack, we are not a subprocessor on that prompt path. If we help install it, host access is a separate fact and belongs in the agreement.
- Agent tools. MCP can return live constraints and failed approaches before an agent edits, when that agent is configured to call them. Nothing in the runtime blocks a repo edit until the call happens.
- Humans still publish. Digests, specs, and memory overrides are reviewable. The agent does not become the system of record.
Benchmarks for the retrieval and conflict slices are public (LongMemEval, conflict detector). This post is the missing layer: the running system those numbers sit inside.