Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
neo4j-contrib avatar

Neo4j Graphrag Skill

  • 533 installs
  • 101 repo stars
  • Updated August 3, 2026
  • neo4j-contrib/neo4j-skills

neo4j-graphrag-skill is a Claude Code skill that wires Neo4j GraphRAG retrieval pipelines in Python using neo4j-graphrag v1.16.0+, selecting retrievers, LLM providers, and prompts for developers building agent-backed Q&A

About

neo4j-graphrag-skill is an agent skill from neo4j-contrib/neo4j-skills for building GraphRAG retrieval pipelines on Neo4j with the neo4j-graphrag Python package at v1.16.0 or newer. It covers six built-in retrievers—VectorRetriever, HybridRetriever, VectorCypherRetriever, HybridCypherRetriever, Text2CypherRetriever, and ToolsRetriever—plus external vector DB retrievers for Weaviate, Pinecone, and Qdrant. The workflow includes embedder setup, index creation, retrieval_query Cypher fragments, query_params, filters, token usage tracking, Cypher 25 SEARCH clause usage, and LangChain or LlamaIndex integration. LLM providers span OpenAI, Anthropic, VertexAI, Bedrock, Cohere, Mistral, and Ollama. Developers reach for it when agents need graph-aware RAG rather than flat vector search alone. It does not handle knowledge-graph construction. Outputs include a wired GraphRAG pipeline, retriever config, and LLM prompt templates.

  • Retriever selection: Vector, Hybrid, VectorCypher, HybridCypher, Text2Cypher, and ToolsRetriever (LLM-routed multi-retri
  • External vector DB retrievers (Weaviate, Pinecone, Qdrant) plus retrieval_query Cypher fragments, query_params, and filt
  • GraphRAG pipeline wiring: retriever + LLM + prompt with providers (OpenAI, Anthropic, VertexAI, Bedrock, Cohere, Mistral
  • Index creation, embedder setup, token usage tracking, and Cypher 25 SEARCH clause guidance
  • LangChain and LlamaIndex integration paths; explicitly defers KG import, plain vector-only, GDS, and agent-memory to sib

Neo4j Graphrag Skill by the numbers

  • 533 all-time installs (skills.sh)
  • +50 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #1,700 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/neo4j-contrib/neo4j-skills --skill neo4j-graphrag-skill

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs533
repo stars101
Security audit3 / 3 scanners passed
Last updatedAugust 3, 2026
Repositoryneo4j-contrib/neo4j-skills

How do you build Neo4j GraphRAG retrieval pipelines?

Wire Neo4j GraphRAG retrieval pipelines in Python—pick retrievers, LLM providers, and GraphRAG prompts for agent-backed Q&A over your graph.

Who is it for?

Python developers building graph-aware RAG agents on Neo4j with neo4j-graphrag v1.16.0+ and multiple retriever or LLM options.

Skip if: Skip neo4j-graphrag-skill when you only need KG construction or a non-Neo4j vector database without graph retrieval.

When should I use this skill?

The user asks to set up Neo4j GraphRAG, pick retrievers, configure embedders, or integrate LangChain or LlamaIndex graph RAG.

What you get

GraphRAG pipeline config, retriever selection, embedder indexes, Cypher retrieval fragments, and LLM prompt wiring.

  • GraphRAG pipeline configuration
  • Retriever and LLM prompt templates

By the numbers

  • Targets neo4j-graphrag Python package v1.16.0 and newer
  • Documents 6 built-in retriever types plus 3 external vector DB integrations
  • Lists 8 LLM providers including OpenAI, Anthropic, VertexAI, Bedrock, Cohere, Mistral, and Ollama

Files

SKILL.mdMarkdownGitHub ↗

Neo4j GraphRAG Skill

When to Use

  • Building GraphRAG retrieval pipelines with neo4j-graphrag Python package
  • Choosing between VectorRetriever, HybridRetriever, VectorCypherRetriever, HybridCypherRetriever
  • Writing retrieval_query Cypher fragments for graph-augmented context
  • Wiring retriever + LLM into a GraphRAG pipeline
  • Using LLM-routed multi-retriever with ToolsRetriever
  • Debugging low retrieval quality
  • Integrating Neo4j with LangChain, LlamaIndex, or Haystack

When NOT to Use

  • KG construction from documentsneo4j-document-import-skill
  • Plain vector/semantic search without graph traversalneo4j-vector-index-skill
  • Hybrid search that combines vector with fulltext or other ranked sourcesneo4j-vector-index-skill
  • GDS algorithms (PageRank, Louvain, node embeddings)neo4j-gds-skill
  • Agent long-term memoryneo4j-agent-memory-skill
  • Writing raw Cypher queriesneo4j-cypher-skill

---

Retriever Selection

Has fulltext index?
  YES → Hybrid variants (HybridRetriever / HybridCypherRetriever)
  NO  → Vector variants (VectorRetriever / VectorCypherRetriever)

Need graph traversal after vector lookup?
  YES → Cypher variants (VectorCypherRetriever / HybridCypherRetriever)
  NO  → plain variants

Natural-language-to-Cypher?        → Text2CypherRetriever (no embedder needed)
LLM should route between retrievers? → ToolsRetriever
Vectors stored in external DB?      → WeaviateNeo4jRetriever / PineconeNeo4jRetriever / QdrantNeo4jRetriever
RetrieverVectorFulltextGraphBest For
VectorRetrieverBaseline semantic search
HybridRetrieverBetter recall, no graph expansion
VectorCypherRetrieverGraphRAG without fulltext
HybridCypherRetrieverProduction GraphRAG — default
Text2CypherRetrieverNL→Cypher, no embedder
ToolsRetrievervariesvariesvariesLLM-routed multi-retriever
WeaviateNeo4jRetrieverVectors in Weaviate
PineconeNeo4jRetrieverVectors in Pinecone
QdrantNeo4jRetrieverVectors in Qdrant

---

Install

pip install neo4j-graphrag[openai]        # OpenAI LLM + embeddings
pip install neo4j-graphrag[anthropic]     # Anthropic Claude
pip install neo4j-graphrag[google]        # Vertex AI / Gemini
pip install neo4j-graphrag[bedrock]       # Amazon Bedrock (boto3)
pip install neo4j-graphrag[cohere]        # Cohere
pip install neo4j-graphrag[mistralai]     # MistralAI
pip install neo4j-graphrag[ollama]        # Ollama (local)
pip install neo4j-graphrag[weaviate]      # Weaviate external retriever
pip install neo4j-graphrag[pinecone]      # Pinecone external retriever
pip install neo4j-graphrag[qdrant]        # Qdrant external retriever

Requires: Python >= 3.10, neo4j >= 5.17.0 (driver 6.x supported).

---

Step 2 — Choose Retriever

Has fulltext index? YES → Hybrid variants (better recall)
                   NO  → Vector variants (baseline)

Needs graph context after vector lookup? YES → Cypher variants
                                         NO  → plain variants

For natural-language-to-Cypher? → Text2CypherRetriever (no embedder needed)
For multi-tool LLM routing?     → ToolsRetriever
Using external vector DB?       → WeaviateNeo4jRetriever / PineconeNeo4jRetriever / QdrantNeo4jRetriever
RetrieverVectorFulltextGraphWhen to use
VectorRetrieverBaseline; quick start
HybridRetrieverBetter recall; no graph context
VectorCypherRetrieverGraphRAG without fulltext
HybridCypherRetrieverProduction GraphRAG — default choice
Text2CypherRetrieverLLM generates Cypher; no embedder
ToolsRetrievervariesvariesvariesMulti-retriever LLM routing

For custom Cypher hybrid search outside the neo4j-graphrag retriever APIs, use neo4j-vector-index-skill.

Vector backend selection [v1.16+, auto]: on Neo4j 2026.01+ all four vector/hybrid retrievers auto-route through the Cypher 25 SEARCH ... WHERE clause when filters are SEARCH-compatible (simple AND comparisons) and all filter props are declared in the index WITH [n.prop] list. $or, $in, $like, or undeclared props → automatic fallback to db.index.vector.queryNodes() procedure path (with warning log). Declare filterable properties via filterable_properties=[...] on create_vector_index().

---

Step 3 — Create Indexes (run once)

// Vector index (all retrievers need this)
CREATE VECTOR INDEX chunk_embedding IF NOT EXISTS
FOR (c:Chunk) ON (c.embedding)
OPTIONS { indexConfig: {
  `vector.dimensions`: 1536,
  `vector.similarity_function`: 'cosine'
} };

// Fulltext index (Hybrid retrievers only)
CREATE FULLTEXT INDEX chunk_fulltext IF NOT EXISTS
FOR (c:Chunk) ON EACH [c.text];

// Confirm ONLINE before ingesting:
SHOW INDEXES YIELD name, state
WHERE name IN ['chunk_embedding', 'chunk_fulltext']
RETURN name, state;
// Both must show state = 'ONLINE'

If index not ONLINE: wait, poll every 5s. Do NOT start ingestion until ONLINE.

---

Step 4 — Core Pattern (HybridCypherRetriever)

from neo4j import GraphDatabase
from neo4j_graphrag.embeddings import OpenAIEmbeddings
from neo4j_graphrag.generation import GraphRAG
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.retrievers import HybridCypherRetriever

driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))
embedder = OpenAIEmbeddings(model="text-embedding-3-large")  # OPENAI_API_KEY from env

