Graph Namespacing

Using group_ids to create isolated graph namespaces

Overview

Graphiti supports the concept of graph namespacing through the use of group_id parameters. Namespacing creates isolated graph environments within one Graphiti instance, enabling multiple distinct knowledge graphs to coexist without interference.

Graph namespacing is particularly useful for:

  • Multi-tenant applications: Isolate data between different customers or organizations
  • Testing environments: Maintain separate development, testing, and production graphs
  • Domain-specific knowledge: Create specialized graphs for different domains or use cases
  • Team collaboration: Allow different teams to work with their own graph spaces

How Namespacing Works

In Graphiti, every node and edge can be associated with a group_id. When you specify a group_id, you’re effectively creating a namespace for that data. Nodes and edges with the same group_id form a cohesive, isolated graph that can be queried and manipulated independently from other namespaces.

Key Benefits

  • Data isolation: Prevent data leakage between different namespaces
  • Simplified management: Organize and manage related data together
  • Performance optimization: Improve query performance by limiting the search space
  • Flexible architecture: Support multiple use cases within a single Graphiti instance

Using group_ids in Graphiti

Adding Episodes with group_id

When adding episodes to your graph, you can specify a group_id to namespace the episode and all its extracted entities:

1await graphiti.add_episode(
2 name="customer_interaction",
3 episode_body="Customer Jane mentioned she loves our new SuperLight Wool Runners in Dark Grey.",
4 source=EpisodeType.text,
5 source_description="Customer feedback",
6 reference_time=datetime.now(),
7 group_id="customer_team" # This namespaces the episode and its entities
8)

Adding Fact Triples with group_id

When manually adding fact triples, ensure both nodes and the edge share the same group_id:

1from graphiti_core.nodes import EntityNode
2from graphiti_core.edges import EntityEdge
3import uuid
4from datetime import datetime
5
6# Define a namespace for this data
7namespace = "product_catalog"
8
9# Create source and target nodes with the namespace
10source_node = EntityNode(
11 uuid=str(uuid.uuid4()),
12 name="SuperLight Wool Runners",
13 group_id=namespace # Apply namespace to source node
14)
15
16target_node = EntityNode(
17 uuid=str(uuid.uuid4()),
18 name="Sustainable Footwear",
19 group_id=namespace # Apply namespace to target node
20)
21
22# Create an edge with the same namespace
23edge = EntityEdge(
24 group_id=namespace, # Apply namespace to edge
25 source_node_uuid=source_node.uuid,
26 target_node_uuid=target_node.uuid,
27 created_at=datetime.now(),
28 name="is_category_of",
29 fact="SuperLight Wool Runners is a product in the Sustainable Footwear category"
30)
31
32# Add the triplet to the graph
33await graphiti.add_triplet(source_node, edge, target_node)

Querying Within a Namespace

When querying the graph, specify the group_id to limit results to a particular namespace:

1# Search within a specific namespace
2search_results = await graphiti.search(
3 query="Wool Runners",
4 group_id="product_catalog" # Only search within this namespace
5)
6
7# For more advanced node-specific searches, use the _search method with a recipe
8from graphiti_core.search.search_config_recipes import NODE_HYBRID_SEARCH_RRF
9
10# Create a search config for nodes only
11node_search_config = NODE_HYBRID_SEARCH_RRF.model_copy(deep=True)
12node_search_config.limit = 5 # Limit to 5 results
13
14# Execute the node search within a specific namespace
15node_search_results = await graphiti._search(
16 query="SuperLight Wool Runners",
17 group_id="product_catalog", # Only search within this namespace
18 config=node_search_config
19)

Best Practices for Graph Namespacing

  1. Consistent naming: Use a consistent naming convention for your group_id values
  2. Documentation: Maintain documentation of your namespace structure and purpose
  3. Granularity: Choose an appropriate level of granularity for your namespaces
    • Too many namespaces can lead to fragmented data
    • Too few namespaces may not provide sufficient isolation
  4. Cross-namespace queries: When necessary, perform multiple queries across namespaces and combine results in your application logic

Example: Multi-tenant Application

Here’s an example of using namespacing in a multi-tenant application:

1async def add_customer_data(tenant_id, customer_data):
2 """Add customer data to a tenant-specific namespace"""
3
4 # Use the tenant_id as the namespace
5 namespace = f"tenant_{tenant_id}"
6
7 # Create an episode for this customer data
8 await graphiti.add_episode(
9 name=f"customer_data_{customer_data['id']}",
10 episode_body=customer_data,
11 source=EpisodeType.json,
12 source_description="Customer profile update",
13 reference_time=datetime.now(),
14 group_id=namespace # Namespace by tenant
15 )
16
17async def search_tenant_data(tenant_id, query):
18 """Search within a tenant's namespace"""
19
20 namespace = f"tenant_{tenant_id}"
21
22 # Only search within this tenant's namespace
23 return await graphiti.search(
24 query=query,
25 group_id=namespace
26 )