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

# Adding Business Data

> **Warning**
>
> Requests to add data to the same graph are completed sequentially to ensure the graph is built correctly, and processing may be slow for large datasets. For large historical datasets, use [batch ingestion](/adding-batch-data).

#### [Backfilling historical data? Use an ingestion pipeline](/zep-ingest)

[`zep-ingest`](/zep-ingest) is the recommended path for bulk and historical imports. Prepare the records in the form the package requires. Then run a pipeline. The pipeline adds preparation, ordering, preview, and monitoring on top of the `graph.add` calls below. For an individual write such as a webhook payload or an API response, call `graph.add` directly.

Use `graph.add` to add business records, documents, events, and communications
to a Context Graph. Zep supports three data types: JSON, text, and message.

## Choose the destination and source information

Use `graph_id` when the context belongs to a shared customer account, project,
product, organization, or business domain. Use `user_id` when the context
belongs to one application user. Set exactly one of these identifiers.

Use `source_description` to give a human-readable description of the source.
Use `metadata` for source attributes that your application will use for search
filters, traceability, or access policies.

```python
import json

new_episode = client.graph.add(
    graph_id="account-acme",
    type="json",
    data=json.dumps({
        "account_id": "acme",
        "plan": "Enterprise",
        "region": "eu-west",
    }),
    source_description="Account record from the CRM",
    metadata={"source": "crm", "account_id": "acme"},
)
```

The source description and metadata do not establish that the source content is
true. See [Source traceability](/source-traceability) for the relationship
between episodes and derived graph data.