# retrieval_query: Cypher fragment executed after the vector/fulltext lookup.
# Auto-injected variables:  node  (matched node)   score  (similarity float)
# MUST include a RETURN clause.  score must appear in RETURN.
retrieval_query = """
MATCH (node)<-[:HAS_CHUNK]-(article:Article)
OPTIONAL MATCH (article)-[:MENTIONS]->(org:Organization)
RETURN node.text AS chunk_text,
       article.title AS article_title,
       collect(DISTINCT org.name) AS mentioned_organizations,
       score
"""

retriever = HybridCypherRetriever(
    driver=driver,
    vector_index_name="chunk_embedding",
    fulltext_index_name="chunk_fulltext",
    retrieval_query=retrieval_query,
    embedder=embedder,
)

llm = OpenAILLM(model_name="gpt-4.1", model_params={"temperature": 0})

rag = GraphRAG(
    retriever=retriever,
    llm=llm,
)

response = rag.search(
    query_text="Who does Alice work for?",
    retriever_config={"top_k": 5},
)
print(response.answer)
driver.close()

---

VectorCypherRetriever

from neo4j_graphrag.retrievers import VectorCypherRetriever

retriever = VectorCypherRetriever(
    driver=driver,
    index_name="chunk_embedding",
    retrieval_query=retrieval_query,
    embedder=embedder,
)

