
Neo4j Genai Plugin Skill
- 367 installs
- 101 repo stars
- Updated August 3, 2026
- neo4j-contrib/neo4j-skills
Call embeddings, completions, structured JSON, and chat from Cypher using Neo4j’s GenAI Plugin for in-database GraphRAG and agent retrieval.
About
Neo4j GenAI plugin skill teaches agents to use Neo4j’s native ai.text.* functions so solo builders can run embeddings, text completion, structured JSON outputs, and chat without bolting a separate orchestration service onto every retrieval query. It fits builders shipping knowledge-heavy agents or SaaS features where the graph is the system of record: configure providers, discover available models, chunk by tokens, and chain vector search with traversals and LLM steps inside Cypher. The skill is explicit about version gates—2025.12+, CYPHER 25, Aura GenAI enabled—and points vector index mechanics to a sibling skill. That makes it a focused integration reference, not a full Python GraphRAG pipeline guide. Install when you are implementing GraphRAG or entity-aware copilots on Neo4j; skip if you only need index DDL or offline batch ETL in another language. Expect agents to need API credentials and careful review of queries that touch production graphs.
- Documents ai.text.embed, embedBatch, completion, aggregateCompletion, structuredCompletion, chat, tokenCount, and chunkB
- Pure-Cypher GraphRAG pattern: embed → vector search → graph traversal → completion in one query
- Provider setup for OpenAI, Azure OpenAI, VertexAI, and Amazon Bedrock with lowercase provider strings
- Requires CYPHER 25 per-query prefix or ALTER DATABASE default; Neo4j 2025.12+ or Aura with GenAI Plugin
- Includes migration path from deprecated genai.vector.* to ai.text.*
Neo4j Genai Plugin Skill by the numbers
- 367 all-time installs (skills.sh)
- +29 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,122 of 4,347 Backend & APIs 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-genai-plugin-skillAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 367 |
|---|---|
| repo stars | ★ 101 |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 3, 2026 |
| Repository | neo4j-contrib/neo4j-skills ↗ |
What it does
Call embeddings, completions, structured JSON, and chat from Cypher using Neo4j’s GenAI Plugin for in-database GraphRAG and agent retrieval.
Files
When to Use
- Generating embeddings inside Cypher without external Python (
ai.text.embed()) - Batch-embedding nodes/chunks during ingestion (
ai.text.embedBatch()) - Calling LLMs directly in Cypher for completions or GraphRAG (
ai.text.completion()) - Extracting structured JSON maps from LLM inside Cypher (
ai.text.structuredCompletion()) - Aggregating LLM summaries over grouped rows (
ai.text.aggregateCompletion()) - Stateful chat sessions in Cypher (
ai.text.chat()) - Counting tokens or chunking text by token limit (
ai.text.tokenCount(),ai.text.chunkByTokenLimit())
When NOT to Use
- Python-based GraphRAG pipelines (VectorCypherRetriever, HybridCypherRetriever) →
neo4j-graphrag-skill - Vector index CREATE / kNN search / SEARCH clause →
neo4j-vector-index-skill - GDS embeddings (FastRP, Node2Vec) →
neo4j-gds-skill - Fulltext / keyword search →
neo4j-cypher-skill
---
Prerequisites
CYPHER 25 required for all ai.* functions. Two ways to enable:
// Per-query prefix (self-managed, no admin rights needed):
CYPHER 25 MATCH (n:Chunk) ...
// Per-database default (admin; applies to all sessions):
ALTER DATABASE neo4j SET DEFAULT LANGUAGE CYPHER 25Installation:
- Aura: GenAI plugin enabled by default — no action needed
- Self-managed JAR: copy plugin JAR to
plugins/directory - Docker:
--env NEO4J_PLUGINS='["genai"]'
---
Provider Config Quick Reference
All ai.text.* functions accept a configuration :: MAP as last argument.
| Provider string | Required keys | Notes |
|---|---|---|
'openai' | token, model | token = OpenAI API key |
'azure-openai' | token, resource, model | token = OAuth2 bearer; resource = Azure resource name |
'vertexai' | model, project, region, token or apiKey | publisher defaults to 'google' |
'bedrock-titan' | model, region, accessKeyId, secretAccessKey | Embedding only |
'bedrock-nova' | model, region, accessKeyId, secretAccessKey | Completion only |
Optional for all: vendorOptions :: MAP passes provider-specific extras (e.g. { dimensions: 1024 } for OpenAI).
❌ Never hardcode API key literals. ✅ Always use $param passed via driver parameters dict.
Full provider config table → references/providers.md
---
Embedding
Single embed [2025.11]
CYPHER 25
MATCH (c:Chunk)
WHERE c.embedding IS NULL
WITH c
CALL {
WITH c
SET c.embedding = ai.text.embed(c.text, 'openai', {
token: $openaiKey,
model: 'text-embedding-3-small'
})
} IN TRANSACTIONS OF 500 ROWSai.text.embed() returns VECTOR — directly storable and queryable in a vector index.
Batch embed procedure [2025.11]
CYPHER 25
MATCH (c:Chunk) WHERE c.embedding IS NULL
WITH collect(c) AS chunks
UNWIND chunks AS c
WITH c.text AS text, c AS node
CALL ai.text.embedBatch(text, 'openai', { token: $openaiKey, model: 'text-embedding-3-small' })
YIELD index, resource, vector
MATCH (c:Chunk {text: resource})
SET c.embedding = vectorProcedure signature: CALL ai.text.embedBatch(resource, provider, config) YIELD index, resource, vector
List configured embed providers
CYPHER 25
CALL ai.text.embed.providers()
YIELD name, requiredConfigType, optionalConfigType, defaultConfig
RETURN name, requiredConfigType---
Text Completion [2025.11]
CYPHER 25
RETURN ai.text.completion(
'Summarize: ' + $text,
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS summaryReturns STRING.
Aggregate completion — summarize across rows [2026.03]
CYPHER 25
MATCH (c:Chunk)-[:PART_OF]->(a:Article {id: $articleId})
RETURN ai.text.aggregateCompletion(
c.text,
'Summarize the following article chunks in 3 sentences',
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS summaryvalue parameter = each row's STRING fed to the LLM. Uses toString() for non-string values.
---
Pure-Cypher GraphRAG Pattern
Embed question → vector search → graph traverse → LLM completion — all in one Cypher query:
CYPHER 25
WITH ai.text.embed($question, 'openai', { token: $openaiKey, model: 'text-embedding-3-small' }) AS qEmbedding
CALL db.index.vector.queryNodes('chunk_embedding', 10, qEmbedding) YIELD node AS chunk, score
MATCH (chunk)<-[:HAS_CHUNK]-(article:Article)
OPTIONAL MATCH path = shortestPath((article)-[*..3]-(other:Article))
WITH chunk, article, collect(DISTINCT other.title) AS related, score
ORDER BY score DESC LIMIT 5
WITH collect(chunk.text + '\n[Source: ' + article.title + ']') AS context, $question AS question
RETURN ai.text.completion(
'Answer based on context:\n' + reduce(s='', c IN context | s + c + '\n') + '\nQuestion: ' + question,
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS answerKey insight (Bergman): shortest path between seed nodes surfaces relationships not visible from direct neighbors alone.
---
Structured Output [2026.02]
Returns MAP — directly storable as node properties or used downstream in Cypher.
CYPHER 25
MATCH (p:Product {id: $productId})
WITH p,
ai.text.structuredCompletion(
'Extract key attributes from: ' + p.description,
{
type: 'object',
properties: {
category: { type: 'string' },
tags: { type: 'array', items: { type: 'string' } },
priceRange: { type: 'string', enum: ['budget', 'mid', 'premium'] }
},
required: ['category', 'tags', 'priceRange'],
additionalProperties: false
},
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS extracted
SET p.category = extracted.category,
p.priceRange = extracted.priceRange
WITH p, extracted.tags AS tags
UNWIND tags AS tag
MERGE (t:Tag {name: tag})
MERGE (p)-[:TAGGED]->(t)Aggregate structured completion — extract across multiple rows [2026.03]
CYPHER 25
MATCH (:User {id: $userId})-[:ORDERED]->(o:Order)-[:CONTAINS]->(p:Product)
RETURN ai.text.aggregateStructuredCompletion(
p.name + ': ' + p.category,
'Build a shopping profile for this user',
{
type: 'object',
properties: {
preferredCategories: { type: 'array', items: { type: 'string' } },
spendingTier: { type: 'string', enum: ['economy', 'standard', 'premium'] }
},
required: ['preferredCategories', 'spendingTier']
},
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS profile---
Chat [2025.12]
Supported providers: openai and azure-openai only.
// Start new conversation (chatId = null → new session)
CYPHER 25
WITH ai.text.chat(
'Hello, who are you?',
null,
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS result
RETURN result.message AS reply, result.chatId AS sessionId
// Continue conversation (pass returned chatId)
CYPHER 25
WITH ai.text.chat(
'What did I just ask you?',
$chatId,
'openai',
{ token: $openaiKey, model: 'gpt-4o-mini' }
) AS result
RETURN result.message AS reply, result.chatId AS sessionIdReturns MAP { message: STRING, chatId: STRING }. Store chatId to continue session.
---
Tokenization & Chunking [2026.04]
// Count tokens before sending to LLM
CYPHER 25
RETURN ai.text.tokenCount($text, 'openai', { token: $openaiKey, model: 'gpt-4o-mini' }) AS tokenCount
// Chunk text by token limit (no external dependencies)
CYPHER 25
UNWIND ai.text.chunkByTokenLimit($longText, 512, 'gpt-4', 50) AS chunk
MERGE (c:Chunk { text: chunk })
// List providers supporting tokenCount
CYPHER 25
CALL ai.text.tokenCount.providers() YIELD name, requiredConfigType
RETURN name, requiredConfigTypeSignatures:
ai.text.tokenCount(input, provider, configuration = {}) :: INTEGER— provider-driven tokenizer; uses provider config (token/model).ai.text.chunkByTokenLimit(input, limit, model = 'gpt-4', overlap = 0) :: LIST<STRING>— local tokenizer keyed offmodel; no provider call, notokenrequired.
---
Write Gate
SET node.embedding = ai.text.embed(...) and SET node.* = ai.text.structuredCompletion(...) write to the graph.
Before bulk writes: 1. Count nodes first: MATCH (c:Chunk) WHERE c.embedding IS NULL RETURN count(c) 2. Verify config with one test node before batch 3. Use CALL { ... } IN TRANSACTIONS OF 500 ROWS for batches > 1000 nodes 4. Require explicit confirmation before executing
---
Deprecated — Do NOT Use
| Old function | Replacement |
|---|---|
genai.vector.encode() [deprecated] | ai.text.embed() |
genai.vector.encodeBatch() [deprecated] | CALL ai.text.embedBatch() |
genai.vector.listEncodingProviders() [deprecated] | CALL ai.text.embed.providers() |
---
Common Errors
| Error | Cause | Fix |
|---|---|---|
Unknown function 'ai.text.embed' | Missing CYPHER 25 prefix OR plugin not installed | Add CYPHER 25 prefix; verify plugin installed |
Cypher version not supported | Using CYPHER 25 on Neo4j < 5.20 or missing plugin | Upgrade Neo4j; ensure GenAI plugin loaded |
Configuration key 'token' missing | Provider config map incomplete | Check required keys for provider (see table above) |
null returned from embed | Wrong model name or provider auth failed | Test with RETURN ai.text.embed('test', 'openai', {token:$k, model:'text-embedding-3-small'}) standalone |
Unsupported provider | Provider string typo (case-sensitive, lowercase) | Use 'openai' not 'OpenAI'; run CALL ai.text.embed.providers() |
ai.text.chat fails on VertexAI | Chat only supported on openai/azure-openai | Switch to openai/azure-openai for chat |
---
Checklist
- [ ]
CYPHER 25prefix present on every ai.text.* query - [ ] GenAI plugin installed (Aura: automatic; self-managed: JAR in plugins/)
- [ ] API key passed as
$param, never as literal string - [ ]
modelkey explicit in config (no silent defaults) - [ ] Provider string lowercase (
'openai','vertexai','bedrock-titan') - [ ] Bulk writes use
IN TRANSACTIONS OF 500 ROWS; count target nodes first - [ ]
genai.vector.encode()replaced withai.text.embed()[2025.11+] - [ ] Chat sessions: store returned
chatIdfor continuation; only openai/azure-openai supported - [ ] Structured output schema uses
additionalProperties: falseto prevent hallucination keys
---
References
- Full provider config — all required/optional keys per provider
- Official docs
- API reference
neo4j-genai-plugin-skill
Skill for calling LLM providers directly from Cypher using the Neo4j GenAI Plugin ai.text.* functions [2025.12].
Covers:
ai.text.embed()/ai.text.embedBatch()— generate vector embeddings in Cypher; replaces deprecatedgenai.vector.encode()ai.text.completion()/ai.text.aggregateCompletion()— LLM text generation over query resultsai.text.structuredCompletion()/ai.text.aggregateStructuredCompletion()— JSON Schema-validated structured outputai.text.chat()— stateful chat withchatId(OpenAI / Azure only)ai.text.tokenCount()/ai.text.chunkByTokenLimit()— tokenization and chunking helpers- Provider discovery:
ai.text.embed.providers(),ai.text.completion.providers() - Provider configuration — OpenAI, Azure OpenAI, VertexAI, Amazon Bedrock
- Pure-Cypher GraphRAG: embed → vector search → graph traversal → completion in one query
- CYPHER 25 requirement: per-query prefix and
ALTER DATABASEdefault - Migration from deprecated
genai.vector.*→ai.text.*
Version / compatibility:
ai.text.*requires Neo4j 2025.12+ (self-managed) or Aura with GenAI Plugin enabled- All functions require
CYPHER 25prefix orALTER DATABASE neo4j SET DEFAULT LANGUAGE CYPHER 25 - Provider strings are lowercase:
'openai','azure-openai','vertexai','bedrock-titan'
Not covered:
- Vector index creation and management →
neo4j-vector-index-skill - GraphRAG pipelines via Python (
neo4j-graphragpackage) →neo4j-graphrag-skill - KG construction from documents →
neo4j-document-import-skill
Install:
npx skills add https://github.com/neo4j-contrib/neo4j-skills --skill neo4j-genai-plugin-skillOr paste this link into your coding assistant: https://github.com/neo4j-contrib/neo4j-skills/tree/main/neo4j-genai-plugin-skill
GenAI Plugin — Full Provider Configuration Reference
All ai.text.* functions and ai.text.embedBatch accept configuration :: MAP as last argument.
Provider strings are lowercase and exact — case-sensitive.
---
OpenAI ('openai')
| Key | Type | Required | Default | Notes |
|---|---|---|---|---|
token | STRING | Yes | — | OpenAI API key |
model | STRING | Yes | — | e.g. 'text-embedding-3-small', 'gpt-4o-mini' |
maxBatchSize | INTEGER | No | 8192 | Max tokens per batch request |
vendorOptions | MAP | No | {} | Extra OpenAI params, e.g. { dimensions: 1024 } for reduced embedding dims |
chatHistory | LIST<ANY> | No | — | Completion/chat only. [{ role: 'user', content: '...' }, ...] |
Embed example
CYPHER 25
RETURN ai.text.embed('Hello', 'openai', {
token: $openaiKey, model: 'text-embedding-3-small',
vendorOptions: { dimensions: 1024 }
}) AS vCompletion example
CYPHER 25
RETURN ai.text.completion('Summarize: ' + $text, 'openai', {
token: $openaiKey, model: 'gpt-4o-mini',
vendorOptions: { instructions: 'Be concise.' }
}) AS summary---
Azure OpenAI ('azure-openai')
| Key | Type | Required | Default | Notes |
|---|---|---|---|---|
token | STRING | Yes | — | Azure OAuth2 bearer token |
resource | STRING | Yes | — | Azure resource name (subdomain of openai.azure.com) |
model | STRING | Yes | — | Deployment name in Azure portal |
maxBatchSize | INTEGER | No | 8192 | Embed batch only |
vendorOptions | MAP | No | {} | Extra Azure params |
chatHistory | LIST<ANY> | No | — | Completion/chat only |
Example
CYPHER 25
RETURN ai.text.embed('Hello', 'azure-openai', {
token: $azureToken,
resource: 'my-azure-resource',
model: 'text-embedding-3-small'
}) AS vOverride Azure base URL [2026.04]
Server-side env var GENAI_AZURE_OPENAI_BASE_URL overrides the default https://<resource>.openai.azure.com for all azure-openai ai.text.* calls. Set on the Neo4j server (not the driver/client). Use for private endpoints, custom hostnames, or proxy gateways.
# neo4j.conf or systemd Environment=
GENAI_AZURE_OPENAI_BASE_URL=https://my-private-endpoint.example.comWhen set, resource in the provider config is appended to this URL.
---
Google VertexAI ('vertexai')
| Key | Type | Required | Default | Notes |
|---|---|---|---|---|
model | STRING | Yes | — | Full model resource name, e.g. 'gemini-embedding-001' |
project | STRING | Yes | — | Google Cloud project ID |
region | STRING | Yes | — | e.g. 'us-central1', 'asia-northeast1' |
token | STRING | Yes* | — | Service account access token (*one of token/apiKey) |
apiKey | STRING | Yes* | — | API key alternative to token |
publisher | STRING | No | 'google' | Model publisher |
vendorOptions | MAP | No | {} | e.g. { outputDimensionality: 1024 } |
chatHistory | LIST<ANY> | No | — | Format: [{ role: 'user', parts: [{ text: '...' }] }] |
Note: ai.text.chat() NOT supported on VertexAI — use openai/azure-openai for chat.
Example
CYPHER 25
RETURN ai.text.embed('Hello', 'vertexai', {
token: $vertexToken,
model: 'gemini-embedding-001',
project: 'my-gcp-project',
region: 'us-central1',
vendorOptions: { outputDimensionality: 1024 }
}) AS v---
Amazon Bedrock — Embeddings ('bedrock-titan')
| Key | Type | Required | Default | Notes |
|---|---|---|---|---|
model | STRING | Yes | — | e.g. 'amazon.titan-embed-text-v1' |
region | STRING | Yes | — | AWS region e.g. 'eu-west-2' |
accessKeyId | STRING | Yes | — | AWS access key ID |
secretAccessKey | STRING | Yes | — | AWS secret access key |
vendorOptions | MAP | No | {} | e.g. { dimensions: 1024 } |
Example
CYPHER 25
RETURN ai.text.embed('Hello', 'bedrock-titan', {
accessKeyId: $awsKeyId,
secretAccessKey: $awsSecret,
model: 'amazon.titan-embed-text-v1',
region: 'eu-west-2'
}) AS v---
Amazon Bedrock — Completions ('bedrock-nova')
| Key | Type | Required | Default | Notes |
|---|---|---|---|---|
model | STRING | Yes | — | Model ID or ARN, e.g. 'us.amazon.nova-micro-v1:0' |
region | STRING | Yes | — | AWS region |
accessKeyId | STRING | Yes | — | AWS access key ID |
secretAccessKey | STRING | Yes | — | AWS secret access key |
vendorOptions | MAP | No | {} | Bedrock-specific options |
chatHistory | LIST<ANY> | No | — | Conversation history |
Note: ai.text.chat() NOT supported on Bedrock — use openai/azure-openai for chat.
---
Provider Discovery — Runtime Check
// Embedding providers
CYPHER 25
CALL ai.text.embed.providers()
YIELD name, requiredConfigType, optionalConfigType, defaultConfig
RETURN name, requiredConfigType;
// Completion providers
CYPHER 25
CALL ai.text.completion.providers()
YIELD name, requiredConfigType, optionalConfigType
RETURN name;
// Chat providers
CYPHER 25
CALL ai.text.chat.providers()
YIELD name
RETURN name;
// Token count providers
CYPHER 25
CALL ai.text.tokenCount.providers()
YIELD name
RETURN name;---
Model Reference
| Provider | Embedding models | Completion models |
|---|---|---|
| OpenAI | text-embedding-3-small (1536d), text-embedding-3-large (3072d), text-embedding-ada-002 (1536d, legacy) | gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo |
| Azure | Same as OpenAI (deployment-name based) | Same as OpenAI |
| VertexAI | gemini-embedding-001 (3072d), text-embedding-004 (768d) | gemini-2.0-flash, gemini-1.5-pro |
| Bedrock | amazon.titan-embed-text-v1 (1536d), amazon.titan-embed-text-v2:0 (1024d) | us.amazon.nova-micro-v1:0, us.amazon.nova-lite-v1:0, us.amazon.nova-pro-v1:0 |
vector.dimensions in vector index MUST match model output dimensions exactly.
Related skills
FAQ
Is Neo4j Genai Plugin 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.