Skip to main content

ADR-0175: Navin Enterprise RAG Agent, a RAG application on top of the Control Plane, deployed by the Navin Manager

  • Status: accepted on 2026-11-03 with the recommended options, applied because the customer did not answer in time and to be confirmed by them (see "Decision on the points to validate")
  • Date: 2026-11-03
  • Scope: new project navin-enterprise-rag/ (FastAPI backend, workers, Next.js 16 frontend, Navin integration), additive extensions of the Control Plane (services/control-plane, domains knowledge, memory, agents, applications), OpenFGA model (deploy/policies/openfga/model.fga), Enterprise portal (activation journey), Navin Manager service descriptor prepared but not published
  • Related documents: ADR-0101 (licence policy), ADR-0103 (vLLM and LiteLLM), ADR-0108 (Opik), ADR-0166 (declared high availability, ClamAV and YARA-X scanning), ADR-0171 (hardened installation), ADR-0173 (separation of the Manager and Enterprise), ADR-0174 (Mem0 and Cognee memory, Navin Memory Provider contract), audit navin-enterprise-rag/docs/en/NAVIN_INTEGRATION_AUDIT.md

Context​

The customer asks for an enterprise RAG application a group can activate from Navin: streaming chatbot, document library, graph memory (Cognee), governed tools, administration, real metrics and branding (name, logo, sidebar colour and navbar colour).

The audit of 2026-11-03 shows that the platform already provides most of the engine, under governance:

  • Control Plane RAG (eai/domains/knowledge): knowledge bases, documents with ACL and classification, embeddings through the Model Gateway, vectors in Qdrant (one collection per tenant and embedding space) or in PostgreSQL, ACL and clearance applied inside the engine, hybrid re-scoring, reranking through the gateway, screening of the retrieved chunks (injection, poisoning, quarantine), reindex by generation without mixing spaces.
  • Memory Manager (brick E) and Navin Memory Provider contract (ADR-0174), providers builtin, mem0, cognee and hybrid, being implemented.
  • Agent runtime: sessions, runs with budget, approvals, resume, steps, checkpoints and SSE event stream (GET /v1/runs/{run_id}/events), SDK Agent and execution engines.
  • Governed applications registry (granted resources, bound credential, SOC kill switch), mandatory file scanning (quarantine, ClamAV, YARA-X, refusal when an engine does not answer), object storage (SeaweedFS, presigned URLs), Model Gateway in front of LiteLLM with quotas and usage events, evaluation (Ragas, Promptfoo), Opik, OpenTelemetry, hash chained audit.
  • Hierarchy tenant, organization, business unit, project; fifteen roles; OpenFGA model with knowledge_base, collection, document, agent, tool and model.

What is missing is the product layer (RAG instances and their lifecycle, conversations and citations, interface, administration, branding, activation) and several RAG capabilities: pages and sections of the chunks, document versions, real lexical search, asynchronous ingestion pipeline with checked states.

Decision​

1. Two planes, one governance​

WhoDoes what
Navin Managerinstalls and operates the RAG runtime (catalog service navin-rag-agent: API, workers, web), its dependencies, TLS, health, backups, upgrades and rollback
Control Planetenants, projects, roles, models, knowledge bases, memory, file scanning, storage, quotas, audit, policies, traces
RAG backendproduct layer: instances, conversations, messages, citations, feedback, branding, preferences, orchestration of the runs, administration; it calls the Control Plane only through the Python SDK enterprise_ai

The RAG backend never calls Qdrant, Cognee, LiteLLM, Docling, ClamAV or YARA-X directly: it goes through the Control Plane domains that already hold their adapters, controls and audit. It only owns its PostgreSQL schema and its Redis namespace.

