Skip to main content

Overview

This quickstart demonstrates how to build a temporally-aware knowledge graph with Graphiti. You’ll learn how to:
  • Connect to a graph database
  • Add episodes (data) to your knowledge graph
  • Search for relationships and entities
  • Use graph-based reranking for contextual results
This guide uses Neo4j as the graph database backend. Graphiti also supports FalkorDB, Kuzu, and Amazon Neptune.

Prerequisites

Before you begin, ensure you have:
  • Python 3.10 or higher
  • A graph database running (Neo4j, FalkorDB, Kuzu, or Amazon Neptune)
  • An OpenAI API key
The simplest way to get started is with Neo4j Desktop or FalkorDB via Docker:
docker run -p 6379:6379 -p 3000:3000 -it --rm falkordb/falkordb:latest

Step 1: Install Graphiti

Install Graphiti using your preferred package manager:
pip install graphiti-core

Step 2: Set Up Environment Variables

Create a .env file or export environment variables:
.env
# Required for LLM and embeddings
OPENAI_API_KEY=your_openai_api_key

# Neo4j connection (adjust if using different backend)
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=password
Keep your API keys secure. Never commit them to version control.

Step 3: Initialize Graphiti

Create a new Python file and initialize your Graphiti instance:
quickstart.py
import asyncio
import os
from datetime import datetime, timezone
from dotenv import load_dotenv
from graphiti_core import Graphiti
from graphiti_core.nodes import EpisodeType

load_dotenv()

# Get connection parameters from environment
neo4j_uri = os.environ.get('NEO4J_URI', 'bolt://localhost:7687')
neo4j_user = os.environ.get('NEO4J_USER', 'neo4j')
neo4j_password = os.environ.get('NEO4J_PASSWORD', 'password')

async def main():
    # Initialize Graphiti with Neo4j connection
    graphiti = Graphiti(neo4j_uri, neo4j_user, neo4j_password)
    
    try:
        # Your code goes here
        pass
    finally:
        # Always close the connection
        await graphiti.close()
        print('Connection closed')

if __name__ == '__main__':
    asyncio.run(main())
Graphiti defaults to using OpenAI for LLM inference and embeddings. Set OPENAI_API_KEY in your environment.

Step 4: Add Episodes to Your Graph

Episodes are the primary units of information in Graphiti. They can be text or structured JSON and are automatically processed to extract entities and relationships.
1

Define Your Episodes

Create a list of episodes with both text and JSON content:
episodes = [
    {
        'content': 'Kamala Harris is the Attorney General of California. '
                  'She was previously the district attorney for San Francisco.',
        'type': EpisodeType.text,
        'description': 'podcast transcript',
    },
    {
        'content': 'As AG, Harris was in office from January 3, 2011 – January 3, 2017',
        'type': EpisodeType.text,
        'description': 'podcast transcript',
    },
    {
        'content': {
            'name': 'Gavin Newsom',
            'position': 'Governor',
            'state': 'California',
            'previous_role': 'Lieutenant Governor',
        },
        'type': EpisodeType.json,
        'description': 'podcast metadata',
    },
]
2

Add Episodes to the Graph

Process each episode and add it to your knowledge graph:
import json

for i, episode in enumerate(episodes):
    await graphiti.add_episode(
        name=f'Podcast Episode {i}',
        episode_body=episode['content'] 
            if isinstance(episode['content'], str) 
            else json.dumps(episode['content']),
        source=episode['type'],
        source_description=episode['description'],
        reference_time=datetime.now(timezone.utc),
    )
    print(f"Added episode {i}: {episode['type'].value}")
Graphiti automatically:
  • Extracts entities (nodes) like “Kamala Harris” and “California”
  • Identifies relationships (edges) like “is Attorney General of”
  • Creates embeddings for semantic search
  • Tracks temporal information

Step 5: Search Your Knowledge Graph

Now that you’ve added data, you can search for information using hybrid search that combines semantic similarity and keyword matching. Search for relationships (edges) in your graph:
print("\nSearching for: 'Who was the California Attorney General?'")
results = await graphiti.search('Who was the California Attorney General?')

# Print search results
print('\nSearch Results:')
for result in results:
    print(f'Fact: {result.fact}')
    if result.valid_at:
        print(f'Valid from: {result.valid_at}')
    if result.invalid_at:
        print(f'Valid until: {result.invalid_at}')
    print('---')
The search() method performs hybrid search combining:
  • Semantic similarity using embeddings
  • BM25 keyword matching
  • Graph-based retrieval

Graph-Aware Reranking

For more contextually relevant results, use a center node to rerank search results based on their graph distance:
if results and len(results) > 0:
    # Get the source node UUID from the top result
    center_node_uuid = results[0].source_node_uuid
    
    print(f'\nReranking with center node: {center_node_uuid}')
    
    reranked_results = await graphiti.search(
        'Who was the California Attorney General?',
        center_node_uuid=center_node_uuid
    )
    
    print('\nReranked Search Results:')
    for result in reranked_results:
        print(f'Fact: {result.fact}')
        print('---')