response = rag.search(
    query_text="What happened at Apple?",
    retriever_config={"top_k": 10},
)

---

Text2CypherRetriever

Translates natural language to Cypher using an LLM. No embedder required.

Security (v1.16.0+): Every LLM-generated Cypher is run through EXPLAIN first.
Any statement classified as write/destructive raises Text2CypherRetrievalError instead
of executing — prevents prompt-injection attacks.
from neo4j_graphrag.retrievers import Text2CypherRetriever

retriever = Text2CypherRetriever(
    driver=driver,
    llm=OpenAILLM(model_name="gpt-4.1"),
    neo4j_schema=None,       # None = auto-fetch schema from DB; pass string to trim
    examples=[
        "Q: Who works at Neo4j? A: MATCH (p:Person)-[:WORKS_AT]->(c:Company {name:'Neo4j'}) RETURN p.name"
    ],
)
results = retriever.search(query_text="Which people work at Neo4j?")

---

ToolsRetriever (LLM-routed multi-retriever)

from neo4j_graphrag.retrievers import ToolsRetriever

tools_retriever = ToolsRetriever(
    llm=llm,
    retrievers=[vector_retriever, text2cypher_retriever],
)
# LLM decides which retriever(s) to invoke per query

# Convert any retriever to a standalone Tool:
tool = vector_retriever.convert_to_tool()

---

Filters (pre-filter before vector search)

results = retriever.search(
    query_text="quarterly earnings",
    top_k=5,
    filters={
        "date": {"$gte": "2024-01-01"},
        "source": {"$eq": "10-K"},
    },
)
# Operators: $eq  $ne  $lt  $lte  $gt  $gte  $between  $in  $like  $ilike

---

query_params (parameterized retrieval_query)

retrieval_query = """
MATCH (node)<-[:HAS_CHUNK]-(a:Article)-[:MENTIONS]->(org:Organization {name: $entity_name})
RETURN node.text, a.title, score
"""

# Pass via retriever.search directly:
results = retriever.search(
    query_text="What happened at Apple?",
    top_k=10,
    query_params={"entity_name": "Apple"},
)

# Or via GraphRAG.search:
response = rag.search(
    query_text="What happened at Apple?",
    retriever_config={"top_k": 10, "query_params": {"entity_name": "Apple"}},
)

---

Cypher 25 SEARCH Clause (v1.16.0, Neo4j 2026.x+)