2. No second engine​

  • Search and ingestion: Control Plane domain knowledge, extended in an additive and backward compatible way (new V*.sql migrations), for the benefit of every Navin agent: document versions, structural chunk metadata (page, section, element type, language, position), Docling artifacts in the object storage, PostgreSQL full text search, reciprocal rank fusion, filters per collection and per document, asynchronous pipeline with checked states. The knowledge bases of a RAG instance are created with vector_store = qdrant.
  • Memory: Navin Memory Provider contract (ADR-0174); the RAG never talks to Cognee directly.
  • Execution: Control Plane agent runtime. Every RAG instance is an agent of the registry and a governed application; every conversation turn is a run (eai.runs) with its steps, budget, approvals and events.
  • Models: Control Plane gateway /v1/gateway/*, in front of LiteLLM; no provider hard coded; capabilities read from the Model Registry.

3. Product data​

  • Schema rag in the catalog PostgreSQL (dedicated database, least privilege role), asynchronous SQLAlchemy 2, asyncpg and Alembic. The Control Plane keeps its V*.sql migrations.
  • The schema rag is the source of truth of the conversation content (messages, parts, citations, attachments, feedback, edit branches). It references the runtime run (run_id) and the knowledge base without duplicating their content.
  • RLS on every tenant scoped table, context set with SET LOCAL in each transaction (never kept by a pooled connection), explicit and audited cross tenant administration paths.
  • Durable jobs in PostgreSQL (FOR UPDATE SKIP LOCKED, same model as the Control Plane worker and operations) with an identity context written by the server; NATS JetStream of the catalog for event fan out when it is installed; Redis only for ephemeral state (authorized cache, rate limits, locks, cancellation, idempotency), with TTL and invalidation.

4. Frontend​

  • Dedicated Next.js 16 application (React 19.3, MUI 9.5, the versions of website/frontend), framer-motion, three and React Three Fiber for the graph view of the memory, with an equivalent accessible list view. The Enterprise portal stays on Next.js 15.
  • BFF: Next.js route handlers, OIDC Authorization Code with PKCE on a confidential client of the existing Keycloak realm, tokens kept on the server, session cookie httpOnly, Secure and SameSite=Strict, CSRF protection, refresh, logout. The browser never receives a token.
  • Markdown: react-markdown, GFM, KaTeX, code highlighting, strict sanitization, no raw HTML.
  • i18n French, English and Arabic with RTL; interface language separate from the answer language.

5. Streaming​

SSE end to end: the Model Gateway streams, the executor of a turn writes every ordered event (run.started to run.failed, with identifier, type, sequence and context) into a canonical log, the API serves it with resume through Last-Event-ID, the BFF relays it without buffering. A run does not depend on the browser connection.

6. Tenants and instances​

  • Shared model: one runtime per cluster serves several instances, isolated by RLS, OpenFGA, Qdrant collections per tenant and space, object storage prefixes per tenant and instance, Redis namespaces and the controlled mappings of Cognee.
  • Dedicated model: one named instance of the catalog service per RAG instance, with its own database, required when the separation of an engine is only logical and the customer policy forbids it (Cognee in the standard profile).
  • The tenant, project and instance context always comes from the validated identity and the Control Plane memberships, never from a browser parameter.
  • The "group" of the journey is an organization or a business unit of the Control Plane hierarchy. The nine logical roles map to the Navin roles and to new OpenFGA relations on the additive types rag_instance and conversation.

7. Activation and lifecycle​

  • States draft, validating, provisioning, starting, ready, degraded, failed, stopping, stopped, updating, deleting, deleted; idempotent transitions and traced steps (validation, resources, migrations, storage, Qdrant, memory, security, deployment, health, startup test, activation).
  • The infrastructure is delegated to the Navin Manager through the platform_manager bridge; the logical resources are created through the Control Plane APIs. Deleting an instance only touches its own resources.
  • The activation journey (group, project, name, logo, colours, services, models, quotas, check, provisioning, progress, opening of the chatbot) lives in the Enterprise portal, where groups and projects live.

8. Service template​

The Manager has no "Services Templates" catalog. The project prepares a descriptor navin-rag-agent.yaml that follows the real catalog schema and a template manifest (configuration and branding schemas, permissions, compatibility), validated by tests on a temporary copy of the catalog. Nothing is added to navin-manager/catalog/services/ before the customer validates it.

9. Security, governance and observability​

  • Mandatory controls fail closed: OpenFGA, OPA, file scanning, quotas. Presidio through the privacy domain, injection screening of documents and tool results, tool results handled as data, citations checked by the server against the retrieved and authorized chunks, secrets in OpenBao, SPIFFE workload identity when SPIRE is installed.
  • One trace per request (W3C traceparent) from the BFF to LiteLLM, AI spans to Opik through the Control Plane adapter with personal data removal, Prometheus metrics, logs to Alloy and OpenSearch, OpenFGA and OPA decisions correlated in the existing audit. No Opik and no dashboard per instance.
  • Grafana, Loki and Tempo are AGPL-3.0 and refused by ADR-0101: dashboards and logs go through the allowed catalog components (Prometheus, Alertmanager, Alloy, OpenSearch and OpenSearch Dashboards, Jaeger, Opik, ClickHouse).

10. Truth of the capabilities​

No feature is declared finished without a real test; no capacity, no SLA and no HA are announced without a measurement. The limits are written in navin-enterprise-rag/docs/KNOWN_LIMITATIONS.md.

Consequences​

  • The RAG improvements benefit every Navin agent; the product stays light and versioned separately.
  • One more hop through the Control Plane, whose latency is measured by the load tests.
  • Two migration tools in the repository: Alembic for the schema rag, V*.sql for the Control Plane.
  • The graph memory depends on the Cognee catalog service and on the Navin Memory Provider contract (ADR-0174).

Points the customer validates​

  1. Grafana, Loki and Tempo (AGPL-3.0) replaced by the allowed catalog components.
  2. Graph persistence of Cognee: standard profile of ADR-0174 (embedded LadybugDB, single instance) or a Navin PostgreSQL adapter, decided by a technical trial; Cognee vectors: pgvector (ADR-0174) or Qdrant through the community adapter with a tested Navin isolation.
  3. Activation journey in the Enterprise portal rather than in the Manager interface.
  4. Dedicated model mandatory for banks while the separation of Cognee is only logical.

Decision on the points to validate​

On 2026-11-03, without an answer of the customer in time, the recommended options are applied; the customer can challenge them at any time:

  1. Grafana, Loki and Tempo are replaced by Prometheus, Alertmanager, Alloy, OpenSearch and OpenSearch Dashboards, Jaeger, Opik and ClickHouse.
  2. The graph persistence and the vector storage of Cognee are set by the technical trial (navin-enterprise-rag/docs/en/COGNEE_TRIAL.md, finished on 2026-11-03): standard profile of ADR-0174, vectors in pgvector (Cognee access control on, one database per dataset: 0 leak in 63 searches between two tenants, complete deletion checked in every store) and graph in embedded LadybugDB, version 0.19.0 (the one Cognee 1.6.6 pins, not the 0.22.1 quoted by ADR-0174), single instance, backed up cold or after CHECKPOINT. Refused: the community Qdrant adapter 0.4.0 (it does not start with Cognee 1.6.6 and, once patched, shares its collections between tenants) and the upstream PostgreSQL graph (demonstration status). The Navin extension of the Qdrant adapter (one collection per tenant and a mandatory filter), green in the trial, is kept only if a customer imposes Qdrant for Cognee.
  3. The activation journey is built in the Enterprise portal.
  4. A dedicated installation per instance is required for banks while the separation of Cognee is only logical.

Rejected alternatives​

  • Standalone RAG backend with its own ingestion, search and model calls: duplication of the existing governance.
  • Direct LiteLLM calls: bypass of the controls, quotas and usage events of the gateway.
  • Tokens in the browser (localStorage or sessionStorage) for the new application.
  • Redis as a persistent queue.
  • Immediate publication in the Manager catalog.

Delivery plan​

Ten lots tracked on the project board: audit and architecture; backend foundations; frontend; documents and RAG; chat; Cognee memory; tools and governance; administration and metrics; Navin provisioning; final validation.