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

> 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.

# Hyperedges

> Create, read, update, and delete hyperedges with the v4 SDKs.

A hyperedge stores one fact that relates more than two nodes. Zep stores the fact on member edges. Each member edge connects two of the nodes, and every member has the same `hyperedge_uuid`.

The hyperedge response holds shared values at the top level: `fact`, `valid_at`, `invalid_at`, `expired_at`, `created_at`, `graph_uuid`, and `uuid`. Each item in `edges` has its own `uuid`, `name`, `source_node_uuid`, and `target_node_uuid`. Zep orders the members by `uuid`.

## Add a hyperedge

Use `graph.edge.add` for a fact about one node pair. Use `graph.hyperedge.add` when the members span at least three distinct nodes.

The request needs `fact` and `edges`. Each member needs a `name`, `source_node`, and `target_node`. You can also set `valid_at`, `invalid_at`, `expired_at`, `attributes`, and `metadata`. Zep stores `attributes` on every member and attaches `metadata` to the episode created for the hyperedge.

Zep assigns the hyperedge UUID and member edge UUIDs when it accepts the task. The member edges become readable after the task completes. Use [task polling](/check-data-ingestion-status) to check completion.

**`Python`**

```python Python
from zep_cloud import EdgeNodeRef, HyperedgeInput

result = client.graph.hyperedge.add(
    graph_uuid,
    fact="Alice introduced Bob to Carol at the conference.",
    edges=[
        HyperedgeInput(
            name="INTRODUCED_TO",
            source_node=EdgeNodeRef(name="Alice"),
            target_node=EdgeNodeRef(name="Bob"),
        ),
        HyperedgeInput(
            name="INTRODUCED_TO",
            source_node=EdgeNodeRef(name="Alice"),
            target_node=EdgeNodeRef(name="Carol"),
        ),
        HyperedgeInput(
            name="MET",
            source_node=EdgeNodeRef(name="Bob"),
            target_node=EdgeNodeRef(name="Carol"),
        ),
    ],
)
```

**`TypeScript`**

```typescript TypeScript
const result = await client.graph.hyperedge.add(graphUuid, {
  fact: "Alice introduced Bob to Carol at the conference.",
  edges: [
    {
      name: "INTRODUCED_TO",
      sourceNode: { name: "Alice" },
      targetNode: { name: "Bob" },
    },
    {
      name: "INTRODUCED_TO",
      sourceNode: { name: "Alice" },
      targetNode: { name: "Carol" },
    },
    {
      name: "MET",
      sourceNode: { name: "Bob" },
      targetNode: { name: "Carol" },
    },
  ],
});
```

**`Go`**

```go Go
result, err := client.Graph.Hyperedge.Add(ctx, graphUUID, &graph.AddHyperedgeRequest{
    Fact: "Alice introduced Bob to Carol at the conference.",
    Edges: []*zep.HyperedgeInput{
        {
            Name:       "INTRODUCED_TO",
            SourceNode: &zep.EdgeNodeRef{Name: zep.String("Alice")},
            TargetNode: &zep.EdgeNodeRef{Name: zep.String("Bob")},
        },
        {
            Name:       "INTRODUCED_TO",
            SourceNode: &zep.EdgeNodeRef{Name: zep.String("Alice")},
            TargetNode: &zep.EdgeNodeRef{Name: zep.String("Carol")},
        },
        {
            Name:       "MET",
            SourceNode: &zep.EdgeNodeRef{Name: zep.String("Bob")},
            TargetNode: &zep.EdgeNodeRef{Name: zep.String("Carol")},
        },
    },
})
if err != nil {
    log.Fatal(err)
}
```

## Read hyperedges

Use `graph.hyperedge.get` to read one hyperedge. If an access policy hides any member, the API returns `404` for the whole hyperedge.

Use `graph.hyperedge.list` to read a page of hyperedges. It supports `node_uuids`, `edge_uuids`, and `episode_uuids` filters. A hyperedge matches a filter when any member matches. It must match every filter you provide. The API rejects other filters. The response has no `total_size`. Zep lists a hyperedge while it has at least one member.

## Update a hyperedge

`graph.hyperedge.update` accepts only `fact`. Zep writes the new fact to every member in one all-or-nothing update. The `name` field belongs to each member. If you change `fact` with `graph.edge.update` on one member, Zep updates the fact on every member.

## Change hyperedge membership

Use `graph.hyperedge.create_edge` to add one member. Set only `name`, `source_node`, and `target_node`. Use an upper-snake-case value for `name`. The new member inherits the hyperedge's fact, timestamps, and episodes.

Use `graph.hyperedge.delete_edge` to remove one member. Deleting the last member removes the hyperedge. Use `graph.hyperedge.delete` to delete every member.

## Retrieve hyperedge facts

`graph.get_context` writes each hyperedge fact once in the context block.

## Extract hyperedges from episodes

Zep can extract hyperedges from the episodes that you add. The project setting `hyperedges_enabled` on `GET /project` and `PATCH /project` controls the extraction.

| Project                                                                            | Default value |
| ---------------------------------------------------------------------------------- | ------------- |
| A project that you create after hyperedge extraction is available for your account | `true`        |
| A project that existed before hyperedge extraction was available for your account  | `false`       |

> **Warning**
>
> The setting is one-way. After you set `hyperedges_enabled` to `true`, you cannot set it to `false`. `PATCH /project` returns `400 invalid_request` when `hyperedges_enabled` is `false`. A second request with `true` has no effect.

To enable extraction, open the project settings in the dashboard. An Account
Owner, Account Admin, or Project Admin can select **Enable Hyperedges**.

Project Editors cannot enable extraction. Project API keys cannot set
`hyperedges_enabled`. If a project API key sends `hyperedges_enabled: true` to
`PATCH /project`, the API returns `403 permission_denied`. A project API key can
still read the value with `GET /project`.

The setting applies to the episodes that Zep receives after the change. Zep does not process again the episodes that it received before the change. An episode that is in the queue at the time of the change keeps the previous value.

The hyperedge API and the hyperedge reads do not use the setting. You can add and read hyperedges in a project where `hyperedges_enabled` is `false`.