Graph-based reranking prioritizes results that are closer in the graph structure to a specific node, giving you more contextually relevant information.

Node Search with Recipes

Graphiti provides predefined search recipes optimized for different scenarios:
from graphiti_core.search.search_config_recipes import NODE_HYBRID_SEARCH_RRF

# Configure a node search recipe
node_search_config = NODE_HYBRID_SEARCH_RRF.model_copy(deep=True)
node_search_config.limit = 5

# Execute the node search
node_results = await graphiti._search(
    query='California Governor',
    config=node_search_config,
)

print('\nNode Search Results:')
for node in node_results.nodes:
    print(f'Node Name: {node.name}')
    print(f'Summary: {node.summary[:100]}...')
    print(f'Labels: {", ".join(node.labels)}')
    print('---')

Complete Example

Here’s the full working example:
quickstart.py
import asyncio
import json
import os
from datetime import datetime, timezone
from dotenv import load_dotenv

from graphiti_core import Graphiti
from graphiti_core.nodes import EpisodeType
from graphiti_core.search.search_config_recipes import NODE_HYBRID_SEARCH_RRF

load_dotenv()

neo4j_uri = os.environ.get('NEO4J_URI', 'bolt://localhost:7687')
neo4j_user = os.environ.get('NEO4J_USER', 'neo4j')
neo4j_password = os.environ.get('NEO4J_PASSWORD', 'password')

async def main():
    # Initialize Graphiti
    graphiti = Graphiti(neo4j_uri, neo4j_user, neo4j_password)
    
    try:
        # Define episodes
        episodes = [
            {
                'content': 'Kamala Harris is the Attorney General of California. '
                          'She was previously the district attorney for San Francisco.',
                'type': EpisodeType.text,
                'description': 'podcast transcript',
            },
            {
                'content': 'As AG, Harris was in office from January 3, 2011 – January 3, 2017',
                'type': EpisodeType.text,
                'description': 'podcast transcript',
            },
            {
                'content': {
                    'name': 'Gavin Newsom',
                    'position': 'Governor',
                    'state': 'California',
                },
                'type': EpisodeType.json,
                'description': 'podcast metadata',
            },
        ]
        
        # Add episodes
        for i, episode in enumerate(episodes):
            await graphiti.add_episode(
                name=f'Podcast Episode {i}',
                episode_body=episode['content'] 
                    if isinstance(episode['content'], str) 
                    else json.dumps(episode['content']),
                source=episode['type'],
                source_description=episode['description'],
                reference_time=datetime.now(timezone.utc),
            )
            print(f"Added episode {i}")
        
        # Search for edges
        print("\nSearching: 'Who was the California Attorney General?'")
        results = await graphiti.search('Who was the California Attorney General?')
        
        for result in results:
            print(f'Fact: {result.fact}')
            print('---')
        
        # Search with reranking
        if results:
            center_node_uuid = results[0].source_node_uuid
            reranked = await graphiti.search(
                'Who was the California Attorney General?',
                center_node_uuid=center_node_uuid
            )
            print(f'\nReranked results: {len(reranked)} found')
        
        # Node search
        node_config = NODE_HYBRID_SEARCH_RRF.model_copy(deep=True)
        node_config.limit = 5
        
        node_results = await graphiti._search(
            query='California Governor',
            config=node_config,
        )
        
        print(f'\nNode search results: {len(node_results.nodes)} found')
        for node in node_results.nodes:
            print(f'- {node.name}')
    
    finally:
        await graphiti.close()

if __name__ == '__main__':
    asyncio.run(main())

Next Steps

Now that you have a working knowledge graph:

Explore Different Backends

Try FalkorDB, Kuzu, or Amazon Neptune

Use Different LLM Providers

Configure Anthropic, Google Gemini, or Ollama

Custom Entity Types

Define domain-specific entities and relationships

Advanced Search

Learn about search recipes and filtering

Troubleshooting

Ensure your graph database is running:Neo4j: Check Neo4j Desktop and verify your DBMS is startedFalkorDB: Verify Docker container is running with docker psConnection refused: Double-check URI, username, and password in your environment variables
  • Verify OPENAI_API_KEY is set correctly
  • Check you have sufficient API credits
  • Ensure you’re using a supported model (defaults to gpt-4o-mini)
Graphiti defaults to low concurrency (SEMAPHORE_LIMIT=10) to avoid rate limits. If you still encounter 429 errors:
export SEMAPHORE_LIMIT=5
If your LLM provider allows higher throughput, increase this value for better performance.
The Neo4j driver defaults to the neo4j database. To use a different database:
from graphiti_core.driver.neo4j_driver import Neo4jDriver

driver = Neo4jDriver(
    uri=neo4j_uri,
    user=neo4j_user,
    password=neo4j_password,
    database="your_db_name"
)
graphiti = Graphiti(graph_driver=driver)

Build docs developers (and LLMs) love