Agentic GraphRAG is a modular, schema-driven system for building knowledge graphs from unstructured and structured data, retrieving evidence across graph and vector indexes, and answering questions with agentic reasoning.
2
stars
13
commits
Python
primary language
Sep 8, 2026
updated
Agentic GraphRAG is a modular, schema-driven system for building knowledge graphs from unstructured and structured data, retrieving evidence across graph and vector indexes, and answering questions with agentic reasoning.
The system is built using:
Agentic GraphRAG stores source material, extracted knowledge, and graph summaries in one typed property graph:
(:Document)<-[:PART_OF]-(:Chunk)-[:MENTIONS]->(:Entity:<Type>)
(:Chunk)-[:NEXT_CHUNK]->(:Chunk)
(:Entity)-[:<RELATION_TYPE>]->(:Entity)
(:Entity)-[:IN_COMMUNITY]->(:Community)
(:Community)-[:PARENT_COMMUNITY]->(:Community)
(:Community)-[:HAS_REPORT]->(:CommunityReport)
Documents keep their source URI, format, loader, content hash, and record identity. Text formats use content-based identities; binary Docling formats use raw-byte hashes. Chunks keep stable document links and source provenance:
Extraction produces mentions first, not graph nodes. Each mention keeps its source chunk, label, text span, confidence, and extractor provenance. Resolution then assigns canonical identities and merges aliases before storage.
Relations are directed subject–predicate–object triples. The active schema constrains valid source type, relation type, and target type combinations, so invalid triples are removed before they reach the graph.
Hierarchical community detection groups related entities and relations into nested topics. Each community can receive an LLM-generated report with a title, summary, findings, and importance score. Community reports provide broad context without forcing retrieval to return every low-level edge.
GraphSchema is a first-class runtime value. It defines:
(source, relation, target) patterns;Use the generic preset for open-domain data or provide a schema for a specific domain. The same schema guides extraction, validation, resolution, storage, and query generation.
Agentic GraphRAG has two main data flows:
Ingestion: source -> document -> chunk -> mentions -> resolved graph -> indexes
Query: question -> plan -> parallel retrieval -> verify -> cited answer
Graph.add() is the single entry point for adding content. The complete pipeline is organized into these stages:
RAISE, SKIP, or QUARANTINE per-source error handling.The extraction cascade replaces a weak local result with the LLM result instead of combining two conflicting outputs. Exact matches use global store-backed lookup; more expensive fuzzy and LLM comparisons are blocked to a smaller candidate set.
Graph.consolidate() provides a separate whole-graph reconciliation pass for duplicates found across ingestion runs. It is dry-run by default so applications can inspect proposed merges before applying them.
The async Embedder, GraphStore, and VectorStore interfaces keep model and database choices outside graph-construction logic.
The Neo4j backend supports local Neo4j and Aura over Bolt, managed read/write transactions, node and relation upserts, constraints, indexes, and native dense vector search. Dynamic labels and relation types are validated before Cypher interpolation.
| Backend | Dense search | Hybrid search | Deployment |
|---|---|---|---|
| Neo4j | Yes | No | Local or Aura |
| Qdrant | Yes | Dense + sparse fusion | Local or Cloud |
| Weaviate | Yes | Native BM25/vector weighting | Custom or Cloud |
| Milvus / Zilliz | Yes | Dense + BM25 fusion | Local or Cloud |
All dedicated vector stores share collection lifecycle, batch upsert, retrieval, scrolling, counting, deletion, filtering, dense search, and hybrid search. Filters use exact scalar matches, OR within a list value, and AND across keys.
Retrieval composes small search methods into retrievers, runs them concurrently, and fuses their results through data-only recipes.
| Recipe | Search methods | Fusion |
|---|---|---|
entity, relation, chunk, community | One focused retriever | Reciprocal Rank Fusion |
hybrid_rrf | Entity + relation + chunk + community | Reciprocal Rank Fusion |
hybrid_cross_encoder | All semantic retrievers + graph expansion | Cross-encoder |
bfs_expand | Entity seeds + bounded graph traversal | Reciprocal Rank Fusion |
text2cypher | Schema-aware Cypher | Reciprocal Rank Fusion |
Reciprocal Rank Fusion, cross-encoder, maximal marginal relevance, and graph-distance rerankers cover different query needs. A recipe can ignore an empty search branch and still return evidence from the remaining methods.
The agent coordinates three roles around the retrieval layer:
If the evidence gate fails, the missing items seed another research round. When the gate passes, or the iteration limit is reached, the orchestrator produces a structured answer with citations, confidence, caveats, and an answerability flag.
BAML defines typed extraction, entity-comparison, community-summary, planning, verification, and answer contracts. Runtime client registries support a single provider, fallback chains, or round-robin routing across OpenAI, Anthropic, AWS Bedrock, Google AI, Vertex AI, Azure OpenAI, and OpenAI-compatible endpoints.
OpenTelemetry API support is part of the core package; exporters and the SDK are optional. Applications can send traces to any OTLP-compatible backend.
Long-running graph builds report bounded, structured stage statistics for ingestion, extraction, resolution, merging, and storage. Failures include the affected item, error type, message, and trace/span IDs. Full detail remains in the trace backend so result objects stay bounded on large corpora.
Agentic GraphRAG requires Python 3.11 or newer.
uv pip install agentic-graphrag
Install only the integrations you use:
# Rich documents and local extraction
uv pip install "agentic-graphrag[docling,extract]"
# LLM extraction and local dense embeddings
uv pip install "agentic-graphrag[llm,embed-local]"
# Neo4j with a dedicated Qdrant vector store and OTLP tracing
uv pip install "agentic-graphrag[neo4j,qdrant,observability]"
| Extra | Adds |
|---|---|
docling | PDF, DOCX, PPTX, image, XML, and layout-aware parsing |
extract | Local GLiNER 2.5 extraction |
llm | BAML-powered extraction and verification |
embed-local | Sentence Transformers dense embeddings |
neo4j | Neo4j graph storage and native vector search |
qdrant | Qdrant dense and hybrid search |
weaviate | Weaviate dense and hybrid search |
milvus | Milvus/Zilliz dense and hybrid search |
observability | OpenTelemetry SDK and OTLP export |
import asyncio
from agrag.ingestion import Graph
async def main() -> None:
graph = await Graph.open()
files = await graph.add(source="./corpus/**/*.md")
text = await graph.add(text="Agentic GraphRAG turns evidence into a graph.")
print(files.documents, len(files.chunks))
print(text.documents, len(text.chunks))
asyncio.run(main())
Graph.add() accepts exactly one of:
source= — a file, directory, glob, or list of paths;text= — raw text as one document;documents= — prebuilt Document objects.from agrag.loaders.corpus.types import ErrorPolicy
result = await graph.add(
source="./corpus",
error_policy=ErrorPolicy.QUARANTINE,
)
for uri, reason in result.quarantined_items:
print(uri, reason)
See the documentation for guides and the generated API reference.
| Format | Extension(s) | Loader |
|---|---|---|
| Plain text and logs | .txt, .log | Core |
| Markdown | .md, .markdown | Core |
| AsciiDoc | .adoc, .asciidoc | Docling, with core fallback |
| HTML | .html, .htm | Core |
| CSV / TSV | .csv, .tsv | Core, one document per row |
| JSON | .json | Core, record-aware |
| JSON Lines | .jsonl, .ndjson | Core, one document per row |
.pdf | Docling | |
| Word | .docx | Docling |
| PowerPoint | .pptx | Docling |
| Images | .png, .jpg, .jpeg, .tif, .tiff, .bmp | Docling |
| XML | .xml | Docling or the core XML reader |
Core loaders remain the default for Markdown, HTML, CSV, TSV, and JSON records. Docling takes precedence for layout-rich documents and AsciiDoc when installed.
agrag/
├── common/data_models/ # documents, chunks, schemas, extraction and storage records
├── chunking/ # Chonkie and Docling chunk adapters
├── loaders/ # core corpus readers and optional Docling loader
├── ingestion/ # Graph API, extraction, resolution, merge and pipeline stages
├── embedding/ # dense and sparse embedding interfaces
├── graphdb/ # graph-store interface and Neo4j backend
├── vectordb/ # vector-store interface and Qdrant/Weaviate/Milvus backends
├── cypher/ # validated Cypher builders
├── retrieval/ # search methods, retrievers, recipes and rerankers
├── agents/ # planner, researcher, verifier and answer synthesis
├── communities/ # hierarchical detection and report generation
├── llm/ # BAML sources, generated client and provider routing
└── observability.py # OpenTelemetry helpers
tests/
├── unit/ # isolated tests with external services mocked
└── integration/ # live backend tests against Docker services
git clone https://github.com/ontogr/agentic-graphrag.git
cd agentic-graphrag
make sync
make lint-check
make lint-typing
make test
Integration tests run against local Neo4j, Qdrant, Weaviate, and Milvus services:
make dev-services-up
make test-integration
make dev-services-down
See CONTRIBUTING.md for the development workflow, test conventions, and pull request guidelines.
This project is licensed under the Apache License 2.0.
Python
99.4%
Agentic GraphRAG is a modular, schema-driven system for building knowledge graphs from unstructured and structured data, retrieving evidence across graph and vector indexes, and answering questions with agentic reasoning.
2
stars
13
commits
Python
primary language
Sep 8, 2026
updated
Agentic GraphRAG is a modular, schema-driven system for building knowledge graphs from unstructured and structured data, retrieving evidence across graph and vector indexes, and answering questions with agentic reasoning.
The system is built using:
Agentic GraphRAG stores source material, extracted knowledge, and graph summaries in one typed property graph:
(:Document)<-[:PART_OF]-(:Chunk)-[:MENTIONS]->(:Entity:<Type>)
(:Chunk)-[:NEXT_CHUNK]->(:Chunk)
(:Entity)-[:<RELATION_TYPE>]->(:Entity)
(:Entity)-[:IN_COMMUNITY]->(:Community)
(:Community)-[:PARENT_COMMUNITY]->(:Community)
(:Community)-[:HAS_REPORT]->(:CommunityReport)
Documents keep their source URI, format, loader, content hash, and record identity. Text formats use content-based identities; binary Docling formats use raw-byte hashes. Chunks keep stable document links and source provenance:
Extraction produces mentions first, not graph nodes. Each mention keeps its source chunk, label, text span, confidence, and extractor provenance. Resolution then assigns canonical identities and merges aliases before storage.
Relations are directed subject–predicate–object triples. The active schema constrains valid source type, relation type, and target type combinations, so invalid triples are removed before they reach the graph.
Hierarchical community detection groups related entities and relations into nested topics. Each community can receive an LLM-generated report with a title, summary, findings, and importance score. Community reports provide broad context without forcing retrieval to return every low-level edge.
GraphSchema is a first-class runtime value. It defines:
(source, relation, target) patterns;Use the generic preset for open-domain data or provide a schema for a specific domain. The same schema guides extraction, validation, resolution, storage, and query generation.
Agentic GraphRAG has two main data flows:
Ingestion: source -> document -> chunk -> mentions -> resolved graph -> indexes
Query: question -> plan -> parallel retrieval -> verify -> cited answer
Graph.add() is the single entry point for adding content. The complete pipeline is organized into these stages:
RAISE, SKIP, or QUARANTINE per-source error handling.The extraction cascade replaces a weak local result with the LLM result instead of combining two conflicting outputs. Exact matches use global store-backed lookup; more expensive fuzzy and LLM comparisons are blocked to a smaller candidate set.
Graph.consolidate() provides a separate whole-graph reconciliation pass for duplicates found across ingestion runs. It is dry-run by default so applications can inspect proposed merges before applying them.
The async Embedder, GraphStore, and VectorStore interfaces keep model and database choices outside graph-construction logic.
The Neo4j backend supports local Neo4j and Aura over Bolt, managed read/write transactions, node and relation upserts, constraints, indexes, and native dense vector search. Dynamic labels and relation types are validated before Cypher interpolation.
| Backend | Dense search | Hybrid search | Deployment |
|---|---|---|---|
| Neo4j | Yes | No | Local or Aura |
| Qdrant | Yes | Dense + sparse fusion | Local or Cloud |
| Weaviate | Yes | Native BM25/vector weighting | Custom or Cloud |
| Milvus / Zilliz | Yes | Dense + BM25 fusion | Local or Cloud |
All dedicated vector stores share collection lifecycle, batch upsert, retrieval, scrolling, counting, deletion, filtering, dense search, and hybrid search. Filters use exact scalar matches, OR within a list value, and AND across keys.
Retrieval composes small search methods into retrievers, runs them concurrently, and fuses their results through data-only recipes.
| Recipe | Search methods | Fusion |
|---|---|---|
entity, relation, chunk, community | One focused retriever | Reciprocal Rank Fusion |
hybrid_rrf | Entity + relation + chunk + community | Reciprocal Rank Fusion |
hybrid_cross_encoder | All semantic retrievers + graph expansion | Cross-encoder |
bfs_expand | Entity seeds + bounded graph traversal | Reciprocal Rank Fusion |
text2cypher | Schema-aware Cypher | Reciprocal Rank Fusion |
Reciprocal Rank Fusion, cross-encoder, maximal marginal relevance, and graph-distance rerankers cover different query needs. A recipe can ignore an empty search branch and still return evidence from the remaining methods.
The agent coordinates three roles around the retrieval layer:
If the evidence gate fails, the missing items seed another research round. When the gate passes, or the iteration limit is reached, the orchestrator produces a structured answer with citations, confidence, caveats, and an answerability flag.
BAML defines typed extraction, entity-comparison, community-summary, planning, verification, and answer contracts. Runtime client registries support a single provider, fallback chains, or round-robin routing across OpenAI, Anthropic, AWS Bedrock, Google AI, Vertex AI, Azure OpenAI, and OpenAI-compatible endpoints.
OpenTelemetry API support is part of the core package; exporters and the SDK are optional. Applications can send traces to any OTLP-compatible backend.
Long-running graph builds report bounded, structured stage statistics for ingestion, extraction, resolution, merging, and storage. Failures include the affected item, error type, message, and trace/span IDs. Full detail remains in the trace backend so result objects stay bounded on large corpora.
Agentic GraphRAG requires Python 3.11 or newer.
uv pip install agentic-graphrag
Install only the integrations you use:
# Rich documents and local extraction
uv pip install "agentic-graphrag[docling,extract]"
# LLM extraction and local dense embeddings
uv pip install "agentic-graphrag[llm,embed-local]"
# Neo4j with a dedicated Qdrant vector store and OTLP tracing
uv pip install "agentic-graphrag[neo4j,qdrant,observability]"
| Extra | Adds |
|---|---|
docling | PDF, DOCX, PPTX, image, XML, and layout-aware parsing |
extract | Local GLiNER 2.5 extraction |
llm | BAML-powered extraction and verification |
embed-local | Sentence Transformers dense embeddings |
neo4j | Neo4j graph storage and native vector search |
qdrant | Qdrant dense and hybrid search |
weaviate | Weaviate dense and hybrid search |
milvus | Milvus/Zilliz dense and hybrid search |
observability | OpenTelemetry SDK and OTLP export |
import asyncio
from agrag.ingestion import Graph
async def main() -> None:
graph = await Graph.open()
files = await graph.add(source="./corpus/**/*.md")
text = await graph.add(text="Agentic GraphRAG turns evidence into a graph.")
print(files.documents, len(files.chunks))
print(text.documents, len(text.chunks))
asyncio.run(main())
Graph.add() accepts exactly one of:
source= — a file, directory, glob, or list of paths;text= — raw text as one document;documents= — prebuilt Document objects.from agrag.loaders.corpus.types import ErrorPolicy
result = await graph.add(
source="./corpus",
error_policy=ErrorPolicy.QUARANTINE,
)
for uri, reason in result.quarantined_items:
print(uri, reason)
See the documentation for guides and the generated API reference.
| Format | Extension(s) | Loader |
|---|---|---|
| Plain text and logs | .txt, .log | Core |
| Markdown | .md, .markdown | Core |
| AsciiDoc | .adoc, .asciidoc | Docling, with core fallback |
| HTML | .html, .htm | Core |
| CSV / TSV | .csv, .tsv | Core, one document per row |
| JSON | .json | Core, record-aware |
| JSON Lines | .jsonl, .ndjson | Core, one document per row |
.pdf | Docling | |
| Word | .docx | Docling |
| PowerPoint | .pptx | Docling |
| Images | .png, .jpg, .jpeg, .tif, .tiff, .bmp | Docling |
| XML | .xml | Docling or the core XML reader |
Core loaders remain the default for Markdown, HTML, CSV, TSV, and JSON records. Docling takes precedence for layout-rich documents and AsciiDoc when installed.
agrag/
├── common/data_models/ # documents, chunks, schemas, extraction and storage records
├── chunking/ # Chonkie and Docling chunk adapters
├── loaders/ # core corpus readers and optional Docling loader
├── ingestion/ # Graph API, extraction, resolution, merge and pipeline stages
├── embedding/ # dense and sparse embedding interfaces
├── graphdb/ # graph-store interface and Neo4j backend
├── vectordb/ # vector-store interface and Qdrant/Weaviate/Milvus backends
├── cypher/ # validated Cypher builders
├── retrieval/ # search methods, retrievers, recipes and rerankers
├── agents/ # planner, researcher, verifier and answer synthesis
├── communities/ # hierarchical detection and report generation
├── llm/ # BAML sources, generated client and provider routing
└── observability.py # OpenTelemetry helpers
tests/
├── unit/ # isolated tests with external services mocked
└── integration/ # live backend tests against Docker services
git clone https://github.com/ontogr/agentic-graphrag.git
cd agentic-graphrag
make sync
make lint-check
make lint-typing
make test
Integration tests run against local Neo4j, Qdrant, Weaviate, and Milvus services:
make dev-services-up
make test-integration
make dev-services-down
See CONTRIBUTING.md for the development workflow, test conventions, and pull request guidelines.
This project is licensed under the Apache License 2.0.
Python
99.4%