Episodes are the fundamental units of information in Graphiti. An episode is any piece of input data—structured or unstructured—that you want to integrate into your knowledge graph. Think of episodes as the raw material that Graphiti processes to extract entities and relationships.
await graphiti.add_episode( name="User Message", episode_body="Alice started working at Acme Corp as a Senior Engineer.", source=EpisodeType.text, source_description="chat message", reference_time=datetime.now(timezone.utc),)
For conversational data with actor-content format:
await graphiti.add_episode( name="Customer Support Chat", episode_body="user: My order hasn't arrived yet.\nassistant: I'll check on that for you.", source=EpisodeType.message, source_description="support ticket #1234", reference_time=datetime.now(timezone.utc),)
For EpisodeType.message, format content as "actor: content" on each line. Example: "user: Hello\nassistant: Hi there"
await graphiti.add_episode( name="Company Blog Post", episode_body="""We're excited to announce our new product launch. The team, led by Sarah Johnson, has been working on this for 18 months. The product will be available in Q2 2024.""", source=EpisodeType.text, source_description="company blog", reference_time=datetime(2024, 3, 1, tzinfo=timezone.utc),)
When you add an episode, Graphiti creates an EpisodicNode in the graph:
class EpisodicNode(Node): name: str # Episode identifier content: str # Raw episode data source: EpisodeType # Type of episode source_description: str # Description of data source valid_at: datetime # When the content occurred created_at: datetime # When ingested into Graphiti entity_edges: list[str] # UUIDs of extracted EntityEdges group_id: str # Partition identifier
Understanding the temporal distinction is crucial:
Field
What It Represents
Example
reference_time
When the episode content occurred
Email sent on Jan 15, 2024
valid_at
Same as reference_time (stored in node)
2024-01-15
created_at
When Graphiti ingested the episode
Processed on Mar 20, 2024
# You find an old email from 2020await graphiti.add_episode( name="Old Email", episode_body="Meeting notes from project kickoff.", source=EpisodeType.text, reference_time=datetime(2020, 3, 15, tzinfo=timezone.utc), # Email date # created_at will be set to now (2024-03-20))
Graphiti uses reference_time to set the valid_at timestamp on extracted edges, ensuring facts are temporally grounded to when they occurred, not when they were processed.
For efficient batch ingestion, use add_episode_bulk():
from graphiti_core.utils.bulk_utils import RawEpisodebulk_episodes = [ RawEpisode( name=f"Email {i}", content=email_texts[i], source=EpisodeType.text, source_description="email archive", reference_time=email_dates[i], ) for i in range(100)]result = await graphiti.add_episode_bulk( bulk_episodes=bulk_episodes, group_id="email_archive",)
add_episode_bulk() processes multiple episodes in parallel for better performance but does not perform edge invalidation. Use add_episode() for incremental updates with contradiction handling.
Sagas group related episodes into a narrative sequence:
# Add episodes to a sagafor i, message in enumerate(conversation_messages): result = await graphiti.add_episode( name=f"Message {i}", episode_body=message, source=EpisodeType.message, reference_time=message_timestamps[i], saga="customer_support_conversation_123", # Saga name )
Graphiti automatically:
Creates a SagaNode (or reuses existing)
Creates HAS_EPISODE edges from saga to episodes
Creates NEXT_EPISODE edges to chain episodes in order
# Retrieve episodes from a specific sagaepisodes = await graphiti.retrieve_episodes( reference_time=datetime.now(timezone.utc), saga="customer_support_conversation_123")# Returns episodes in chronological order
# Good: Use the actual event timereference_time=email_metadata['sent_date']# Bad: Using current time for historical datareference_time=datetime.now(timezone.utc) # Wrong for old data!
# For chat messagessource=EpisodeType.message# For API responses, database recordssource=EpisodeType.json# For documents, articles, emailssource=EpisodeType.text