Neo4j Graph RAG Query Skill
This skill teaches you how to query the Neo4j knowledge graph that powers the Shakudo business intelligence system.
Prerequisites
- Neo4j MCP tools available (
neo4j_execute_query, etc.) - Connection to the knowledge graph database
Data Sources in the Knowledge Graph
The knowledge graph aggregates data from 4 sources:
| Source | Node Label | Description |
|---|---|---|
| Fireflies | Parent |
Call transcripts with speaker/company info |
| Mattermost | MMThread |
Team chat threads and discussions |
| HubSpot | EmailThread |
Customer email communications |
| GitHub | GithubThread |
Issue discussions and PR comments |
Schema Overview
Parent Node (Fireflies Calls)
(:Parent {
id: String, # Unique identifier
title: String, # Call/meeting title
call_date: DateTime, # When the call occurred
company: String, # Associated company name
transcript: String, # Full transcript text
summary: String, # AI-generated summary
embedding: [Float] # Vector embedding for similarity search
})
MMThread Node (Mattermost)
(:MMThread {
id: String,
channel_name: String,
created_at: DateTime,
content: String,
embedding: [Float]
})
EmailThread Node (HubSpot)
(:EmailThread {
id: String,
subject: String,
from_email: String,
to_email: String,
sent_at: DateTime,
body: String,
embedding: [Float]
})
GithubThread Node (GitHub Issues)
(:GithubThread {
id: String,
repo: String,
issue_number: Integer,
title: String,
body: String,
created_at: DateTime,
embedding: [Float]
})
Common Query Patterns
1. Vector Similarity Search (Recommended)
For semantic search across all data sources:
// Search Fireflies calls by semantic similarity
CALL db.index.vector.queryNodes('parent_embedding', 10, $queryEmbedding)
YIELD node, score
RETURN node.title, node.company, node.call_date, score
ORDER BY score DESC
Note: You need to generate the query embedding using the same embedding model (stella_en_1.5b_v5 via Ollama).
2. Find Calls by Company
MATCH (p:Parent)
WHERE p.company CONTAINS $companyName
RETURN p.title, p.call_date, p.summary
ORDER BY p.call_date DESC
LIMIT 10
3. Find Calls in Date Range
MATCH (p:Parent)
WHERE p.call_date >= datetime($startDate)
AND p.call_date <= datetime($endDate)
RETURN p.title, p.company, p.call_date
ORDER BY p.call_date DESC
4. Search Mattermost for Topic
MATCH (m:MMThread)
WHERE m.content CONTAINS $searchTerm
RETURN m.channel_name, m.content, m.created_at
ORDER BY m.created_at DESC
LIMIT 20
5. Find Emails from/to Contact
MATCH (e:EmailThread)
WHERE e.from_email CONTAINS $email OR e.to_email CONTAINS $email
RETURN e.subject, e.from_email, e.to_email, e.sent_at
ORDER BY e.sent_at DESC
LIMIT 20
6. Search GitHub Issues by Repo
MATCH (g:GithubThread)
WHERE g.repo = $repoName
RETURN g.issue_number, g.title, g.created_at
ORDER BY g.created_at DESC
LIMIT 20
7. Cross-Source Search (All Data)
// Search across all sources with text matching
MATCH (n)
WHERE (n:Parent OR n:MMThread OR n:EmailThread OR n:GithubThread)
AND (
n.content CONTAINS $searchTerm OR
n.transcript CONTAINS $searchTerm OR
n.body CONTAINS $searchTerm OR
n.summary CONTAINS $searchTerm OR
n.title CONTAINS $searchTerm
)
RETURN labels(n)[0] AS source,
COALESCE(n.title, n.subject, 'Thread') AS title,
COALESCE(n.call_date, n.created_at, n.sent_at) AS date
ORDER BY date DESC
LIMIT 20
Using the Graph RAG API
The Graph RAG API at http://graph-rag-api:8000 provides a higher-level interface:
curl -X POST http://graph-rag-api:8000/query \
-H "Content-Type: application/json" \
-d '{"query": "What did we discuss with Acme Corp last month?"}'
The API uses a SmolAgents CodeAgent that:
- Generates embeddings for your query
- Searches across all 4 data sources
- Uses Cypher queries for structured filtering
- Returns synthesized answers with source citations
Execution Examples
Direct Neo4j Query
neo4j_execute_query({
query: `
MATCH (p:Parent)
WHERE p.company CONTAINS $company
RETURN p.title, p.summary, p.call_date
ORDER BY p.call_date DESC
LIMIT 5
`,
params: { company: "Acme" }
})
Create a Node
neo4j_create_node({
label: "Note",
properties: {
content: "Important meeting note",
created_at: new Date().toISOString()
}
})
Create a Relationship
neo4j_create_relationship({
fromNodeId: 123,
toNodeId: 456,
type: "MENTIONED_IN",
properties: { context: "Sales discussion" }
})
Best Practices
- Use parameterized queries: Always use
$paramNamesyntax to prevent injection - Add LIMIT clauses: Prevent returning too much data
- Use indexes: Query on indexed properties (id, company, call_date) for performance
- Prefer vector search: For semantic queries, vector similarity is more accurate than text matching
- Filter by date: Narrow results by time range when possible
Common Mistakes to Avoid
- Wrong node label: Use
Parentfor Fireflies, notCallorTranscript - Wrong date property: Use
call_datefor Parent nodes,created_atfor others - Missing LIMIT: Always limit results to avoid memory issues
- Case sensitivity: Use
CONTAINSfor case-insensitive search, ortoLower()
Troubleshooting
No results returned
- Check node label spelling (case-sensitive)
- Verify property names exist
- Try broader search terms
- Check date formats (use ISO 8601)
Slow queries
- Add LIMIT clause
- Use indexed properties in WHERE
- Avoid
CONTAINSon large text fields - Use vector search instead of text matching