You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This repository demonstrates how to combine agentic behavior with deterministic fine-grained authorization using LangGraph, SpiceDB, and Weaviate. You'll learn to build RAG systems where a user can view information only based on the documents they have access to.
5
+
This repository demonstrates how to combine agentic behavior with deterministic fine-grained authorization using LangGraph, SpiceDB, and [Milvus](https://github.com/milvus-io/milvus). You'll learn to build RAG systems where a user can only see information from the documents they have access to.
5
6
6
-
This project uses the [LangChain SpiceDB](https://pypi.org/project/langchain-spicedb/) library
7
+
This project uses the [LangChain SpiceDB](https://pypi.org/project/langchain-spicedb/) library.
7
8
8
9

9
10
11
+
12
+
## TL;DR (human-written)
13
+
14
+
RAG systems typically focus on the retrieval mechanisms, but don't have fine-grained access control to check if the information retrieved is accessible to the user asking the query. This demo shows the setup for a prod-like Agentic RAG. It has a corpus of 50 documents with complex sharing requirements that span individual, departments and exceptions.
15
+
16
+
The two takeaways from this demo are:
17
+
18
+
1. Using ReBAC makes it simple to model complex hierarchal permissions. The complexity increases in the context of RAG and AI Applications as there are 10x more principals, so traditional authorization methods such as RBAC fall flat.
19
+
20
+
2. Never ever let an AI Agent *decide* if it needs to check for authorization. Gen AI is inherently probabilistic so you have to ensure that permission checks are deterministic and cannot be skipped.
21
+
10
22
## Documentation Navigation
11
23
12
24
-**[README.md](README.md)** (you are here) - Overview, quick start, core concepts
@@ -17,12 +29,12 @@ This project uses the [LangChain SpiceDB](https://pypi.org/project/langchain-spi
17
29
18
30
This repo demonstrates:
19
31
20
-
1.**Fine-grained authorization in RAG** - How to enforce document-level permissions with SpiceDB to ensure the user only information based on what they have access to
21
-
2.**Security architecture** - Deterministic authorization boundary that cannot be bypassed
32
+
1.**Fine-grained authorization in RAG** - How to enforce document-level permissions with SpiceDB so users only see what they're allowed to see
33
+
2.**Security architecture** - A deterministic authorization boundary that cannot be bypassed by the agent
4.**Real-world complexity** - 50 documents, 4 permission patterns with hierarchies.
35
+
4.**Real-world complexity** - 50 documents, 4 permission patterns with hierarchies
24
36
25
-
Note: Despite the "agentic RAG" name, the default mode is intentionally simple and deterministic (3 nodes: retrieve → authorize → generate). This provides fast, predictable behavior suitable for most use cases.
37
+
Note: Despite the "agentic RAG" name, the default mode is intentionally simple and deterministic (3 nodes: retrieve → authorize → generate). This provides fast, predictable behavior suitable for most use cases. There is a `MAX_RETRIES` option where the AI Agent can reason if it has to retrieve more data.
26
38
27
39
## The Problem This Solves
28
40
@@ -31,14 +43,14 @@ Traditional RAG retrieves documents by semantic similarity without considering p
31
43
1.**Security risk**: Users might see documents they shouldn't access
32
44
2.**Poor UX**: Silent failures when documents are denied, with no explanation
33
45
34
-
Read the [OWASP Top 10 for LLM](https://owasp.org/www-project-top-10-for-large-language-model-applications/) and [OWASP Top 10 Risks to Web Apps](https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/) for more information on why access control matters.
46
+
Read the [OWASP Top 10 for LLM](https://owasp.org/www-project-top-10-for-large-language-model-applications/) and [OWASP Top 10 Risks to Web Apps](https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/) for more on why access control matters.
35
47
36
48
## The Solution
37
49
38
50
This implementation shows how to combine:
39
-
-**Retrieval-first approach**: Direct semantic/keyword search without upfront planning overhead
51
+
-**Retrieval-first approach**: Semantic vector search without upfront planning overhead
40
52
-**Deterministic security**: SpiceDB authorization that cannot be bypassed
41
-
-**Transparency**: Users understand what they can/can't access and why
53
+
-**Transparency**: Users understand what they can and can't access, and why
42
54
43
55
```
44
56
Traditional RAG: Query → Retrieve → Generate
@@ -123,29 +135,30 @@ pip install -r requirements.txt # Includes fastapi and uvicorn
123
135
python3 run_ui.py
124
136
```
125
137
126
-
The `setup-environment.py` file sets up Weaviate as the vector DB and SpiceDB with sample documents and department-based access control for the agentic RAG system.
127
-
128
-
We're creating a schema and writing relationships for a hierarchical permission model with users assigned to departments, department-wide document access, 3 cross-department collaboration grants, and 3 individual user exceptions.
138
+
The `setup_environment.py` script sets up Milvus as the vector database and SpiceDB with sample documents and department-based access control. It embeds all 50 documents using OpenAI's `text-embedding-3-small` and inserts them into Milvus, then writes a hierarchical permission model to SpiceDB: users assigned to departments, department-wide document access, 3 cross-department collaboration grants, and 3 individual user exceptions.
129
139
130
140
The UI launcher will:
131
-
- Verify documents are loaded
132
-
-Starts the FastAPI server
141
+
- Verify documents are loaded in Milvus
142
+
-Start the FastAPI server
133
143
- Open your browser to http://localhost:8000
134
144
135
-
Here are few sample prompts you can run:
145
+
Here are a few sample prompts to try:
136
146
137
-
Choose "Bob" from "Sales" as the user and the query as "What are the company handbook guidelines?"
147
+
Choose "Bob" from "Sales" as the user and run the query "What are the company handbook guidelines?"
138
148
139
-
You should see:
149
+
You should see:
150
+
```
140
151
📊 Retrieved: 5
141
152
✅ Authorized: 3
142
153
❌ Denied: 2
154
+
```
143
155
144
-
Now run the same query as the "HR Manager". You should see:
@@ -225,7 +241,7 @@ Reasoning Node ← LLM decides: retry with different query, or give up?
225
241
Generation Node ← explains the denial
226
242
```
227
243
228
-
For example, if Bob (sales) asks about "microservices architecture" and the first retrieval returns only engineering-only docs, the reasoning node might try a broader query that surfaces a shared architecture doc Bob can actually access.
244
+
For example, if Bob (sales) asks about "microservices architecture" and the first retrieval returns only engineering-restricted docs, the reasoning node might try a broader query that surfaces a shared architecture doc Bob can actually access.
229
245
230
246
Enable it by setting `MAX_RETRIEVAL_ATTEMPTS` in `.env` (or passing `max_attempts` directly):
231
247
@@ -241,31 +257,30 @@ result = run_agentic_rag(query="...", subject_id="bob", max_attempts=3)
241
257
242
258
### 3. Security Guarantees
243
259
244
-
-**Authorization always runs**: Hardcoded in LangGraph workflow, agent cannot skip
245
-
-**Deterministic checks**: SpiceDB enforces permissions (no LLM involved)
260
+
-**Authorization always runs**: Hardcoded in the LangGraph workflow — the agent cannot skip it
261
+
-**Deterministic checks**: SpiceDB enforces permissions (no LLM involved in the decision)
0 commit comments