# Enable SEARCH clause syntax in vector/hybrid retrievers (requires Neo4j 2026+)
retriever = VectorRetriever(
    driver=driver,
    index_name="chunk_embedding",
    embedder=embedder,
    use_search_clause=True,
)

---

ORDER BY on Cypher Retrievers (v1.16.0)

results = retriever.search(
    query_text="...",
    top_k=10,
    order_by="score DESC",
)

If neo4j_schema=None: retriever fetches schema automatically. For large schemas, pass a trimmed string to reduce LLM prompt size.

Destructive-query guard [v1.16+]: Text2CypherRetriever runs EXPLAIN on the generated Cypher before execution and rejects queries that produce writes (CREATE, MERGE, DELETE, SET, REMOVE, etc.). LLM-generated writes are never executed against the graph.

---

Custom Prompt Template

from neo4j_graphrag.generation.prompts import RagTemplate

template = RagTemplate(
    template="""Answer using ONLY the context below.
Context: {context}
Question: {query_text}
Answer:""",
    expected_inputs=["context", "query_text"],
)

rag = GraphRAG(retriever=retriever, llm=llm, prompt_template=template)

---

return_context and response_fallback

response = rag.search(
    query_text="...",
    retriever_config={"top_k": 5},
    return_context=True,                        # include raw retrieved chunks
    response_fallback="No relevant context.",   # skip LLM call if retriever returns nothing
)
print(response.answer)
print(response.retriever_result)    # RawSearchResult when return_context=True

---

Message History (multi-turn)

from neo4j_graphrag.message_history import InMemoryMessageHistory

history = InMemoryMessageHistory()
r1 = rag.search(query_text="Who is Alice?", message_history=history)
r2 = rag.search(query_text="Where does she work?", message_history=history)

---

External Retrievers

# --- Weaviate ---
from neo4j_graphrag.retrievers import WeaviateNeo4jRetriever
import weaviate

weaviate_client = weaviate.connect_to_local()
retriever = WeaviateNeo4jRetriever(
    driver=driver,
    client=weaviate_client,
    collection="Chunk",
    id_property_external="neo4j_id",
    id_property_neo4j="id",
    retrieval_query=retrieval_query,
    node_label_neo4j="Chunk",       # optional: speeds up Neo4j lookup
)

# --- Pinecone ---
from neo4j_graphrag.retrievers import PineconeNeo4jRetriever
from pinecone import Pinecone

pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
retriever = PineconeNeo4jRetriever(
    driver=driver,
    client=pc,
    index_name="my-index",
    id_property_neo4j="id",
    retrieval_query=retrieval_query,
)

# --- Qdrant ---
from neo4j_graphrag.retrievers import QdrantNeo4jRetriever
from qdrant_client import QdrantClient

retriever = QdrantNeo4jRetriever(
    driver=driver,
    client=QdrantClient(url="http://localhost:6333"),
    collection_name="Chunk",
    id_property_external="neo4j_id",
    id_property_neo4j="id",
    id_property_getter=lambda hit: hit.payload["neo4j_id"],  # custom ID extraction
    retrieval_query=retrieval_query,
)

---

LLM Providers

All implement LLMBase. All support sync + async, tool calling, and automatic rate limiting.

ClassExtraNotes
OpenAILLMopenaiStructured output; tool calling
AzureOpenAILLMopenaiAzure-hosted OpenAI
AnthropicLLManthropicTool calling
VertexAILLMgoogleStructured output; tool calling
MistralAILLMmistralaiTool calling
CohereLLMcohere
OllamaLLMollamaLocal; tool calling
BedrockLLMbedrockBoto3 Converse API; added v1.15.0
from neo4j_graphrag.llm import (
    OpenAILLM, AzureOpenAILLM, AnthropicLLM, VertexAILLM,
    MistralAILLM, CohereLLM, OllamaLLM, BedrockLLM,
)

llm = OpenAILLM(model_name="gpt-4.1", model_params={"temperature": 0})
llm = AnthropicLLM(model_name="claude-3-5-sonnet-20241022")
llm = VertexAILLM(model_name="gemini-2.0-flash")
llm = OllamaLLM(model_name="llama3")           # no API key needed
llm = BedrockLLM(model_id="anthropic.claude-3-5-sonnet-20241022-v2:0")

# Token usage tracking (v1.15.0+)
response = llm.invoke("Hello")
# response.usage → LLMUsage(request_tokens=N, response_tokens=M, total_tokens=T)

# Graceful resource cleanup (v1.16.0+)
llm.close()         # sync
await llm.aclose()  # async

