A production-grade Enterprise Agentic Retrieval-Augmented Generation (RAG) platform built with Embabel's Agent Framework, Spring AI, PostgreSQL (pgvector + JSONB), and Docling.
The system features multi-tenant data sandboxing, hierarchical Role-Based Access Control (RBAC), structure-aware document chunking with surrounding-context windowing, dual-write persistence, and an agentic search loop equipped with semantic vector search, exact full-text retrieval, and multimodal image citations.
flowchart TB
subgraph Client["🌐 Client & Security Layer"]
UI["Web UI / Client App"]
JWT["JWT Bearer Token"]
AUTH["JwtAuthenticationFilter<br/>UserContextHolder"]
CTRL["QueryController<br/>POST /api/query"]
end
subgraph Agent["🤖 Embabel AgentProcess (Utility Pattern)"]
TRIGGER["Event Trigger<br/>UserMessage.class"]
BIND["@Action<br/>bindUser(OperationContext)<br/>➔ EnterpriseUser"]
ACTION["@Action<br/>ChatActions.respond()"]
RBAC["Dynamic PropertyFilter<br/>tenantId + allowedRoles OR"]
end
subgraph AI["✨ Ai Interface & ToolishRag"]
TEMPLATE["Jinja Template<br/>enterprise-rag.jinja"]
TOOLS["Scoped ToolishRag<br/>.withMetadataFilter(rbacFilter)"]
LOOP{"Agentic Tool Loop<br/>vectorSearch & textSearch"}
LLM_CALL["LLM Inference<br/>Google Gemini 2.5 Flash"]
end
subgraph Storage["🗄️ PostgreSQL 16 + pgvector"]
PGV["pgvector_store Table<br/>Vector Cosine Ops (HNSW)"]
GIN["JSONB Metadata Index (GIN)<br/>tenantId & allowedRoles"]
FTS["Full-Text / Trigram Index (GIN)<br/>Lexical Keyword Match"]
end
subgraph Response["💬 Grounded Response"]
ASSIST["Assistant Message<br/>Grounded Citations + [Image: ...]"]
SEND["context.sendMessage()<br/>JSON Envelope"]
end
UI -->|"Bearer JWT"| JWT
JWT --> AUTH
AUTH --> CTRL
CTRL -->|"session.onUserMessage()"| TRIGGER
TRIGGER -->|"triggers"| BIND
BIND -->|"binds EnterpriseUser"| ACTION
ACTION --> RBAC
RBAC -->|"injects filter"| TOOLS
ACTION -->|"context.ai()"| TEMPLATE
TEMPLATE --> TOOLS
TOOLS --> LOOP
LOOP -->|"1. Vector Similarity"| PGV
LOOP -->|"2. Lexical Fallback"| FTS
PGV -.->|"enforces RBAC"| GIN
FTS -.->|"enforces RBAC"| GIN
PGV -->|"authorized chunks"| LOOP
FTS -->|"authorized chunks"| LOOP
LOOP --> LLM_CALL
LLM_CALL -->|"synthesized answer"| ASSIST
ASSIST --> SEND
SEND -->|"JSON response"| UI
style Client fill:#d4eeff,stroke:#63c0f5,color:#1e1e1e
style Agent fill:#e8dcf4,stroke:#9f77cd,color:#1e1e1e
style AI fill:#fff3cd,stroke:#e9b306,color:#1e1e1e
style Storage fill:#ffe4d6,stroke:#f58a5b,color:#1e1e1e
style Response fill:#d4f5d4,stroke:#3fd73c,color:#1e1e1e
-
Mathematical Isolation: Cross-tenant data isolation is enforced directly at the PostgreSQL JSONB index layer via
@>containment operators—preventing data leaks before chunks enter LLM memory. -
Role Hierarchy Inheritance:
-
ADMIN$\rightarrow$ Access toADMIN,ANALYST, andVIEWERdocuments. -
ANALYST$\rightarrow$ Access toANALYSTandVIEWERdocuments. -
VIEWER$\rightarrow$ Access to public/general internal documents (VIEWER).
-
-
Document Classifications: Granular tagging (
PUBLIC,INTERNAL,CONFIDENTIAL,RESTRICTED) automatically mapped to clearance roles.
- Docling Integration: Preserves structural layout (
TITLE,SECTION_HEADER,TABLE,FIGURE,CAPTION,CODE,LIST_ITEM). - Atomic Tables: Tables are indexed intact as standalone chunks—never cut across chunk boundaries.
- Multimodal Context Windowing: For architecture diagrams and figures:
- Automatically decodes and persists images to local disk.
- Scans preceding and subsequent narrative paragraphs (
findPrecedingContextandfindSubsequentContext) to enrich the figure chunk's text representation for dense vector similarity. - Embeds persistent image URLs (
[Image: /api/documents/<id>/images/<name>.png]) for inline UI visualization.
- Dual-Write Architecture:
- Write 1 (Relational Store -
document_chunks): Saved via JPA for management REST endpoints and administrative inspection. - Write 2 (Vector Store -
pgvector_store): Saved via EmbabelPgVectorStorewith HNSW vector indexing and GIN metadata indexing.
- Write 1 (Relational Store -
- Hybrid Tool Execution: Equips the LLM with
vectorSearch(dense semantic search) andtextSearch(lexical BM25/full-text search). - Self-Healing Loop: If initial semantic queries yield 0 results, the agent automatically reformulates the query, lowers similarity thresholds, or falls back to targeted keyword searches.
- Verbatim Grounded Citations: Strict prompt guidelines prevent URL hallucinations and require exact passage citations.
- Spring Security + JJWT: Stateless bearer tokens carrying tenant, roles, and user identity claims.
- ThreadLocal Safety: Claims propagate across service boundaries via
UserContextHolderwith guaranteed cleanup in filterfinallyblocks. - Observability Suite: Built-in Micrometer metrics, Actuator health checks, Prometheus scraping, OpenTelemetry log record export, and pre-built Grafana dashboards.
| Layer | Technologies |
|---|---|
| Language & Runtime | Java 21 (LTS), GraalVM / OpenJDK |
| Application Framework | Spring Boot 3.5, Spring Security, Spring AI |
| Agent Framework | Embabel Agent Platform 1.0.0 (GOAP & Utility Action Patterns), embabel-rag-pgvector |
| Database & Vector Index | PostgreSQL 16, pgvector (HNSW cosine similarity, GIN JSONB, Trigram indexes) |
| Document Parser | Docling Serve (REST API) |
| LLM & Embeddings | Google Gemini 2.5 Flash via OpenRouter / OpenAI, text-embedding-3-small |
| Authentication | JJWT (Java JWT 0.12.6) with HMAC-SHA signing |
| Migration & Build | Flyway DB Migrations, Maven 3.9+ |
| Observability | OpenTelemetry, Micrometer, Prometheus, Grafana |
- Java 21+ installed
- Docker & Docker Compose installed
- An OpenRouter API Key (or OpenAI API Key)
git clone https://github.com/itsourav/agentic-rag.git
cd agentic-ragSet your OpenRouter API key in your terminal session or export it in your shell profile:
export OPENROUTER_API_KEY="your-openrouter-api-key"Start PostgreSQL (with pgvector), pgAdmin, and Docling Serve:
docker compose up -dVerify that all containers are healthy:
docker compose ps- PostgreSQL:
localhost:5432 - Docling Serve:
localhost:5001 - pgAdmin:
localhost:80
Run database migrations and start the Spring Boot application:
./mvnw spring-boot:runThe application will start on http://localhost:8080.
The database automatically seeds 4 enterprise test accounts upon initial boot:
| Username | Password | Tenant | Role | Department | Access Level |
|---|---|---|---|---|---|
admin |
admin123 |
acme-corp |
ADMIN |
IT | Unrestricted access across acme-corp |
analyst |
analyst123 |
acme-corp |
ANALYST |
Data Science | Operational + General docs |
viewer |
viewer123 |
acme-corp |
VIEWER |
Marketing | Internal/Public docs only |
external_analyst |
external123 |
partner-inc |
ANALYST |
Research | Sandboxed exclusively to partner-inc |
Open your browser to http://localhost:8080:
- Login Page (
/login.html): Authenticate with any of the pre-seeded accounts to receive an enterprise JWT. - Document Ingestion Hub (
/index.html): Upload PDFs with custom Tenant, Classification, and Minimum Allowed Role tags. - Interactive Agentic Chat (
/chat.html): Ask questions across indexed documents. View inline diagram figures, citations, and conversation history.
POST /api/auth/login— Authenticate and retrieve JWT token:{ "username": "admin", "password": "admin123" }POST /api/auth/register— Register a new enterprise user.
POST /api/documents— Multipart document upload:- Form fields:
file,tenant,classification,allowedRoles,department.
- Form fields:
GET /api/documents— List uploaded documents for the user's tenant.GET /api/documents/{id}— Get document metadata and ingestion status.DELETE /api/documents/{id}— Delete document and associated vector chunks.GET /api/documents/{id}/images/{imageName}— Fetch extracted figure images.
POST /api/query— Query knowledge base with agentic multi-turn conversation:{ "question": "How does the AKS control plane architecture work? Show any diagrams.", "conversationId": "optional-uuid" }GET /api/query/history/{conversationId}— Retrieve conversation history.DELETE /api/query/conversation— Clear all session memory for the authenticated user.
Run all unit tests and integration tests:
./mvnw testRun test suite for Enterprise RBAC and Multi-Tenancy isolation:
./mvnw test -Dtest=EnterpriseRbacTestRun full integration suite (starts embedded Testcontainers for PostgreSQL + pgvector):
./mvnw verifyFor in-depth explanations of the internal design, step-by-step sequence diagrams, and test run outcomes, see walkthrough.md.