> This page is for version v4 (default).
> For other versions, use one of these documentation indexes:
> - v4 (default): https://docs-beta.getzep.com/v4/llms.txt
> - v3: https://docs-beta.getzep.com/v3/llms.txt
> - v2: https://docs-beta.getzep.com/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs-beta.getzep.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-beta.getzep.com/_mcp/server.

# Episodes

## Overview

An **episode** is a raw data artifact a developer hands to Zep — a chat message, a freeform text chunk, or a JSON object. Zep stores each episode verbatim alongside the entities, edges, and summaries it derives from that data, so the original source remains available even after extraction has finished. Thread messages are also episodes: each call to [`thread.add_messages`](/adding-messages) persists a `message` episode on the user's graph.

Use episodes when an agent needs the original ingested source content. For
example, an application can quote the wording associated with a fact, cite the
source, or retrieve surrounding content that did not become a fact. An episode
records what the application ingested. It does not establish that the source
content is true.

## Ingestion

Episodes enter Zep in two ways:

* [`thread.add_messages`](/adding-messages) for conversational data — each message becomes a `message` episode on a [thread](/threads).
* [`graph.episode.add`](/adding-business-data) for non-conversational data, with `type` set to `text` (a document excerpt, note, or transcript) or `json` (a structured record such as a CRM entry, ticket, or event). Pass a [`document_id`](/documents) when extraction of an episode reads better against earlier episodes in that group, most often to resolve a pronoun.

## Content policy state

An episode of a graph with a bound [content policy](/content-policies) carries a `content_policy` object with `status`, `revision`, `violated`, `category_keys`, `retained_count`, and `dropped_count`. Zep evaluates the artifacts that it derives from the episode, not the episode text, and drops each artifact that matches a rule. The episode is `processed` only after `content_policy.status` reaches `complete`. A `pending` or `failed` evaluation leaves `processed: false`. By default, episode lists and episode search omit an episode whose `violated` is `true`. The project setting `include_policy_violating_episodes` includes them again.

## Retrieval

The SDK lets you list the episodes of a graph, fetch one by UUID, list the episodes of a [document](/documents), or search a graph for episodes.

Each call takes the UUID of a graph. For a user graph, use the `graph_uuid` that `user.create` returns. Store this UUID in your application database next to your own user ID.

### List and fetch

**`Python`**

```python Python
from zep_cloud.client import Zep

client = Zep(api_key=API_KEY)

# The graph_uuid of the user, from your application database.
graph_uuid = zep_graph_uuid

# List the episodes on a user's graph.
# The pager fetches the next page when you iterate.
episodes = client.graph.episode.list(graph_uuid, limit=20)

for ep in episodes:
    print(ep.reference_time, ep.source, ep.content)

# Fetch a single item by UUID.
item = client.graph.episode.get(graph_uuid, episode_uuid)
```

**`TypeScript`**

```typescript TypeScript
import { ZepClient } from "@getzep/zep-cloud";

const client = new ZepClient({ apiKey: API_KEY });

// The graph UUID of the user, from your application database.
const graphUuid = zepGraphUuid;

// List the episodes on a user's graph.
// The pager fetches the next page when you iterate.
const episodes = await client.graph.episode.list(graphUuid, { limit: 20, body: {} });

for await (const ep of episodes) {
  console.log(ep.referenceTime, ep.source, ep.content);
}

// Fetch a single item by UUID.
const item = await client.graph.episode.get(graphUuid, episodeUuid);
```

**`Go`**

```go Go
import (
    "context"
    "fmt"

    zep "github.com/getzep/zep-go/v4"
    zepclient "github.com/getzep/zep-go/v4/client"
    "github.com/getzep/zep-go/v4/graph"
    "github.com/getzep/zep-go/v4/option"
)

client := zepclient.NewClient(option.WithAPIKey(API_KEY))

// The graph UUID of the user, from your application database.
graphUUID := zepGraphUUID

// List the episodes on a user's graph.
// The iterator fetches the next page when it reaches the end of a page.
episodes, err := client.Graph.Episode.List(
    context.TODO(),
    graphUUID,
    &graph.EpisodeListRequest{Limit: zep.Int(20)},
)
if err != nil {
    // handle error
}

iter := episodes.Iterator()
for iter.Next(context.TODO()) {
    ep := iter.Current()
    fmt.Println(*ep.ReferenceTime, *ep.Source, *ep.Content)
}
if err := iter.Err(); err != nil {
    // handle error
}

// Fetch a single item by UUID.
item, err := client.Graph.Episode.Get(context.TODO(), graphUUID, episodeUUID)
```

Episode lists use cursor pagination. The SDK pager fetches the next page when you iterate. Set `limit` to control the page size. To list the episodes of one document, use `graph.episode.list_for_document`.

### Search

To get the episodes most relevant to a query — for example, the source quotes behind a fact in the Context Block — use `graph.search_episodes`. The call returns one page of results. See [graph search](/searching-the-graph) for the full search API:

**`Python`**

```python Python
results = client.graph.search_episodes(
    graph_uuid,
    query="payment failure",
    limit=5,
)

for ep in results.items or []:
    print(ep.content, ep.score)
```

**`TypeScript`**

```typescript TypeScript
const results = await client.graph.searchEpisodes(graphUuid, {
  limit: 5,
  body: { query: "payment failure" },
});

for (const ep of results.data) {
  console.log(ep.content, ep.score);
}
```

**`Go`**

```go Go
results, err := client.Graph.SearchEpisodes(context.TODO(), graphUUID, &zep.GraphSearchEpisodesRequest{
    Limit: zep.Int(5),
    Body:  &zep.SearchRequest{Query: "payment failure"},
})
if err != nil {
    // handle error
}

for _, ep := range results.Results {
    fmt.Println(*ep.Content, *ep.Score)
}
```

## Episodes and the Context Block

Episodes are included in the default [Context Block](/retrieving-context): the episodes most relevant to the user's recent messages are rendered alongside facts and entities. To customize which episodes appear or how they are formatted, define a [context template](/context-templates) using the `%{episodes}` variable, or build a custom block via [advanced context block construction](/advanced-context-block-construction).