One container.
One database.
Two pipelines.
System design, schema, API surface, and the decisions behind each constraint. Runs locally against any Postgres 14+.
Runtime, in three boxes.
A single borg-engine process talks MCP and REST on :8080. It reads from and writes to one Postgres, and calls out to OpenAI or Azure OpenAI only for extraction and embeddings.
borg-engine
- FastAPI + FastMCP 3
- MCP endpoint /mcp
- REST /api/{think,learn,recall,forget,guard,…}
- Background extraction worker
- 24 h snapshot loop
PostgreSQL 14+
- pgvector, pgAudit, pg_trgm, uuid-ossp
- borg_* tables — 15 + 1 fn
- Managed · self-hosted · local
- Recursive CTE traversal · GIN full-text index
OpenAI · Azure OpenAI
- text-embedding-3-small — 1 536-dim
- gpt-5-mini / gpt-4o-mini
- BYO key. Off-loaded async — never blocks
borg_think
Fifteen tables.
One function.
Every table cleanly separates canonical data from derived serving state. Hot-path denormalization lives in *_state, the source of truth in the parent table.
borg_traverse() — recursive CTE function
Used by the graph_neighborhood retrieval strategy. 1–2 hop traversal, cycle-safe via path tracking, scoped to a single namespace.
-- 1-2 hop graph walk, cycle-safe, ns-scoped SELECT * FROM borg_traverse( p_entity_id := 'a1b2c3…', p_max_hops := 2, p_namespace := 'product-engineering' ); -- returns: entity_id, entity_name, entity_type, -- fact_id, predicate, evidence_status, -- hop_depth, path
Seven MCP tools.
REST mirror. Admin.
Enterprise deployment runs with Entra JWT auth and RBAC. Core MCP operations are also exposed through authenticated REST, with additional namespace and administrative endpoints.
| POST | /mcp |
| POST | /api/think |
| POST | /api/learn |
| POST | /api/recall |
| GET | /api/episodes/{episode_id} |
| POST | /api/forget |
| POST | /api/guard |
| GET | /api/admin/namespaces/{namespace}/summary |
| GET | /api/namespaces |
| GET | /api/namespaces/:ns |
| POST | /api/namespaces |
| PUT | /api/namespaces/:ns |
| DEL | /api/namespaces/:ns |
| GET | /api/admin/queue |
| GET | /api/admin/entities |
| GET | /api/admin/facts |
| GET | /api/admin/procedures |
| GET | /api/admin/conflicts |
| GET | /api/admin/predicates |
| POST | /api/admin/process-episode |
| POST | /api/admin/requeue-failed |
| POST | /api/admin/snapshot |
| GET | /api/admin/audit |
| GET | /api/admin/episodes |
| GET | /api/admin/cost-summary |
The constraints
are intentional.
Every choice below has a failure mode it prevents and a cost it accepts. If you disagree, file an issue.
borg_think. The alternative (embed-only) gives you similarity search but not a queryable graph.model parameter.