---

Embedder Providers

All include automatic rate limiting with tenacity exponential backoff.

ClassExtraDims
OpenAIEmbeddingsopenai3072 / 1536
AzureOpenAIEmbeddingsopenaivaries
VertexAIEmbeddingsgoogle768
MistralAIEmbeddingsmistralai1024
CohereEmbeddingscohere1024
OllamaEmbeddingsollamavaries
SentenceTransformerEmbeddingssentence-transformers384+
BedrockEmbeddingsbedrockvaries; added v1.15.0
from neo4j_graphrag.embeddings import (
    OpenAIEmbeddings, VertexAIEmbeddings, CohereEmbeddings,
    OllamaEmbeddings, SentenceTransformerEmbeddings, BedrockEmbeddings,
)

embedder = OpenAIEmbeddings(model="text-embedding-3-large")   # 3072 dims
embedder = OpenAIEmbeddings(model="text-embedding-3-small")   # 1536 dims
embedder = SentenceTransformerEmbeddings(model="all-MiniLM-L6-v2")  # 384 dims, local
embedder = BedrockEmbeddings(model_id="amazon.titan-embed-text-v2:0")

---

Index Setup

from neo4j_graphrag.indexes import create_vector_index

# Vector index — adjust dimensions to match your embedding model
create_vector_index(
    driver,
    name="chunk_embedding",
    label="Chunk",
    embedding_property="embedding",
    dimensions=1536,
    similarity_fn="cosine",       # or "euclidean"
)

# Fulltext index (run as Cypher)
# CREATE FULLTEXT INDEX chunk_fulltext IF NOT EXISTS
#   FOR (c:Chunk) ON EACH [c.text]

---

Schema Inspection

from neo4j_graphrag.schema import get_schema, get_structured_schema

schema_str = get_schema(driver, sample=1000)           # human-readable string
schema_dict = get_structured_schema(driver, sample=1000)  # dict with labels/rels/props

---

Common Errors

ErrorCauseFix
ModuleNotFoundError: neo4j_genaiOld package namepip uninstall neo4j-genai && pip install neo4j-graphrag
retrieval_query returns 0 rowsMissing MATCH or wrong rel directionEXPLAIN the fragment; check CALL db.schema.visualization()
KeyError: 'score' in resultsretrieval_query RETURN missing scoreAdd score to every retrieval_query RETURN clause
score variable not foundscore re-declared in retrieval_queryDo not re-declare score — it is auto-injected
Text2CypherRetrievalErrorLLM generated a write statementExpected security behavior (v1.16.0+); refine prompt or schema
TypeError: coroutineMissing await / asyncio.run()Wrap async calls: asyncio.run(pipeline.run_async(...))
Empty results from HybridRetrieverFulltext index not ONLINESHOW INDEXES YIELD name, state WHERE state <> 'ONLINE'
Embedding dimension mismatchIndex dims ≠ model dimsRecreate index with correct dimensions= value

---

Verification Checklist

  • [ ] neo4j-graphrag (not neo4j-genai) installed; neo4j >= 5.17.0 driver
  • [ ] Vector index ONLINE before ingesting embeddings or running retriever
  • [ ] Fulltext index ONLINE if using Hybrid variants
  • [ ] Embedding dims in create_vector_index match the embedder output
  • [ ] retrieval_query returns node and score in RETURN (not re-declared)
  • [ ] query_params passed via retriever_config on rag.search() (not on retriever constructor)
  • [ ] API keys in env vars; never hardcoded
  • [ ] llm.close() called when done to release resources

---

References

Load on demand:

Related skills

How it compares

Pick neo4j-graphrag-skill over generic RAG skills when retrieval must combine Cypher graph traversal with vector or hybrid search on Neo4j.

FAQ

Which retrievers does neo4j-graphrag-skill support?

neo4j-graphrag-skill covers VectorRetriever, HybridRetriever, VectorCypherRetriever, HybridCypherRetriever, Text2CypherRetriever, and ToolsRetriever in neo4j-graphrag v1.16.0+, plus Weaviate, Pinecone, and Qdrant external retrievers.

Does neo4j-graphrag-skill build knowledge graphs?

neo4j-graphrag-skill wires GraphRAG retrieval pipelines and LLM prompts on existing Neo4j data. Knowledge-graph construction and ingestion are explicitly out of scope.

Is Neo4j Graphrag Skill safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

AI & Agent Buildingagentsllmautomation

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.