The message type is ideal for adding data in the form of chat messages that are not directly associated with a Zep [Thread's](/threads) chat history. This encompasses any communication with a designated speaker, such as emails or previous chat logs.

The text type is designed for raw text data without a specific speaker attribution. This category includes content from internal documents, wiki articles, or company handbooks. It's important to note that Zep does not process text directly from links or files.

The JSON type may be used to add any JSON document to Zep. This may include REST API responses or JSON-formatted business data.

## Adding Message Data

Here's an example demonstrating how to add message data to the graph:

**`Python`**

```python Python
from zep_cloud.client import Zep

client = Zep(
    api_key=API_KEY,
)

message = "Paul (user): I went to Eric Clapton concert last night"

new_episode = client.graph.add(
    user_id="user123",    # Optional: You can use graph_id instead of user_id
    type="message",       # Specify type as "message"
    data=message
)
```

**`TypeScript`**

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

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

const message = "User: I really enjoy working with TypeScript and React";

const newEpisode = await client.graph.add({
    userId: "user123",  // Optional: You can use graphId instead of userId
    type: "message",
    data: message
});
```

**`Go`**

```go Go
import (
    "context"
    "log"

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

client := zepclient.NewClient(
    option.WithAPIKey(apiKey),
)

message := "Paul (user): I went to Eric Clapton concert last night"
userID := "user123"

newEpisode, err := client.Graph.Add(context.TODO(), &zep.AddDataRequest{
    UserID: &userID,  // Optional: You can use GraphID instead of UserID
    Type:   zep.GraphDataTypeMessage,
    Data:   message,
})
if err != nil {
    log.Fatalf("Failed to add message data: %v", err)
}
```

## Adding Text Data

Here's an example demonstrating how to add text data to the graph:

**`Python`**

```python Python
from zep_cloud.client import Zep

client = Zep(
    api_key=API_KEY,
)

new_episode = client.graph.add(
    user_id="user123",  # Optional: You can use graph_id instead of user_id
    type="text",        # Specify type as "text"
    data="The user is an avid fan of Eric Clapton"
)
```

**`TypeScript`**

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

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

const newEpisode = await client.graph.add({
    userId: "user123",  // Optional: You can use graphId instead of userId
    type: "text",
    data: "The user is interested in machine learning and artificial intelligence"
});
```

**`Go`**

```go Go
import (
    "context"
    "log"

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

client := zepclient.NewClient(
    option.WithAPIKey(apiKey),
)

userID := "user123"

newEpisode, err := client.Graph.Add(context.TODO(), &zep.AddDataRequest{
    UserID: &userID,  // Optional: You can use GraphID instead of UserID
    Type:   zep.GraphDataTypeText,
    Data:   "The user is an avid fan of Eric Clapton",
})
if err != nil {
    log.Fatalf("Failed to add text data: %v", err)
}
```

## Adding JSON Data

> **Tip**
>
> Before ingesting JSON, [name and contextualize each record](/prepare-data-for-ingestion#name-and-contextualize-json-records) so Zep builds an accurate graph from it.

Here's an example demonstrating how to add JSON data to the graph:

**`Python`**

```python Python
from zep_cloud.client import Zep
import json

client = Zep(
    api_key=API_KEY,
)

json_data = {"name": "Eric Clapton", "age": 78, "genre": "Rock"}
json_string = json.dumps(json_data)
new_episode = client.graph.add(
    user_id=user_id,  # Optional: You can use graph_id instead of user_id
    type="json",
    data=json_string,
)
```

**`TypeScript`**

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

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

const jsonString = '{"name": "Eric Clapton", "age": 78, "genre": "Rock"}';
const newEpisode = await client.graph.add({
    userId: userId,  // Optional: You can use graphId instead of userId
    type: "json",
    data: jsonString,
});
```

**`Go`**

```go Go
import (
    "context"
    "encoding/json"
    "log"

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

client := zepclient.NewClient(
    option.WithAPIKey(apiKey),
)

jsonData := map[string]interface{}{
    "name":  "Eric Clapton",
    "age":   78,
    "genre": "Rock",
}
jsonBytes, err := json.Marshal(jsonData)
if err != nil {
    log.Fatalf("Failed to marshal JSON: %v", err)
}
jsonString := string(jsonBytes)

userID := "user123"

newEpisode, err := client.Graph.Add(context.TODO(), &zep.AddDataRequest{
    UserID: &userID,  // Optional: You can use GraphID instead of UserID
    Type:   zep.GraphDataTypeJSON,
    Data:   jsonString,
})
if err != nil {
    log.Fatalf("Failed to add JSON data: %v", err)
}
```

## Setting data timestamps

When adding data via the `graph.add` method, you can provide the `created_at` timestamp in RFC3339 format. The `created_at` timestamp represents the time when the data was originally created. For messages, this would be when the message was originally sent. For events represented as JSON, this would be when the event occurred. Setting the `created_at` timestamp ensures the user's Context Graph has accurate temporal understanding of user history (since this time is used in our fact invalidation process).

**`Python`**

```python Python
from zep_cloud.client import Zep
import json

client = Zep(
    api_key=API_KEY,
)

# Example: Adding a JSON event with its original timestamp
event_data = {"event": "purchase", "item": "laptop", "amount": 1299.99}
json_string = json.dumps(event_data)

new_episode = client.graph.add(
    user_id="user123",
    type="json",
    data=json_string,
    created_at="2025-06-01T13:11:12Z"  # Time the event originally occurred
)
```

**`TypeScript`**

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

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

// Example: Adding a JSON event with its original timestamp
const eventData = JSON.stringify({ event: "purchase", item: "laptop", amount: 1299.99 });

const newEpisode = await client.graph.add({
    userId: "user123",
    type: "json",
    data: eventData,
    createdAt: "2025-06-01T13:11:12Z"  // Time the event originally occurred
});
```

**`Go`**

```go Go
import (
    "context"
    "encoding/json"
    "log"

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

client := zepclient.NewClient(
    option.WithAPIKey(apiKey),
)

// Example: Adding a JSON event with its original timestamp
eventData := map[string]interface{}{
    "event":  "purchase",
    "item":   "laptop",
    "amount": 1299.99,
}
jsonBytes, err := json.Marshal(eventData)
if err != nil {
    log.Fatalf("Failed to marshal JSON: %v", err)
}
jsonString := string(jsonBytes)

userID := "user123"
createdAt := "2025-06-01T13:11:12Z"  // Time the event originally occurred

newEpisode, err := client.Graph.Add(context.TODO(), &zep.AddDataRequest{
    UserID:    &userID,
    Type:      zep.GraphDataTypeJSON,
    Data:      jsonString,
    CreatedAt: &createdAt,
})
if err != nil {
    log.Fatalf("Failed to add JSON data: %v", err)
}
```

## Grouping episodes with a document ID

Assign a [`document_id`](/documents) when extraction of a later episode needs earlier episodes. For example, an earlier episode can identify the subject of a pronoun.

Pass the same ID on each add in the group. See [Documents](/documents).

Zep scopes prior-episode context to that ID, so extraction can resolve pronouns and other references against the earlier episodes. Zep also generates an incremental document summary.

Omit `document_id` for independent records that share only a folder, customer, or export. `document_id` is optional and 1 to 100 characters. Use a stable identifier from the source system.

## Data Size Limit and Chunking

The `graph.add` endpoint has a data size limit of 10,000 characters when adding data to the graph. If you need to add a document which is more than 10,000 characters, see our [Chunking Large Documents](/chunking-large-documents) cookbook for a complete implementation with contextualized retrieval and best practices for chunking for Zep. Pass the same [`document_id`](/documents) on every chunk so Zep treats them as one source.

## Episode metadata

You can attach key-value metadata to episodes when adding data. Metadata is useful for tagging episodes with their data source, category, priority, or other attributes. Zep [projects this metadata onto every graph artifact derived from the episode](/episode-metadata-projection), which is what lets you [filter graph search results](/searching-the-graph#episode-metadata-filtering) so that only facts derived from matching episodes are returned.

Metadata values must be scalars (string, number (int/float), or boolean) or non-empty arrays of such scalars, such as `{"tags": ["red", "blue"]}`. A maximum of 10 keys are allowed per episode. Nested objects are not supported, and empty arrays or arrays containing null are rejected.

**`Python`**

```python Python
from zep_cloud.client import Zep

client = Zep(
    api_key=API_KEY,
)

new_episode = client.graph.add(
    user_id="user123",
    type="text",
    data="Patient blood glucose level was 95 mg/dL, within normal range.",
    metadata={"source": "lab_report", "priority": 5, "reviewed": True},
)
```

**`TypeScript`**

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

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

const newEpisode = await client.graph.add({
    userId: "user123",
    type: "text",
    data: "Patient blood glucose level was 95 mg/dL, within normal range.",
    metadata: { source: "lab_report", priority: 5, reviewed: true },
});
```

**`Go`**

```go Go
import (
    "context"
    "log"

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

client := zepclient.NewClient(
    option.WithAPIKey(apiKey),
)

userID := "user123"

newEpisode, err := client.Graph.Add(context.TODO(), &zep.AddDataRequest{
    UserID: &userID,
    Type:   zep.GraphDataTypeText,
    Data:   "Patient blood glucose level was 95 mg/dL, within normal range.",
    Metadata: map[string]interface{}{
        "source":   "lab_report",
        "priority": 5,
        "reviewed": true,
    },
})
if err != nil {
    log.Fatalf("Failed to add data: %v", err)
}
```

### Updating episode metadata

You can update an episode's metadata after creation using merge semantics: new keys are added, existing keys are overwritten, and keys set to `null` are removed.

**`Python`**

```python Python
from zep_cloud.client import Zep

client = Zep(
    api_key=API_KEY,
)

# Original metadata: {"source": "lab_report", "priority": 5, "reviewed": True}
updated_episode = client.graph.episode.update(
    uuid_=episode_uuid,
    metadata={"priority": 10, "department": "endocrinology", "reviewed": None},
)
# Result: {"source": "lab_report", "priority": 10, "department": "endocrinology"}
# "priority" was overwritten, "department" was added, "reviewed" was removed
```

**`TypeScript`**

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

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

// Original metadata: { source: "lab_report", priority: 5, reviewed: true }
const updatedEpisode = await client.graph.episode.update(episodeUuid, {
    metadata: { priority: 10, department: "endocrinology", reviewed: null },
});
// Result: { source: "lab_report", priority: 10, department: "endocrinology" }
// "priority" was overwritten, "department" was added, "reviewed" was removed
```

**`Go`**

```go Go
import (
    "context"
    "log"

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

client := zepclient.NewClient(
    option.WithAPIKey(apiKey),
)

// Original metadata: {"source": "lab_report", "priority": 5, "reviewed": true}
updatedEpisode, err := client.Graph.Episode.Update(context.TODO(), episodeUUID, &zep.EpisodeUpdateRequest{
    Metadata: map[string]interface{}{
        "priority":   10,
        "department": "endocrinology",
        "reviewed":   nil,
    },
})
if err != nil {
    log.Fatalf("Failed to update episode: %v", err)
}
// Result: {"source": "lab_report", "priority": 10, "department": "endocrinology"}
// "priority" was overwritten, "department" was added, "reviewed" was removed
```

## Managing Your Data on the Graph

The `graph.add` method returns the
[episode](/graphiti/core-concepts/adding-episodes) that was created when you
added the data. You can maintain a mapping between your data and its episode.
You can then delete specific data from the graph with the
[delete episode](/deleting-data-from-the-graph#delete-an-episode) method.