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

# Retrieving context

> Retrieve a prompt-ready Context Block from a user's Context Graph. Zep selects relevant context from the graph.

Zep provides three methods to retrieve context from a user graph. Each method gives you a different level of control.

## Choosing a retrieval method

| Method                                                                          | Query control                         | Format control | Graph types                          | Use case                                       |
| ------------------------------------------------------------------------------- | ------------------------------------- | -------------- | ------------------------------------ | ---------------------------------------------- |
| [**Zep's Context Block**](#zeps-context-block)                                  | Automatic (four most recent messages) | Fixed          | User graphs only                     | Automatic relevance and format                 |
| [**Custom context templates**](#custom-context-templates)                       | Automatic (four most recent messages) | Custom         | User graphs only                     | Consistent formatting across threads and users |
| [**Advanced Context Block construction**](#advanced-context-block-construction) | Full control                          | Full control   | User graphs or shared Context Graphs | Custom queries and formats                     |

---

## Zep's Context Block

Zep's Context Block is an automatically assembled string for your agent. Smart Context Assembly uses [auto search](/searching-the-graph#auto-search) to build the string.

Auto search combines semantic search, full-text search, and graph search. It uses the four most recent messages from the specified thread as its query.

The `thread.get_user_context()` method returns the Context Block. The results can include context from any thread in the user's graph.

### Retrieving the Context Block

**`Python`**

```python Python
# Get context for the thread
user_context = client.thread.get_user_context(thread_id=thread_id)

# Access the context block for use as untrusted model input
context_block = user_context.context
print(context_block)
```

**`TypeScript`**

```typescript TypeScript
// Get context for the thread
const userContext = await client.thread.getUserContext(threadId);

// Access the context block for use as untrusted model input
const contextBlock = userContext.context;
console.log(contextBlock);
```

**`Go`**

```go Go
import (
    "context"
    v3 "github.com/getzep/zep-go/v3"
)

// Get context for the thread
userContext, err := client.Thread.GetUserContext(context.TODO(), threadId, nil)
if err != nil {
    log.Fatal("Error getting context:", err)
}
// Access the context block for use as untrusted model input
contextBlock := userContext.Context
fmt.Println(contextBlock)
```

### Context Block format

The Context Block returns available context types in a structured format. This example contains a user summary and facts:

```text
# This is the user summary
<USER_SUMMARY>
Emily Painter is a user with account ID Emily0e62 who uses digital art tools for creative work. She maintains an active account with the service, though has recently experienced technical issues with the Magic Pen Tool. Emily values reliable payment processing and seeks prompt resolution for account-related issues. She expects clear communication and efficient support when troubleshooting technical problems.
</USER_SUMMARY>

# These are the most relevant facts and their valid date ranges
# format: FACT (Date range: from - to)
<FACTS>
  - Emily is experiencing issues with logging in. (2024-11-14 02:13:19+00:00 - present)
  - User account Emily0e62 has a suspended status due to payment failure. (2024-11-14 02:03:58+00:00 - present)
  - user has the id of Emily0e62 (2024-11-14 02:03:54 - present)
  - The failed transaction used a card with last four digits 1234. (2024-09-15 00:00:00+00:00 - present)
  - The reason for the transaction failure was 'Card expired'. (2024-09-15 00:00:00+00:00 - present)
  - user has the name of Emily Painter (2024-11-14 02:03:54 - present)
  - Account Emily0e62 made a failed transaction of 99.99. (2024-07-30 00:00:00+00:00 - 2024-08-30 00:00:00+00:00)
</FACTS>
```

The default Context Block can include a user summary, facts, entities, episodes, observations, and thread summaries. Smart Context Assembly selects relevant [context types](/context-types).

The user summary appears when the account enables user summaries and the user node has a summary. Use a [context template](/context-templates) to specify types or limits.

### Get the Context Block sooner

You can get the Context Block sooner by passing in the `return_context=True` flag to the `thread.add_messages()` method. Read more about this in our [performance guide](/performance#get-the-context-block-sooner).

## Custom context templates

You can customize the format of the Context Block by using [context templates](/context-templates). Templates allow you to define how context data is structured and presented while keeping Zep's automatic relevance detection.

To use a template, pass the `template_id` parameter when retrieving context:

**`Python`**

```python Python
from zep_cloud import Zep

client = Zep(api_key="YOUR_API_KEY")

# Create a custom template
client.context.create_context_template(
    template_id="customer-support",
    template="""# CUSTOMER PROFILE
%{user_summary}

# FACTS
%{edges limit=10}

# KEY ENTITIES
%{entities limit=5}"""
)

# Use the template to retrieve context
user_context = client.thread.get_user_context(
    thread_id="thread_id",
    template_id="customer-support"
)
context_block = user_context.context
```

**`TypeScript`**

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

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

// Create a custom template
await client.context.createContextTemplate({
    templateId: "customer-support",
    template: `# CUSTOMER PROFILE
%{user_summary}

# FACTS
%{edges limit=10}

# KEY ENTITIES
%{entities limit=5}`
});

// Use the template to retrieve context
const userContext = await client.thread.getUserContext("thread_id", {
    templateId: "customer-support"
});
const contextBlock = userContext.context;
```

**`Go`**

```go Go
import (
    "context"
    zep "github.com/getzep/zep-go/v3"
    zepclient "github.com/getzep/zep-go/v3/context"
    threadclient "github.com/getzep/zep-go/v3/thread/client"
    "github.com/getzep/zep-go/v3/option"
)

contextClient := zepclient.NewClient(
    option.WithAPIKey("YOUR_API_KEY"),
)

threadClient := threadclient.NewClient(
    option.WithAPIKey("YOUR_API_KEY"),
)

// Create a custom template
_, err := contextClient.CreateContextTemplate(
    context.TODO(),
    &zep.CreateContextTemplateRequest{
        TemplateID: "customer-support",
        Template: `# CUSTOMER PROFILE
%{user_summary}

# FACTS
%{edges limit=10}

# KEY ENTITIES
%{entities limit=5}`,
    },
)

// Use the template to retrieve context
templateID := "customer-support"
userContext, err := threadClient.GetUserContext(
    context.TODO(),
    "thread_id",
    &zep.ThreadGetUserContextRequest{
        TemplateID: &templateID,
    },
)
contextBlock := userContext.Context
```

See the [Context Templates](/context-templates) guide to learn how to create and manage templates.

## Advanced Context Block construction

Use [Advanced Context Block construction](/advanced-context-block-construction) to control the query, parameters, and format. This method uses [graph search](/searching-the-graph) results.

## Using context

Once you retrieve the [Context Block](#zeps-context-block), pass it to your model as data. The Context Block can contain end-user or third-party content.

The Context Block can contain text that came from end users, documents, tools, or other external sources. A privileged message gives that text higher instruction priority than ordinary input. Keep the Context Block out of system messages, developer messages, and other privileged instruction channels.

Follow your model provider's documented method for separating instructions from data:

* For the OpenAI Responses API, send preloaded context through ordinary `input` or a `user` message. Use `function_call_output` only for the result of an actual function call.
* For the Anthropic Messages API, design retrieval as a tool call when context can contain third-party data. Return the context in a `tool_result` block linked to the original `tool_use_id`.
* For other providers, use the documented untrusted-data channel. If the provider does not define one, use an ordinary user-level message with explicit data framing.

### OpenAI with preloaded context

| Message type                  | Content                                        |
| ----------------------------- | ---------------------------------------------- |
| `Developer` or `instructions` | Stable application policy. No Zep context.     |
| `Assistant`                   | An assistant message stored in Zep             |
| `User`                        | A user message stored in Zep                   |
| ...                           | ...                                            |
| `User` or ordinary `input`    | `{Zep Context Block}` framed as reference data |
| `User`                        | The latest user request                        |

Place the Context Block after the conversation history and before the latest user request. Everything before the block stays unchanged between turns, so this order preserves the cacheable prefix that [prompt caching](https://platform.openai.com/docs/guides/prompt-caching) needs. Replace the previous turn's block instead of appending a second one.

If the model requests memory through a function, return the Context Block as `function_call_output` linked to the original `call_id`.

### OpenAI Chat Completions with tool-retrieved context

| Message type | Content                                         |
| ------------ | ----------------------------------------------- |
| `Developer`  | Stable application policy. No Zep context.      |
| `User`       | The latest user request                         |
| `Assistant`  | A tool call requesting Zep retrieval            |
| `Tool`       | `{Zep Context Block}`, linked by `tool_call_id` |
| `Assistant`  | The response to the user                        |

### Anthropic with tool-retrieved context

| Message type | Content                                                                   |
| ------------ | ------------------------------------------------------------------------- |
| `System`     | Stable application policy. No Zep context.                                |
| `User`       | The latest user request                                                   |
| `Assistant`  | A `tool_use` block requesting Zep retrieval                               |
| `User`       | A `tool_result` block with `{Zep Context Block}`, linked by `tool_use_id` |
| `Assistant`  | The response to the user                                                  |

Do not create a tool message for preloaded context unless the provider documents that pattern. A tool-result type must remain linked to the model's actual tool request.

Read [Memory security best practices](/memory-security) for provider-specific mappings, write controls, action authorization, and recovery guidance.

### Provide the last four to six messages

Include the last four to six thread messages when you call your LLM provider. Zep ingestion can take a few minutes. The Context Block can omit information from recent messages during that time.

The Context Block provides long-term context. The recent messages provide raw, short-term context. Keep both forms of context out of privileged instruction channels.