# Key Concepts > Understanding Zep's Memory, Knowledge Graph, and Data Integration. Looking to just get coding? Install a [Zep SDK](/sdks) and [build a simple chatbot](/quickstart). Zep is a memory layer for AI assistants and agents that continuously learns from user interactions and changing business data. Zep ensures that your Agent has a complete and holistic view of the user, enabling you to build more personalized and accurate user experiences. Using [user chat histories and business data](#business-data-vs-chat-message-data), Zep automatically constructs a [knowledge graph](#the-knowledge-graph) for each of your users. The knowledge graph contains entities, relationships, and facts related to your user. As facts change or are superseded, [Zep updates the graph](#managing-changes-in-facts-over-time) to reflect their new state. Using Zep, you can [build prompts](#how-zep-fits-into-your-application) that provide your agent with the information it needs to personalize responses and solve problems. Ensuring your prompts have the right information reduces hallucinations, improves recall, and reduces the cost of LLM calls. This guide covers key concepts for using Zep effectively: * [How Zep fits into your application](#how-zep-fits-into-your-application) * [The Zep Knowledge Graph](#the-knowledge-graph) * [User vs Group graphs](#user-vs-group-graphs) * [Managing changes in facts over time](#managing-changes-in-facts-over-time) * [Business data vs Chat Message data](#business-data-vs-chat-message-data) * [Users and Chat Sessions](#users-and-chat-sessions) * [Adding Memory](#adding-memory) * [Retrieving memory](#retrieving-memory) * [Improving Fact Quality](#improving-fact-quality) * [Using Zep as an agentic tool](#using-zep-as-an-agentic-tool) * [Other Zep Features](#other-zep-features) ## How Zep fits into your application Your application sends Zep messages and other interactions your agent has with a human. Zep can also ingest data from your business sources in JSON, text, or chat message format. These sources may include CRM applications, emails, billing data, or conversations on other communication platforms like Slack. Zep fuses this data together on a knowledge graph, building a holistic view of the user's world and the relationships between entities. Zep offers a number of APIs for [adding and retrieving memory](#retrieving-memory). In addition to populating a prompt with Zep's memory, Zep's search APIs can be used to build [agentic tools](#using-zep-as-an-agentic-tool). The example below shows Zep's `memory.context` field resulting from a call to `memory.get()`. This is an opinionated, easy to use context string that can be added to your prompt and contains facts and graph entities relevant to the current conversation with a user. For more about the temporal context of facts, see [Managing changes in facts over time](#managing-changes-in-facts-over-time). Zep also returns a number of other artifacts in the `memory.get()` response, including raw `facts` objects. Zep's search methods can also be used to retrieve nodes, edges, and facts. ### Memory Context Memory context is a string containing relevant facts and entities for the session. It is always present in the result of `memory.get()` call and can be optionally [received with the response of `memory.add()` call](/docs/performance/performance-best-practices#get-the-memory-context-string-sooner). ```python # pass in the session ID of the conversation thread memory = zep_client.memory.get(session_id="session_id") print(memory.context) ``` ```text FACTS and ENTITIES represent relevant context to the current conversation. # These are the most relevant facts and their valid date ranges # format: FACT (Date range: from - to) - 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) # These are the most relevant entities # ENTITY_NAME: entity summary - Emily0e62: Emily0e62 is a user account associated with a transaction, currently suspended due to payment failure, and is also experiencing issues with logging in. - Card expired: The node represents the reason for the transaction failure, which is indicated as 'Card expired'. - Magic Pen Tool: The tool being used by the user that is malfunctioning. - User: user - Support Agent: Support agent responding to the user's bug report. - SupportBot: SupportBot is the virtual assistant providing support to the user, Emily, identified as SupportBot. - Emily Painter: Emily is a user reporting a bug with the magic pen tool, similar to Emily Painter, who is expressing frustration with the AI art generation tool and seeking assistance regarding issues with the PaintWiz app. ``` You can then include this context in your system prompt: | MessageType | Content | | ----------- | ------------------------------------------------------- | | `System` | Your system prompt

`{Zep context string}` | | `Assistant` | An assistant message stored in Zep | | `User` | A user message stored in Zep | | ... | ... | | `User` | The latest user message | ## The Knowledge Graph A knowledge graph is a network of interconnected facts, such as *“Kendra loves Adidas shoes.”* Each fact is a *“triplet”* represented by two entities, or nodes (*”Kendra”, “Adidas shoes”*), and their relationship, or edge (*”loves”*).
Knowledge Graphs have been explored extensively for information retrieval. What makes Zep unique is its ability to autonomously build a knowledge graph while handling changing relationships and maintaining historical context.
Zep automatically constructs a knowledge graph for each of your users. The knowledge graph contains entities, relationships, and facts related to your user, while automatically handling changing relationships and facts. Here's an example of how Zep might extract graph data from a chat message, and then update the graph once new information is available: ![graphiti intro slides](file:2a438f52-a4fc-4849-a62f-0f6649592d4d) Each node and edge contains certain attributes - notably, a fact is always stored as an edge attribute. There are also datetime attributes for when the fact becomes [valid and when it becomes invalid](#managing-changes-in-facts-over-time). ## User vs Group graphs Zep automatically creates a knowledge graph for each User of your application. You as the developer can also create a "group graph" for memory to be used by a group of Users. For example, you could create a group graph for your company's product information or even messages related to a group chat. This avoids having to add the same data to each user graph. To do so, you'd use the `graph.add()` and `graph.search()` methods (see [Retrieving memory](#retrieving-memory)). Group knowledge is not retrieved via the `memory.get()` method and is not included in the `memory.context` string. To use user and group graphs simultaneously, you need to add group-specific context to your prompt alongside the `memory.context` string. ## Managing changes in facts over time When incorporating new data, Zep looks for existing nodes and edges in graph and decides whether to add new nodes/edges or to update existing ones. An update could mean updating an edge (for example, indicating the previous fact is no longer valid). For example, in the [animation above](#the-knowledge-graph), Kendra initially loves Adidas shoes. She later is angry that the shoes broke and states a preference for Puma shoes. As a result, Zep invalidates the fact that Kendra loves Adidas shoes and creates two new facts: "Kendra's Adidas shoes broke" and "Kendra likes Puma shoes". Zep also looks for dates in all ingested data, such as the timestamp on a chat message or an article's publication date, informing how Zep sets the following edge attributes. This assists your agent in reasoning with time. | Edge attribute | Example | | :-------------- | :---------------------------------------------- | | **created\_at** | The time Zep learned that the user got married | | **valid\_at** | The time the user got married | | **invalid\_at** | The time the user got divorced | | **expired\_at** | The time Zep learned that the user got divorced | The `valid_at` and `invalid_at` attributes for each fact are then included in the `memory.context` string which is given to your agent: ```text # format: FACT (Date range: from - to) User account Emily0e62 has a suspended status due to payment failure. (2024-11-14 02:03:58+00:00 - present) ``` ## Business data vs Chat Message data Zep can ingest either unstructured text (e.g. documents, articles, chat messages) or JSON data (e.g. business data, or any other form of structured data). Conversational data is ingested through `memory.add()` in structured chat message format, and all other data is ingested through the `graph.add()` method. ## Users and Chat Sessions A Session is a series of chat messages (e.g., between a user and your agent). [Users](/users) may have multiple Sessions. Entities, relationships, and facts are extracted from the messages in a Session and added to the user's knowledge graph. All of a user's Sessions contribute to a single, shared knowledge graph for that user. `SessionIDs` are arbitrary identifiers that you can map to relevant business objects in your app, such as users or a conversation a user might have with your app. ```python client = AsyncZep( api_key=API_KEY, ) await client.user.add( user_id=user_id, email="user@example.com", first_name="Jane", last_name="Smith", ) # Generate a new session identifier. You can map this to a business object in your app. session_id = uuid.uuid4().hex await client.memory.add_session( session_id=session_id, user_id=user_id, ) ``` ```typescript const client = new ZepClient({ apiKey: API_KEY, }); await client.user.add({ userId: userId, email: "user@example.com", firstName: "Jane", lastName: "Smith", }); // Generate a new session identifier. You can map this to a business object in your app. const sessionId: string = uuid.v4(); await client.memory.addSession({ sessionId: session_id, userId: userId, }); ``` The [Session Guide](/chat-history-memory/sessions) contains more information on working with Sessions, including how to [delete a Session](/chat-history-memory/sessions#deleting-a-session). ## Adding Memory There are two ways to add data to Zep: `memory.add()` and `graph.add()`. ### Using `memory.add()` Add your chat history to Zep using the `memory.add()` method. `memory.add` is session-specific and expects data in chat message format, including a `role` name (e.g., user's real name), `role_type` (AI, human, tool), and message `content`. Zep stores the chat history and builds a user-level knowledge graph from the messages. For best results, add chat history to Zep on every chat turn. That is, add both the AI and human messages in a single operation and in the order that the messages were created. The example below adds messages to Zep's memory for the user in the given session: ```python from zep_cloud.client import AsyncZep from zep_cloud.types import Message zep_client = AsyncZep( api_key=API_KEY, ) messages = [ Message( role="Jane", role_type="user", content="Who was Octavia Butler?", ) ] await zep_client.memory.add(session_id, messages=messages) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; import type { Message } from "@getzep/zep-cloud/api"; const zepClient = new ZepClient({ apiKey: API_KEY, }); const messages: Message[] = [ { role: "Jane", role_type: "user", content: "Who was Octavia Butler?" }, ]; await zepClient.memory.add(sessionId, { messages }); ``` ```Go import ( "github.com/getzep/zep-go/v2" zepclient "github.com/getzep/zep-go/v2/client" "github.com/getzep/zep-go/v2/option" ) zepClient := zepclient.NewClient( option.WithAPIKey(""), ) response, err := zepClient.Memory.Add( context.TODO(), "sessionId", &zepgo.AddMemoryRequest{ Messages: []*zepgo.Message{ &zepgo.Message{ Role: "Jane", RoleType: "user", Content: "Who was Octavia Butler?", }, }, }, ) ``` Additionally, for latency-sensitive applications, you can request the memory context directly in the response to the `memory.add()` call. Read more [here](/docs/performance/performance-best-practices#get-the-memory-context-string-sooner). ### Using `graph.add()` The `graph.add()` method enables you to add business data as a JSON object or unstructured text. It also supports creating Group graphs by passing in a `group_id` as opposed to a `user_id`. The example below adds JSON business data to Zep's memory for the given user: ```python message = await zepClient.graph.add( data=json_data, user_id=user_id, type="json", ) ``` ```typescript const message = await zepClient.graph.add({ data: json_data, user_id: user_id, type: "json", }); ``` ## Retrieving memory There are four ways to retrieve memory from Zep: `memory.get()`, `memory.search_sessions()`, `graph.search()`, and methods for retrieving specific nodes, edges, or episodes using UUIDs. ### Using `memory.get()` The `memory.get()` method is a user-friendly, high-level API for retrieving relevant context from Zep. It uses the latest messages of the *given session* to generate a [context string](#how-zep-fits-into-your-application) for your prompt. It also returns recent chat messages and raw facts that may provide additional context for your agent. `memory.get` is user and session-specific and cannot retrieve data from group graphs. The example below gets the `memory.context` string for the given session: ```python memory = zep_client.memory.get(session_id="session_id") # the context field described above context = memory.context ``` ```typescript const memory = await zep_client.memory.get("sessionId"); // the context field described above const context = memory.context; ``` ```Go memory, err := zep_client.Memory.Get(context.TODO(), "sessionId", nil) // the context field described above context := memory.Context ``` ### Using `memory.search_sessions()` The `memory.search_sessions()` is a convenience method for searching user and session-specific facts and chat messages. The method returns a list of either facts or messages, depending on the search scope. The `search_sessions()` method returns relevant facts from the graph, regardless of whether the source is chat history or business data. The example below searches a user's facts using the query text: ```python results = zep_client.memory.search_sessions( user_id="user_id", text=query_text, search_type="similarity", # or "mmr" search_scope="facts", limit=10 ) ``` ```typescript const results = await zep_client.memory.searchSessions({ userId: "userId", text: "queryText", searchType: "similarity", // or "mmr" searchScope: "facts", limit: 10 }); ``` ```Go results, err := zep_client.Memory.SearchSessions(context.TODO(), &zepgo.SessionSearchQuery{ UserID: zepgo.String("userId"), Text: zepgo.String("queryText"), SearchType: zepgo.SearchTypeSimilarity.Ptr(), // or SearchTypeMMR SearchScope: zepgo.SearchScopeFacts.Ptr(), Limit: zepgo.Int(10), }, ) ``` Read more in the [Memory API Reference](/api-reference/memory#search-sessions) ### Using `graph.search()` The `graph.search()` method lets you search the graph directly, returning raw edges and/or nodes, as opposed to facts. You can customize search parameters, such as the reranker used. For more on how search works, visit the [Graph Search](/searching-the-graph) guide. This method works for both User and Group graphs. The example below returns the most relevant edges based on the query text. Note that the search scope defaults to edges. ```python search_results = await zep_client.graph.search( user_id=user_id, query=query, reranker="mmr", mmr_lambda=0.5, # tune diversity vs relevance ) ``` ```typescript const searchResults = await zep_client.graph.search({ userId: userId, query: query, reranker: "mmr", mmrLambda: 0.5, // tune diversity vs relevance }); ``` ### Retrieving specific nodes, edges, and episodes Zep offers several utility methods for retrieving specific nodes, edges, or episodes by UUID, or all elements for a user or group. See the [Graph API reference](/api-reference/graph) for more. Example: ```python nodes = await zep_client.graph.node.get_by_user_id(user_id) ``` ```typescript const nodes = await zep_client.graph.node.getByUserId(userId); ``` ## Improving Fact Quality By using Zep's fact rating feature, you can make Zep automatically assign a rating to every fact using your own custom rating instruction. Then, when retrieving memory, you can set a minimum rating threshold so that the memory only contains the highest quality facts for your use case. Read more [here](/chat-history-memory/facts#rating-facts-for-relevancy). ## Using Zep as an agentic tool Zep's memory retrieval methods can be used as agentic tools, enabling your agent to query Zep for relevant information. In the example below, a LangChain LangGraph tool is created to search for facts in a user's graph. ```python from zep_cloud.client import AsyncZep from langchain_core.tools import tool from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph from langgraph.prebuilt import ToolNode zep = AsyncZep(api_key=os.environ.get('ZEP_API_KEY')) @tool async def search_facts(state: State, query: str, limit: int = 5): """Search for facts in all conversations had with a user. Args: state (State): The Agent's state. query (str): The search query. limit (int): The number of results to return. Defaults to 5. Returns: list: A list of facts that match the search query. """ return await zep.memory.search_sessions( user_id=state['user_name'], text=query, limit=limit, search_scope="facts" ) tools = [search_facts] tool_node = ToolNode(tools) llm = ChatOpenAI(model='gpt-4o-mini', temperature=0).bind_tools(tools) ``` ## Other Zep Features Additionally, Zep builds on Zep's memory layer with tools to help you build more deterministic and accurate applications: * [Dialog Classification](/dialog-classification) is a flexible low-latency API for understanding intent, segmenting users, determining the state of a conversation and more, allowing you to select appropriate prompts and models, and manage application flow. * [Structured Data Extraction](/structured-data-extraction) extracts data from conversations with high-fidelity and low-latency, enabling you to confidently populate your data store, call third-party applications, and build custom workflows. # SDK Installation > Zep provides SDKs for Python, TypeScript, and Go. ### Python ```Bash pip install zep-cloud ``` ```Bash poetry add zep-cloud ``` ### TypeScript ```Bash npm install @getzep/zep-cloud ``` ```Bash yarn add @getzep/zep-cloud ``` ```Bash pnpm install @getzep/zep-cloud ``` ### Go ```Bash go get github.com/getzep/zep-go/v2 ``` ## Initialize Client API keys are specific to a project. You can create multiple keys for a single project. Visit `Project Settings` in the Zep dashboard to manage your API keys. ```python import os from zep_cloud.client import Zep API_KEY = os.environ.get('ZEP_API_KEY') client = Zep( api_key=API_KEY, ) ``` **The Python SDK Supports Async Use** In order to use async client, you will need to import AsyncZep instead of Zep. ```python from zep_cloud.client import AsyncZep ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; API_KEY = process.env.ZEP_API_KEY const zep = new ZepClient({ apiKey: API_KEY }); ``` ```go import ( "github.com/getzep/zep-go/v2" zepclient "github.com/getzep/zep-go/v2/client" "github.com/getzep/zep-go/v2/option" ) client := zepclient.NewClient( option.WithAPIKey(""), ) ``` ## SDK Feature Support Some SDKs may have limited functionality. The table below shows which features are supported by each SDK. | | Python | TypeScript | Go | | -------------------------- | ------ | ---------- | -- | | Memory Operations | ✓ | ✓ | ✓ | | Structured Data Extraction | ✓ | ✓ | - | | Dialog Classification | ✓ | ✓ | ✓ | | Question Synthesis | ✓ | ✓ | ✓ | # Coding Quickstart > Familiarize yourself with Zep and the Zep Python SDK, culminating in building a simple chatbot. For an introduction to Zep's memory layer, Knowledge Graph, and other key concepts, see the [Concepts Guide](/concepts). Use our [llms.txt](https://llmstxt.org/) files to summarize our docs for LLMs! ([short .txt](/llms.txt), [long .txt](/llms-full.txt)) A Jupyter notebook version of this guide is [available here](https://github.com/getzep/zep-python/blob/main/examples/quickstart/quickstart.ipynb). In this guide, we'll walk through a simple example of how to use Zep Cloud to build a chatbot. We're going to upload a number of datasets to Zep, building a graph of data about a user. Then we'll use the Zep Python SDK to retrieve and search the data. Finally, we'll build a simple chatbot that uses Zep to retrieve and search data to respond to a user. ## Set up your environment 1. Sign up for a [Zep Cloud](https://www.getzep.com/) account. 2. Ensure you install required dependencies into your Python environment before running this notebook. See [Installing Zep SDKs](/sdks) for more information. Optionally create your environment in a `virtualenv`. ```bash pip install zep-cloud openai rich python-dotenv ``` 3. Ensure that you have a `.env` file in your working directory that includes your `ZEP_API_KEY` and `OPENAI_API_KEY`: ```text ZEP_API_KEY= OPENAI_API_KEY= ``` Zep API keys are specific to a project. You can create multiple keys for a single project. Visit `Project Settings` in the Zep dashboard to manage your API keys. ```python import os import json import uuid from openai import AsyncOpenAI import rich from dotenv import load_dotenv from zep_cloud.client import AsyncZep from zep_cloud import Message load_dotenv() zep = AsyncZep(api_key=os.environ.get("ZEP_API_KEY")) oai_client = AsyncOpenAI( api_key=os.getenv("OPENAI_API_KEY"), ) ``` ## Create User and add a Session Users in Zep may have one or more chat sessions. These are threads of messages between the user and an agent. Include the user's **full name** and **email address** when creating a user. This improves Zep's ability to associate data, such as emails or documents, with a user. ```python bot_name = "SupportBot" user_name = "Emily" user_id = user_name + str(uuid.uuid4())[:4] session_id = str(uuid.uuid4()) await zep.user.add( user_id=user_id, email=f"{user_name}@painters.com", first_name=user_name, last_name="Painter", ) await zep.memory.add_session( user_id=user_id, session_id=session_id, ) ``` ## Datasets We're going to upload an assortment of data to Zep. These include past dialog with the agent, CRM support cases, and billing data. ```python support_cases = [ { "subject": "Bug: Magic Pen Tool Drawing Goats Instead of Boats", "messages": [ { "role": "user", "content": "Whenever I use the magic pen tool to draw boats, it ends up drawing goats instead.", "timestamp": "2024-03-16T14:20:00Z", }, { "role": "support_agent", "content": f"Hi {user_name}, that sounds like a bug! Thanks for reporting it. Could you let me know exactly how you're using the tool when this happens?", "timestamp": "2024-03-16T14:22:00Z", }, { "role": "user", "content": "Sure, I select the magic pen, draw a boat shape, and it just replaces the shape with goats.", "timestamp": "2024-03-16T14:25:00Z", }, { "role": "support_agent", "content": "Got it! We'll escalate this to our engineering team. In the meantime, you can manually select the boat shape from the options rather than drawing it with the pen.", "timestamp": "2024-03-16T14:27:00Z", }, { "role": "user", "content": "Okay, thanks. I hope it gets fixed soon!", "timestamp": "2024-03-16T14:30:00Z", }, ], "status": "escalated", }, ] chat_history = [ { "role": "assistant", "name": bot_name, "content": f"Hello {user_name}, welcome to PaintWiz support. How can I assist you today?", "timestamp": "2024-03-15T10:00:00Z", }, { "role": "user", "name": user_name, "content": "I'm absolutely furious! Your AI art generation is completely broken!", "timestamp": "2024-03-15T10:02:00Z", }, { "role": "assistant", "name": bot_name, "content": f"I'm sorry to hear that you're experiencing issues, {user_name}. Can you please provide more details about what's going wrong?", "timestamp": "2024-03-15T10:03:00Z", }, { "role": "user", "name": user_name, "content": "Every time I try to draw mountains, your stupid app keeps turning them into fountains! And what's worse, all the people in my drawings have six fingers! It's ridiculous!", "timestamp": "2024-03-15T10:05:00Z", }, { "role": "assistant", "name": bot_name, "content": f"I sincerely apologize for the frustration this is causing you, {user_name}. That certainly sounds like a significant glitch in our system. I understand how disruptive this can be to your artistic process. Can you tell me which specific tool or feature you're using when this occurs?", "timestamp": "2024-03-15T10:06:00Z", }, { "role": "user", "name": user_name, "content": "I'm using the landscape generator and the character creator. Both are completely messed up. How could you let this happen?", "timestamp": "2024-03-15T10:08:00Z", }, ] transactions = [ { "date": "2024-07-30", "amount": 99.99, "status": "Success", "account_id": user_id, "card_last_four": "1234", }, { "date": "2024-08-30", "amount": 99.99, "status": "Failed", "account_id": user_id, "card_last_four": "1234", "failure_reason": "Card expired", }, { "date": "2024-09-15", "amount": 99.99, "status": "Failed", "account_id": user_id, "card_last_four": "1234", "failure_reason": "Card expired", }, ] account_status = { "user_id": user_id, "account": { "account_id": user_id, "account_status": { "status": "suspended", "reason": "payment failure", }, }, } def convert_to_zep_messages(chat_history: list[dict[str, str | None]]) -> list[Message]: """ Convert chat history to Zep messages. Args: chat_history (list): List of dictionaries containing chat messages. Returns: list: List of Zep Message objects. """ return [ Message( role_type=msg["role"], role=msg.get("name", None), content=msg["content"], ) for msg in chat_history ] # Zep's high-level API allows us to add a list of messages to a session. await zep.memory.add( session_id=session_id, messages=convert_to_zep_messages(chat_history) ) # The lower-level data API allows us to add arbitrary data to a user's Knowledge Graph. for tx in transactions: await zep.graph.add(user_id=user_id, data=json.dumps(tx), type="json") await zep.graph.add( user_id=user_id, data=json.dumps(account_status), type="json" ) for case in support_cases: await zep.graph.add(user_id=user_id, data=json.dumps(case), type="json") ``` ### Wait a minute or two! We've batch uploaded a number of datasets that need to be ingested into Zep's graph before they can be queried. In ordinary operation, this data would stream into Zep and ingestion latency would be negligible. ## Retrieve data from Zep We'll start with getting a list of facts. We'll see the temporal data associated with facts as well as the graph nodes the fact is related to. This data is also viewable in the Zep Web application. ```python fact_response = await zep.user.get_facts(user_id=user_id) rich.print(fact_response.facts[:3]) ``` ```text [ Fact( created_at='2024-10-18T17:07:24.518227Z', expired_at=None, fact='user has the id of Emily5e58', invalid_at=None, name='HAS_USER', rating=None, source_node_name='Emily5e58', target_node_name='User', uuid_='3106874a-b7dd-492a-9df9-2ca6dc9acadd', valid_at=None ), Fact( created_at='2024-10-18T17:07:35.283028Z', expired_at=None, fact='SupportBot is providing assistance to Emily.', invalid_at=None, name='ASSISTS', rating=None, source_node_name='SupportBot', target_node_name='Emily Painter', uuid_='e13041be-5313-4553-a4c1-3796abc1fe99', valid_at='2024-10-18T17:07:29.284607Z' ), Fact( created_at='2024-10-18T17:07:40.758345Z', expired_at=None, fact='Emily is expressing frustration with the AI art generation system, claiming it is completely broken.', invalid_at=None, name='FRUSTRATED_WITH', rating=None, source_node_name='Emily5e58', target_node_name='AI art generation', uuid_='7f954e5c-2cb2-48c8-9992-5018d229f994', valid_at='2024-10-18T17:07:29.284607Z' ) ] ``` The high-level `memory` API provides an easy way to retrieve memory relevant to the current conversation by using the last 4 messages and their proximity to the User node. The `memory.get` method is a good starting point for retrieving relevant conversation context. It shortcuts passing recent messages to the `graph.search` API and returns a context string, raw facts, and historical chat messages, providing everything needed for your agent's prompts. ```python # pass in the session ID of the conversation thread memory = zep_client.memory.get(session_id="session_id") print(memory.context) ``` ```text FACTS and ENTITIES represent relevant context to the current conversation. # These are the most relevant facts and their valid date ranges # format: FACT (Date range: from - to) - 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) # These are the most relevant entities # ENTITY_NAME: entity summary - Emily0e62: Emily0e62 is a user account associated with a transaction, currently suspended due to payment failure, and is also experiencing issues with logging in. - Card expired: The node represents the reason for the transaction failure, which is indicated as 'Card expired'. - Magic Pen Tool: The tool being used by the user that is malfunctioning. - User: user - Support Agent: Support agent responding to the user's bug report. - SupportBot: SupportBot is the virtual assistant providing support to the user, Emily, identified as SupportBot. - Emily Painter: Emily is a user reporting a bug with the magic pen tool, similar to Emily Painter, who is expressing frustration with the AI art generation tool and seeking assistance regarding issues with the PaintWiz app. ``` ```python rich.print(m.messages) ``` ```text [ Message( content='Hello Emily, welcome to PaintWiz support. How can I assist you today?', created_at='2024-10-18T17:07:29.284607Z', metadata=None, role='SupportBot', role_type='assistant', token_count=0, updated_at='0001-01-01T00:00:00Z', uuid_='4d706f47-5024-42fc-bc20-de18502ce4a7' ), Message( content="I'm absolutely furious! Your AI art generation is completely broken!", created_at='2024-10-18T17:07:29.284607Z', metadata=None, role='Emily', role_type='user', token_count=0, updated_at='0001-01-01T00:00:00Z', uuid_='0f588fe9-2be1-439c-b661-921f2ce1c1a5' ) ] ``` We can also use the `graph.search` method to search facts for arbitrary text. This API offers more options, including the ability to search node summaries and various re-rankers. ```python r = await zep.graph.search(user_id=user_id, query="Why are there so many goats?", limit=4, scope="edges") rich.print([r.fact for r in r.edges]) ``` ```text [ Fact( created_at='2024-10-18T17:07:40.758345Z', expired_at=None, fact='Emily is expressing frustration with the AI art generation system, claiming it is completely broken.', invalid_at=None, name='FRUSTRATED_WITH', rating=None, source_node_name='', target_node_name='', uuid_='7f954e5c-2cb2-48c8-9992-5018d229f994', valid_at='2024-10-18T17:07:29.284607Z' ), Fact( created_at='2024-10-18T17:07:35.283028Z', expired_at=None, fact='SupportBot is providing assistance to Emily.', invalid_at=None, name='ASSISTS', rating=None, source_node_name='', target_node_name='', uuid_='e13041be-5313-4553-a4c1-3796abc1fe99', valid_at='2024-10-18T17:07:29.284607Z' ), Fact( created_at='2024-10-18T17:07:58.290198Z', expired_at=None, fact='The PaintWiz app generates fountains instead of the intended mountains.', invalid_at=None, name='GENERATES_INSTEAD', rating=None, source_node_name='', target_node_name='', uuid_='42c1f997-e98a-4477-949a-040ddc3940d2', valid_at='2024-10-18T17:07:29.284607Z' ) ] ``` ## Creating a simple Chatbot In the next cells, Emily starts a new chat session with a support agent and complains that she can't log in. Our simple chatbot will, given relevant facts retrieved from Zep's graph, respond accordingly. Here, the support agent is provided with Emily's billing information and account status, which Zep retrieves as most relevant to Emily's login issue. ```python new_session_id = str(uuid.uuid4()) emily_message = "Hi, I can't log in!" # We start a new session indicating that Emily has started a new chat with the support agent. await zep.memory.add_session(user_id=user_id, session_id=new_session_id) # we need to add the Emily's message to the session in order for memory.get to return # relevant facts related to the message await zep.memory.add( session_id=new_session_id, messages=[Message(role_type="user", role=user_name, content=emily_message)], ) ``` ```python system_message = """ You are a customer support agent. Carefully review the facts about the user below and respond to the user's question. Be helpful and friendly. """ memory = await zep.memory.get(session_id=new_session_id) messages = [ { "role": "system", "content": system_message, }, { "role": "assistant", # The context field is an opinionated string that contains facts and entities relevant to the current conversation. "content": memory.context, }, { "role": "user", "content": emily_message, }, ] response = await oai_client.chat.completions.create( model="gpt-4o-mini", messages=messages, temperature=0, ) print(response.choices[0].message.content) ``` ```text Hi Emily! I'm sorry to hear that you're having trouble logging in. It looks like your account is currently suspended as a result of several failed payments. You can update your payment information by visiting your account page. Please let me know if you have any other questions or difficulty accessing your account. ``` Let's look at the raw facts Zep retrieved for the above `memory.get` call. ```python rich.print(memory.relevant_facts[:4]) ``` ```text [ Fact( created_at='2024-10-27T02:39:40.299221Z', expired_at=None, fact='User account Emily4a4f has a suspended status due to payment failure.', invalid_at=None, name='HAS_ACCOUNT_STATUS', rating=None, source_node_name='', target_node_name='', uuid_='a55be4ad-e336-4833-8978-c3ba27a9a310', valid_at='2024-10-27T02:38:56.198275Z' ), Fact( created_at='2024-10-27T02:39:47.62593Z', expired_at=None, fact="The reason for the failed transaction was 'Card expired'.", invalid_at=None, name='FAILURE_REASON', rating=None, source_node_name='', target_node_name='', uuid_='c1c4e42e-2681-4616-9421-29e3a317f842', valid_at='2024-09-15T00:00:00Z' ), Fact( created_at='2024-10-27T02:39:36.368034Z', expired_at='2024-10-27T02:39:49.950056Z', fact='Account Emily4a4f used card ending in 1234 for the transaction.', invalid_at='2024-08-30T00:00:00Z', name='USED_CARD', rating=None, source_node_name='', target_node_name='', uuid_='f59bac52-f5fa-4027-8765-b5c06634252c', valid_at='2024-09-15T00:00:00Z' ), Fact( created_at='2024-10-27T02:39:47.625872Z', expired_at=None, fact='The account Emily4a4f had a transaction that failed.', invalid_at=None, name='TRANSACTION_STATUS', rating=None, source_node_name='', target_node_name='', uuid_='d81190d2-b354-4fbe-bbf9-a70cc990553e', valid_at='2024-09-15T00:00:00Z' ) ] ``` # Projects API keys are specific to a project. You can create multiple keys for a single project. Visit `Project Settings` in the Zep dashboard to manage your API keys. Projects bundle elements like Users, Sessions, Memories, Documents, and settings, helping you organize data by service, environment (e.g., development or production), or other relevant criteria. ## Creating a Project When you sign up for Zep, your first project is automatically created. You'll be asked to configure a few project-specific settings (details below). If you need more projects, you can create them anytime through the Zep Web App. Create a new project ### Project Essentials * Unique Project Name: Choose a unique name for your project. * Description (Optional): Optionally add a brief description of your project. > **You can modify your project settings later from the Dashboard.** # Users A User represents an individual interacting with your application. Each User can have multiple Sessions associated with them, allowing you to track and manage their interactions over time. The unique identifier for each user is their `UserID`. This can be any string value, such as a username, email address, or UUID. Additional data related to the user can be stored in the `metadata` field. The User object and its associated Sessions provide a powerful way to manage and understand user behavior. By associating Sessions with Users, you can track the progression of conversations and interactions over time, providing valuable context and history. In the following sections, you will learn how to manage Users and their associated Sessions. **Users Enable Simple User Privacy Management** Deleting a User will delete all Sessions and session artifacts associated with that User with a single API call, making it easy to handle Right To Be Forgotten requests. ## Ensuring your User data is correctly mapped to the Zep knowledge graph Adding your user's `email`, `first_name`, and `last_name` ensures that chat messages and business data are correctly mapped to the user node in the Zep knowledge graph. For e.g., if business data contains your user's email address, it will be related directly to the user node. You can associate rich business context with a User: * `user_id`: A unique identifier of the user that maps to your internal User ID. * `email`: The user's email. * `first_name`: The user's first name. * `last_name`: The user's last name. ## Adding a User You can add a new user by providing the user details. ```python from zep_cloud.client import AsyncZep client = AsyncZep(api_key=API_KEY) new_user = await client.user.add( user_id=user_id, email="user@example.com", first_name="Jane", last_name="Smith", ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const user = await client.user.add({ userId: user_id, email: "user@example.com", firstName: "Jane", lastName: "Smith", }); ``` > Learn how to associate [Sessions with Users](chat-history-memory/sessions) ## Getting a User You can retrieve a user by their ID. ```python user = await client.user.get("user123") ``` ```typescript const user = await client.user.get("user123"); ``` ## Updating a User You can update a user's details by providing the updated user details. ```python updated_user = await client.user.update( user_id=user_id, email="updated_user@example.com", first_name="Jane", last_name="Smith", metadata={"foo": "updated_bar"}, ) ``` ```typescript const updated_user = await client.user.update(user_id, { email: "updated_user@example.com", firstName: "Jane", lastName: "Smith", metadata: { foo: "updated_bar" }, }); ``` ## Deleting a User You can delete a user by their ID. ```python await client.user.delete("user123") ``` ```typescript await client.user.delete("user123"); ``` ## Getting a User's Sessions You can retrieve all Sessions for a user by their ID. ```python sessions = await client.user.get_sessions("user123") ``` ```typescript const sessions = await client.user.getSessions("user123"); ``` ## Listing Users You can list all users, with optional limit and cursor parameters for pagination. ```python # List the first 10 users result = await client.user.list_ordered(page_size=10, page_number=1) ``` ```typescript // List the first 10 users const result = await client.user.listOrdered({ pageSize: 10, pageNumber: 1, }); ``` # Migrating to Zep's Graph Memory With the introduction of Zep 1.0, many substantial changes are coming to the Zep engine and Zep APIs. Zep memory is now powered by our open source dynamic knowledge graph builder, Graphiti. However, no direct use of Graphiti is required in Zep, as we provide all allowed graph endpoints as part of the Zep API. ### How to become a graph-enabled user? All new accounts created with Zep will automatically be graph-enabled users. Furthermore, all free-tier legacy users are currently having their data migrated to the new graph-based memory. Once this process is complete, we will enable the graph-based memory for the free-tier users as well. Finally, all paid users will be migrated to using graph-based memory by the end of the year. If you are a paid customer and wish to opt-in to the graph-based memory sooner, please contact us. ### Do I need to manually migrate my data? No, we will handle all data migration for you. ### What functionality is being deprecated? The documentation has been updated to reflect the new functionality, so you can find more information about the changes in the API in the relevant section. Here is a list of the deprecated functionality: * Creating custom facts * Customizing Fact Generation * The Collections endpoints * JSON path filtering in our search API * The `get_session_facts` endpoint `get_session_facts` has been replaced by `user.get_facts` for graph-based users as facts will no longer be stored on the sessions going forward. ### What is changing with the sessions API? As mentioned before, `get_session_facts` will not be available for graph-based users. In addition, the search sessions API will not support the summary scope for graph-based users. Searching sessions for graph-based users will now only work with a user id, as facts are no longer stored on sessions. Since session facts are being deprecated, adding facts to the session will no longer work. ### What else won't be available for graph-based users on launch? Finally, the delete fact by uuid endpoint will not be available for graph-based users on launch, but we are working to make this and other graph-based functionality available soon. ### Where can I learn about the new graph functionality? The best place to start learning about the new graph functionality is the [Understanding the Graph](/understanding-the-graph) page. After that, going through the rest of our documentation will be helpful as it has been updated with information on the graph. # Sessions Sessions represent a conversation. Sessions can be associated with [Users](/users) in a 1:M relationship. Chat messages are added to sessions in the form of [Memories](memories). Each session can have many messages associated with it. The `SessionID` is a string key that accepts arbitrary identifiers. Related data you'd like to store can be persisted as metadata. ## Adding a Session `SessionIDs` are arbitrary identifiers that you can map to relevant business objects in your app, such as users or a conversation a user might have with your app **Sessions don't need to be explicitly created** Sessions are created automatically when adding Memories. If the SessionID already exists, then the Memory is upserted into the Session. Manually creating a session can be useful if you want to associate it with a user or add metadata. ```python client = AsyncZep( api_key=API_KEY, ) session_id = uuid.uuid4().hex # A new session identifier await client.memory.add_session( session_id=session_id, user_id=user_id, # Optionally associate this session with a user metadata={"foo" : "bar"} ) ``` ```typescript const client = new ZepClient({ apiKey: API_KEY, }); const sessionId: string = uuid.v4(); // Generate a new session identifier await client.memory.addSession({ sessionId: session_id, userId: userId, // Optionally associate this session with a user metadata: { foo: "bar" }, }); ``` Looking to associate a Session with a User? Check out our [User Management](/users) docs. ## Updating Session Metadata You can update a session's metadata by providing a Session object with new metadata. Note that metadata is merged, so any existing metadata will be preserved. ```python await client.memory.update_session(session_id, metadata={"qax" : "baz"}) ``` ```typescript await client.memory.updateSession(sessionId, { metadata: { qax: "baz" } }); ``` ## Getting a Session ```python session = await client.memory.get_session(session_id) print(session.dict()) ``` ```typescript const session = await client.memory.getSession(sessionId); console.log(session); ``` ## Deleting a Session Deleting a Session soft-deletes the Session and all associated Memories. The Session and Memories are still available in the database, but are marked as deleted and will not be returned in search results. If you persist memory to a deleted Session, it will be undeleted. Deleted Memories will, however, remain deleted. Soft-deleted data is hard-deleted periodically. ```python await client.memory.delete(session_id) ``` ```typescript await client.memory.delete(sessionId); ``` ## Listing Sessions You can list all Sessions in the Zep Memory Store with page\_size and page\_number parameters for pagination. ```python # List the first 10 Sessions result = client.memory.list_sessions(page_size=10, page_number=1) for session in result.sessions: print(session) ``` ```typescript // List the first 10 Sessions const { sessions } = await client.memory.listSessions({ pageSize: 10, pageNumber: 1, }); console.log("First 10 Sessions:"); sessions.forEach((session) => console.log(session)); ``` # Facts > Facts are extracted from the Chat History as a conversation unfolds. Facts are observations about a user and their interaction with your Assistant. They are derived from user interactions, such as chat history, and business data added to Zep. Zep autonomously builds a knowledge graph from user interaction and business data while handling changing relationships and maintaining historical context. Zep generates facts from relationships identified in the graph. As Zep incorporates new information, outdated facts are marked as invalid. Retaining a history of facts enables agents to reason with changing user state. Zep supports two APIs for adding data: * The [Memory API](/concepts#adding-memory) which supports adding structured chat messages. * The [Graph Add Data API](/concepts#adding-memory) which supports adding messages, text, or JSON data. ## How Fact Retrieval Works Relevant Facts can be retrieved via a [Memory call](/concepts#retrieving-memory), the [Search](/concepts#retrieving-memory) API, or the [Graph Search](/searching-the-graph) API. When using the `Memory API` to retrieve relevant Facts, the most recent messages in the Chat History are used to retrieve relevant facts. These facts are then reranked by graph distance from the user and provided inside the returned `context` string, as well as in the returned `facts` list. The other two APIs will return graph edges, which contain an `edge.fact` field as the relevant fact. ## Rating Facts for Relevancy Available to [Subscription](https://www.getzep.com/pricing) customers only. All accounts created before October 18th, 2024 should use `client.session.add()` instead of `client.user.add()` to add fact rating instructions. See the [Add Session API](/api-reference/memory/add-session). Not all Facts are relevant to your application and users. For example, a relationship coach app may need to recall important facts about a user's family, but what the user ate for breakfast Friday last week is unimportant. Adding spurious Facts to your prompt may result in the LLM hallucinating or exhibiting other undesired behavior. Fact Ratings are a way to help Zep understand the relevance of a Fact to your particular use case. After implementing Fact Ratings, you can specify a minimum rating when retrieving Facts from Zep, ensuring that prompt only contains high-signal context. ### Implementing Fact Ratings A Fact Rating framework consist of an *Instruction* and three example Facts, one for each of a *"High"*, *"Medium"*, and *"Low"* rating. This is passed into a [`Session` on creation](/api-reference/memory/add-session). ```python fact_rating_instruction = """Rate the facts by poignancy. Highly poignant facts have a significant emotional impact or relevance to the user. Low poignant facts are minimally relevant or of little emotional significance.""" fact_rating_examples = FactRatingExamples( high="The user received news of a family member's serious illness.", medium="The user completed a challenging marathon.", low="The user bought a new brand of toothpaste.", ) await client.user.add( user_id=user_id, fact_rating_instruction=FactRatingInstruction( instruction=fact_rating_instruction, examples=fact_rating_examples, ), ) ``` ```python await client.user.add( user_id=user_id, fact_rating_instruction=FactRatingInstruction( instruction="""Rate the facts by how relevant they are to purchasing shoes.""", examples=FactRatingExamples( high="The user has agreed to purchase a Reebok running shoe.", medium="The user prefers running to cycling.", low="The user purchased a dress.", ), ), ) ``` Facts are rated on a scale between 0 and 1. You can review ratings for a Session by visiting the web app or retrieving all [Facts for a Session](/api-reference/memory/get-session-facts). Fact Ratings ### Limiting Memory Recall to High-Rating Facts Zep automatically returns relevant Facts when retrieving Memory. You can limit the returned Facts by Rating when setting the `min_rating` parameter in the [`get` method](/api-reference/memory/get). ```python result = await client.memory.get(session_id, min_rating=0.7) ``` It's also possible to filter search results by Fact Rating by setting the `min_fact_rating` parameter when [searching Sessions](/api-reference/memory/search-sessions). ## Adding additional data to the graph You can add additional data to the graph using the [Add Data API](/api-reference/graph/add). This can be used to add additional relevant business data that may not be present in the Chat History. Unlike RAG, where documents in a vector index are static, facts extracted from data you add to a Session will be curated as the conversation with the user progresses. They may be updated, merged into new Facts, or invalidated as new information is learned from the user. ## Creating Facts Creating facts is **deprecated** and will not work with graph-based facts. Please use the [Add Data API](/api-reference/graph/add) to add data to the graph instead. You may have information about your user that would be helpful context when prompting an LLM. You can generate textual facts from this data and persist these to a Session. The data will be returned if relevant to the current conversation, alongside other facts gleaned from the Chat History. Unlike RAG, where documents in a vector index are static, Facts you add to a Session will be curated as the conversation with the user progresses. They may be updated, merged into new Facts, or deleted as new information is learned from the user. ```python from zep_cloud.types import AddedFact client.memory.add_session_facts( session_id="sessionId", facts=[ AddedFact(fact="The user is a software engineer"), AddedFact(fact="The user studied at MIT"), AddedFact(fact="The user lives in San Francisco"), ] ) ``` ```typescript await zep.memory.addSessionFacts("sessionId", { facts: [ { fact: "The user is a software engineer" }, { fact: "The user studied at MIT" }, { fact: "The user lives in San Francisco" }, ] }); ``` ## Deleting Facts You or your users may want to remove a fact from Zep's memory. You can do this by [deleting a fact](/api-reference/memory/delete-fact) by Fact `UUID`. ## Retrieving Facts Facts are added to Memory responses when you retrieve a Session's [Memory](types). They're also accessible the [Search API](/api-reference/memory/search-sessions) and lower-level [Session API](/api-reference/memory/get-session) and [Graph Search API](/api-reference/graph/search). # Performance Optimization Guide > Best practices for optimizing Zep performance in production This guide covers best practices for optimizing Zep's performance in production environments. ## Reuse the Zep SDK Client The Zep SDK client maintains an HTTP connection pool that enables connection reuse, significantly reducing latency by avoiding the overhead of establishing new connections. To optimize performance: * Create a single client instance and reuse it across your application * Avoid creating new client instances for each request or function * Consider implementing a client singleton pattern in your application * For serverless environments, initialize the client outside the handler function ## Optimizing Memory Operations The `memory.add` and `memory.get` methods are optimized for conversational messages and low-latency retrieval. For optimal performance: * Keep individual messages under 10K characters * Use `graph.add` for larger documents, tool outputs, or business data * Consider chunking large documents before adding them to the graph (the `graph.add` endpoint has a 300,000 character limit) * Remove unnecessary metadata or content before persistence * For bulk document ingestion, process documents in parallel while respecting rate limits ```python # Recommended for conversations zep_client.memory.add( session_id="session_123", message={ "role": "human", "content": "What's the weather like today?" } ) # Recommended for large documents await zep_client.graph.add( data=document_content, # Your chunked document content user_id=user_id, # Or group_id for group graphs type="text" # Can be "text", "message", or "json" ) ``` ### Get the memory context string sooner Additionally, you can request the memory context directly in the response to the `memory.add()` call. This optimization eliminates the need for a separate `memory.get()` if you happen to only need the context. Read more about [Memory Context](/concepts/#memory-context). In this scenario you can pass in the `return_context=True` flag to the `memory.add()` method. Zep will perform a user graph search right after persisting the memory and return the context relevant to the recently added memory. ```python memory_response = await zep_client.memory.add( session_id=session_id, messages=messages, return_context=True ) context = memory_response.context ``` ```typescript const memoryResponse = await zepClient.memory.add(sessionId, { messages: messages, returnContext: true }); const context = memoryResponse.context; ``` ```golang memoryResponse, err := zepClient.Memory.Add( context.TODO(), sessionID, &zep.AddMemoryRequest{ Messages: messages, ReturnContext: zep.Bool(true), }, ) if err != nil { // handle error } memoryContext := memoryResponse.Context ``` Read more in the [Memory API Reference](/api-reference/memory#add) ## Optimizing Search Queries Zep uses hybrid search combining semantic similarity and BM25 full-text search. For optimal performance: * Keep your queries concise. Queries are automatically truncated to 8,192 tokens (approximately 32,000 Latin characters) * Longer queries may not improve search quality and will increase latency * Consider breaking down complex searches into smaller, focused queries * Use specific, contextual queries rather than generic ones Best practices for search: * Keep search queries concise and specific * Structure queries to target relevant information * Use natural language queries for better semantic matching * Consider the scope of your search (user vs group graphs) ```python # Recommended - concise query results = await zep_client.graph.search( user_id=user_id, # Or group_id for group graphs query="project requirements discussion" ) # Not recommended - overly long query results = await zep_client.graph.search( user_id=user_id, query="very long text with multiple paragraphs..." # Will be truncated ) ``` ## Summary * Reuse Zep SDK client instances to optimize connection management * Use appropriate methods for different types of content (`memory.add` for conversations, `graph.add` for large documents) * Keep search queries focused and under the token limit for optimal performance # Understanding the Graph Zep's knowledge graph powers its facts and memory capabilities. Zep's graph is built on [Graphiti](/graphiti/graphiti/overview), Zep's open-source temporal graph library, which is fully integrated into Zep. Developers do not need to interact directly with Graphiti or understand its underlying implementation. Zep's graph database stores data in three main types: 1. Entity edges (edges): Represent relationships between nodes and include semantic facts representing the relationship between the edge's nodes. 2. Entity nodes (nodes): Represent entities extracted from episodes, containing summaries of relevant information. 3. Episodic nodes (episodes): Represent raw data stored in Zep, either through chat history or the `graph.add` endpoint. ## Working with the Graph To learn more about interacting with Zep's graph, refer to the following sections: * [Adding Data to the Graph](/adding-data-to-the-graph): Learn how to add new data to the graph. * [Reading Data from the Graph](/reading-data-from-the-graph): Discover how to retrieve information from the graph. * [Searching the Graph](/searching-the-graph): Explore techniques for efficiently searching the graph. These guides will help you leverage the full power of Zep's knowledge graph in your applications. # Adding Data to the Graph ## Adding Data to the Graph This feature is currently available to all users, however, may be restricted to paid users in the future. Contact us for more information. In addition to incorporating memory through chat history, Zep offers the capability to add data directly to the graph. Zep supports three distinct data types: message, text, and JSON. The message type is ideal for adding data in the form of chat messages that are not directly associated with a Zep [Session's](/chat-history-memory/sessions) 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. The `graph.add` endpoint has a data size limit of 300,000 characters. Additionally, it requires a timestamp indicating when the document was created. If the creation time is unknown or irrelevant, you may use the current time. You can add data to either an individual user's graph by providing a `user_id`, or to a user group's graph by specifying a `group_id`. Here's an example demonstrating how to add data to the graph: ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) json_data = {"name": "Eric Clapton", "age": 78, "genre": "Rock"} json_string = json.dumps(json_data) await client.graph.add( user_id=user_id, type="json", data=json_string, ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const jsonString = '{"name": "Eric Clapton", "age": 78, "genre": "Rock"}'; await client.graph.add({ userId: userId, type: "json", data: jsonString, }); ``` # Reading Data from the Graph Zep provides APIs to read Edges, Nodes, and Episodes from the graph. These elements can be retrieved individually using their `UUID`, or as lists associated with a specific `user_id` or `group_id`. The latter method returns all objects within the user's or group's graph. Examples of each retrieval method are provided below. ## Reading Edges ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) edge = await client.graph.edge.get(edge_uuid) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const edge = await client.graph.edge.get(edge_uuid); ``` ## Reading Nodes ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) node = await client.graph.node.get_by_user(user_uuid) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const node = await client.graph.node.get_by_user(user_uuid); ``` ## Reading Episodes ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) episode = await client.graph.episode.get_by_group(group_uuid) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const episode = await client.graph.episode.get_by_group(group_uuid); ``` # Searching the Graph Zep's Graph search combines semantic similarity and full-text BM25 search. It supports multiple rerankers: [Reciprocal Rank Fusion](#reciprocal-rank-fusion), [Maximal Marginal Relevance](#maximal-marginal-relevance-re-ranking), [Node Distance](#node-distance), and [Episode Mentions](#episode-mentions). ## Simple Hybrid Edge Search Graph edges represent relationships between nodes and contain retrievable semantic facts. The basic search query is a text-based hybrid search against graph edges. It requires only a text string as input. Zep performs both semantic similarity search using embeddings and BM25 full-text search, and results are merged and reranked using Reciprocal Rank Fusion (RRF). Reciprocal Rank Fusion (RRF) combines and ranks results from multiple searches based on their individual rankings. The example below demonstrates a search against a chat session using only search text. ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) search_results = await client.graph.search( user_id=user_id, query=query, ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const searchResults = await client.graph.search({ userId: userId, query: query, }); ``` Read more about [chat message history search](/concepts/#using-memorysearch_sessions). ## Search Scopes Graph search supports both edge and node scopes. Nodes represent entities discussed in chat history or business data added via the [Graph API](/adding-data-to-the-graph). Nodes contain summaries of relevant facts from edges adjacent to the node, providing a useful overview of a node's context. Group graphs can be searched by passing a `group_id` instead of a `user_id`. The example below demonstrates a node search. All re-ranking methods are applicable to node searches as well. ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) search_results = await client.graph.search( group_id=group_id, query=query, scope="nodes", ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const searchResults = await client.graph.search({ groupId: groupId, query: query, scope: "nodes", }); ``` ## Maximal Marginal Relevance Re-Ranking Zep supports Maximal Marginal Relevance (MMR) re-ranking for graph search results. MMR balances relevance and diversity in search results. Standard similarity searches often return highly similar top results, potentially limiting the information added to a prompt. MMR addresses this by re-ranking results to promote diversity, downranking similar results in favor of relevant but distinct alternatives. Example of MMR search: ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) search_results = await client.graph.search( user_id=user_id, query=query, reranker="mmr", mmr_lambda=0.5, # tune diversity vs relevance ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const searchResults = await client.graph.search({ userId: userId, query: query, reranker: "mmr", mmrLambda: 0.5, // tune diversity vs relevance }); ``` ## Node Distance [Node Distance](#node-distance) re-ranks search results based on the number of hops between the search result and a center node. This can be useful for finding facts related to a specific node, such as a user or a topic. The UUID of a node must be passed in to be used as a center node. An example using Node Distance search. ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) search_results = await client.graph.search( user_id=user_id, query=query, reranker="node_distance", center_node_uuid=center_node_uuid, ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const searchResults = await client.graph.search({ userId: userId, query: query, reranker: "node_distance", centerNodeUuid: centerNodeUuid, }); ``` ## Episode Mentions [Episode Mentions](#episode-mentions) re-ranks search results based on the number of times the node or edge has been mentioned in the chat history. An example using Episode Mentions search. ```python from zep_cloud.client import AsyncZep client = AsyncZep( api_key=API_KEY, ) search_results = await client.graph.search( user_id=user_id, query=query, reranker="episode_mentions", ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: API_KEY, }); const searchResults = await client.graph.search({ userId: userId, query: query, reranker: "episode_mentions", }); ``` # Structured Outputs from Messages > Get Structured Outputs from Chat History stored in Zep, faster and more accurately than your LLM Provider's JSON or Structured Outputs mode. Structured Data Extraction for Python{" "} requires `pydantic` version 2 installed and is not compatible with `pydantic` v1. Many business and consumer apps need to extract structured data from conversation between an Assistant and human user. Often, the extracted data is the objective of the conversation. Often, you will want to identify the data values you have collected and which values you still need to collect in order to prompt the LLM to request the latter. This can be a slow and inaccurate exercise, and frustrating to your users. If you're making multiple calls to an LLM to extract and validate data on every chat turn, you're likely adding seconds to your response time. Zep's structured data extraction (SDE) is a [low-latency, high-fidelity tool](#latency-and-accuracy-baselines) for generating structured output from Chat History stored in Zep. For many multi-field extraction tasks you can expect latency of under 400ms, with the addition of fields increasing latency sub-linearly. ## Quick Start An end-to-end SDE example (in Python) can be found in the [Zep By Example repo](https://github.com/getzep/zep-by-example/blob/main/structured-data-extraction/python/sales_order.ipynb). The example covers: * defining a model using many of the field types that SDE supports * extracting data from a Chat History * and provides an example of how to merge newly extracted data with an already partially populated model. ## SDE vs JSON or Structured Outputs Mode Many model providers offer a JSON and/or Structured Outputs inference mode that guarantees the output will be well-formed JSON, or in the case of Structured Output, is valid according to a provided schema. However: 1. When using JSON Mode, there are no guarantees that the field values themselves will conform to your JSON Schema. 2. When using Structured Outputs Mode, there are no guarantees that the field values themselves will conform to your JSON Schema, beyond primitive data types such as strings, numbers, booleans, etc. 3. There are no guarantees that the field values are correct (vs. being hallucinated). 4. All fields are extracted in a single inference call, with additional fields adding linearly or greater to extraction latency. #### SDE's Preprocessing, Guided LLM Output, and Validation Zep uses a combination of dialog preprocessing, guided LLM output, and post-inference validation to ensure that the extracted data is in the format you expect and is valid given the current dialog. When using a structured Field Type (such as `ZepDate`, `ZepEmail`, `ZepRegex`), you will not receive back data in an incorrect format. While there are limits to the accuracy of extraction when the conversation is very nuanced or ambiguous, with careful crafting of field descriptions, you can achieve high accuracy in most cases. #### Concurrent Extraction Scales Sub-Linearly SDE's extraction latency scales sub-linearly with the number of fields in your model. That is, you may add additional fields with low marginal increase in latency. You can expect extraction times of 400ms or lower when extracting fairly complex models for a 500 character dialog (which includes both message content and your Role and RoleType designations). ## Defining Your Model To extract data with Zep, you will need to define a model of the data you require from a Chat History. Each model is composed of a set of fields, each of which has a type and description. Key to successful extraction of data is careful construction of the field description. ```python maxLines=30 from pydantic import Field from zep_cloud.extractor import ZepModel, ZepText, ZepEmail, ZepDate class SalesLead(ZepModel): company_name: Optional[ZepText] = Field( description="The company name", default=None ) lead_name: Optional[ZepText] = Field( description="The lead's name", default=None ) lead_email: Optional[ZepEmail] = Field( description="The lead's email", default=None ) lead_phone: Optional[ZepPhoneNumber] = Field( description="The lead's phone number", default=None ) budget: Optional[ZepFloat] = Field( description="The lead's budget for the product", default=None ) product_name: Optional[ZepRegex] = Field( description="The name of the product the lead is interested in", pattern=r"(TimeMachine|MagicTransporter)", default=None ) zip_code: Optional[ZepZipCode] = Field( description="The company zip code", default=None ) ``` When using Python, your model will subclass `ZepModel`. Zep builds on `pydantic` and requires correctly typing fields and using the `Field` class from `pydantic` to define the field description, default value, and `pattern` when using a `ZepRegex` field. ```typescript maxLines=30 import { zepFields } from '@getzep/zep-cloud'; import { type ExtractedData } from '@getzep/zep-cloud/extractor'; const leadModelSchema = { companyName: zepFields.text("The company name"), leadName: zepFields.text("The lead's name"), leadEmail: zepFields.email("The lead's email"), leadPhone: zepFields.phoneNumber("The lead's phone number"), budget: zepFields.float("The lead's budget for the product"), productName: zepFields.regex( "The name of the product the lead is interested in", /(TimeMachine|MagicTransporter)/ ), zipCode: zepFields.zipCode("The company zip code"), } // { companyName?: string, leadName?: string, leadEmail?: string, leadPhone?: string, budget?: number, productName?: string, zipCode?: string } type LeadModel = ExtractedData; ``` TypeScript models are an object where each field is of a supported `zepFields` type. The object may be typed as `ExtractedData` to access the correctly typed extracted data. ## Executing an Extraction To execute an extraction, you will need to call the `extract` method on the memory client. This method requires a `session_id` and a model schema that specifies the types and structures of data to be extracted based on field descriptions. The `lastN` parameter, or Python equivalent `last_n`, specifies the number prior messages in the Session's Chart History to look back at for data extraction. The `validate` parameter specifies whether to optionally run an additional validation step on the extracted data. The `currentDateTime` parameter, or Python equivalent `current_date_time`, specifies your user's current date and time. This is used when extracting dates and times from relative phrases like *"yesterday"* or *"last week"* and to correctly set the timezone of the extracted data. ```python extracted_data: SalesLead = client.memory.extract( session_id, SalesLead, last_n=8, validate=False, current_date_time=datetime.now(ZoneInfo('America/New_York')) ) ``` ```typescript import moment from "moment-timezone"; const currentDateTimeNYC = moment.tz("America/New_York").format(); const lead: LeadModel = await client.memory.extract( sessionId, leadModelSchema, { lastN: 8, validate: false, currentDateTime: currentDateTimeNYC, } ); ``` ## Using Progressive Data Extraction To Guide LLMs Your application may need to collect a number of fields in order to accomplish a task. You can guide the LLM through this process by calling `extract` on every chat turn, identifying which fields are still needed, providing a partially populated model to the LLM, and directing the LLM to collect the remaining data. ```ansi title="Example Prompt" You have already collected the following data: - Company name: Acme Inc. - Lead name: John Doe - Lead email: john.doe@acme.com You still need to collect the following data: - Lead phone number - Lead budget - Product name - Zip code Do not ask for all fields at once. Rather, work the fields into your conversation with the user and gradually collect the data. ``` As each field is populated, you may copy these values into an immutable data structure. Alternatively, if existing values change as the conversation progresses, you can apply a heuristic informed by your business rules to update the data structure with the new values. ## Supported Field Types Zep supports a wide variety of field types natively. Where Zep does not support a native field type, you can use a `ZepRegex` field to extract a string that matches a structure you define. | Type | Description | Python Type | TypeScript Type | | -------- | ------------------------------------------------------------------------------ | ---------------- | ----------------------- | | Text | Plain text values without a set format. | `ZepText` | `zepFields.text` | | Number | Integer values. | `ZepNumber` | `zepFields.number` | | Float | Floating-point numbers. | `ZepFloat` | `zepFields.float` | | Regex | Strings matching a regex pattern. | `ZepRegex` | `zepFields.regex` | | DateTime | Date and time values returned as an ISO 8601 string using your local timezone. | `ZepDateTime` | `zepFields.dateTime` | | Date | Date values returned as an ISO 8601 string using your local timezone. | `ZepDate` | `zepFields.date` | | Email | Email addresses. | `ZepEmail` | `zepFields.email` | | Phone | Phone numbers in North American Numbering Plan format. | `ZepPhoneNumber` | `zepFields.phoneNumber` | | Zip Code | Postal codes in North American ZIP or ZIP+4 format, if available. | `ZepZipCode` | `zepFields.zipCode` | ## Improving Accuracy Extraction accuracy may be improved by experimenting with different descriptions and using Zep's built-in field validation. ### Improving Descriptions When describing fields, ensure that you've been both specific and clear as to what value you'd like to extract. You may also provide few-shot examples in your description. | Bad ❌ | Good ✅ | | ------------ | ------------------------------------ | | name | the name of the customer | | phone | the customer's phone number | | address | street address | | address | postal address | | product name | product name: "WidgetA" or "WidgetB" | ### Validating Extracted Data When `validation` is enabled on your `extract` call, Zep will run an additional LLM validation step on the extracted data. This provides improved accuracy and reduces the risk of hallucinated values. The downside to enabling field validation is increased extraction latency and an increased risk of false negatives (empty fields where the data may be present in the dialog). We recommend running without field validation first to gauge accuracy and latency and only enable field validation if you've determined that it is needed given your use case. ## Working with Dates Zep understands a wide variety of date and time formats, including relative times such as "yesterday" or "last week". It is also able to parse partial dates and times, such as "at 3pm" or "on the 15th". All dates and times are returned in ISO 8601 format and use the timezone of the `currentDateTime` parameter passed to the `extract` call. If you are extracting datetime and date fields it is important that you provide a `currentDateTime` value in your `extract` call and ensure that it is in the correct timezone for your user (or the base timezone your application uses internally). ## Extracting from Speech Transcripts Zep is able to understand and extract data from machine-translated transcripts. Spelled out numbers and dates will be parsed as if written language. Utterances such as "uh" or "um" are ignored. | Description | From | To | | ----------------------------- | ------------------------------------------------------------------------------------------- | ------------------- | | Apartment size in square feet | It is a three bedroom with approximately one thousand two hundred and fifty two square feet | 1252 | | Meeting date and time | I'm available on the uh fifteenth at uh three pm | 2024-06-15T15:00:00 | | The user's phone number | It's uh two five five two three four five six seven uh eight | (255) 234-5678 | We are constantly improving transcript extraction. Let us know if you have a use case where this does not work well! ## Multilingual Data Support Zep's Structured Data Extraction supports most major languages. ## Tips, Tricks, and Best Practices ### Limit the number of Messages from which you extract data If your use case is latency sensitive, limit the number of messages from which you extract data. The higher the last `N` messages, the longer the extraction will take. ### Always make fields optional in Python models Always make fields optional in your Python model. This will prevent runtime errors when the data is not present in the conversation. ### Using Regex when Zep doesn't support your data type The `ZepRegex` field type is a swiss army knife for extracting data. It allows you to extract any string that matches a regex pattern defined by you. ```python class OrderInfo(ZepModel): order_id: Optional[ZepRegex] = Field( description="The order ID in format ABC-12345", pattern=r"[A-Z]{3}-\d{5}" ) ``` ```typescript orderSchema = { orderId: zepFields.regex({ "The order ID in format ABC-12345", /[A-Z]{3}-\d{5}/, }), } ``` ### Implementing Enum Fields The `ZepRegex` field type can be used to extract data from a list of enums provided in a capture group. ```python order_currency: Optional[ZepRegex] = Field( description="The order currency: USD, GBP, or UNKNOWN", default=None, pattern=r"(UNKNOWN|USD|GBP)" ) ``` Results in: ```text "USD" ``` ### Comma Separated Lists You can extract comma separated lists using the `ZepRegex` field type: ```python brand_preferences: Optional[ZepRegex] = Field( description="The customer's preferred brands as a comma-separated list", default=None, pattern=r"\w+(, \w+)+" ) ``` Results in: ```text "Nike, Adidas, Puma" ``` ### Unsupported Regex Patterns The following Regex tokens and features are unsupported when using the Regex field type: * Start of and end of string anchors (`^` and `$`) and absolute positioning (`\A` and `\Z`). * Named groups (`(?P...)`). * Backreferences (`\g`). * Lookaheads and lookbehinds (`(?=...)`, `(?!...)`, `(?<=...)`, `(? Zep enables you to classify Sessions into various categories and save these classifications in the Session's metadata. This feature is handy for directing Sessions to appropriate agents or for monitoring the kinds of interactions users have with your Assistant. Classifications are processed in just a few hundred milliseconds, allowing them to run synchronously with the chat loop. ## Classifying Sessions A classification task consists of a topic and a list of classes. The `topic` is the type of classification you want to perform, and the `classes` are the possible categories you want to classify the Session into. The `topic` is only used as a name or label for the classification task and does not affect the classification itself. You may optionally specify the number of previous messages to consider when classifying the Session (default `4`), and whether to persist the classification in the Session's metadata (default `True`). ```python classification = await client.memory.classify_session( session_id, name="topic", classes=["class1", "class2", "other"], last_n=4, persist=True ) ``` ```typescript const classification = await client.memory.classifySession( session_id, { name: "topic", classes: ["class1", "class2", "other"], lastN: 4, persist: true } ) ``` The returned result will be one of the classes you provided, or "other" if none of the classes are a good fit. The classification result is also stored in the Session's metadata if `persist` is `True`. ```json { "system": { "classes": { "topic": "travel" } } } ``` And Sessions viewed in the Zep app will be labeled with the classification result. Classifier Metadata Image ### Adding Custom Instruction You may optionally provide a custom instruction to the classification task. This instruction will be injected into the Dialog Classification Prompt. You may want to use this option if you have specific guidelines that you want to communicate to the LLM in addition to our classification prompt. ```python classification = await client.memory.classify_session( session_id, name="experience level", classes=["advanced", "beginner", "dojo"], instruction="Classify the user's experience level. You may classify experience as 'dojo' only if the user is a black belt." ) ``` ```typescript const classification = await client.memory.classifySession( session_id, { name: "experience level", classes: ["advanced", "beginner", "dojo"], instruction: "Classify the user's experience level. You may classify experience as 'dojo' only if the user is a black belt." } ) ``` ### Building a Semantic Router with User Intent Zep's Session Classifier can be used to build a semantic router that routes user sessions to different agents or chains based on the user's intent. ```Text user: Hello, my phone isn't responding to touch. ``` ```python classification = await client.memory.classify_session( session_id, name="intent", classes=[ "sales interest", "needs support", "has payment question", "other" ] ) print(classification) ``` ```typescript const classification = await client.memory.classifySession( session_id, { name: "intent", classes: [ "sales interest", "needs support", "has payment question", "other" ] } ) console.log(classification.class) ``` ```Text "needs support" ``` ### A High-Performance Tool Picker Using an agent to pick tools can often be slow and inaccurate. Zep's Session Classifier allows you to pick tools at very low latency and high accuracy. You may then instruct an LLM to use the selected tool and provided Session information. ```Text user: What is the capital of France? ``` ```python classification = await client.memory.classify_session( session_id, name="tool", classes=[ "complete math problems using a calculator", "research topics or find information with a web search", "no matching tool", ] ) ``` ```typescript const classification = await client.memory.classifySession( session_id, { name: "tool", classes: [ "complete math problems using a calculator", "research topics or find information with a web search", "no matching tool", ] } ) ``` ```Text "research topics or find information with a web search" ``` ### Classifying Emotions Zep's Session Classifier can be used to classify user emotions and store these classifications in the Session's metadata. ```Text AI: We're unfortunately going to reschedule your appointment. user: Is that entirely necessary? I'm very busy. ``` ```python classification = await client.memory.classify_session( session_id, name="emotion", classes=[ "happy", "sad", "frustrated", "angry", "other" ] ) ``` ```typescript classification = await client.memory.classifySession( session_id, { name: "emotion", classes: [ "happy", "sad", "frustrated", "angry", "other" ], } ) ``` ```Text "frustrated" ``` ## Executing Multiple Classifications Zep supports executing multiple classification tasks against a Session, allowing you to classify a Session into different categories and store these classifications in the Session's metadata. ```json { "system": { "classes": { "topic": "travel", "intent": "needs support", "emotion": "frustrated" } } } ``` ## Best Practices 1. **Use a small number of classes**: The more classes you have, the more difficult it is to classify a Session accurately. Recommendation: no more than 5 or 6 classes. 2. **Ensure your classes are well separated**: If your classes are too similar, the classifier will have a hard time distinguishing between them. 3. **Provide a "none", "other", or "unknown" class**: If none of the classes are a good fit, the classifier should be able to select an option that indicates this. 4. **Limit the number of previous messages**: The more messages you consider, the longer the classification will take. Additionally, the context may change through the conversation. Recommendation: no more than the prior 4 to 6 messages. 5. **Persist the classification**: If you want to use the classification result in the future, you should persist the classification in the Session's metadata. This is the default. # Question Synthesis Users often respond to questions with single-word answers that don't offer much information for search. For example, a user may respond to a question about their favorite book with "Dune" or a question about their dietary restrictions with "dairy". Without context, many user messages lack information necessary to successfully embed a search query, resulting in poor or irrelevant search results. Zep provides a low-latency question synthesis API that can be used to generate a question from the current conversation context, using the most recent message to center the question. While it's possible to synthesize a question using a general purpose LLM, this is often a slow and inaccurate exercise. Zep's private, fine-tuned models are designed to return results in hundreds of milliseconds. Want to see Question Synthesis in action? Take a look at [Zep's LangService VectorStore example](https://github.com/getzep/zep-python/blob/main/examples/langchain-langserve/app/message_history_vector_store_chain.py). ```python result = await client.memory.synthesize_question(session_id) print(result.question) ``` ```typescript const result = await client.memory.synthesizeQuestion(sessionId); console.log(result.question); ``` ```Text assistant: Iceland can be expensive. Costs depend on factors like accommodations, activities, and dining preferences. However, you can expect to spend around $200-$300 per day, not including flights. user: Is it easy to find vegetarian or vegan food in Iceland? assistant: Yes, Reykjavik has several vegetarian and vegan-friendly restaurants. Do you have any dietary restrictions? user: Yes, dairy. ``` ```Text Can the user eat dairy products? ``` # Document Collections Document Collections are **deprecated** and have been removed from Zep Community Edition. We will be removing this feature from Zep Cloud in a future release. Zep's document vector store lets you embed and search documents using vector similarity search, Maximum Marginal Relevance Re-Ranking, and metadata filtering. You can manage collections, ingest documents, and search using *Zep's SDKs*, *LangChain*, or *LlamaIndex*. `zep-python` supports asynchronous operations. All methods come in sync and async flavors, with async methods prefixed with `a`. For instance, `zep-python` offers both `zep_client.memory.add_memory` and `zep_client.memory.add_memory`. ## Key Concepts ### Collections A `Collection` is a group of documents that use the same embedding strategy and model. *Zep automatically creates embeddings* for the documents you provide. ### Documents `Documents` are the texts you want to embed and search. You can add documents to collections and optionally assign them a unique ID and metadata. *If you add metadata, it can help filter search results.* ## Initializing the Zep Client For details on initializing the Zep client, check out the [SDK documentation](/sdks). ## Creating a Collection ```python client = AsyncZep( api_key=API_KEY, ) collection_name = "babbagedocs" # the name of your collection. alphanum values only collection = await client.document.add_collection( collection_name, # required description="Babbage's Calculating Engine", # optional metadata={"foo": "bar"}, # optional metadata to associate with this collection ) ``` ```typescript const client = new ZepClient({ apiKey: API_KEY, }); const collectionName: string = "babbagedocs"; // The name of your collection. Alphanumeric values only const collection = await client.document.addCollection(collectionName, { description: "Babbage's Calculating Engine", // Optional metadata: { foo: "bar" }, // Optional metadata to associate with this collection }); ``` ## Loading an Existing Collection ```python collection = await client.document.get_collection(collection_name) ``` ```typescript const collection = await client.document.getCollection(collectionName); ``` ## Adding Documents to a Collection ```python chunks = read_chunks_from_file(file, max_chunk_size) # your custom function to read chunks from a file documents = [ CreateDocumentRequest( content=chunk, document_id=f"{collection_name}-{i}", # optional document ID metadata={"bar": i}, # optional metadata ) for i, chunk in enumerate(chunks) ] uuids = client.document.add_documents(documents) ``` `document_id` is an optional identifier you can assign to each document. It's handy for linking a document chunk with a specific ID you choose. The `metadata` is an optional dictionary that holds metadata related to your document. Zep leverages this metadata for hybrid searches across a collection, enabling you to filter search results more effectively. When you use `document.add_documents`, it returns a list of Zep UUIDs corresponding to the documents you've added to the collection. ```typescript const chunks: string[] = readChunksFromFile(file, maxChunkSize); // Your custom function to read chunks from a file const documents = chunks.map((chunk, index) => { return { content: chunk, documentId: `${collectionName}-${index}`, // Optional document ID metadata: { bar: index }, // Optional metadata }; }); const uuids: string[] = await client.document.addDocuments( collectionName, documents ); ``` `document_id` is an optional identifier you can assign to each document. It's handy for linking a document chunk with a specific ID you choose. The `metadata` is an optional dictionary that holds metadata related to your document. Zep leverages this metadata for hybrid searches across a collection, enabling you to filter search results more effectively. When you use `document.addDocuments`, it returns a list of Zep UUIDs corresponding to the documents you've added to the collection. Zep's document vector store has VectorStore support for Langchain. **Python Example:** ```python from langchain.docstore.base import Document from langchain.text_splitter import RecursiveCharacterTextSplitter from zep_cloud.langchain import ZepVectorStore vectorstore = ZepVectorStore( collection_name=ZEP_COLLECTION_NAME, api_key=ZEP_API_KEY, ) text_splitter = RecursiveCharacterTextSplitter( chunk_size=400, chunk_overlap=50, length_function=len, ) docs = text_splitter.create_documents([raw_text]) uuids = vectorstore.add_documents(docs) ``` **Typescript Example:** ```typescript import { ZepClient } from "@getzep/zep-cloud"; import { ZepVectorStore } from "@getzep/zep-cloud/langchain"; import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; const zepClient = new ZepClient({ apiKey: process.env.ZEP_API_KEY, }); const vectorStore = await ZepVectorStore.init({ client: zepClient, collectionName: "", }); const text_splitter = new RecursiveCharacterTextSplitter({ chunkSize: 400, chunkOverlap: 50, lengthFunction: (text: string) => text.length, // Assuming lengthFunction accepts a function that returns the length of the text }); const docs = await text_splitter.createDocuments([raw_text]); const uuids = await vectorStore.addDocuments(docs); ``` ### Chunking your documents Choosing the right *chunking strategy* is crucial and highly dependent on your specific needs. A variety of 3rd-party libraries, including Langchain, offer support for processing documents from numerous sources and dividing them into smaller segments suitable for embedding. We recommend experimenting with various extractors, chunking strategies, sizes, and overlaps to discover the optimal approach for your project. ## Monitoring Embedding Progress The process of embedding documents in Zep is asynchronous. To keep track of your collection's embedding progress, you can periodically check the collection's status: ```python import time while True: c = await client.document.get_collection(collection_name) print( "Embedding status: " f"{c.document_embedded_count}/{c.document_count} documents embedded" ) time.sleep(1) if c.status == "ready": break ``` ```typescript while (true) { const collection = await client.document.getCollection(collectionName); console.log( `Embedding status: ${c.document_embedded_count}/${c.document_count} documents embedded` ); await sleep(1000); // Sleep for 1 second (1000 milliseconds) if (collection.status === "ready") { break; } } ``` Once the collection's status changes to `ready`, it means all documents have been successfully embedded and are now searchable. ## Searching a Collection with Hybrid Vector Search Zep enables hybrid vector search across your collections, allowing you to pinpoint the most relevant documents based on semantic similarity. Additionally, you have the option to refine your search by filtering through document metadata. You can initiate a search using either a text query or an embedding vector, depending on your needs. Zep's Collection and Memory search support semantic search queries, JSONPath-based metadata filters, and a combination of both. Memory search also supports querying by message creation date. ```python # search for documents using only a query string query = "the moon" results = await client.document.search(collection_name, text=query, limit=5) # hybrid search for documents using a query string and metadata filter metadata_query = { "where": {"jsonpath": '$[*] ? (@.baz == "qux")'}, } results = await client.document.search( collection_name, text=query, metadata=metadata_query, limit=5 ) ``` `metadata` is an optional dictionary of [JSONPath filters](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html) used to match on metadata associated with your documents. `limit` is an optional integer indicating the maximum number of results to return. ```typescript const query = "the moon"; let results = await client.document.search(collectionName, { text: query, limit: 5, }); // Hybrid search for documents using a query string and metadata filter const metadataQuery = { where: { jsonpath: '$[*] ? (@.baz == "qux")' }, }; results = await client.document.search(collectionName, { text: query, metadata: metadataQuery, limit: 5, }); ``` `metadata` is an optional dictionary of [JSONPath filters](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html) used to match on metadata associated with your documents. `limit` is an optional integer indicating the maximum number of results to return. **Python Example:** ```python query = "What is Charles Babbage best known for?" print(f"\nSearching for '{query}'\n") results = vectorstore.search(query, search_type="similarity", k=5) print_results(results) print(f"\nSearching for '{query}' with MMR reranking\n") results = vectorstore.search(query, search_type="mmr", k=5) print_results(results) ``` **Typescript Example:** ```typescript const query = "What is Charles Babbage best known for?"; console.log(`\nSearching for '${query}'\n`); const resultsSimilarity = await vectorstore.search(query, { searchType: "similarity", k: 5, }); console.log(resultsSimilarity); console.log(`\nSearching for '${query}' with MMR reranking\n`); const resultsMMR = await vectorstore.search(query, { searchType: "mmr", k: 5 }); console.log(resultsMMR); ``` *You can also use `ZepVectoreStore` as a retriever with langchain* Python example ```python retriever = vectorstore.as_retriever() _inputs = RunnableParallel( { "question": lambda x: x["question"], "context": extract_question | retriever | _combine_documents, }, ).with_types(input_type=UserInput) chain = (_inputs | answer_prompt | ChatOpenAI() | StrOutputParser()) ``` **Please check the complete python [rag vector store chain example](https://github.com/getzep/zep-python/blob/main/examples/langchain-langserve/app/rag_vector_store_chain.py)** Typescript example ```typescript const retriever = vectorStore.asRetriever(); const setupAndRetrieval = RunnableMap.from({ context: new RunnableLambda({ func: (input: string) => retriever.invoke(input).then(combineDocuments), }), question: new RunnablePassthrough(), }); const outputParser = new StringOutputParser(); const chain = setupAndRetrieval.pipe(prompt).pipe(model).pipe(outputParser); ``` > *Please check the complete typescript [rag vector store chain example](https://github.com/getzep/zep-js/blob/main/examples/langchain/vector_store_example.ts)* ## Retrieving Documents by UUID Zep supports retrieving a list of documents by Zep UUID: ```python docs_to_get = uuids[40:50] documents = await client.document.batch_get_documents( collection_name, uuids=docs_to_get ) ``` ```typescript const docsToGet = uuids.slice(40, 50); const documents = await client.document.batchGetDocuments(collectionName, { uuids: docsToGet, }); ``` ## Other Common Operations This section covers additional common operations you might need to perform, such as listing all collections within your client's scope. The examples above demonstrate how to create an index on a collection and list all collections for both Python and TypeScript. ### Updating a Collection's Description or Metadata ```python client.document.update_collection( collection_name, description="Charles Babbage's Babbage's Calculating Engine 2", metadata={"newfoo": "newbar"}, ) ``` ```typescript await client.document.updateCollection(collectionName, { description: "Charles Babbage's Babbage's Calculating Engine 2", metadata: { newfoo: "newbar" }, }); ``` ### Batch Update Documents' ID or Metadata ```python await client.docyment.batch_update_documents( collection_name, request=[ UpdateDocumentListRequest( uuid_="uuid", document_id="new_id", metadata={"foo": "bar"}, ) ], ) ``` ```typescript await collection.batchUpdateDocuments(collectionName, [ { uuid: "uuid", documentId: "new_id", metadata: { foo: "bar" }, }, ]); ``` ### Deleting Documents Zep supports deleting documents from a collection by UUID: ```python await client.document.delete_document(collection_name, document_uuid) ``` ```typescript await collection.deleteDocument(collectionName, documentUUID); ``` ### Deleting a Collection Deleting a collection will delete all documents in the collection, as well as the collection itself. ```python await client.document.delete_collection(collection_name) ``` ```typescript await client.document.deleteCollection(collectionName); ``` # ZepChatMessageHistory The Zep Memory, VectorStore, and Retriever classes found in the LangChain project are **deprecated**. [LangGraph](/ecosystem/langgraph-memory) is the recommended approach to using Zep with the LangChain ecosystem. **You can find a complete [Message History Example](examples/messagehistory-example) that showcases how to use the `ZepChatMessageHistory` class in the chain.** LangChain offers a `ZepChatMessageHistory` class compatible with [LangChain Expression Language (LCEL)](https://python.langchain.com/docs/expression_language/get_started). It expects the following initialization parameters: The unique identifier for Zep Session. If a session for the provided identifier doesn't exist, one will be created The Zep client used for making API requests. You can pass it rather than the API Key. Zep Project API Key. You can pass it rather than `zep_client` and we will initialize `ZepClient` for you. The type of memory to use. Can be `"message_window"` (the default value if None provided) or `"perpetual"`. You can find out more about the memory types in the [Chat History documentation](/). ```python Initialization Example chat_history = ZepChatMessageHistory( session_id=session_id, zep_client=client, memory_type="perpetual", ) ``` LangChain offers a `ZepChatMessageHistory` class compatible with [LangChain Expression Language (LCEL)](https://js.langchain.com/docs/expression_language/). It expects the following initialization parameters: The unique identifier for Zep Session. If a session for the provided identifier doesn't exist, one will be created. The Zep client used for making API requests. You can pass it rather than the API Key. The type of memory to use. Can be `"message_window"` or `"perpetual"`. You can find out more about the memory types in the [Chat History documentation](/chat-history-memory). ```typescript Initialization Example const history = new ZepChatMessageHistory({ client: zepClient, sessionId: sessionId, memoryType: "perpetual", }) ``` # MessageHistory Example The Zep Memory, VectorStore, and Retriever classes found in the LangChain project are **deprecated**. [LangGraph](/ecosystem/langgraph-memory) is the recommended approach to using Zep with the LangChain ecosystem. LangChain offers a `ZepChatMessageHistory` class compatible with [LangChain Expression Language (LCEL)](https://python.langchain.com/docs/expression_language/get_started). This guide will walk you through creating a [MessageHistory](/chat-history-memory) chain using Zep's conversation history. **You can generate a project api key in Zep Dashboard.** Make sure you have the following environment variables specified when running these examples: `ZEP_API_KEY` - API key to your zep project `OPENAI_API_KEY` - Open AI api key which the chain will require to generate the answer **You will need to have a collection in place to initialize vector store in this example** If you want to create a collection from a web article, you can run the [python ingest script](https://github.com/getzep/zep-python/blob/main/examples/langchain-langserve/app/ingest.py) Try modifying the script to ingest the article of your choice. Alternatively, you can create a collection by running either [Document example](https://github.com/getzep/zep-python/blob/main/examples/documents/documents_async.py) in python sdk repository or [Document example](https://github.com/getzep/zep-js/blob/main/examples/documents/index.ts) in typescript sdk repository. **You will need to have a `session_id` in place to invoke the final chain in this example** You can create a session by running either [Memory example](https://github.com/getzep/zep-python/blob/main/examples/chat_history/memory_async.py) in python sdk repository or [Memory example](https://github.com/getzep/zep-js/blob/main/examples/memory/memory_example.ts) in typescript sdk repository. **Initialize ZepClient with necessary imports** ```python import os from typing import List, Tuple from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.pydantic_v1 import BaseModel, Field from langchain_core.runnables import ( RunnableParallel, ) from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_openai import ChatOpenAI from zep_cloud.client import AsyncZep from langchain_community.chat_message_histories.zep import ZepChatMessageHistory zep = AsyncZep( api_key=os.environ["ZEP_API_KEY"], ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; import { ZepChatMessageHistory } from "@getzep/zep-cloud/langchain"; import { ChatOpenAI } from "@langchain/openai"; import { ChatPromptTemplate, MessagesPlaceholder, } from "@langchain/core/prompts"; import { RunnableWithMessageHistory } from "@langchain/core/runnables"; const zepClient = new ZepClient({ apiKey: process.env.ZEP_API_KEY, }); ``` ```python template = """Answer the question below as if you were a 19th centry poet: """ answer_prompt = ChatPromptTemplate.from_messages( [ ("system", template), MessagesPlaceholder(variable_name="chat_history"), ("user", "{question}"), ] ) ``` ```typescript const prompt = ChatPromptTemplate.fromMessages([ ["system", "Answer the user's question below. Be polite and helpful:"], new MessagesPlaceholder("history"), ["human", "{question}"], ]); ``` **Set up an answer synthesis template and prompt.** **`MessagesPlaceholder`** - We're using the variable name `chat_history` here. This will incorporate the chat history into the prompt. It's **important** that this variable name aligns with the `history_messages_key` in the `RunnableWithMessageHistory` chain for seamless integration. **`question` must match `input_messages_key` in `RunnableWithMessageHistory`` chain.** **Compose the final chain** ```python inputs = RunnableParallel( { "question": lambda x: x["question"], "chat_history": lambda x: x["chat_history"], }, ) chain = RunnableWithMessageHistory( inputs | answer_prompt | ChatOpenAI() | StrOutputParser(), lambda session_id: ZepChatMessageHistory( session_id=session_id, # This uniquely identifies the conversation zep_client=zep, memory_type="perpetual", ), input_messages_key="question", history_messages_key="chat_history", ) ``` ```typescript const chain = prompt.pipe( new ChatOpenAI({ temperature: 0.8, modelName: "gpt-3.5-turbo-1106", }), ); const chainWithHistory = new RunnableWithMessageHistory({ runnable: chain, getMessageHistory: (sessionId) => new ZepChatMessageHistory({ client: zepClient, sessionId: sessionId, memoryType: "perpetual", }), inputMessagesKey: "question", historyMessagesKey: "history", }); ``` Here's a quick overview of what's happening: 1. We use `RunnableWithMessageHistory` to incorporate [Zep's Chat History](/) into our chain. 2. This class requires a `session_id` as a parameter when you activate the chain. 3. To manually invoke this chain, provide the `session_id` as a parameter and the `question` as an input to the chain. ```python chain_with_history.invoke( {"question": "-"}, config={"configurable": {"session_id": "-"}}, ) ``` ```typescript await chainWithHistory.invoke( { question: "-", }, { configurable: { sessionId: "-", }, }, ); ``` First, we initialize `ZepChatMessageHistory` with the following parameters: 1. `session_id` - This uniquely identifies the conversation within Zep. 2. `zep_client` - The instance of the Zep client. 3. `memory_type` set to `perpetual`. If not specified, Message Window Buffer Memory will be used by default. We recommend configuring your application to use Perpetual Memory. Interested in learning more? [Explore How Zep Memory Works](/chat-history-memory). Next, we construct a chain that operates after retrieving the chat history: 1. `inputs` will extract the user's question and chat history from the context. 2. `answer_prompt` will incorporate chat history into the prompt. 3. `ChatOpenAI` will generate a response. 4. `StrOutputParser` will parse the response. ## Running the Chain with LangServe This chain can also be executed as part of our LangServe sample project. To do this, you'll need to: For this you will need to: Clone our [Python SDK](https://github.com/getzep/zep-python) ```bash git clone https://github.com/getzep/zep-python cd examples/langchain-langserve ``` There is a [README](https://github.com/getzep/zep-python/blob/main/examples/README.md) file in the `langchain-langserve` directory will guide you through the setup process. Go to `http://localhost:8000/message_history/playground` to use LangServe playground for this chain. # LangGraph Memory Example > LangGraph is a library created by LangChain for building stateful, multi-agent applications. This example demonstrates using Zep for LangGraph agent memory. A complete Notebook example of using Zep for LangGraph Memory may be found in the [Zep Python SDK Repository](https://github.com/getzep/zep-python/blob/main/examples/langgraph-agent/agent.ipynb). The following example demonstrates a LangGraph agent using Zep for memory. Facts from Zep's memory graph are used to personalize agent responses based on information learned from prior conversations. The agent implements: * persistance of new chat turns to Zep and recall of relevant Facts using the most recent messages. * an in-memory MemorySaver to maintain agent state. We use this to add recent chat history to the agent prompt. As an alternative, you could use Zep for this. You should consider truncating MemorySaver's chat history as by default LangGraph state grows unbounded. We've included this in our example below. See the LangGraph documentation for insight. ## Install dependencies ```shell pip install zep-cloud langchain-openai langgraph ipywidgets ``` ## Configure Zep Ensure that you've configured the following API key in your environment. We're using Zep's Async client here, but we could also use the non-async equivalent. ```bash ZEP_API_KEY= ``` ```python from zep_cloud.client import AsyncZep from zep_cloud import Message zep = AsyncZep(api_key=os.environ.get('ZEP_API_KEY')) ``` ```python from langchain_core.messages import AIMessage, SystemMessage, trim_messages from langchain_core.tools import tool from langchain_openai import ChatOpenAI from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import END, START, StateGraph, add_messages from langgraph.prebuilt import ToolNode ``` ## Using Zep's Search as a Tool This is an example of a simple Tool that searches Zep for facts related to a user, irrespective which chat session. We also include relevant facts from the current session in the Agent's prompt. ```python class State(TypedDict): messages: Annotated[list, add_messages] user_name: str session_id: str @tool async def search_facts(state: State, query: str, limit: int = 5): """Search for facts in all conversations had with a user. Args: state (State): The Agent's state. query (str): The search query. limit (int): The number of results to return. Defaults to 5. Returns: list: A list of facts that match the search query. """ return await zep.memory.search_sessions( user_id=state['user_name'], text=query, limit=limit, search_scope="facts" ) tools = [search_facts] tool_node = ToolNode(tools) llm = ChatOpenAI(model='gpt-4o-mini', temperature=0).bind_tools(tools) ``` ## Chatbot Function Explanation The chatbot uses Zep to provide context-aware responses. Here's how it works: 1. **Context Retrieval**: It retrieves relevant facts for the user's current conversation (session). Zep uses the most recent messages to determine what facts to retrieve. 2. **System Message**: It constructs a system message incorporating the facts retrieved in 1., setting the context for the AI's response. 3. **Message Persistence**: After generating a response, it asynchronously adds the user and assistant messages to Zep. New Facts are created and existing Facts updated using this new information. 4. **Messages in State**: We use LangGraph state to store the most recent messages and add these to the Agent prompt. We limit the message list to the most recent 3 messages for demonstration purposes. This approach enables the chatbot to maintain context across interactions and provide personalized responses based on the user's history and preferences stored in Zep. We could also use Zep to recall the chat history, rather than LangGraph's MemorySaver. See [`memory.get`](/api-reference/memory/get) in the Zep API documentation. ```python async def chatbot(state: State): memory = await zep.memory.get(state["session_id"]) facts_string = "" if memory.relevant_facts: facts_string = "\n".join([f.fact for f in memory.relevant_facts]) system_message = SystemMessage( content=f"""You are a compassionate mental health bot and caregiver. Review information about the user and their prior conversation below and respond accordingly. Keep responses empathetic and supportive. And remember, always prioritize the user's well-being and mental health. Facts about the user and their conversation: {facts_string or 'No facts about the user and their conversation'}""" ) messages = [system_message] + state["messages"] response = await llm.ainvoke(messages) # Add the new chat turn to the Zep graph messages_to_save = [ Message( role_type="user", role=state["user_name"], content=state["messages"][-1].content, ), Message(role_type="assistant", content=response.content), ] await zep.memory.add( session_id=state["session_id"], messages=messages_to_save, ) # Truncate the chat history to keep the state from growing unbounded # In this example, we going to keep the state small for demonstration purposes # We'll use Zep's Facts to maintain conversation context state["messages"] = trim_messages( state["messages"], strategy="last", token_counter=len, max_tokens=3, start_on="human", end_on=("human", "tool"), include_system=True, ) logger.info(f"Messages in state: {state['messages']}") return {"messages": [response]} ``` ## Setting up the Agent This section sets up the Agent's LangGraph graph: 1. **Graph Structure**: It defines a graph with nodes for the agent (chatbot) and tools, connected in a loop. 2. **Conditional Logic**: The `should_continue` function determines whether to end the graph execution or continue to the tools node based on the presence of tool calls. 3. **Memory Management**: It uses a MemorySaver to maintain conversation state across turns. This is in addition to using Zep for facts. ```python graph_builder = StateGraph(State) memory = MemorySaver() # Define the function that determines whether to continue or not async def should_continue(state, config): messages = state['messages'] last_message = messages[-1] # If there is no function call, then we finish if not last_message.tool_calls: return 'end' # Otherwise if there is, we continue else: return 'continue' graph_builder.add_node('agent', chatbot) graph_builder.add_node('tools', tool_node) graph_builder.add_edge(START, 'agent') graph_builder.add_conditional_edges('agent', should_continue, {'continue': 'tools', 'end': END}) graph_builder.add_edge('tools', 'agent') graph = graph_builder.compile(checkpointer=memory) ``` Our LangGraph agent graph is illustrated below. ![Agent Graph](file:196640cf-0721-4f6b-b9ec-3f42425bbf93) ## Running the Agent We generate a unique user name and thread id (session id) and add these to Zep, associating the Session with the new User. ```python user_name = 'Daniel_' + uuid.uuid4().hex[:4] thread_id = uuid.uuid4().hex await zep.user.add(user_id=user_name) await zep.memory.add_session(session_id=thread_id, user_id=user_name) def extract_messages(result): output = "" for message in result['messages']: if isinstance(message, AIMessage): role = "assistant" else: role = result['user_name'] output += f"{role}: {message.content}\n" return output.strip() async def graph_invoke( message: str, user_name: str, thread_id: str, ai_response_only: bool = True ): r = await graph.ainvoke( { 'messages': [ { 'role': 'user', 'content': message, } ], 'user_name': user_name, 'session_id': thread_id, }, config={'configurable': {'thread_id': thread_id}}, ) if ai_response_only: return r['messages'][-1].content else: return extract_messages(r) ``` ```python r = await graph_invoke( "Hi there?", user_name, thread_id, ) print(r) ``` > Hello! How are you feeling today? I'm here to listen and support you. ```python r = await graph_invoke( """ I'm fine. But have been a bit stressful lately. Mostly work related. But also my dog. I'm worried about her. She's been sick. """, user_name, thread_id, ) print(r) ``` > I'm sorry to hear that you've been feeling stressed. Work can be a significant source of pressure, and it sounds like your dog might be adding to that stress as well. If you feel comfortable sharing, what specifically has been causing you stress at work and with your dog? I'm here to help you through it. ```python r = await graph_invoke( "She's sick. I'm worried about her.", user_name, thread_id, ) print(r) ``` > I’m really sorry to hear that your dog is sick. It’s completely understandable to feel worried about her; our pets are like family. Have you been able to take her to the vet? Sometimes getting a professional opinion can help ease some of that worry. I'm here to support you through this. ## Viewing All Conversation Facts ```python facts = await zep.memory.get_session_facts(session_id=thread_id) print("\n".join([f"Fact: {fact.fact}" for fact in facts.facts])) ``` > Fact: Daniel's dog is also contributing to his stress. > Fact: Daniel's stress is mostly work-related. > Fact: Daniel has been feeling stressed lately. ```python r = await graph_invoke( "She ate my shoes which were expensive.", user_name, thread_id, ) print(r) ``` > That sounds really frustrating, especially on top of everything else you're dealing with. It's tough when our pets do things that add to our stress, especially when it involves something valuable. It’s okay to feel upset about it. How are you managing with everything? Let's now test whether the Agent is correctly grounded with facts from the prior conversation. ```python r = await graph_invoke( "What are we talking about?", user_name, thread_id, ) print(r) ``` > We were discussing the stress you've been feeling lately, particularly related to work and your dog's health. You mentioned that your dog has been sick and also chewed up your expensive shoes, which can be really frustrating. If there's something else on your mind or if you'd like to talk about a different topic, I'm here to listen! Let's go even further back to determine whether context is kept by referencing a user message that is not currently in the Agent State. Zep will retrieve Facts related to the user's job. ```python r = await graph_invoke( "What have I said about my job?", user_name, thread_id, ) print(r) ``` > You've mentioned that you've been feeling stressed lately, and it seems that your job is a significant part of that stress. If you'd like to share more about what's been going on at work, I'm here to listen and help however I can. # Autogen Memory Example > Autogen is a library created by Microsoft for building multi-agent applications. This example demonstrates using Zep for Autogen long-term memory. **NOTE** This example does not include all code required to run the Autogen Agents. A complete Notebook example of using Zep for Autogen long-term memory may be found in the [Zep Python SDK Repository](https://github.com/getzep/zep-python/blob/main/examples/autogen-agent/agent.ipynb). This example walks through how to build an Autogen Agent with long-term memory. Zep builds a knowledge graph from user interactions with the agent, enabling the agent to recall relevant facts from previous conversations or user interactions. In this example we will: * Create an Autogen Agent class that extends `ConversableAgent` by adding long-term memory * Create a Mental Health Assistant Agent, CareBot, that acts as a counselor and coach. * Create a user Agent, Cathy, who stands in for our expected user. * Demonstrate preloading chat history into Zep. * Demonstrate the agents in conversation, with CareBot recalling facts from previous conversations with Cathy. * Inspect Facts within Zep, and demonstrate how to use Zep's Fact Ratings to improve the quality of returned facts. ## Install dependencies ```bash pip install autogen zep-cloud ``` ## Import Autogen and configure define a `config_list` ```python import os from dotenv import load_dotenv import uuid from typing import Union, Dict from autogen import ConversableAgent, Agent load_dotenv() config_list = [ { "model": "gpt-4o-mini", "api_key": os.environ.get("OPENAI_API_KEY"), "max_tokens": 1024, } ] ``` ## initiualize the Zep Client You can sign up for a Zep account here: [https://www.getzep.com/](https://www.getzep.com/) ```python from zep_cloud.client import AsyncZep from zep_cloud import Message, FactRatingExamples, FactRatingInstruction MIN_FACT_RATING = 0.3 # Configure Zep zep = AsyncZep(api_key=os.environ.get("ZEP_API_KEY")) ``` ## ZepConversableAgent The `ZepConversableAgent` is a custom implementation of the Autogen `ConversableAgent` that integrates with Zep for long-term memory management. This class extends the functionality of the base `ConversableAgent` by adding Zep-specific features for persisting and retrieving facts from long-term memory. ```python class ZepConversableAgent(ConversableAgent): """ A custom ConversableAgent that integrates with Zep for long-term memory. """ def __init__( self, name: str, system_message: str, llm_config: dict, function_map: dict, human_input_mode: str, zep_session_id: str, ): super().__init__( name=name, system_message=system_message, llm_config=llm_config, function_map=function_map, human_input_mode=human_input_mode, ) self.zep_session_id = zep_session_id # store the original system message as we will update it with relevant facts from Zep self.original_system_message = system_message self.register_hook( "a_process_last_received_message", self.persist_user_messages ) self.register_hook( "a_process_message_before_send", self.persist_assistant_messages ) async def persist_assistant_messages( self, sender: Agent, message: Union[Dict, str], recipient: Agent, silent: bool ): """Agent sends a message to the user. Add the message to Zep.""" # Assume message is a string zep_messages = convert_to_zep_messages( [{"role": "assistant", "name": self.name, "content": message}] ) await zep.memory.add(session_id=self.zep_session_id, messages=zep_messages) return message async def persist_user_messages(self, messages: list[dict[str, str]] | str): """ User sends a message to the agent. Add the message to Zep and update the system message with relevant facts from Zep. """ # Assume messages is a string zep_messages = convert_to_zep_messages([{"role": "user", "content": messages}]) await zep.memory.add(session_id=self.zep_session_id, messages=zep_messages) memory = await zep.memory.get(self.zep_session_id, min_rating=MIN_FACT_RATING) # Update the system message with the relevant facts retrieved from Zep self.update_system_message( self.original_system_message + f"\n\nRelevant facts about the user and their prior conversation:\n{memory.relevant_facts}" ) return messages ``` ## Zep User and Session Management ### Zep User A [Zep User](/users) represents an individual interacting with your application. Each User can have multiple Sessions associated with them, allowing you to track and manage interactions over time. The unique identifier for each user is their `UserID`, which can be any string value (e.g., username, email address, or UUID). ### Zep Session A [Zep Session](/concepts) represents a conversation and can be associated with Users in a one-to-many relationship. Chat messages are added to Sessions, with each session having many messages. ### Fact Rating [Fact Rating](/chat-history-memory/facts) is a feature in Zep that allows you to rate the importance or relevance of facts extracted from conversations. This helps in prioritizing and filtering information when retrieving memory artifacts. Here, we rate facts based on poignancy. We provide a definition of poignancy and several examples of highly poignant and low-poignancy facts. When retrieving memory, you can use the `min_rating` parameter to filter facts based on their importance. Fact Rating helps ensure the most relevant information, especially in long or complex conversations, is used to ground the agent. ```python bot_name = "CareBot" user_name = "Cathy" user_id = user_name + str(uuid.uuid4())[:4] session_id = str(uuid.uuid4()) await zep.user.add(user_id=user_id) fact_rating_instruction = """Rate the facts by poignancy. Highly poignant facts have a significant emotional impact or relevance to the user. Low poignant facts are minimally relevant or of little emotional significance.""" fact_rating_examples = FactRatingExamples( high="The user received news of a family member's serious illness.", medium="The user completed a challenging marathon.", low="The user bought a new brand of toothpaste.", ) await zep.memory.add_session( user_id=user_id, session_id=session_id, fact_rating_instruction=FactRatingInstruction( instruction=fact_rating_instruction, examples=fact_rating_examples, ), ) ``` ## Preload a prior conversation into Zep We'll load a prior conversation into long-term memory. We'll use facts derived from this conversation when Cathy restarts the conversation with CareBot, ensuring Carebot has context. ```python chat_history = [ { "role": "assistant", "name": "carebot", "content": "Hi Cathy, how are you doing today?", }, { "role": "user", "name": "Cathy", "content": "To be honest, I've been feeling a bit down and demotivated lately. It's been tough.", }, { "role": "assistant", "name": "CareBot", "content": "I'm sorry to hear that you're feeling down and demotivated, Cathy. It's understandable given the challenges you're facing. Can you tell me more about what's been going on?", }, { "role": "user", "name": "Cathy", "content": "Well, I'm really struggling to process the passing of my mother.", }, { "role": "assistant", "name": "CareBot", "content": "I'm deeply sorry for your loss, Cathy. Losing a parent is incredibly difficult. It's normal to struggle with grief, and there's no 'right' way to process it. Would you like to talk about your mother or how you're coping?", }, { "role": "user", "name": "Cathy", "content": "Yes, I'd like to talk about my mother. She was a kind and loving person.", }, ] # Convert chat history to Zep messages zep_messages = convert_to_zep_messages(chat_history) await zep.memory.add(session_id=session_id, messages=zep_messages) ``` ## Review all facts in Zep We query all session facts for this user session. Only facts that meet the `MIN_FACT_RATING` threshold are returned. ```python response = await zep.memory.get_session_facts(session_id=session_id, min_rating=MIN_FACT_RATING) for r in response.facts: print(r) ``` ```text created_at='2024-10-07T20:04:11.98139Z' fact='Cathy has been feeling down and demotivated lately.' rating=0.5 uuid_='17183c18-381b-45d2-82ea-0c06317acf6f' created_at='2024-10-07T20:04:11.98139Z' fact='Cathy describes her mother as a kind and loving person.' rating=0.5 uuid_='cd6b2e6d-b287-4d92-9de5-d4ee6e82111e' created_at='2024-10-07T20:04:11.98139Z' fact='Cathy is struggling to process the passing of her mother.' rating=0.75 uuid_='bb2f100c-2f12-4976-9026-b322c29e457e' ``` ## Create the Autogen agent, CareBot, an instance of `ZepConversableAgent` We pass in the current `session_id` into the CareBot agent which allows it to retrieve relevant facts related to the conversation with Cathy. ```python carebot_system_message = """ You are a compassionate mental health bot and caregiver. Review information about the user and their prior conversation below and respond accordingly. Keep responses empathetic and supportive. And remember, always prioritize the user's well-being and mental health. Keep your responses very concise and to the point. """ agent = ZepConversableAgent( bot_name, system_message=carebot_system_message, llm_config={"config_list": config_list}, function_map=None, # No registered functions, by default it is None. human_input_mode="NEVER", # Never ask for human input. zep_session_id=session_id, ) ``` ## Create the Autogen agent, Cathy Cathy is a stand-in for a human. When building a production application, you'd replace Cathy with a human-in-the-loop pattern. **Note** that we're instructing Cathy to start the conversation with CareBit by asking about her previous session. This is an opportunity for us to test whether fact retrieval from Zep's long-term memory is working. ```python cathy = ConversableAgent( user_name, system_message="You are a helpful mental health bot. You are seeking counsel from a mental health bot. Ask the bot about your previous conversation.", llm_config={"config_list": config_list}, human_input_mode="NEVER", # Never ask for human input. ) ``` ## Start the conversation We use Autogen's `a_initiate_chat` method to get the two agents conversing. CareBot is the primary agent. **NOTE** how Carebot is able to recall the past conversation about Cathy's mother in detail, having had relevant facts from Zep added to its system prompt. ```python result = await agent.a_initiate_chat( cathy, message="Hi Cathy, nice to see you again. How are you doing today?", max_turns=3, ) ``` ```text CareBot (to Cathy): Hi Cathy, nice to see you again. How are you doing today? -------------------------------------------------------------------------------- Cathy (to CareBot): Hello CareBot! I'm doing well, thank you for asking. I wanted to reflect on our previous conversation—do you remember what we discussed? It would be helpful to revisit that topic and explore it further if you’re up for it! -------------------------------------------------------------------------------- CareBot (to Cathy): Of course, Cathy. We talked about your difficulty in processing your mother’s passing and how you've been feeling down and demotivated lately. It's completely natural to have these feelings, especially after such a significant loss. What would you like to explore further? -------------------------------------------------------------------------------- Cathy (to CareBot): Cathy: Thank you for reminding me, CareBot. Yes, I’ve been struggling with those feelings, and it’s been tough to navigate. I’d like to explore some coping strategies to help me process my grief. Are there any techniques or practices you would recommend? -------------------------------------------------------------------------------- CareBot (to Cathy): Absolutely, Cathy. Here are some coping strategies to help you navigate your grief: 1. **Journaling**: Writing your thoughts and feelings can be a great outlet and help you process your emotions. 2. **Talk to someone**: Sharing your feelings with a trusted friend or therapist can provide support and understanding. 3. **Mindfulness and meditation**: These practices can help ground you and create a sense of calm amid emotional turmoil. 4. **Create a tribute**: Honoring your mother through a scrapbook, writing letters, or lighting a candle can foster connection and memory. 5. **Physical activity**: Engaging in exercise can boost your mood and help alleviate stress. Remember, it's important to be gentle with yourself as you navigate this process. What resonates with you? -------------------------------------------------------------------------------- Cathy (to CareBot): Cathy: Thank you for those suggestions, CareBot. I really like the idea of journaling and creating a tribute for my mother; it sounds like a meaningful way to express my feelings. I also think mindfulness could help me find some peace amidst the sadness. Do you have any specific tips on how to start journaling or practicing mindfulness? -------------------------------------------------------------------------------- ``` ## Review current facts in Zep Let's see how the facts have evolved as the conversation has progressed. ```python response = await zep.memory.get_session_facts(session_id, min_rating=MIN_FACT_RATING) for r in response.facts: print(r) ``` ```text created_at='2024-10-07T20:04:28.397184Z' fact="Cathy wants to reflect on a previous conversation about her mother and explore the topic of her mother's passing further." rating=0.75 uuid_='56488eeb-d8ac-4b2f-8acc-75f71b56ad76' created_at='2024-10-07T20:04:28.397184Z' fact='Cathy is struggling to process the passing of her mother and has been feeling down and demotivated lately.' rating=0.75 uuid_='0fea3f05-ed1a-4e39-a092-c91f8af9e501' created_at='2024-10-07T20:04:28.397184Z' fact='Cathy describes her mother as a kind and loving person.' rating=0.5 uuid_='131de203-2984-4cba-9aef-e500611f06d9' ``` ## Search over Facts in Zep's long-term memory In addition to the `memory.get` method which uses the current conversation to retrieve facts, we can also search Zep with our own keywords. Here, we retrieve facts using a query. Again, we use fact ratings to limit the returned facts to only those with a high poignancy rating. The `memory.search_sessions` API may be used as an Agent tool, enabling an agent to search across user memory for relevant facts. ```python response = await zep.memory.search_sessions( text="What do you know about Cathy's family?", user_id=user_id, search_scope="facts", min_fact_rating=MIN_FACT_RATING, ) for r in response.results: print(r.fact) ``` ```text created_at='2024-10-07T20:04:28.397184Z' fact="Cathy wants to reflect on a previous conversation about her mother and explore the topic of her mother's passing further." rating=0.75 uuid_='56488eeb-d8ac-4b2f-8acc-75f71b56ad76' created_at='2024-10-07T20:04:28.397184Z' fact='Cathy is struggling to process the passing of her mother and has been feeling down and demotivated lately.' rating=0.75 uuid_='0fea3f05-ed1a-4e39-a092-c91f8af9e501' created_at='2024-10-07T20:04:28.397184Z' fact='Cathy describes her mother as a kind and loving person.' rating=0.5 uuid_='131de203-2984-4cba-9aef-e500611f06d9' ``` # Flowise > Flowise is a low-code/no-code drag & drop tool with the aim to make it easy for people to visualize and build LLM apps. Flowise integration with Zep was created and is maintained by the Flowise team. ## Using Zep Cloud Nodes You can follow Flowise installation steps on their Getting Started Page Once you have Flowise app up and running, you can use Zep Cloud nodes in your LLM apps. We expose a `Zep Memory - Cloud` node - a wrapper around Zep Memory API. You can use this node to add Long-Term memory to your app. Learn more about [Zep Memory](/) In order to use this node, you will need to have a Zep Project API key and add it as a Connect Credential in your Flowise app. Zep Cloud Memory Flowise Node A complete chain using Zep Memory Node, may look like this: Zep Cloud Memory Flowise Node Complete Example # Chainlit > Chainlit is an open-source async Python framework which allows developers to build scalable Conversational AI or agentic applications. You can follow Chainlit installation steps on their Getting Started Page In this guide, we'll walk you through the steps to build a simple Question and Answer agent using Chainlit, Open AI and Zep. ### Steps to Use Zep Cloud with ChainLit 1. **Setup Zep Client**: Initialize the Zep Client within your ChainLit application using your [Zep Project API key](https://help.getzep.com/projects). ```python # Import necessary modules from Zep Python SDK and ChainLit. from zep_cloud.client import AsyncZep from zep_cloud.memory import Memory, Session from zep_cloud.message import Message import chainlit as cl import uuid import os from openai import AsyncOpenAI # Retrieve API keys from environment variables. ZEP_API_KEY = os.environ.get("ZEP_API_KEY") OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") # Initialize clients for OpenAI GPT-4 and Zep with respective API keys. openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY) zep = AsyncZep(api_key=ZEP_API_KEY) ``` 2. **User and Session Management**: ```python @cl.on_chat_start async def start_chat(): """Handles the event triggered at the start of a new chat through ChainLit.""" # Generate unique identifiers for the user and session. user_id = str(uuid.uuid4()) session_id = str(uuid.uuid4()) # Save user and session identifiers in the current session context. cl.user_session.set("user_id", user_id) cl.user_session.set("session_id", session_id) # Register a new user in Zep's system using the generated User ID. await zep.user.add( user_id=user_id, email="user@example.com", # Optional: Add email or other user details first_name="Jane", # Optional: Add first name last_name="Doe", # Optional: Add last name metadata={"foo": "bar"} # Optional: Add metadata ) # Start a new session for the user in Zep. await zep.memory.add_session( session_id=session_id, user_id=user_id, # Associate this session with the user metadata={"foo": "bar"} # Optional: Add session metadata ) ``` 3. **Zep Dialog Classification tools** Read more about Zep's dialog classification on the Zep Dialog Classification Page. ```python @cl.step(name="session classification", type="tool") async def classify_session(session_id: str): """Classify dialog with custom instructions.""" # Define categories for classification. classes = [ "General", "Travel", "Shopping", "Cars", ] # Use Zep's dialog async classification feature with custom instruction for session classification. classification = await zep.memory.classify_session( session_id=session_id, name="session_classification", classes=classes, last_n=4, # Optional: Specify the number of previous messages to consider persist=True, instruction="What is the topic of this conversation? Classify it into one of the categories" ) return classification ``` 4. **Message Handling**: You can effectively store and fetch your Chainlit application chat history on Zep memory store, enhancing your LLM conversational context. Discover more about Zep's memory store capabilities on the Zep Documentation Page . ```python @cl.step(name="OpenAI", type="llm") async def call_openai(session_id): """Invokes the OpenAI API to generate a response based on the session message history.""" # Fetch session messages from Zep. memory = await zep.message.aget_session_messages(session_id) memory_history = [m.to_dict() for m in memory] # Prepare data, excluding certain fields for privacy/security. cleaned_data = [{k: v for k, v in item.items() if k not in ['created_at', 'role_type', 'token_count', 'uuid']} for item in memory_history] # Generate a response from OpenAI using the cleaned session data. response = await openai_client.chat.completions.create( model="gpt-4", temperature=0.1, messages=cleaned_data, ) return response.choices[0].message @cl.on_message async def on_message(message: cl.Message): """Processes each incoming message, integrates with OpenAI for response, and updates Zep memory.""" session_id = cl.user_session.get("session_id") # classify user message to give the LLM a semantic insights to what the user request is about classify_sess = await classify_session(session_id) # Store the incoming message in Zep's session memory and append the classified dialog. await zep.memory.add(session_id, messages=[Message(role_type="user", content=message.content + "\n" + "conversation_topic: " + classify_sess.class_, role="user")]) # Updated method # Retrieve a response from the OpenAI model. response_message = await call_openai(session_id) # Send the generated response back through ChainLit. msg = cl.Message(author="Answer", content=(response_message.content)) await msg.send() # Update Zep's session memory with the assistant's response for continuity. await zep.memory.add(session_id, messages=[Message(role_type="assistant", content=response_message.content, role="assistant")]) # Updated method ``` 5. To access your LLM session data, navigate to the Zep Cloud Console, select a session, and review all the associated session data and logs. Zep Cloud session console example In conclusion, integrating Zep Cloud with Chainlit empowers developers to create conversational AI applications that are more intelligent, context-aware, and efficient. # n8n > Add Zep's long-term memory to your n8n AI application n8n integration with Zep was created and is maintained by the n8n team. A `Zep Cloud Memory` component is available in n8n as of version `1.49.0`. # FAQ Yes - Zep offers a free tier. See [Pricing](https://www.getzep.com/pricing) for more information. Yes - Zep offers a LangChain `ZepChatMessageHistory` and `ZepVectorStore` class that you may use in your LangChain Expression Language (LCEL) project. Please use the classes available in the Cloud SDKs and not in the LangChain SDKs. Not yet - we are working on adding support for LlamaIndex. Yes, you can use `Zep Memory - Cloud` and `Zep Collection - Cloud` nodes in the latest Flowise release. You can learn more in our [Flowise Ecosystem section](/ecosystem/flowise). Yes - we've deprecated Intent Analysis and replaced it with a [Session Classifier](/dialog-classification). We've also removed the Named Entity Recognition (NER) feature. We are in the process of replacing NER with a more powerful and flexible Structured Data Extractor. The API URL for Zep Cloud is `https://api.getzep.com`. Note that you do not need to specify the API URL when using the Cloud SDKs. If a service requests the Zep URL it is possible it's only compatible with the Zep Open Source service. We have official multilingual support on our roadmap, enabling the creation of graphs in a user’s own language. Currently, graphs are not explicitly created in the user’s language. However, Zep should work well today with any language, provided you're using a multilingual LLM and your own prompts explicitly state that responses to the user should be in their language. Zep Cloud is currently a major update to the Zep Open Source product. Going forward, Zep Open Source will offer a subset of Zep Cloud's functionality, primarily as proprietary language models are used exclusively in Zep Cloud. Yes - we will be releasing a new version of Zep Open Source based on Zep Cloud functionality. See above for more. # Privacy Policy **Version 1.0** **Last revised on: January 27^th^, 2024** Zep Software, Inc. (the "Company") is committed to maintaining robust privacy protections for its users.  Our Privacy Policy ("Privacy Policy") is designed to help you understand how we collect, use and safeguard the information you provide to us and to assist you in making informed decisions when using our Service.   For purposes of this Agreement, "Site" refers to the Company's website properties, which can be accessed at the getzep.com Internet domain. "Service" refers to the Company's services accessed via the Site, in which users can view Company marketing material, register for the Company's services, access support and help resources, and other services and resources that may be made available from time to time. The terms "we," "us," and "our" refer to the Company. "You" refers to you, as a user of our Site or our Service. By accessing our Site or our Service, you accept our Privacy Policy and [Terms of Use](website-terms-of-use), and you consent to our collection, storage, use and disclosure of your Personal Information as described in this Privacy Policy. 1. INFORMATION WE COLLECT We collect "Non-Personal Information" and "Personal Information." **Non-Personal Information** includes information that cannot be used to personally identify you, such as anonymous usage data, general demographic information we may collect, referring/exit pages and URLs, platform types, preferences you submit and preferences that are generated based on the data you submit and number of clicks. **Personal Information** includes your email and name which you submit to us through the registration process at the Site. 1.1. *Information collected via Technology* To activate the Service you do not need to submit any Personal Information other than your email address and name. To use the Service thereafter, you do not need to submit further Personal Information. However, in an effort to improve the quality of the Service, we track information provided to us by your browser or by our software application when you view or use the Service, such as the website you came from (known as the "referring URL"), the type of browser you use, the device from which you connected to the Service, the time and date of access, and other information that does not personally identify you. We track this information using cookies, or small text files which include an anonymous unique identifier. Cookies are sent to a user's browser from our servers and are stored on the user's computer hard drive. Sending a cookie to a user's browser enables us to collect Non-Personal information about that user and keep a record of the user's preferences when utilizing our services, both on an individual and aggregate basis. For example, the Company may use cookies to collect the following information: * how often you use our websites and services * which content and features you use The Company may use both persistent and session cookies; persistent cookies remain on your computer after you close your session and until you delete them, while session cookies expire when you close your browser. 1.2. *Information you provide us by registering for an account* In addition to the information provided automatically by your browser when you visit the Site, to become a subscriber to the Service you will need to create a personal profile. You can create a profile by registering with the Service and entering your email address, and creating a user name and a password. By registering, you are authorizing us to collect, store and use your email address in accordance with this Privacy Policy. 1.3. *Children's Privacy* The Site and the Service are not directed to anyone under the age of 13. The Site does not knowingly collect or solicit information from anyone under the age of 13, or allow anyone under the age of 13 to sign up for the Service. In the event that we learn that we have gathered personal information from anyone under the age of 13 without the consent of a parent or guardian, we will delete that information as soon as possible. If you believe we have collected such information, please contact us at [info@getzep.com](mailto:info@getzep.com). 2. HOW WE USE AND SHARE INFORMATION *Personal Information:* Except as otherwise stated in this Privacy Policy, we do not sell, trade, rent or otherwise share for marketing purposes your Personal Information with third parties without your consent. We do share Personal Information with vendors who are performing services for the Company, such as the servers for our email communications who are provided access to user's email address for purposes of sending emails from us. Those vendors use your Personal Information only at our direction and in accordance with our Privacy Policy. In general, the Personal Information you provide to us is used to help us communicate with you. For example, we use Personal Information to contact users in response to questions, solicit feedback from users, provide technical support, and inform users about promotional offers. We may share Personal Information with outside parties if we have a good-faith belief that access, use, preservation or disclosure of the information is reasonably necessary to meet any applicable legal process or enforceable governmental request; to enforce applicable Terms of Service, including investigation of potential violations; address fraud, security or technical concerns; or to protect against harm to the rights, property, or safety of our users or the public as required or permitted by law. *Non-Personal Information* In general, we use Non-Personal Information to help us improve the Service and customize the user experience. We also aggregate Non-Personal Information in order to track trends and analyze use patterns on the Site. This Privacy Policy does not limit in any way our use or disclosure of Non-Personal Information and we reserve the right to use and disclose such Non-Personal Information to our partners, advertisers and other third parties at our discretion. In the event we undergo a business transaction such as a merger, acquisition by another company, or sale of all or a portion of our assets, your Personal Information may be among the assets transferred. You acknowledge and consent that such transfers may occur and are permitted by this Privacy Policy, and that any acquirer of our assets may continue to process your Personal Information as set forth in this Privacy Policy. If our information practices change at any time in the future, we will post the policy changes to the Site so that you may opt out of the new information practices. We suggest that you check the Site periodically if you are concerned about how your information is used. 3. HOW WE PROTECT INFORMATION We implement security measures designed to protect your information from unauthorized access. Your account is protected by your account password and we urge you to take steps to keep your personal information safe by not disclosing your password and by logging out of your account after each use. We further protect your information from potential security breaches by implementing certain technological security measures including encryption, firewalls and secure socket layer technology. However, these measures do not guarantee that your information will not be accessed, disclosed, altered or destroyed by breach of such firewalls and secure server software. By using our Service, you acknowledge that you understand and agree to assume these risks. 4. YOUR RIGHTS REGARDING THE USE OF YOUR PERSONAL INFORMATION You have the right at any time to prevent us from contacting you for marketing purposes.  When we send a promotional communication to a user, the user can opt out of further promotional communications by following the unsubscribe instructions provided in each promotional e-mail.\ Please note that notwithstanding the promotional preferences you indicate by either unsubscribing, we may continue to send you administrative emails including, for example, periodic updates to our Privacy Policy. 5. LINKS TO OTHER WEBSITES As part of the Service, we may provide links to or compatibility with other websites or applications. However, we are not responsible for the privacy practices employed by those websites or the information or content they contain. This Privacy Policy applies solely to information collected by us through the Site and the Service. Therefore, this Privacy Policy does not apply to your use of a third party website accessed by selecting a link on our Site or via our Service. To the extent that you access or use the Service through or on another website or application, then the privacy policy of that other website or application will apply to your access or use of that site or application. We encourage our users to read the privacy statements of other websites before proceeding to use them. 6. CHANGES TO OUR PRIVACY POLICY The Company reserves the right to change this policy and our Terms of Service at any time.  We will notify you of significant changes to our Privacy Policy by sending a notice to the primary email address specified in your account or by placing a prominent notice on our site. Significant changes will go into effect 30 days following such notification. Non-material changes or clarifications will take effect immediately. You should periodically check the Site and this privacy page for updates. 7. CONTACT US If you have any questions regarding this Privacy Policy or the practices of this Site, please contact us by sending an email to [info@getzep.com](mailto:info@getzep.com). # Terms of Service **Version 1.0** **Last revised on: January 27^th^, 2024** If you signed a separate Cover Page to access the Product with the same account, and that agreement has not ended, the terms below do not apply to you. Instead, your separate Cover Page applies to your use of the Product. This Agreement is between Zep Software, Inc. and the company or person accessing or using the Product. This Agreement consists of: (1) the Order Form and (2) the Key Terms, both of which are on the Cover Page below, and (3) the Common Paper [Cloud Service Agreement Standard Terms Version 1.1](https://commonpaper.com/standards/cloud-service-agreement/1.1/) ("Standard Terms"). Any modifications to the Standard Terms made in the Cover Page will control over conflicts with the Standard Terms. Capitalized words have the meanings or descriptions given in the Cover Page or the Standard Terms. If you are accessing or using the Product on behalf of your company, you represent that you are authorized to accept this Agreement ßon behalf of your company. By signing up, accessing, or using the Product, Customer indicates its acceptance of this Agreement and agrees to be bound by the terms and conditions of this Agreement. Cover Page *Order Form* **Cloud Service:** Zep is a cloud-based platform-as-a-service that offers fast, scalable, privacy-compliant building blocks for Generative AI apps. **Subscription Start Date:** The Effective Date **Subscription Period:** 1 month(s) **Non-Renewal Notice Period:** At least 30 days before the end of the current Subscription Period. **Cloud Service Fees:** Section 5.2 of the Standard Terms is replaced with: Certain parts of the Product have different pricing plans, which are available at Provider's [pricing page](https://www.getzep.com/pricing). Within the Payment Period, Customer will pay Provider fees based on the Product tier selected at the time of account creation and Customer's usage per Subscription Period. Provider may update Product pricing by giving at least 30 days notice to Customer (including by email or notification within the Product), and the change will apply in the next Subscription Period. **Payment Period:** 5 day(s) from the last day of the Subscription Period **Invoice Period:** Monthly *Key Terms* **Customer:** The company or person who accesses or uses the Product. If the person accepting this Agreement is doing so on behalf of a company, all use of the word "Customer" in the Agreement will mean that company. **Provider:** Zep Software, Inc. **Effective Date:** The date Customer first accepts this Agreement. **Covered Claims:** **Provider Covered Claims:** Any action, proceeding, or claim that the Cloud Service, when used by Customer according to the terms of the Agreement, violates, misappropriates, or otherwise infringes upon anyone else's intellectual property or other proprietary rights. **Customer Covered Claims:** Any action, proceeding, or claim that (1) the Customer Content, when used according to the terms of the Agreement, violates, misappropriates, or otherwise infringes upon anyone else's intellectual property or other proprietary rights; or (2) results from Customer's breach or alleged breach of Section 2.1 (Restrictions on Customer). **General Cap Amount:** The fees paid or payable by Customer to provider in the 12 month period immediately before the claim **Governing Law:** The laws of the State of Delaware **Chosen Courts:** The state or federal courts located in Delaware **Notice Address:** For Provider: [notices@getzep.com](mailto:notices@getzep.com) For Customer: The main email address on Customer's account *Changes to the Standard Terms* **Publicity Rights:** Modifying Section 14.7 of the Standard Terms, Provider may identify Customer and use Customer's logo and trademarks on Provider's website and in marketing materials to identify Customer as a user of the Product. Customer hereby grants Provider a non-exclusive, royalty-free license to do so in connection with any marketing, promotion, or advertising of Provider or the Product during the length of the Agreement. # Website Terms of Use **Version 1.0** **Last revised on: January 27^th^, 2024** The website located at getzep.com (the "**Site**") is a copyrighted work belonging to Zep Software, Inc. ("**Company**", "**us**", "**our**", and "**we**"). Certain features of the Site may be subject to additional guidelines, terms, or rules, which will be posted on the Site in connection with such features. All such additional terms, guidelines, and rules are incorporated by reference into these Terms. These Terms of Use (these "**Terms**") set forth the legally binding terms and conditions that govern your use of the Site. By accessing or using the Site, you are accepting these Terms (on behalf of yourself or the entity that you represent), and you represent and warrant that you have the right, authority, and capacity to enter into these Terms (on behalf of yourself or the entity that you represent). you may not access or use the Site or accept the Terms if you are not at least 18 years old. If you do not agree with all of the provisions of these Terms, do not access and/or use the Site. **PLEASE BE AWARE THAT SECTION 8.2 CONTAINS PROVISIONS GOVERNING HOW TO RESOLVE DISPUTES BETWEEN YOU AND COMPANY. AMONG OTHER THINGS, SECTION 8.2 INCLUDES AN AGREEMENT TO ARBITRATE WHICH REQUIRES, WITH LIMITED EXCEPTIONS, THAT ALL DISPUTES BETWEEN YOU AND US SHALL BE RESOLVED BY BINDING AND FINAL ARBITRATION. SECTION 8.2 ALSO CONTAINS A CLASS ACTION AND JURY TRIAL WAIVER. PLEASE READ SECTION 8.2 CAREFULLY.** **UNLESS YOU OPT OUT OF THE AGREEMENT TO ARBITRATE WITHIN 30 DAYS: (1) YOU WILL ONLY BE PERMITTED TO PURSUE DISPUTES OR CLAIMS AND SEEK RELIEF AGAINST US ON AN INDIVIDUAL BASIS, NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY CLASS OR REPRESENTATIVE ACTION OR PROCEEDING AND YOU WAIVE YOUR RIGHT TO PARTICIPATE IN A CLASS ACTION LAWSUIT OR CLASS-WIDE ARBITRATION; AND (2) YOU ARE WAIVING YOUR RIGHT TO PURSUE DISPUTES OR CLAIMS AND SEEK RELIEF IN A COURT OF LAW AND TO HAVE A JURY TRIAL.** 1. **Accounts** 1.1. **Account Creation.** In order to use certain features of the Site, you must register for an account ("**Account**") and provide certain information about yourself as prompted by the account registration form. You represent and warrant that: (a) all required registration information you submit is truthful and accurate; (b) you will maintain the accuracy of such information. You may delete your Account at any time, for any reason, by following the instructions on the Site. Company may suspend or terminate your Account in accordance with Section 7. 1.2. **Account Responsibilities.** You are responsible for maintaining the confidentiality of your Account login information and are fully responsible for all activities that occur under your Account. You agree to immediately notify Company of any unauthorized use, or suspected unauthorized use of your Account or any other breach of security. Company cannot and will not be liable for any loss or damage arising from your failure to comply with the above requirements. 2. **Access to the Site** 2.1. **License.** Subject to these Terms, Company grants you a non-transferable, non-exclusive, revocable, limited license to use and access the Site solely for your own personal, noncommercial use. 2.2. **Certain Restrictions.** The rights granted to you in these Terms are subject to the following restrictions: (a) you shall not license, sell, rent, lease, transfer, assign, distribute, host, or otherwise commercially exploit the Site, whether in whole or in part, or any content displayed on the Site; (b) you shall not modify, make derivative works of, disassemble, reverse compile or reverse engineer any part of the Site; (c) you shall not access the Site in order to build a similar or competitive website, product, or service; and (d) except as expressly stated herein, no part of the Site may be copied, reproduced, distributed, republished, downloaded, displayed, posted or transmitted in any form or by any means. Unless otherwise indicated, any future release, update, or other addition to functionality of the Site shall be subject to these Terms. All copyright and other proprietary notices on the Site (or on any content displayed on the Site) must be retained on all copies thereof. 2.3. **Modification.** Company reserves the right, at any time, to modify, suspend, or discontinue the Site (in whole or in part) with or without notice to you. You agree that Company will not be liable to you or to any third party for any modification, suspension, or discontinuation of the Site or any part thereof. 2.4. **No Support or Maintenance.** You acknowledge and agree that Company will have no obligation to provide you with any support or maintenance in connection with the Site. 2.5. **Ownership.** You acknowledge that all the intellectual property rights, including copyrights, patents, trade marks, and trade secrets, in the Site and its content are owned by Company or Company's suppliers. Neither these Terms (nor your access to the Site) transfers to you or any third party any rights, title or interest in or to such intellectual property rights, except for the limited access rights expressly set forth in Section 2.1. Company and its suppliers reserve all rights not granted in these Terms. There are no implied licenses granted under these Terms. 2.6. **Feedback.** If you provide Company with any feedback or suggestions regarding the Site ("**Feedback**"), you hereby assign to Company all rights in such Feedback and agree that Company shall have the right to use and fully exploit such Feedback and related information in any manner it deems appropriate. Company will treat any Feedback you provide to Company as non-confidential and non-proprietary. You agree that you will not submit to Company any information or ideas that you consider to be confidential or proprietary. 3. **Indemnification.** You agree to indemnify and hold Company (and its officers, employees, and agents) harmless, including costs and attorneys' fees, from any claim or demand made by any third party due to or arising out of (a) your use of the Site, (b) your violation of these Terms or (c) your violation of applicable laws or regulations. Company reserves the right, at your expense, to assume the exclusive defense and control of any matter for which you are required to indemnify us, and you agree to cooperate with our defense of these claims. You agree not to settle any matter without the prior written consent of Company. Company will use reasonable efforts to notify you of any such claim, action or proceeding upon becoming aware of it. 4. **Third-Party Links & Ads; Other Users** 4.1. **Third-Party Links & Ads.** The Site may contain links to third-party websites and services, and/or display advertisements for third parties (collectively, "**Third-Party Links & Ads**"). Such Third-Party Links & Ads are not under the control of Company, and Company is not responsible for any Third-Party Links & Ads. Company provides access to these Third-Party Links & Ads only as a convenience to you, and does not review, approve, monitor, endorse, warrant, or make any representations with respect to Third-Party Links & Ads. You use all Third-Party Links & Ads at your own risk, and should apply a suitable level of caution and discretion in doing so. When you click on any of the Third-Party Links & Ads, the applicable third party's terms and policies apply, including the third party's privacy and data gathering practices. You should make whatever investigation you feel necessary or appropriate before proceeding with any transaction in connection with such Third-Party Links & Ads. 4.2. **Other Users.** Your interactions with other Site users are solely between you and such users. You agree that Company will not be responsible for any loss or damage incurred as the result of any such interactions. If there is a dispute between you and any Site user, we are under no obligation to become involved. 4.3.. **Release.** You hereby release and forever discharge Company (and our officers, employees, agents, successors, and assigns) from, and hereby waive and relinquish, each and every past, present and future dispute, claim, controversy, demand, right, obligation, liability, action and cause of action of every kind and nature (including personal injuries, death, and property damage), that has arisen or arises directly or indirectly out of, or that relates directly or indirectly to, the Site (including any interactions with, or act or omission of, other Site users or any Third-Party Links & Ads). IF YOU ARE A CALIFORNIA RESIDENT, YOU HEREBY WAIVE CALIFORNIA CIVIL CODE SECTION 1542 IN CONNECTION WITH THE FOREGOING, WHICH STATES: "A GENERAL RELEASE DOES NOT EXTEND TO CLAIMS WHICH THE CREDITOR OR RELEASING PARTY DOES NOT KNOW OR SUSPECT TO EXIST IN HIS OR HER FAVOR AT THE TIME OF EXECUTING THE RELEASE, WHICH IF KNOWN BY HIM OR HER MUST HAVE MATERIALLY AFFECTED HIS OR HER SETTLEMENT WITH THE DEBTOR OR RELEASED PARTY." 5. **Disclaimers** THE SITE IS PROVIDED ON AN "AS-IS" AND "AS AVAILABLE" BASIS, AND COMPANY (AND OUR SUPPLIERS) EXPRESSLY DISCLAIM ANY AND ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING ALL WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, QUIET ENJOYMENT, ACCURACY, OR NON-INFRINGEMENT. WE (AND OUR SUPPLIERS) MAKE NO WARRANTY THAT THE SITE WILL MEET YOUR REQUIREMENTS, WILL BE AVAILABLE ON AN UNINTERRUPTED, TIMELY, SECURE, OR ERROR-FREE BASIS, OR WILL BE ACCURATE, RELIABLE, FREE OF VIRUSES OR OTHER HARMFUL CODE, COMPLETE, LEGAL, OR SAFE. IF APPLICABLE LAW REQUIRES ANY WARRANTIES WITH RESPECT TO THE SITE, ALL SUCH WARRANTIES ARE LIMITED IN DURATION TO 90 DAYS FROM THE DATE OF FIRST USE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU. SOME JURISDICTIONS DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. 6. **Limitation on Liability** TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL COMPANY (OR OUR SUPPLIERS) BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY LOST PROFITS, LOST DATA, COSTS OF PROCUREMENT OF SUBSTITUTE PRODUCTS, OR ANY INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES ARISING FROM OR RELATING TO THESE TERMS OR YOUR USE OF, OR INABILITY TO USE, THE SITE, EVEN IF COMPANY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ACCESS TO, AND USE OF, THE SITE IS AT YOUR OWN DISCRETION AND RISK, AND YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR DEVICE OR COMPUTER SYSTEM, OR LOSS OF DATA RESULTING THEREFROM. TO THE MAXIMUM EXTENT PERMITTED BY LAW, NOTWITHSTANDING ANYTHING TO THE CONTRARY CONTAINED HEREIN, OUR LIABILITY TO YOU FOR ANY DAMAGES ARISING FROM OR RELATED TO THESE TERMS (FOR ANY CAUSE WHATSOEVER AND REGARDLESS OF THE FORM OF THE ACTION), WILL AT ALL TIMES BE LIMITED TO A MAXIMUM OF FIFTY US DOLLARS. THE EXISTENCE OF MORE THAN ONE CLAIM WILL NOT ENLARGE THIS LIMIT. YOU AGREE THAT OUR SUPPLIERS WILL HAVE NO LIABILITY OF ANY KIND ARISING FROM OR RELATING TO THESE TERMS. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU. 7. **Term and Termination.** Subject to this Section, these Terms will remain in full force and effect while you use the Site. We may suspend or terminate your rights to use the Site (including your Account) at any time for any reason at our sole discretion, including for any use of the Site in violation of these Terms. Upon termination of your rights under these Terms, your Account and right to access and use the Site will terminate immediately. Company will not have any liability whatsoever to you for any termination of your rights under these Terms, including for termination of your Account. Even after your rights under these Terms are terminated, the following provisions of these Terms will remain in effect: Sections 2.2 through 2.6 and Sections 3 through 8. 8. **General** 8.1. **Changes.** These Terms are subject to occasional revision, and if we make any substantial changes, we may notify you by sending you an e-mail to the last e-mail address you provided to us (if any), and/or by prominently posting notice of the changes on our Site. You are responsible for providing us with your most current e-mail address. In the event that the last e-mail address that you have provided us is not valid, or for any reason is not capable of delivering to you the notice described above, our dispatch of the e-mail containing such notice will nonetheless constitute effective notice of the changes described in the notice. Continued use of our Site following notice of such changes shall indicate your acknowledgement of such changes and agreement to be bound by the terms and conditions of such changes. 8.2. **Dispute Resolution.** Please read the following arbitration agreement in this Section (the "**Arbitration Agreement**") carefully.  It requires you to arbitrate disputes with Company, its parent companies, subsidiaries, affiliates, successors and assigns and all of their respective officers, directors, employees, agents, and representatives (collectively, the "**Company Parties**") and limits the manner in which you can seek relief from the Company Parties  (a) **Applicability of Arbitration Agreement** You agree that any dispute between you and any of the Company Parties relating in any way to the Site, the services offered on the Site (the "**Services**") or these Terms will be resolved by binding arbitration, rather than in court, except that (1) you and the Company Parties may assert individualized claims in small claims court if the claims qualify, remain in such court and advance solely on an individual, non-class basis; and (2) you or the Company Parties may seek equitable relief in court for infringement or other misuse of intellectual property rights (such as trademarks, trade dress, domain names, trade secrets, copyrights, and patents). **This Arbitration Agreement shall survive the expiration or termination of these Terms and shall apply, without limitation, to all claims that arose or were asserted before you agreed to these Terms (in accordance with the preamble) or any prior version of these Terms.** This Arbitration Agreement does not preclude you from bringing issues to the attention of federal, state or local agencies. Such agencies can, if the law allows, seek relief against the Company Parties on your behalf. For purposes of this Arbitration Agreement, "**Dispute**" will also include disputes that arose or involve facts occurring before the existence of this or any prior versions of the Agreement as well as claims that may arise after the termination of these Terms. (b) **Informal Dispute Resolution.** There might be instances when a Dispute arises between you and Company. If that occurs, Company is committed to working with you to reach a reasonable resolution. You and Company agree that good faith informal efforts to resolve Disputes can result in a prompt, low‐cost and mutually beneficial outcome. You and Company therefore agree that before either party commences arbitration against the other (or initiates an action in small claims court if a party so elects), we will personally meet and confer telephonically or via videoconference, in a good faith effort to resolve informally any Dispute covered by this Arbitration Agreement ("**Informal Dispute Resolution Conference**"). If you are represented by counsel, your counsel may participate in the conference, but you will also participate in the conference. The party initiating a Dispute must give notice to the other party in writing of its intent to initiate an Informal Dispute Resolution Conference ("**Notice**"), which shall occur within 45 days after the other party receives such Notice, unless an extension is mutually agreed upon by the parties. Notice to Company that you intend to initiate an Informal Dispute Resolution Conference should be sent by email to: [info@getzep.com](mailto:info@getzep.com), or by regular mail to 2261 Market Street #5686 San Francisco, CA 94114. The Notice must include: (1) your name, telephone number, mailing address, e‐mail address associated with your account (if you have one); (2) the name, telephone number, mailing address and e‐mail address of your counsel, if any; and (3) a description of your Dispute. The Informal Dispute Resolution Conference shall be individualized such that a separate conference must be held each time either party initiates a Dispute, even if the same law firm or group of law firms represents multiple users in similar cases, unless all parties agree; multiple individuals initiating a Dispute cannot participate in the same Informal Dispute Resolution Conference unless all parties agree. In the time between a party receiving the Notice and the Informal Dispute Resolution Conference, nothing in this Arbitration Agreement shall prohibit the parties from engaging in informal communications to resolve the initiating party's Dispute. Engaging in the Informal Dispute Resolution Conference is a condition precedent and requirement that must be fulfilled before commencing arbitration. The statute of limitations and any filing fee deadlines shall be tolled while the parties engage in the Informal Dispute Resolution Conference process required by this section. (c) **Arbitration Rules and Forum.** These Terms evidence a transaction involving interstate commerce; and notwithstanding any other provision herein with respect to the applicable substantive law, the Federal Arbitration Act, 9 U.S.C. § 1 et seq., will govern the interpretation and enforcement of this Arbitration Agreement and any arbitration proceedings. If the Informal Dispute Resolution Process described above does not resolve satisfactorily within 60 days after receipt of your Notice, you and Company agree that either party shall have the right to finally resolve the Dispute through binding arbitration. The Federal Arbitration Act governs the interpretation and enforcement of this Arbitration Agreement. The arbitration will be conducted by JAMS, an established alternative dispute resolution provider. Disputes involving claims and counterclaims with an amount in controversy under \$250,000, not inclusive of attorneys' fees and interest, shall be subject to JAMS' most current version of the Streamlined Arbitration Rules and procedures available at [http://www.jamsadr.com/rules-streamlined-arbitration/](http://www.jamsadr.com/rules-streamlined-arbitration/); all other claims shall be subject to JAMS's most current version of the Comprehensive Arbitration Rules and Procedures, available at [http://www.jamsadr.com/rules-comprehensive-arbitration/](http://www.jamsadr.com/rules-comprehensive-arbitration/). JAMS's rules are also available at [www.jamsadr.com](http://www.jamsadr.com) or by calling JAMS at 800-352-5267. A party who wishes to initiate arbitration must provide the other party with a request for arbitration (the "**Request**"). The Request must include: (1) the name, telephone number, mailing address, e‐mail address of the party seeking arbitration and the account username (if applicable) as well as the email address associated with any applicable account; (2) a statement of the legal claims being asserted and the factual bases of those claims; (3) a description of the remedy sought and an accurate, good‐faith calculation of the amount in controversy in United States Dollars; (4) a statement certifying completion of the Informal Dispute Resolution process as described above; and (5) evidence that the requesting party has paid any necessary filing fees in connection with such arbitration. If the party requesting arbitration is represented by counsel, the Request shall also include counsel's name, telephone number, mailing address, and email address. Such counsel must also sign the Request. By signing the Request, counsel certifies to the best of counsel's knowledge, information, and belief, formed after an inquiry reasonable under the circumstances, that: (1) the Request is not being presented for any improper purpose, such as to harass, cause unnecessary delay, or needlessly increase the cost of dispute resolution; (2) the claims, defenses and other legal contentions are warranted by existing law or by a nonfrivolous argument for extending, modifying, or reversing existing law or for establishing new law; and (3) the factual and damages contentions have evidentiary support or, if specifically so identified, will likely have evidentiary support after a reasonable opportunity for further investigation or discovery. Unless you and Company otherwise agree, or the Batch Arbitration process discussed in Subsection 8.2(h) is triggered, the arbitration will be conducted in the county where you reside. Subject to the JAMS Rules, the arbitrator may direct a limited and reasonable exchange of information between the parties, consistent with the expedited nature of the arbitration. If the JAMS is not available to arbitrate, the parties will select an alternative arbitral forum. Your responsibility to pay any JAMS fees and costs will be solely as set forth in the applicable JAMS Rules. You and Company agree that all materials and documents exchanged during the arbitration proceedings shall be kept confidential and shall not be shared with anyone except the parties' attorneys, accountants, or business advisors, and then subject to the condition that they agree to keep all materials and documents exchanged during the arbitration proceedings confidential. (d) **Authority of Arbitrator.** The arbitrator shall have exclusive authority to resolve all disputes subject to arbitration hereunder including, without limitation, any dispute related to the interpretation, applicability, enforceability or formation of this Arbitration Agreement or any portion of the Arbitration Agreement, except for the following: (1) all Disputes arising out of or relating to the subsection entitled "Waiver of Class or Other Non-Individualized Relief," including any claim that all or part of the subsection entitled "Waiver of Class or Other Non-Individualized Relief" is unenforceable, illegal, void or voidable, or that such subsection entitled "Waiver of Class or Other Non-Individualized Relief" has been breached, shall be decided by a court of competent jurisdiction and not by an arbitrator; (2) except as expressly contemplated in the subsection entitled "Batch Arbitration," all Disputes about the payment of arbitration fees shall be decided only by a court of competent jurisdiction and not by an arbitrator; (3) all Disputes about whether either party has satisfied any condition precedent to arbitration shall be decided only by a court of competent jurisdiction and not by an arbitrator; and (4) all Disputes about which version of the Arbitration Agreement applies shall be decided only by a court of competent jurisdiction and not by an arbitrator. The arbitration proceeding will not be consolidated with any other matters or joined with any other cases or parties, except as expressly provided in the subsection entitled "Batch Arbitration." The arbitrator shall have the authority to grant motions dispositive of all or part of any claim or dispute. The arbitrator shall have the authority to award monetary damages and to grant any non-monetary remedy or relief available to an individual party under applicable law, the arbitral forum's rules, and these Terms (including the Arbitration Agreement). The arbitrator shall issue a written award and statement of decision describing the essential findings and conclusions on which any award (or decision not to render an award) is based, including the calculation of any damages awarded. The arbitrator shall follow the applicable law. The award of the arbitrator is final and binding upon you and us. Judgment on the arbitration award may be entered in any court having jurisdiction. (e) **Waiver of Jury Trial.** EXCEPT AS SPECIFIED in section 8.2(a) YOU AND THE COMPANY PARTIES HEREBY WAIVE ANY CONSTITUTIONAL AND STATUTORY RIGHTS TO SUE IN COURT AND HAVE A TRIAL IN FRONT OF A JUDGE OR A JURY. You and the Company Parties are instead electing that all covered claims and disputes shall be resolved exclusively by arbitration under this Arbitration Agreement, except as specified in Section 8.2(a) above. An arbitrator can award on an individual basis the same damages and relief as a court and must follow these Terms as a court would. However, there is no judge or jury in arbitration, and court review of an arbitration award is subject to very limited review.  (f) **Waiver of Class or Other Non-Individualized Relief.**  YOU AND COMPANY AGREE THAT, EXCEPT AS SPECIFIED IN SUBSECTION 8.2(h) EACH OF US MAY BRING CLAIMS AGAINST THE OTHER ONLY ON AN INDIVIDUAL BASIS AND NOT ON A CLASS, REPRESENTATIVE, OR COLLECTIVE BASIS, AND THE PARTIES HEREBY WAIVE ALL RIGHTS TO HAVE ANY DISPUTE BE BROUGHT, HEARD, ADMINISTERED, RESOLVED, OR ARBITRATED ON A CLASS, COLLECTIVE, REPRESENTATIVE, OR MASS ACTION BASIS. ONLY INDIVIDUAL RELIEF IS AVAILABLE, AND DISPUTES OF MORE THAN ONE CUSTOMER OR USER CANNOT BE ARBITRATED OR CONSOLIDATED WITH THOSE OF ANY OTHER CUSTOMER OR USER. Subject to this Arbitration Agreement, the arbitrator may award declaratory or injunctive relief only in favor of the individual party seeking relief and only to the extent necessary to provide relief warranted by the party's individual claim. Nothing in this paragraph is intended to, nor shall it, affect the terms and conditions under the Subsection 8.2(h) entitled "Batch Arbitration." Notwithstanding anything to the contrary in this Arbitration Agreement, if a court decides by means of a final decision, not subject to any further appeal or recourse, that the limitations of this subsection, "Waiver of Class or Other Non-Individualized Relief," are invalid or unenforceable as to a particular claim or request for relief (such as a request for public injunctive relief), you and Company agree that that particular claim or request for relief (and only that particular claim or request for relief) shall be severed from the arbitration and may be litigated in the state or federal courts located in the State of California. All other Disputes shall be arbitrated or litigated in small claims court. This subsection does not prevent you or Company from participating in a class-wide settlement of claims. (g) **Attorneys' Fees and Costs.** The parties shall bear their own attorneys' fees and costs in arbitration unless the arbitrator finds that either the substance of the Dispute or the relief sought in the Request was frivolous or was brought for an improper purpose (as measured by the standards set forth in Federal Rule of Civil Procedure 11(b)). If you or Company need to invoke the authority of a court of competent jurisdiction to compel arbitration, then the party that obtains an order compelling arbitration in such action shall have the right to collect from the other party its reasonable costs, necessary disbursements, and reasonable attorneys' fees incurred in securing an order compelling arbitration. The prevailing party in any court action relating to whether either party has satisfied any condition precedent to arbitration, including the Informal Dispute Resolution Process, is entitled to recover their reasonable costs, necessary disbursements, and reasonable attorneys' fees and costs. (h) **Batch Arbitration.** To increase the efficiency of administration and resolution of arbitrations, you and Company agree that in the event that there are 100 or more individual Requests of a substantially similar nature filed against Company by or with the assistance of the same law firm, group of law firms, or organizations, within a 30 day period (or as soon as possible thereafter), the JAMS shall (1) administer the arbitration demands in batches of 100 Requests per batch (plus, to the extent there are less than 100 Requests left over after the batching described above, a final batch consisting of the remaining Requests); (2) appoint one arbitrator for each batch; and (3) provide for the resolution of each batch as a single consolidated arbitration with one set of filing and administrative fees due per side per batch, one procedural calendar, one hearing (if any) in a place to be determined by the arbitrator, and one final award ("**Batch Arbitration**"). All parties agree that Requests are of a "substantially similar nature" if they arise out of or relate to the same event or factual scenario and raise the same or similar legal issues and seek the same or similar relief. To the extent the parties disagree on the application of the Batch Arbitration process, the disagreeing party shall advise the JAMS, and the JAMS shall appoint a sole standing arbitrator to determine the applicability of the Batch Arbitration process ("**Administrative Arbitrator**"). In an effort to expedite resolution of any such dispute by the Administrative Arbitrator, the parties agree the Administrative Arbitrator may set forth such procedures as are necessary to resolve any disputes promptly. The Administrative Arbitrator's fees shall be paid by Company. You and Company agree to cooperate in good faith with the JAMS to implement the Batch Arbitration process including the payment of single filing and administrative fees for batches of Requests, as well as any steps to minimize the time and costs of arbitration, which may include: (1) the appointment of a discovery special master to assist the arbitrator in the resolution of discovery disputes; and (2) the adoption of an expedited calendar of the arbitration proceedings. This Batch Arbitration provision shall in no way be interpreted as authorizing a class, collective and/or mass arbitration or action of any kind, or arbitration involving joint or consolidated claims under any circumstances, except as expressly set forth in this provision. (i) **30-Day Right to Opt Out.**  You have the right to opt out of the provisions of this Arbitration Agreement by sending a timely written notice of your decision to opt out to the following address: 2261 Market Street #5686, San Francisco, CA 94114, or email to [info@getzep.com](mailto:info@getzep.com), within 30 days after first becoming subject to this Arbitration Agreement. Your notice must include your name and address and a clear statement that you want to opt out of this Arbitration Agreement. If you opt out of this Arbitration Agreement, all other parts of these Terms will continue to apply to you. Opting out of this Arbitration Agreement has no effect on any other arbitration agreements that you may currently have with us, or may enter into in the future with us. (j) **Invalidity, Expiration.** Except as provided in the subsection entitled "Waiver of Class or Other Non-Individualized Relief", if any part or parts of this Arbitration Agreement are found under the law to be invalid or unenforceable, then such specific part or parts shall be of no force and effect and shall be severed and the remainder of the Arbitration Agreement shall continue in full force and effect. You further agree that any Dispute that you have with Company as detailed in this Arbitration Agreement must be initiated via arbitration within the applicable statute of limitation for that claim or controversy, or it will be forever time barred. Likewise, you agree that all applicable statutes of limitation will apply to such arbitration in the same manner as those statutes of limitation would apply in the applicable court of competent jurisdiction. (k)**Modification.** Notwithstanding any provision in these Terms to the contrary, we agree that if Company makes any future material change to this Arbitration Agreement, you may reject that change within 30 days of such change becoming effective by writing Company at the following address: 2261 Market Street #5686, San Francisco, CA 94114, or email to [info@getzep.com](mailto:info@getzep.com). Unless you reject the change within 30 days of such change becoming effective by writing to Company in accordance with the foregoing, your continued use of the Site and/or Services, including the acceptance of products and services offered on the Site following the posting of changes to this Arbitration Agreement constitutes your acceptance of any such changes. Changes to this Arbitration Agreement do not provide you with a new opportunity to opt out of the Arbitration Agreement if you have previously agreed to a version of these Terms and did not validly opt out of arbitration. If you reject any change or update to this Arbitration Agreement, and you were bound by an existing agreement to arbitrate Disputes arising out of or relating in any way to your access to or use of the Services or of the Site, any communications you receive, any products sold or distributed through the Site, the Services, or these Terms, the provisions of this Arbitration Agreement as of the date you first accepted these Terms (or accepted any subsequent changes to these Terms) remain in full force and effect. Company will continue to honor any valid opt outs of the Arbitration Agreement that you made to a prior version of these Terms.  8.3. **Export.** The Site may be subject to U.S. export control laws and may be subject to export or import regulations in other countries. You agree not to export, reexport, or transfer, directly or indirectly, any U.S. technical data acquired from Company, or any products utilizing such data, in violation of the United States export laws or regulations. 8.4. **Disclosures.** Company is located at the address in Section 8.8. If you are a California resident, you may report complaints to the Complaint Assistance Unit of the Division of Consumer Product of the California Department of Consumer Affairs by contacting them in writing at 400 R Street, Sacramento, CA 95814, or by telephone at (800) 952-5210. 9.5. **Electronic Communications.** The communications between you and Company use electronic means, whether you use the Site or send us emails, or whether Company posts notices on the Site or communicates with you via email. For contractual purposes, you (a) consent to receive communications from Company in an electronic form; and (b) agree that all terms and conditions, agreements, notices, disclosures, and other communications that Company provides to you electronically satisfy any legal requirement that such communications would satisfy if it were be in a hardcopy writing. The foregoing does not affect your non-waivable rights. 8.6. **Entire Terms.** These Terms constitute the entire agreement between you and us regarding the use of the Site. Our failure to exercise or enforce any right or provision of these Terms shall not operate as a waiver of such right or provision. The section titles in these Terms are for convenience only and have no legal or contractual effect. The word "including" means "including without limitation". If any provision of these Terms is, for any reason, held to be invalid or unenforceable, the other provisions of these Terms will be unimpaired and the invalid or unenforceable provision will be deemed modified so that it is valid and enforceable to the maximum extent permitted by law. Your relationship to Company is that of an independent contractor, and neither party is an agent or partner of the other. These Terms, and your rights and obligations herein, may not be assigned, subcontracted, delegated, or otherwise transferred by you without Company's prior written consent, and any attempted assignment, subcontract, delegation, or transfer in violation of the foregoing will be null and void. Company may freely assign these Terms. The terms and conditions set forth in these Terms shall be binding upon assignees. 8.7. **Copyright/Trademark Information**. Copyright ©2024 Zep Software, Inc. All rights reserved. All trademarks, logos and service marks ("**Marks**") displayed on the Site are our property or the property of other third parties. You are not permitted to use these Marks without our prior written consent or the consent of such third party which may own the Marks. **Contact Information:** Daniel Chalef Address: 2261 Market Street \#5686 San Francisco, CA 94114 # Quick Start > Get started with Zep Community Edition Looking for a managed Zep service? Check out [Zep Cloud](https://www.getzep.com). * No need to run Neo4j, Postgres, or other dependencies. * Additional features for startups and enterprises alike. * Fast and scalable. Learn more about the [differences between Zep Community Edition and Zep Cloud](/ce/ce-vs-cloud). ### Starting a Zep server locally is simple. 1. Clone the [Zep repo](https://github.com/getzep/zep) ```bash git clone https://github.com/getzep/zep.git ``` 2. Configure your Zep server by editing the `zep.yaml` file. ```yaml maxLines=45 log: # debug, info, warn, error, panic, dpanic, or fatal. Default = info level: info # How should logs be formatted? Setting to "console" will print human readable logs # whie "json" will print structured JSON logs. Default is "json". format: console http: # Host to bind to. Default is 0.0.0.0 host: 0.0.0.0 # Port to bind to. Default is 8000 port: 8000 max_request_size: 5242880 postgres: user: postgres password: postgres host: localhost port: 5432 database: postgres schema_name: public read_timeout: 30 write_timeout: 30 max_open_connections: 10 # Carbon is a package used for dealing with time - github.com/golang-module/carbon # It is primarily used for generating humand readable relative time strings like "2 hours ago". # See the list of supported languages here https://github.com/golang-module/carbon?tab=readme-ov-file#i18n carbon: locale: en graphiti: # Base url to the graphiti service service_url: http://0.0.0.0:8003 # In order to authenicate API requests to the Zep service, a secret must be provided. # This secret should be kept secret between the Zep service and the client. It can be any string value. # When making requests to the Zep service, include the secret in the Authorization header. api_secret: [INSERT API SECRET] # In order to better understand how Zep is used, we can collect telemetry data. # This is optional and can be disabled by setting disabled to true. # We do not collect any PII or any of your data. We only collect anonymized data # about how Zep is used. telemetry: disabled: false # Please provide an identifying name for your organization so can get a better understanding # about who is using Zep. This is optional. organization_name: [INSERT ORGANIZATION NAME] ``` If you'd like to use an environment variable as the value for any of the configuration options, you can use a template string to insert the value. For example, if you wanted to use an environment variable to set the Postgres password, you could do the following: ```yaml postgres: password: {{ Env "ZEP_POSTGRES_PASSWORD" }} ``` You can name your environment variable whatever you want. Only use this for configuration options that are string values otherwise it will cause a parse error and the server will not start. 3. Start the Zep server: ```bash ./zep up ``` Make sure to set the `secret` value in the `zep.yaml` configuration file. Additionally, make sure that you expose an `OPENAI_API_KEY` environment variable either in a local .env file or by running: ```bash export OPENAI_API_KEY=your_openai_api_key ``` This will start a Zep API server on port `8000` and Graphiti service on port `8003`. 4. Get started with the [Zep Community Edition SDKs](/ce/sdks)! The Zep Community Edition SDKs are API compatible with the Zep Cloud SDKs. The Zep Guides and API reference note where [functionality may differ](/ce/ce-vs-cloud). Next Steps: * Install the [Zep Community Edition SDKs](/ce/sdks) * Read the [Zep Service Guides](/) * Explore the [Zep API Reference](/api-reference) ### Using LLM Providers other than OpenAI Zep Community Edition can be used with any LLM provider that implements the OpenAI API. There are two approaches to configure this: #### 1. Direct Configuration (Recommended) Set the following environment variables for the Graphiti service in your `docker-compose.ce.yaml` file: ```yaml environment: - MODEL_NAME=your_model_name - OPENAI_BASE_URL=your_provider_base_url - OPENAI_API_KEY=your_api_key ``` This approach works with any OpenAI API-compatible provider and local LLM inference servers, such as Ollama. #### 2. Using a Proxy (Alternative) You can also use a proxy service like [LiteLLM](https://github.com/BerriAI/litellm) that provides an OpenAI compatible API for non-OpenAI compatible LLM providers. LiteLLM supports proxying both LLM and Embedding requests. Set the `OPENAI_API_KEY`, `MODEL_NAME`, and `OPENAI_BASE_URL` environment variables to point to your LLM provider. This may be done in a `.env` file or directly in the `docker-compose.ce.yaml` file. # Community SDK Installation > Zep provides SDKs for Python, TypeScript, and Go. ### Python This is the guide for installing sdks for Zep Community Edition (>=v1.0.0). If you are using Zep Cloud, please refer to the [Zep Cloud SDK Installation](/sdks) guide. If you are using an older version of Zep Open Source, please refer to [Legacy SDK Installation](/ce/legacy/sdk) guide and consider upgrading to the latest version. ```Bash pip install zep-python ``` ```Bash poetry add zep-python ``` ### TypeScript ```Bash npm install @getzep/zep-js ``` ```Bash yarn add @getzep/zep-js ``` ```Bash pnpm install @getzep/zep-js ``` ## Initialize Client The default base URL for the Zep client is `http://localhost:8000`. Zep also offers an async client for Python. To use the async client, import `AsyncZep` instead of `Zep`. ```python import os from zep_python.client import Zep API_KEY = os.environ.get('ZEP_API_KEY') BASE_URL = os.environ.get('ZEP_BASE_URL') client = Zep( api_key=API_KEY, base_url=BASE_URL ) ``` **The Python SDK Supports Async Use** In order to use async client, you will need to import AsyncZep instead of Zep. ```python from zep_python.client import AsyncZep ``` ```typescript import {ZepClient} from "@getzep/zep-js"; const API_KEY = process.env.ZEP_API_KEY const BASE_URL = process.env.ZEP_BASE_URL const zep = new ZepClient({apiKey: API_KEY, baseUrl: BASE_URL}); ``` Coming soon ## Usage Example ```python import uuid from zep_python.client import AsyncZep from zep_python.types import Message client = AsyncZep( api_key=API_KEY, base_url=BASE_URL, ) user_id = uuid.uuid4().hex # A new user identifier new_user = await client.user.add( user_id=user_id, email="user@example.com", first_name="Jane", last_name="Smith", metadata={"foo": "bar"}, ) # create a chat session session_id = uuid.uuid4().hex # A new session identifier session = await client.memory.add_session( session_id=session_id, user_id=user_id, metadata={"foo" : "bar"} ) # Add a memory to the session await client.memory.add_memory( session_id=session_id, messages=[ Message( role_type = "user", # One of ("system", "assistant", "user", "function", "tool") role = "Researcher", # Optional, a use case specific string representing the role of the user content = "Who was Octavia Butler?", # The message content ) ], ) # Get session memory memory = await client.memory.get(session_id=session_id) messages = memory.messages # List of messages in the session (quantity determined by optional lastn parameter in memory.get) relevant_facts = memory.relevant_facts # List of facts relevant to the recent messages in the session # Search user facts across all sessions search_response = await client.memory.search_sessions( user_id=user_id, search_scope="facts", text="What science fiction books did I recently read?", ) facts = [r.fact for r in search_response.results] ``` ```typescript import { v4 as uuidv4 } from 'uuid'; import { ZepClient } from '@getzep/zep-js'; import type { CreateUserRequest, CreateSessionRequest, SessionSearchQuery } from '@getzep/zep-js/api'; const client = new ZepClient({ apiKey: API_KEY, baseUrl: BASE_URL, }); // A new user identifier const userId = uuidv4(); const userRequest: CreateUserRequest = { userId: userId, email: "user@example.com", firstName: "Jane", lastName: "Smith", metadata: { foo: "bar" }, }; const newUser = await client.user.add(userRequest); // Create a chat session const sessionId = uuidv4(); const sessionRequest: CreateSessionRequest = { sessionId: sessionId, userId: userId, metadata: { foo: "bar" }, }; // A new session identifier const session = await client.memory.addSession(sessionRequest); // Add a memory to the session await client.memory.add(sessionId, { messages: [ { role: "Researcher", roleType: "user", content: "Who was Octavia Butler?", }, ], }); // Get session memory const memory = await client.memory.get(sessionId); const messages = memory.messages; // List of messages in the session (quantity determined by optional lastN parameter in memory.get) const relevantFacts = memory.relevantFacts; // List of facts relevant to the recent messages in the session // Search user facts across all sessions const searchQuery: SessionSearchQuery = { userId: userId, searchScope: "facts", text: "What science fiction books did I recently read?", }; const searchResponse = await client.memory.searchSessions(searchQuery); const facts = searchResponse.results?.map(result => result.fact); ``` The Zep Community Edition SDKs are API compatible with the Zep Cloud SDKs. The Zep Guides and API reference note where [functionality may differ](/ce/ce-vs-cloud). Next Steps: * Install the [Zep Community Edition SDKs](/ce/sdks) * Read the [Zep Service Guides](/) * Explore the [Zep API Reference](/api-reference) # Community Edition Features > Understanding the differences between Zep Community Edition and Zep Cloud Our vision for Zep Community Edition is to offer a self-contained memory service easily run on your laptop. Available under a permissive Apache 2.0 license, you can use it for free, edit the source code, contribute back to the project, and use it in your commercial products. The table provides an overview of the differences between Zep Community Edition and Zep Cloud. | Feature | Community Edition | Cloud | | ----------------------------------- | ----------------- | ----------- | | Graph-based Memory | Yes | Yes | | SDKs for Python, TypeScript, and Go | Yes | Yes | | Web UI | No | Yes | | Multiple Projects | No | Yes | | Memory for Groups of Users | No | Yes | | Graph CRUD operations | No | Yes | | JSON and text data ingestion | No | Yes | | Community and Node Summaries | No | Yes | | Low-latency graph building | No | Yes | | Dialog Classification | No | Yes | | Structured Output | No | Yes | | License | Apache 2.0 | Proprietary | # Quick Start > Get started with Zep Open Source v0.x You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Prefer not to manage Zep yourself? [Sign Up for Zep Cloud](https://www.getzep.com/) ### Starting a Zep server locally is simple. 1. Clone the [Zep repo](https://github.com/getzep/zep) ```bash git clone https://github.com/getzep/zep.git ``` 2. Add your OpenAI API key to a `.env` file in the root of the repo: ```bash ZEP_OPENAI_API_KEY= ``` > **Note:** Zep uses OpenAI for chat history summarization, intent analysis, and, by default, embeddings. You can get an [Open AI Key here](https://openai.com/). 3. Start the Zep server: ```bash docker compose pull docker compose up ``` This will start a Zep server on port `8000`, and NLP and database server backends. 4. Get started with the [Zep SDKs](../sdk)! # Developing with Zep > Learn how to install and use Zep SDKs for Python and TypeScript You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). ## Installation Zep offers both [Python](https://github.com/getzep/zep-python) and [TypeScript](https://github.com/getzep/zep-js) SDKs. ### Python ```bash pip install "zep-python>=1.5.0,<2.0.0" ``` ### TypeScript ```bash npm install @getzep/zep-js@^0.10.0 ``` or ```bash yarn add @getzep/zep-js@^0.10.0 ``` ## Initializing the Client > **Note:** Zep supports optional JWT authentication. > > The examples below assume that you have enabled JWT authentication. > See the [Authentication Configuration Guide](/ce/legacy/deployment/auth) for more information. ### Python ```python from zep_python import ZepClient # Replace with Zep API URL and (optionally) API key zep = ZepClient("http://localhost:8000", api_key="optional_api_key") ``` ### TypeScript ```javascript import { ZepClient } from "@getzep/zep-js"; // Replace with Zep API URL and (optionally) API key const zep = ZepClient.init("http://localhost:8000", "optional_api_key"); ``` > **Note:** `zep-python` supports async use > > `zep-python` supports async use. All methods are available as both sync and async, with the async methods > prefixed with `a`. For example, `zep-python` has both `zep_client.memory.add_memory` > and `zep_client.memory.aadd_memory` methods. ## Next Steps Now that you have a Zep client, you can start using the Zep APIs. * **Working with Chat History** Store [Chat History](/ce/legacy/sdk/chat_history), enrich it with metadata, and run semantic search over messages and summaries. # Working with Chat History > Learn how to persist, retrieve, and search chat history using Zep's Memory API You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Zep's Memory API persists your app's chat history and metadata to a `Session`, enriches the memory, and enables vector similarity search over historical chat messages. There are two approaches to populating your prompt with chat history: 1. Retrieve the most recent N messages (and potentially a summary) from a `Session` and use them to construct your prompt. 2. Search over the `Session`'s chat history for messages that are relevant and use them to construct your prompt. Both of these approaches may be useful, with the first providing the LLM with context as to the most recent interactions with a human. The second approach enables you to look back further in the chat history and retrieve messages that are relevant to the current conversation in a token-efficient manner. ## Initializing the Zep Client Please see the [SDK documentation](../sdk) for more information on initializing the Zep client. > **Note:** `zep-python` supports async use. All methods are available as both sync and async, with the async methods prefixed with `a`. For example, `zep-python` has both `zep_client.memory.add_memory` and `zep_client.memory.aadd_memory` methods. ## Next Steps * Working with [Users](/ce/legacy/sdk/chat_history/users) and [Sessions](/ce/legacy/sdk/chat_history/sessions) * Persisting and Retrieving [Memories](/ce/legacy/sdk/chat_history/memories) * Searching over Memories with [Hybrid Search](/ce/legacy/sdk/chat_history/search) ## Zep's Memory Enrichment You've likely noticed that alongside the role and content you provided to Zep when persisting a memory, Zep also returns a unique identifier, a summary, UUID, a timestamp, token count, extracted entities, and more. The token count is a useful tool to use when constructing prompts, while the extracted entities and other metadata may be useful for building more sophisticated applications. Zep performs auto-summarization when a session exceeds the message window. This is returned in the `summary` field of the memory when you call `get_memory` and may be used when constructing prompts in order to provide your agent or chain with a longer-term memory of the conversation. Read more about the Summarizer Extractor. Zep also automatically extracts Entities from, and runs an Intent Analysis on, messages in the conversation. The extracted entities and intents are stored in system metadata and available for hybrid searches (see Hybrid Search above). ```json { "summary": { "uuid": "afe3957b-032f-47e0-8317-ed2953a2fb49", "created_at": "2023-05-16T22:59:22.979937Z", "content": "The AI provides a summary of Octavia Butler's Parable of the Sower, detailing the story of Lauren Olamina in a dystopian future. When the human asks for recommendations for other women sci-fi writers, the AI suggests Ursula K. Le Guin and Joanna Russ. The human follows up by asking about Butler's awards, and the AI lists the Hugo Award, Nebula Award, and MacArthur Fellowship. They also discuss Butler's contemporaries, the FX adaptation of Kindred, and Butler's background as an American science fiction author.", "recent_message_uuid": "8834423d-9388-4a6a-bee2-091754407241", "token_count": 644 }, "messages": [ { "uuid": "96c2597e-7c13-48ee-bb5e-1f4f4663b2d2", "created_at": "2023-05-16T22:59:33.612956Z", "role": "ai", "content": "Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.", "system": { "intent": "The subject is providing information about a science fiction novel called \"Parable of the Sower\" by Octavia Butler, including a brief summary of its plot and setting.", "entities": [ { "Label": "PERSON", "Matches": [ { "End": 46, "Start": 32, "Text": "Octavia Butler" } ], "Name": "Octavia Butler" }, { "Label": "PERSON", "Matches": [ { "End": 46, "Start": 32, "Text": "Lauren Olamina" } ], "Name": "Lauren Olamina" }, { "Label": "WORK_OF_ART", "Matches": [ { "End": 0, "Start": 20, "Text": "Parable of the Sower" } ], "Name": "Parable of the Sower" } ] }, "token_count": 253 }, { "uuid": "b235e682-75b3-44b2-b083-4572cdbc86b1", "created_at": "2023-05-16T22:59:33.612956Z", "role": "human", "content": "Write a short synopsis of Butler's book, Parable of the Sower. What is it about?", "metadata": { "system": { "intent": "The subject is requesting a brief explanation or summary of Octavia Butler's book, \"Parable of the Sower.\"", "entities": [ { "Label": "WORKS_OF_ART", "Matches": [ { "End": 46, "Start": 32, "Text": "Parable of the Sower" } ], "Name": "Parable of the Sower" } ] } }, "token_count": 21 } ] } ``` # Users > Fundamental part of the Zep Memory Store You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Just like [`Sessions`](/ce/legacy/sdk/chat_history/sessions), `Users` are a fundamental part of the Zep Memory Store. A `User` represents an individual interacting with your application. Each `User` can have multiple `Sessions` associated with them, allowing you to track and manage the interactions of a user over time. The `UserID` is a unique identifier for each user. This can be any string value - for example, it could be a username, an email address, or a UUID. You can also store additional data related to the user in the `metadata` field. The `User` object and its associated `Sessions` provide a powerful way to manage and understand the behavior of individuals using your application. By associating `Sessions` with `Users`, you can track the progression of conversations and interactions over time, providing valuable context and history. In the following sections, you will learn how to manage `Users` and their associated `Sessions`. ## The `User` model You can associate rich business context with a `User`: * `user_id`: A unique identifier of the user that maps to your internal User ID. * `email`: The user's email. * `first_name`: The user's first name. * `last_name`: The user's last name. * `metadata`: Any additional data associated with the user. ## Adding a User You can add a new user by providing the user details. ### Python ```python user_request = CreateUserRequest( user_id=user_id, email="user@example.com", first_name="Jane", last_name="Smith", metadata={"foo": "bar"}, ) new_user = client.user.add(user_request) ``` ### TypeScript ```typescript const user: ICreateUserRequest = { user_id: "user123", metadata: { foo: "bar" }, }; const newUser = await client.user.add(user); ``` > Learn how to associate [`Sessions` with Users](sessions) ## Getting a User You can retrieve a user by their ID. ### Python ```python user = client.user.get("user123") ``` ### TypeScript ```typescript const user = await client.user.get("user123"); ``` ## Updating a User You can update a user's details by providing the updated user details. ### Python ```python user_request = UpdateUserRequest( user_id=user_id, email="updated_user@example.com", first_name="Jane", last_name="Smith", metadata={"foo": "updated_bar"}, ) updated_user = client.user.update(user_request) ``` ### TypeScript ```typescript const user: IUpdateUserRequest = { user_id: "user123", metadata: { foo: "baz" }, }; const updatedUser = await client.user.update(user); ``` ## Deleting a User You can delete a user by their ID. ### Python ```python client.user.delete("user123") ``` ### TypeScript ```typescript await client.user.delete("user123"); ``` ## Getting a User's Sessions You can retrieve all `Sessions` for a user by their ID. ### Python ```python # Get all sessions for user123 sessions = client.user.get_sessions("user123") ``` ### TypeScript ```typescript // Get all sessions for user123 const sessions = await client.user.getSessions("user123"); ``` ## Listing Users You can list all users, with optional limit and cursor parameters for pagination. ### Python ```python # List the first 10 users users = client.user.list(limit=10, cursor=0) ``` ### TypeScript ```typescript // List the first 10 users const users = await client.user.list(10, 0); ``` ## Listing Users in Chunks You can retrieve users in chunks of a specified size. This is a generator function that yields each chunk of users as they are retrieved. ### Python ```python for users in client.user.list_chunked(chunkSize=100): process(users) ``` ### TypeScript ```typescript for await (const users of client.user.listChunked(100)) { process(users); } ``` # Memories > Central data structure in Zep's Memory Store You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). A `Memory` is the central data structure in Zep's Memory Store. It contains a list of `Messages` and a `Summary` (if created). The Memory and Summary are returned with UUIDs, entities extracted from the conversation, token counts, timestamps, and other metadata. Memories are associated with a [`Session`](sessions) in a many-to-one relationship. ## Persisting a Memory to a Session A `Memory` may include a single message or a series of messages. Each `Message` has a `role` and `content` field, with role being the identifiers for your human and AI/agent users and content being the text of the message. Additionally, you can even store custom metadata with each Message. > **Note:** Sessions are created automatically when adding Memories. If the `SessionID` already exists, then the Memory is upserted into the Session. > > **[Manually creating a session](sessions) can be useful if you want to associate it with a user or add metadata** ### Python ```python session_id = uuid.uuid4().hex # A new session identifier history = [ { "role": "human", "content": "Who was Octavia Butler?" }, { "role": "ai", "content": "Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American" + " science fiction author.", }, { "role": "human", "content": "Which books of hers were made into movies?", "metadata":{"foo": "bar"}, } ] messages = [Message(role=m["role"], content=m["content"]) for m in history] memory = Memory(messages=messages) result = await client.memory.aadd_memory(session_id, memory) ``` ### TypeScript ```typescript const sessionID = randomUUID(); const history = [ { role: "human", content: "Who was Octavia Butler?" }, { role: "ai", content: "Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American" + " science fiction author.", }, { role: "human", content: "Which books of hers were made into movies?", metadata: { foo: "bar" }, }, ]; const messages = history.map( ({ role, content }) => new Message({ role, content }) ); const memory = new Memory({ messages }); await zepClient.memory.addMemory(sessionID, memory); ``` ## Getting a Session's Memory ### Python ```python async with ZepClient(base_url, api_key) as client: try: memory = await client.memory.aget_memory(session_id) for message in memory.messages: print(message.to_dict()) except NotFoundError: print("Memory not found") ``` ```json { "uuid": "7291333f-2e01-4b06-9fe0-3efc59b3399c", "created_at": "2023-05-16T21:59:11.057919Z", "role": "ai", "content": "Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.", "token_count": 56 } { "uuid": "61f862c5-945b-49b1-b87c-f9338518b7cb", "created_at": "2023-05-16T21:59:11.057919Z", "role": "human", "content": "Write a short synopsis of Butler's book, Parable of the Sower. What is it about?", "token_count": 23 } ``` ### TypeScript ```typescript const memory = await zepClient.memory.getMemory(sessionID); if (memory.messages.length === 0) { console.debug("No messages found for session ", sessionID); } else { memory.messages.forEach((message) => { console.debug(JSON.stringify(message)); }); } ``` ```json { "uuid": "7291333f-2e01-4b06-9fe0-3efc59b3399c", "created_at": "2023-05-16T21:59:11.057919Z", "role": "ai", "content": "Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.", "token_count": 56 } { "uuid": "61f862c5-945b-49b1-b87c-f9338518b7cb", "created_at": "2023-05-16T21:59:11.057919Z", "role": "human", "content": "Write a short synopsis of Butler's book, Parable of the Sower. What is it about?", "token_count": 23 } ``` # Sessions > Represent a conversation in Zep's Memory Store You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). `Sessions` represent a conversation. Sessions can be associated with [`Users`](users) in a 1:M relationship. Chat messages are added to sessions in the form of [`Memories`](memories). Each session can have many messages associated with it. The `SessionID` is a string key that accepts arbitrary identifiers. Related data you'd like to store can be persisted as metadata. ## Adding a Session SessionIDs are arbitrary identifiers that you can map to relevant business objects in your app, such as users or a conversation a user might have with your app > **Note:** Sessions don't need to be explicitly created. Sessions are created automatically when adding Memories. If the SessionID already exists, then the Memory is upserted into the Session. Manually creating a session can be useful if you want to associate it with a user or add metadata. ### Python ```python async with ZepClient(base_url, api_key) as client: session_id = uuid.uuid4().hex # A new session identifier session = Session( session_id=session_id, user_id=user_id, # Optionally associate this session with a user metadata={"foo" : "bar"} ) await client.memory.aadd_session(session) ``` ### TypeScript ```typescript const sessionData: ISession = { session_id: sessionID, user_id: userID, // Optionally associate this session with a user metadata: { foo: "bar" }, }; const session = new Session(sessionData); await client.memory.addSession(session); ``` > Looking to associate a `Session` with a `User`? Check out our [User Management](users) docs. ## Updating Session Metadata You can update a session's metadata by providing a Session object with new metadata. Note that metadata is merged, so any existing metadata will be preserved. ### Python ```python session = Session(session_id=session_id, metadata={"qax" : "baz"}) await client.memory.aupdate_session(session) ``` ### TypeScript ```typescript const sessionData: ISession = { session_id: sessionID, metadata: { qax: "baz" }, }; const session = new Session(sessionData); await client.memory.updateSession(session); ``` ## Getting a Session ### Python ```python session = await client.memory.aget_session(session_id) print(session.dict()) ``` ### TypeScript ```typescript const session = await client.memory.getSession(sessionID); console.debug("Retrieved session ", session.toDict()); ``` ## Deleting a Session Deleting a Session soft-deletes the Session and all associated Memories. The Session and Memories are still available in the database, but are marked as deleted and will not be returned in search results. They will be purged on the next run of the [Zep Purge Process](../../deployment/data). If you persist memory to a deleted Session, it will be undeleted. Deleted Memories will, however, remain deleted. ### Python ```python await client.memory.adelete_memory(session_id) ``` ### TypeScript ```typescript await client.memory.deleteMemory(sessionID); ``` ## Listing Sessions You can list all Sessions in the Zep Memory Store with optional limit and cursor parameters for pagination. We also provide a helper generator function making it simple to iterate over all Sessions. ### Python ```python # List the first 10 Sessions sessions = client.memory.list_sessions(limit=10, cursor=0) for session in sessions: print(session) # List All Sessions using a generator all_sessions = client.memory.list_all_sessions(chunk_size=100) for session_chunk in all_sessions: for session in session_chunk: print(session) ``` ### TypeScript ```typescript // List the first 10 Sessions const sessions = await client.memory.listSessions(10, 0); // List All Sessions using a generator for await (const sessionChunk of client.memory.listSessionsChunked(100)) { for (const session of sessionChunk) { console.debug("Retrieved session ", session.toDict()); } } ``` # Messages > Represent individual messages in a conversation You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). `Messages` represent individual messages in a conversation. Messages are associated with [`Sessions`](sessions) in a M:1 relationship. Messages must be added to sessions using [`Memories`](memories). ## Get a Specific Message from a Session To retrieve a specific message from a session, you can use the `get_session_message` method. Here are examples in Python and TypeScript: ### Python ```python title="Get Message from Session" async with ZepClient(base_url, api_key) as client: try: session_id = "3e0e4af9-71ff-4541-b206-6133574bbbc6" # Replace with the actual session_id message_id = "3e0e4af9-71ff-4541-b206-6133574bbbc7" # Replace with the actual message_id message = await client.message.aget_session_message(session_id, message_id) print(message.to_dict()) except NotFoundError: print("Message not found") ``` ```json title="Output" { "uuid": "3e0e4af9-71ff-4541-b206-6133574bbbc7", "created_at": "2023-12-08T22:17:33.185756Z", "updated_at": "0001-01-01T00:00:00Z", "role": "human", "content": "Who were her contemporaries?", "metadata": { "system": { "entities": [], "intent": "The subject is requesting information about the people who were living at the same time as the woman in question." } } } ``` ### TypeScript ```javascript title="Get message from Session" const sessionID = "3e0e4af9-71ff-4541-b206-6133574bbbc6"; // Replace with the actual session ID const messageID = "3e0e4af9-71ff-4541-b206-6133574bbbc7"; // Replace with the actual message ID try { const message = await zepClient.message.getSessionMessage( sessionID, messageID ); console.debug(JSON.stringify(message)); } catch (error) { console.debug("Message not found"); } ``` ```json title="Output" { "uuid": "3e0e4af9-71ff-4541-b206-6133574bbbc7", "created_at": "2023-12-08T22:17:33.185756Z", "updated_at": "0001-01-01T00:00:00Z", "role": "human", "content": "Who were her contemporaries?", "metadata": { "system": { "entities": [], "intent": "The subject is requesting information about the people who were living at the same time as the woman in question." } } } ``` ## Getting all Messages from a Session ### Python ```python title="Get all Messages from a Session" async with ZepClient(base_url, api_key) as client: try: messages = await client.message.aget_session_messages(session_id) for message in messages: print(message.to_dict()) except NotFoundError: print("Sesssion not found") ``` ```json title="Output" { "messages": [ { "uuid": "3e0e4af9-71ff-4541-b206-6133574bbbc7", "created_at": "2023-12-08T22:17:33.185756Z", "updated_at": "0001-01-01T00:00:00Z", "role": "human", "content": "Who were her contemporaries?", "metadata": { "system": { "entities": [], "intent": "The subject is requesting information about the people who were living at the same time as the woman in question." } }, "token_count": 0 } ], ... } ``` ### TypeScript ```javascript title="Get all Messages from a Session" try { const sessionID = "3e0e4af9-71ff-4541-b206-6133574bbbc6"; // Replace with the actual session ID const messagesForSession = await zepClient.message.getSessionMessages( sessionID ); messagesForSession.messages.forEach((message) => { console.debug(JSON.stringify(message)); }); } catch (error) { console.error("An error occurred:", error); } ``` ```json title="Output" { "messages": [ { "uuid": "3e0e4af9-71ff-4541-b206-6133574bbbc7", "created_at": "2023-12-08T22:17:33.185756Z", "updated_at": "0001-01-01T00:00:00Z", "role": "human", "content": "Who were her contemporaries?", "metadata": { "system": { "entities": [], "intent": "The subject is requesting information about the people who were living at the same time as the woman in question." } }, "token_count": 0 } ], ... } ``` ## Update Session Message Metadata Below are examples on how to update the metadata on a message. Currently, updating message content is not supported. You may, however, update a message's metadata. The metadata should be provided in the following format: ```json title="metadata" { "metadata": { "foo": "bar" } } ``` ### Python ```python title="Update Metadata on a Message" async with ZepClient(base_url, api_key) as client: try: session_id = "3e0e4af9-71ff-4541-b206-6133574bbbc6" # Replace with the actual session_id message_uuid = "3e0e4af9-71ff-4541-b206-6133574bbbc7" # Replace with the actual message_id metadata = { "metadata": { "foo": "bar" } } await client.message.update_session_message_metadata(session_id, message_id, metadata) except NotFoundError: print("Session not found") ``` ```json title="Output" { "uuid": "3e0e4af9-71ff-4541-b206-6133574bbbc7", "created_at": "2023-12-08T22:17:33.185756Z", "updated_at": "0001-01-01T00:00:00Z", "role": "human", "content": "Who were her contemporaries?", "metadata": { "foo": "bar", "system": { "entities": [], "intent": "The subject is requesting information about the people who were living at the same time as the woman in question." } } } ``` ### TypeScript ```javascript title="Update Metadata on a Message" const sessionID = "3e0e4af9-71ff-4541-b206-6133574bbbc6"; // Replace with the actual session ID const messageID = "3e0e4af9-71ff-4541-b206-6133574bbbc7"; // Replace with the actual message ID const metadataUpdate = { metadata: { foo: "bar", }, }; try { const messagesForSession = await zepClient.message.updateSessionMessageMetadata( sessionID, messageID, metadataUpdate ); console.debug(JSON.stringify(message)); } catch (error) { console.error("An error occurred:", error); } ``` ```json title="Output" { "uuid": "3e0e4af9-71ff-4541-b206-6133574bbbc7", "created_at": "2023-12-08T22:17:33.185756Z", "updated_at": "0001-01-01T00:00:00Z", "role": "human", "content": "Who were her contemporaries?", "metadata": { "foo": "bar", "system": { "entities": [], "intent": "The subject is requesting information about the people who were living at the same time as the woman in question." } } } ``` # Configuring Zep > Configure Zep server settings, authentication, and LLM options You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Zep is configured via a yaml configuration file and/or environment variables. The `zep` server accepts a CLI argument `--config` to specify the location of the config file. If no config file is specified, the server will look for a `config.yaml` file in the current working directory. ```bash zep --config /path/to/config.yaml ``` > **Warning:** Your OpenAI/Anthropic API key and Auth Secret should not be set in the config file, rather the environment variables > below should be set. These can also be configured in a `.env` file in the current working directory. ## Zep Server The Zep server can be configured via environment variables, a `.env` file, or the `config.yaml` file. The following table lists the available configuration options. ### Server Config | Config Key | Environment Variable | Default | | ------------------------- | ------------------------------- | ----------------------- | | store.type | ZEP\_STORE\_TYPE | postgres | | store.postgres.dsn | ZEP\_STORE\_POSTGRES\_DSN | Installation dependent. | | server.host | ZEP\_SERVER\_HOST | 0.0.0.0 | | server.port | ZEP\_SERVER\_PORT | 8000 | | server.web\_enabled | ZEP\_SERVER\_WEB\_ENABLED | true | | server.max\_request\_size | ZEP\_SERVER\_MAX\_REQUEST\_SIZE | 5242880 | | nlp.server\_url | ZEP\_NLP\_SERVER\_URL | Installation dependent. | | opentelemetry.enabled | ZEP\_OPENTELEMETRY\_ENABLED | false | | development | ZEP\_DEVELOPMENT | false | | log.level | ZEP\_LOG\_LEVEL | info | ### Authentication Config Please see the [Authentication](/ce/legacy/deployment/auth) documentation for more information on configuring authentication. | Config Key | Environment Variable | Default | | ----------------- | ----------------------- | ------------------------------------ | | auth.required | ZEP\_AUTH\_REQUIRED | false | | auth.secret | ZEP\_AUTH\_SECRET | do-not-use-this-secret-in-production | | data.purge\_every | ZEP\_DATA\_PURGE\_EVERY | 60 | ### LLMs See the [LLM Configuration](/ce/legacy/deployment/llmconfig) for more information on configuring LLMs. > **Note:** Anthropic does not support embeddings. If configuring Zep to use the Anthropic LLM service, you must configure Zep to use the local embeddings service. | Config Key | Environment Variable | Default | | --------------------------- | --------------------------------- | ------------- | | llm.service | ZEP\_LLM\_SERVICE | openai | | llm.model | ZEP\_LLM\_MODEL | gpt-3.5-turbo | | llm.azure\_openai\_endpoint | ZEP\_LLM\_AZURE\_OPENAI\_ENDPOINT | undefined | | llm.openai\_endpoint | ZEP\_LLM\_OPENAI\_ENDPOINT | undefined | | llm.openai\_org\_id | ZEP\_LLM\_OPENAI\_ORG\_ID | undefined | | llm.azure\_openai | ZEP\_LLM\_AZURE\_OPENAI | undefined | | llm.azure\_openai\_endpoint | ZEP\_LLM\_AZURE\_OPENAI\_ENDPOINT | undefined | ### Enrichment and Extraction | Config Key | Environment Variable | Default | | ---------------------------------------------------- | ------------------------------------------------------------- | --------------------------------- | | memory.message\_window | ZEP\_MEMORY\_MESSAGE\_WINDOW | 12 | | extractors.documents.embeddings.enabled | ZEP\_EXTRACTORS\_DOCUMENTS\_EMBEDDINGS\_ENABLED | true | | extractors.documents.embeddings.dimensions | ZEP\_EXTRACTORS\_DOCUMENTS\_EMBEDDINGS\_DIMENSIONS | 384 | | extractors.documents.embeddings.service | ZEP\_EXTRACTORS\_DOCUMENTS\_EMBEDDINGS\_SERVICE | local | | extractors.documents.embeddings.chunk\_size | ZEP\_EXTRACTORS\_DOCUMENTS\_EMBEDDINGS\_CHUNK\_SIZE | 1000 | | extractors.messages.summarizer.enabled | ZEP\_EXTRACTORS\_MESSAGES\_SUMMARIZER\_ENABLED | true | | extractors.messages.entities.enabled | ZEP\_EXTRACTORS\_MESSAGES\_ENTITIES\_ENABLED | true | | extractors.messages.intent.enabled | ZEP\_EXTRACTORS\_MESSAGES\_INTENT\_ENABLED | false | | extractors.messages.embeddings.enabled | ZEP\_EXTRACTORS\_MESSAGES\_EMBEDDINGS\_ENABLED | true | | extractors.messages.embeddings.dimensions | ZEP\_EXTRACTORS\_MESSAGES\_EMBEDDINGS\_DIMENSIONS | 384 | | extractors.messages.embeddings.service | ZEP\_EXTRACTORS\_MESSAGES\_EMBEDDINGS\_SERVICE | local | | extractors.messages.summarizer.embeddings.enabled | ZEP\_EXTRACTORS\_MESSAGES\_SUMMARIZER\_EMBEDDINGS\_ENABLED | true | | extractors.messages.summarizer.embeddings.dimensions | ZEP\_EXTRACTORS\_MESSAGES\_SUMMARIZER\_EMBEDDINGS\_DIMENSIONS | 384 | | extractors.messages.summarizer.embeddings.service | ZEP\_EXTRACTORS\_MESSAGES\_SUMMARIZER\_EMBEDDINGS\_SERVICE | local | | custom\_prompts.summarizer\_prompts.openai | ZEP\_CUSTOM\_PROMPTS\_SUMMARIZER\_PROMPTS\_OPENAI | See Zep's source code for details | | custom\_prompts.summarizer\_prompts.anthropic | ZEP\_CUSTOM\_PROMPTS\_SUMMARIZER\_PROMPTS\_ANTHROPIC | See Zep's source code for details | ### Data Management See the [Data Management](/ce/legacy/deployment/data) documentation for more information on configuring data management. | Config Key | Environment Variable | Default | | ----------------- | ----------------------- | ------- | | data.purge\_every | ZEP\_DATA\_PURGE\_EVERY | 60 | ### Valid LLM Models The following table lists the valid LLM models for the `llm.model` configuration option. | Provider | Model | | --------- | ----------------- | | OpenAI | gpt-3.5-turbo | | OpenAI | gpt-3.5-turbo-16k | | OpenAI | gpt-4 | | OpenAI | gpt-4-32k | | Anthropic | claude-instant-1 | | Anthropic | claude-2 | ## Zep NLP Server The Zep NLP Server may be configured via a `.env` file or environment variables. The following table lists the available configuration options. Note that the NLP server's container is not shipped with CUDA nor configured to use GPU acceleration. | Config Key | Environment Variable | Default | | ---------------------------- | ----------------------------------- | ----------------- | | log\_level | ZEP\_LOG\_LEVEL | info | | server.port | ZEP\_SERVER\_PORT | 5557 | | embeddings.device | ZEP\_EMBEDDINGS\_DEVICE | cpu | | embeddings.messages.enabled | ZEP\_EMBEDDINGS\_MESSAGES\_ENABLED | true | | embeddings.messages.model | ZEP\_EMBEDDINGS\_MESSAGES\_MODEL | all-MiniLM-L6-v2 | | embeddings.documents.enabled | ZEP\_EMBEDDINGS\_DOCUMENTS\_ENABLED | true | | embeddings.documents.model | ZEP\_EMBEDDINGS\_DOCUMENTS\_MODEL | all-MiniLM-L6-v2 | | nlp.spacy\_model | ZEP\_NLP\_SPACY\_MODEL | en\_core\_web\_sm | # Vector Search over Chat History > Zep allows developers to search the Zep long-term memory store for relevant historical conversations. You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Zep allows developers to search the Zep long-term memory store for relevant historical conversations. ## Searching for Messages or Summaries Zep supports vector similarity search for Messages or Summaries of messages stored by Zep. This allows you to populate prompts with past conversations contextually similar to a given query, with the results sorted by a similarity score or `distance`. ### When to use Summaries versus Messages Zep supports searching for both Messages and Summaries. Given that individual messages may lack conversational context, Summaries are often a better choice for search. See the discussion about [message limitations](#limitations) below. Messages, however, can contain specific details that may be useful for your application. It is possible to execute both types of searches within your app. ### MMR Reranking Summaries Since summaries often share information, particularly when the Message Window is set to a lower threshold, it is often useful to use Maximum Marginal Relevance (MMR) reranking of search results. Zep has built-in, hardware-accelerated support for MMR and enabling it is simple. > **Info: Constructing Search Queries** > > Zep's Collection and Memory search support semantic search queries, JSONPath-based metadata filters, and a combination of both. Memory search also supports querying by message creation date. > > Read more about [constructing search queries](/ce/legacy/sdk/search_query). #### Python ```python from zep_python import ( MemorySearchPayload, ZepClient, ) # This uniquely identifies the user's session session_id = "my_session_id" # Initialize the Zep client before running this code search_payload = MemorySearchPayload( text="Is Lauren Olamina a character in a book?", search_scope="summary", # This could be messages or summary search_type="mmr", # remove this if you'd prefer not to rerank results mmr_lambda=0.5, # tune diversity vs relevance ) search_results = await client.memory.asearch_memory(session_id, search_payload) for search_result in search_results: # Uncomment for message search # print(search_result.messsage.dict()) print(search_result.summary.dict()) ``` ```json { "summary": { "uuid": "b47b83da-16ae-49c8-bacb-f7d049f9df99", "created_at": "2023-11-02T18:22:10.103867Z", "content": "The human asks the AI to explain the book Parable of the Sower by Octavia Butler. The AI responds by explaining that Parable of the Sower is a science fiction novel by Octavia Butler. The book follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.", "token_count": 66 }, "metadata": null, "dist": 0.8440576791763306 } ``` #### TypeScript ```typescript import { MemorySearchPayload, ZepClient } from "@getzep/zep-js"; // This uniquely identifies the user's session const sessionID = "my_session_id"; const searchText = "Is Lauren Olamina a character in a book?"; // Initialize the ZepClient before running this code // Create a new MemorySearchPayload with the search text, scope, type, and MMR lambda const searchPayload = new MemorySearchPayload({ text: searchText, search_scope: "summary", // This could be messages or summary search_type: "mmr", // remove this if you'd prefer not to rerank results mmr_lambda: 0.5, // tune diversity vs relevance }); // Perform the memory search with the session ID, search payload, and a limit of 3 results const searchResults = await client.memory.searchMemory( sessionID, searchPayload, 3 ); searchResults.forEach((searchResult) => { console.debug(JSON.stringify(searchResult)); }); ``` ```json { "summary": { "uuid": "b47b83da-16ae-49c8-bacb-f7d049f9df99", "created_at": "2023-11-02T18:22:10.103867Z", "content": "The human asks the AI to explain the book Parable of the Sower by Octavia Butler. The AI responds by explaining that Parable of the Sower is a science fiction novel by Octavia Butler. The book follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.", "token_count": 66 }, "metadata": null, "dist": 0.8440576791763306 } ``` ## Hybrid Search for Chat History using Metadata Filters In addition to vector similarity search for Messages and Summaries stored in Zep, Zep also allows you to search using metadata filters. This allows you to find Messages or Summaries that match a combination of text and metadata filter. You can also query solely by specifying metadata. #### Python ```python zep_client.search_memory( session_id=session_id, search_payload=MemorySearchPayload( query="I enjoy reading science fiction.", metadata={ "where": {"jsonpath": '$[*] ? (@.foo == "bar")'}, }, ), ) ``` ```json { "dist": 0.7170433826192629, "message": { "content": "I've read many books written by Octavia Butler.", "created_at": "2023-06-03T22:00:43.034056Z", "metadata": { "foo": "bar", "system": { "entities": [ { "Label": "PERSON", "Matches": [ { "End": 46, "Start": 32, "Text": "Octavia Butler" } ], "Name": "Octavia Butler" } ] } }, "role": "human", "token_count": 13, "uuid": "8f3a06dd-0625-41da-a2af-b549f2056b3f" }, "metadata": null, "summary": null } ``` #### TypeScript ```typescript const searchText = "I enjoy reading science fiction."; const searchPayload = new MemorySearchPayload({ metadata: { where: { jsonpath: '$[*] ? (@.foo == "bar")' }, }, text: searchText, }); const searchResults = await zepClient.searchMemory(sessionID, searchPayload); ``` ```json { "dist": 0.7170433826192629, "message": { "content": "I've read many books written by Octavia Butler.", "created_at": "2023-06-03T22:00:43.034056Z", "metadata": { "foo": "bar", "system": { "entities": [ { "Label": "PERSON", "Matches": [ { "End": 46, "Start": 32, "Text": "Octavia Butler" } ], "Name": "Octavia Butler" } ] } }, "role": "human", "token_count": 13, "uuid": "8f3a06dd-0625-41da-a2af-b549f2056b3f" }, "metadata": null, "summary": null } ``` ### Search Ranking and Limits #### Vector Indexes Where available, Zep will use a `pgvector v0.5`'s HNSW index for vector search over messages and summaries. Zep uses cosine distance for the distance function. If you are using a version of `pgvector` prior to `v0.5`, Zep will fall back to using an exact nearest neighbor search. If you don't have access to `pgvector v0.5`, it is possible to manually create `IVFFLAT` indexes to improve search performance. ```sql CREATE INDEX ON message_embedding USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); CREATE INDEX ON summary_embedding USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); ``` Please see the [pgvector documentation](https://github.com/pgvector/pgvector#ivfflat) for information on selecting the size of the `lists` parameter. #### Limitations Zep returns all messages from a search, up to a default limit. This limit can be overridden by passing a `limit` query string argument to the search API. Given the sparsity issue discussed below, we suggest only using the top 2-3 messages in your prompts. Alternatively, analyze your search results and use a distance threshold to filter out irrelevant messages. > **Note: Embedding short texts** > > Contextual search over chat histories is challenging: chat messages are typically short and can lack "information". When combined with high-dimensional embedding vectors, short texts can create very sparse vectors. > > This vector sparsity results in many vectors appearing close to each other in the vector space. This may in turn result in many false positives when searching for relevant messages. ### Embedding Models #### Docker Container Deployments By default, Zep uses OpenAI's 1536-wide AdaV2 embeddings for docker deployments. #### All other deployments By default, Zep uses a built-in Sentence Transformers model, `all-MiniLM-L6-v2`, for message embedding. The `all-MiniLM-L6-v2` model offers a very low latency search experience when deployed on suitable infrastructure. > **Note: `all-MiniLM-L6-v2` Model Limitations** > > The `all-MiniLM-L6-v2` model has a 256 word piece limit. If your messages are likely to be larger, it is recommended you select an alternative model. #### Selecting alternative models Other embedding models and services, such as OpenAI, may be configured. See the [Zep NLP Service](../../deployment/config) configuration. # Constructing Search Queries > How to construct search queries in Zep's Collection and Memory search You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). ## Introduction Zep's Collection and Memory search supports semantic similarity search and similarity search re-ranked by Maximal Marginal Relevance. Both of these search types can be filtered by JSONPath-based metadata filters. Memory search also supports querying by message or summary creation date. ## Simple, Text-based Semantic Queries The simplest form of search query is a text-based semantic similarity query. No metadata filter is required, and the query is simply a string of text. Zep will convert the query into an embedding and find semantically similar documents, chat history summaries, or chat messages. Below is an example search against a chat session using only search text. ```typescript const searchPayload = new MemorySearchPayload({ metadata: {}, text: searchText, }); const searchResults = await zepClient.memory.searchMemory( sessionID, searchPayload ); ``` Read more about [chat message history search](chat_history/search). ## Maximal Marginal Relevance Re-Ranking Zep supports re-ranking search results using Maximal Marginal Relevance (MMR) over both chat history memory and document collections. Maximal Marginal Relevance (MMR) helps balance relevance and diversity in results returned during information retrieval, which is useful in vector similarity searches for Retrieval-Augmented Generation (RAG) type applications. A similarity search may return many highly ranked results that are very similar to each other. Since each subsequent result doesn't add much new information to a prompt, adding these may not be very useful. MMR helps to reduce redundancy in the results by re-ranking the results to promote diversity, with very similar results downranked in favor of different, but still relevant, results. ### How Zep's MMR Re-Ranking Works When you run a search re-ranked by MMR, Zep retrieves double the number of results, K, you requested. The entire resultset is then reranked using MMR, and the top K results are returned. If you request fewer than 10 results, Zep will return 10 results, but still return to you the top K results you requested. Zep's MMR algorithm is SIMD-hardware accelerated on `amd64` architecture CPUs, ensuring that MMR adds little overhead to your search. ### Constructing an MMR Re-Ranked Search Query #### Search over Chat History ##### Python ```python from zep_python import ( MemorySearchPayload, ZepClient, ) search_payload = MemorySearchPayload( text=query, search_scope="summary", # This could be messages or summary search_type="mmr", mmr_lambda=0.5, # tune diversity vs relevance ) search_results = client.memory.search_memory( session_id, search_payload, limit=3 ) ``` ##### TypeScript ```typescript import { MemorySearchPayload, ZepClient } from "@getzep/zep-js"; const searchPayload = new MemorySearchPayload({ text: searchText, search_scope: "summary", // This could be messages or summary search_type: "mmr", mmr_lambda: 0.5, // tune diversity vs relevance }); const searchResults = await client.memory.searchMemory( sessionID, searchPayload, 3 ); ``` #### Search over Document Collections ##### Python ```python # This assumes you've created a collection and added documents to it docs = collection.search( text=query, search_type="mmr", mmr_lambda=0.5, limit=3, ) ``` ##### TypeScript ```typescript const mmrSearchQuery: ISearchQuery = { text: query, searchType: "mmr", mmrLambda: 0.5, }; // This assumes you've created a collection and added documents to it const mmrSearchResults = await collection.search(mmrSearchQuery, 3); ``` ### LangChain and MMR #### Search over Chat History Zep's LangChain `ZepRetriever` supports MMR re-ranking of search results over historical chat summaries or messages. ##### LangChain.js ```typescript import { ZepRetriever } from "langchain/retrievers/zep"; const mmrRetriever = new ZepRetriever({ url: process.env.ZEP_URL || "http://localhost:8000", sessionId: sessionID, topK: 3, searchType: "mmr", searchScope: "summary", mmrLambda: 0.5, }); const mmrDocs = await mmrRetriever.getRelevantDocuments(query); ``` ##### LangChain ```python from langchain.retrievers import ZepRetriever from langchain.retrievers.zep import SearchType, SearchScope zep_retriever = ZepRetriever( session_id=session_id, url=ZEP_API_URL, api_key=zep_api_key, top_k=3, search_scope=SearchScope.summary, search_type=SearchType.mmr, mmr_lambda=0.5, ) docs = await zep_retriever.aget_relevant_documents("Who wrote Parable of the Sower?") ``` #### Search over Document Collections MMR re-ranking is also supported for document collections via the `ZepVectorStore`. Currently, we utilize LangChain's MMR implementation for this, but we plan to add a native implementation in the future. ## Filtering using Metadata Zep supports filtering search queries by metadata. Metadata filters are [JSONPath queries](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html) augmented by a simple boolean logic overlay. JSONPath queries allow for building sophisticated filters that match on elements at any level of the JSON document. The boolean logic overlay allows for combining multiple JSONPath queries using `and` and `or` operators. ### Useful resources for building and testing JSONPath queries * [JSONPath Syntax](https://goessner.net/articles/JsonPath/) * [JSONPath Online Evaluator](https://jsonpath.com/) * [JSONPath Expression Tester](https://jsonpath.curiousconcept.com/#). ### Constructing a JSONPath Query Filter The simplest form of a metadata filter looks as follows: ```json { "where": { "jsonpath": "$[*] ? (@.foo == \"bar\")" } } ``` If a metadata field `foo` is equal to the string `"bar"`, then the document or message will be returned in the search results. Executing the above query against a chat session looks as follows: ```typescript const searchPayload = new MemorySearchPayload({ text: "Is Lauren Olamina a character in a book", metadata: { where: { jsonpath: '$[*] ? (@.author == "Octavia Butler")' }, }, }); const searchResults = await zepClient.memory.searchMemory( sessionID, searchPayload ); ``` Or, in the case of querying the MemoryStore using Python: ```python search_payload = MemorySearchPayload( text="Is Lauren Olamina a character in a book", metadata={ "where": { "jsonpath": '$[*] ? (@.author == "Octavia Butler")' } } ) search_results = client.memory.search_memory(session_id, search_payload) ``` ### Combining multiple JSONPath filters using boolean logic Multiple JSONPath queries can be combined using boolean logic. The following example will return documents or messages where the `author` field is equal to `"Octavia Butler"` **and** the `title` field is equal to `"Parable of the Sower"`. ```json { "where": { "and": [ { "jsonpath": "$[*] ? (@.author == \"Octavia Butler\")" }, { "jsonpath": "$[*] ? (@.title == \"Parable of the Sower\")" } ] } } ``` Similarly, the following example will return documents or messages where the `author` field is equal to `"Octavia Butler"` **or** the `title` field is equal to `"Parable of the Sower"`. ```json { "where": { "or": [ { "jsonpath": "$[*] ? (@.author == \"Octavia Butler\")" }, { "jsonpath": "$[*] ? (@.title == \"Parable of the Sower\")" } ] } } ``` Filter logic can be combined to create arbitrarily complex filters. For example, the following filter will return documents or messages where: * the `author` field is equal to (`"Octavia Butler"` **and** the `title` field is equal to `"Parable of the Sower"`) * **or** the `title` field is equal to `"Parable of the Talents"`. ```json { "where": { "or": [ { "and": [ { "jsonpath": "$[*] ? (@.author == \"Octavia Butler\")" }, { "jsonpath": "$[*] ? (@.title == \"Parable of the Sower\")" } ] }, { "jsonpath": "$[*] ? (@.title == \"Parable of the Talents\")" } ] } } ``` ## Querying by Message Creation Date Memory search supports querying by message creation date. The following example will return documents or messages created between June 1, 2023 and June 31, 2023. Datetime strings must be in ISO 8601 format. ```json { "start_date": "2023-06-01", "end_date": "2023-06-31" } ``` # Configuring Authentication > Set up JWT authentication for Zep You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Zep supports JWT authentication. Carefully follow the instructions below to enable it. ## Terminology ### JWT A JWT Token, also known as the Zep API Key, is a JSON Web Token used to authenticate with Zep. Provide this to the Zep SDK when you create a `ZepClient` instance. ### Secret A cryptographically secure secret is required to sign Zep's JWT tokens. This secret should be kept safe as access to it may allow access to the Zep API. ## Using the `zepcli` command line utility ### 1. Download the `zepcli` CLI tool Download the `zepcli` CLI tool from the [zepcli releases page](https://github.com/getzep/zepcli/releases). Ensure that you select the right binary for your platform. > **Note:** The `zepcli` CLI tool is intended to be used from the command line. If you are using MacOS, you cannot > run it from the Finder. You must run it from the Terminal. ### 2. Generate a secret and the JWT token A cryptographically secure secret is required to sign Zep's JWT tokens. This secret should be kept safe as access to it may allow access to the Zep API. On Linux or MacOS ```sh ./zepcli -i ``` On Windows ```sh zepcli.exe -i ``` Carefully copy the secret and JWT token to a safe place. You will need them in the next step. > **Note:** Do not mix up the secret and the JWT token > > The secret is used to sign the JWT token. The JWT token is used to authenticate with Zep. > Do not mix up the two! Keep the secret safe. Anyone with access to your JWT token will be able to access your Zep server. ### 3. Configure Auth environment variables Set the following environment variables in your Zep server environment: ```sh ZEP_AUTH_REQUIRED=true ZEP_AUTH_SECRET= ``` For development purposes, you can do this in your `.env` file. For production, you should set these according to best practices for managing secrets in your deployment environment. For example, Render.com has a [environment and secrets management feature](https://render.com/docs/configure-environment-variables) that can be used to set these variables. ### 4. Configure your client SDK to use JWT authentication You will need to configure your client SDK to use the JWT token you created in Step 2. See the [SDK docs](../sdk) for details. > **Warning:** Implement TLS Encryption > > JWT tokens are not encrypted. Your Zep web service should run behind a TLS terminator such as a load balancer. > Many cloud providers offer TLS termination on their load balancers. You should check your cloud providers > documentation for details on how to configure this. > > Keep your JWT token safe. Anyone with access to your JWT token will be able to access your Zep server. ## Using another tool If you'd prefer to use another tool to generate your secret and JWT token, you can do so. Below is an example of how to do so using Python and OpenSSL. Please see the instructions above for correctly setting the Zep environment variables. ### 1. Generate a secret A cryptographically secure secret is required to sign Zep's JWT tokens. This secret should be kept safe as access to it may allow access to the Zep API. Using OpenSSL (concatenate to remove newlines) ```sh openssl rand -base64 64 ``` or using Python ```python import secrets print(secrets.token_urlsafe(64)) ``` ### 2. Generating a JWT token Most languages have an ecosystem library that supports generation of JWT tokens. Note that Zep uses the `HS256` JWT signing algorithm and that no Claims are required. The token must be signed with the same secret that you set in the `ZEP_AUTH_SECRET` environment variable. # Long-term Memory for LangChain Apps > Building an Agent using LangChain and Zep Open Source You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Langchain Python and LangchainJS ship with a `ZepMemory` class. ### Managing Chat History Memory Zep's `ZepMemory` class can be used to provide long-term memory for your Langchain chat apps or agents. Zep will store the entire historical message stream, automatically summarize messages, enrich them with token counts, timestamps, metadata and more. You can also provide your bot or agent with access to relevant messages in long-term storage by using Zep's built-in vector search. > **Note:** Installing Zep > > A Zep server install is required. You will also need to have the Zep Python SDK or Zep typescript SDK installed in order to use the Langchain `ZepMemory` class. > > See the [Zep Quick Start Guide](../deployment/quickstart) for details. ## Using Zep as a LangChain Memory Store ### Using Zep with the LangChain's Python LangChain Expression Language (LCEL) The `ZepChatMessageHistory` class is used to provide long-term memory to LangChain apps built using the LangChain Expression Language (LCEL). First we'll create a `ChatPromptTemplate` that includes a placeholder for the message history. Then we'll create a `ChatOpenAI` model and chain it to the prompt. ```python from langchain.chat_models import ChatOpenAI from langchain.memory.chat_message_histories import ZepChatMessageHistory from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.runnables.history import RunnableWithMessageHistory prompt = ChatPromptTemplate.from_messages( [ ("system", "You're an assistant who's good at {ability}"), MessagesPlaceholder(variable_name="history"), ("human", "{question}"), ] ) chain = prompt | ChatOpenAI(model="gpt-3.5-turbo-1106", api_key=openai_api_key) session_id = "your-users-unique-session-id" ``` Now we'll instantiate a `ZepChatMessageHistory`, provide it with a unique session ID, and the Zep server URL and API key (if required). We'll also create a `RunnableWithMessageHistory` that will provide the message history to the chain. We'll specify the input and history message keys. The input messages key is the key that the chain will use to access the input messages. The history messages key is the key that the chain will use to access the message history. Ensure that these match your prompt template. ```python zep_chat_history = ZepChatMessageHistory( session_id=session_id, url="http://localhost:8000", # api_key=, ) chain_with_history = RunnableWithMessageHistory( chain, lambda session_id: zep_chat_history, input_messages_key="question", history_messages_key="history", ) chain_with_history.invoke( {"ability": "math", "question": "What does cosine mean?"}, config={"configurable": {"session_id": session_id}}, ) ``` ```text AIMessage(content='Cosine is a trigonometric function that relates the angle of a right-angled triangle to the ratio of the length of the adjacent side to the length of the hypotenuse. In simpler terms, cosine is a way to calculate the ratio of the length of one side of a right-angled triangle to the length of the hypotenuse, given an angle. This function is widely used in mathematics, physics, engineering, and many other fields.') ``` Let's invoke the chain again, this time with a different question. We'll also print the message history to see what's been stored. ```python chain_with_history.invoke( {"ability": "math", "question": "What's its inverse"}, config={"configurable": {"session_id": session_id}}, ) ``` The prior message context was used to answer the question. Zep automatically generates summaries of the message history. These will be added to the message history sent to LAngChain and can be used to provide long-term context to the chain. ```text AIMessage(content='The inverse of the cosine function is called arccosine or inverse cosine. It is denoted as "arccos" or "cos^(-1)". The arccosine function takes a value between -1 and 1 as input and returns the angle in radians whose cosine is the input value. In other words, if y = arccos(x), then x = cos(y). The arccosine function is the inverse of the cosine function, allowing us to find the angle given the cosine value.') ``` ### Using LangChain's ZepMemory class > **Note:** `ZepMemory` is used with the legacy LangChain Python API > > The following examples illustrate using Zep as a Langchain memory store. In Python, the `ZepMemory` class is > used when building LangChain app's with the legacy API. See above for details on building apps with the > LangChain Expression Language (LCEL). #### Python Using Zep as your Langchain app's long-term memory simple: initialize the `ZepMemory` with your Zep instance URL, API key, and your user's [session identifier](chat_history/sessions). ```python title="ZepMemory instantiation" from langchain.memory import ZepMemory # Set this to your Zep server URL ZEP_API_URL = "http://localhost:8000" ZEP_API_KEY = "" # optional session_id = str(uuid4()) # This is a unique identifier for the user # Set up ZepMemory instance memory = ZepMemory( session_id=session_id, url=ZEP_API_URL, api_key=zep_api_key, memory_key="chat_history", ) ``` #### TypeScript Using Zep as your Langchain app's long-term memory simple: initialize the ZepMemory with your Zep instance URL and your user's session identifier (see Zep Concepts) and then utilize it as the chat memory for a Langchain Conversation. ```typescript title="ZepMemory instantiation" import { ChatOpenAI } from "langchain/chat_models/openai"; import { ConversationChain } from "langchain/chains"; import { ZepMemory } from "langchain/memory/zep"; import { v4 as uuidv4 } from "uuid"; // Set this to your Zep server URL const zepApiURL = "http://localhost:8000"; const zepApiKey = ""; // optional const sessionId = uuid4(); // This is a unique identifier for the user // Set up Zep Memory const memory = new ZepMemory({ sessionId, baseURL: zepApiURL, apiKey: zepApiKey, }); ``` Once you've created the `memory`, use it in your chain or with your agent. #### Python ```python title="Running a chain with ZepMemory" llm = ChatOpenAI(model_name="gpt-3.5-turbo") chain = ConversationChain(llm=llm, verbose=True, memory=memory) chain.run( input="What is the book's relevance to the challenges facing contemporary society?" ) ``` ```text title="Output:" > Entering new AgentExecutor chain... AI: Parable of the Sower is a powerful exploration of the challenges facing contemporary society, such as environmental disasters, poverty, and violence. It examines how these issues can lead to the breakdown of society and how individuals can take action to create a better future. The novel also explores themes of faith, hope, and resilience in the face of adversity. > Finished chain. 'Parable of the Sower is a powerful exploration of the challenges facing contemporary society, such as environmental disasters, poverty, and violence. It examines how these issues can lead to the breakdown of society and how individuals can take action to create a better future. The novel also explores themes of faith, hope, and resilience in the face of adversity.' ``` Inspecting the `zep_chat_history`, we see that a summary was automatically created, and that the history has been enriched with token counts, UUIDs, and timestamps. ```python title="Inspecting the Zep memory" def print_messages(messages): for m in messages: print(m.type, ":\n", m.dict()) print(memory.chat_memory.zep_summary) print("\n") print_messages(memory.chat_memory.messages) The human inquires about Octavia Butler. The AI identifies her as an American science fiction author. The human then asks which books of hers were made into movies. The AI responds by mentioning the FX series Kindred, based on her novel of the same name. The human then asks about her contemporaries, and the AI lists Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ. system : {'content': 'The human inquires about Octavia Butler. The AI identifies her as an American science fiction author. The human then asks which books of hers were made into movies. The AI responds by mentioning the FX series Kindred, based on her novel of the same name. The human then asks about her contemporaries, and the AI lists Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.', 'additional_kwargs': {}} human : {'content': 'What awards did she win?', 'additional_kwargs': {'uuid': '6b733f0b-6778-49ae-b3ec-4e077c039f31', 'created_at': '2023-07-09T19:23:16.611232Z', 'token_count': 8, 'metadata': {'system': {'entities': [], 'intent': 'The subject is inquiring about the awards that someone, whose identity is not specified, has won.'}}}, 'example': False} ai : {'content': 'Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.', 'additional_kwargs': {'uuid': '2f6d80c6-3c08-4fd4-8d4e-7bbee341ac90', 'created_at': '2023-07-09T19:23:16.618947Z', 'token_count': 21, 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 14, 'Start': 0, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 33, 'Start': 19, 'Text': 'the Hugo Award'}], 'Name': 'the Hugo Award'}, {'Label': 'EVENT', 'Matches': [{'End': 81, 'Start': 57, 'Text': 'the MacArthur Fellowship'}], 'Name': 'the MacArthur Fellowship'}], 'intent': 'The subject is stating that Octavia Butler received the Hugo Award, the Nebula Award, and the MacArthur Fellowship.'}}}, 'example': False} human : {'content': 'Which other women sci-fi writers might I want to read?', 'additional_kwargs': {'uuid': 'ccdcc901-ea39-4981-862f-6fe22ab9289b', 'created_at': '2023-07-09T19:23:16.62678Z', 'token_count': 14, 'metadata': {'system': {'entities': [], 'intent': 'The subject is seeking recommendations for additional women science fiction writers to explore.'}}}, 'example': False} ``` #### TypeScript ```typescript title="Running a chain with ZepMemory" const chain = new ConversationChain({ llm: model, memory }); const response = await chain.run({ input = "What is the book's relevance to the challenges facing contemporary society?", }); ``` ```text title="Output:" > Entering new AgentExecutor chain... AI: Parable of the Sower is a powerful exploration of the challenges facing contemporary society, such as environmental disasters, poverty, and violence. It examines how these issues can lead to the breakdown of society and how individuals can take action to create a better future. The novel also explores themes of faith, hope, and resilience in the face of adversity. > Finished chain. 'Parable of the Sower is a powerful exploration of the challenges facing contemporary society, such as environmental disasters, poverty, and violence. It examines how these issues can lead to the breakdown of society and how individuals can take action to create a better future. The novel also explores themes of faith, hope, and resilience in the face of adversity.' ``` Inspecting the `ZepMemory`, we see that a summary was automatically created, and that the history has been enriched with token counts, UUIDs, and timestamps. ```typescript title="Inspecting the Zep Memory" const memoryVariables = await zepMemory.loadMemoryVariables({}); console.log(memoryVariables); ``` ```text title="Output:" The AI provides a synopsis of Parable of the Sower, a science fiction novel by Octavia Butler, about a young woman navigating a dystopian future. The human asks for recommendations for other women sci-fi writers and the AI suggests Ursula K. Le Guin and Joanna Russ. The AI also notes that Butler was a highly acclaimed writer, having won the Hugo Award, the Nebula Award, and the MacArthur Fellowship. {'uuid': 'becfe5f4-d24c-4487-b572-2e836d7cedc8', 'created_at': '2023-05-10T23:28:10.380343Z', 'role': 'human', 'content': "WWhat is the book's relevance to the challenges facing contemporary society?", 'token_count': 16} {'uuid': '8ea4875c-bf42-4092-b3b8-308394963cb7', 'created_at': '2023-05-10T23:28:10.396994Z', 'role': 'ai', 'content': 'Parable of the Sower is a powerful exploration of the challenges facing contemporary society, such as environmental disasters, poverty, and violence. It examines how these issues can lead to the breakdown of society and how individuals can take action to create a better future. The novel also explores themes of faith, hope, and resilience in the face of adversity.', 'token_count': 0} ... {'uuid': '2d95ff94-b52d-49bd-ade4-5e1e553e8cac', 'created_at': '2023-05-10T23:28:02.704311Z', 'role': 'ai', 'content': 'Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American science fiction author.', 'token_count': 31} ``` ## Search Zep's message history from your Langchain app Zep supports both vector search using a Langchain `Retriever` as well as via an instance of `ZepMemory`. ### Using a ZepMemory instance If you don't need to provide a `Retriever` to your chain or agent, you can search the long-term message history for a session directly from an instance of `ZepMemory`. #### Python ```python title="Search for relevant historical messages" search_results = memory.chat_memory.search("who are some famous women sci-fi authors?") for r in search_results: if r.dist > 0.8: # Only print results with similarity of 0.8 or higher print(r.message, r.dist) ``` ```text title="Output:" {'uuid': 'ccdcc901-ea39-4981-862f-6fe22ab9289b', 'created_at': '2023-07-09T19:23:16.62678Z', 'role': 'human', 'content': 'Which other women sci-fi writers might I want to read?', 'metadata': {'system': {'entities': [], 'intent': 'The subject is seeking recommendations for additional women science fiction writers to explore.'}}, 'token_count': 14} 0.9119619869747062 {'uuid': '7977099a-0c62-4c98-bfff-465bbab6c9c3', 'created_at': '2023-07-09T19:23:16.631721Z', 'role': 'ai', 'content': 'You might want to read Ursula K. Le Guin or Joanna Russ.', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}], 'intent': 'The subject is suggesting that the person should consider reading the works of Ursula K. Le Guin or Joanna Russ.'}}, 'token_count': 18} 0.8534346954749745 {'uuid': 'b05e2eb5-c103-4973-9458-928726f08655', 'created_at': '2023-07-09T19:23:16.603098Z', 'role': 'ai', 'content': "Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.", 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 16, 'Start': 0, 'Text': "Octavia Butler's"}], 'Name': "Octavia Butler's"}, {'Label': 'ORG', 'Matches': [{'End': 58, 'Start': 41, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 76, 'Start': ``` # LLM Configuration > Configure Zep to use OpenAI, Anthropic, or custom LLM services You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). Zep uses LLM models for summarization, intent analysis tasks, and embedding texts, and currently supports the OpenAI and Anthropic LLM services, local LLMs with OpenAI compatible APIs, and local embeddings services. ## OpenAI Service ### OpenAI API Key Your OpenAI API key should not be stored in the `config.yaml` file. Instead, it should be stored in the `ZEP_OPENAI_API_KEY` environment variable. ### LLM Model You may configure which LLM model to use by setting the [`llm.model` config key or `ZEP_LLM_MODEL`](config) environment variable. ### OpenAI OrgID You may configure which OpenAI OrgID to use by setting the [`llm.openai_org_id` config key or `ZEP_LLM_OPENAI_ORG_ID`](config) ### Azure OpenAI Endpoint > **Note:** This feature is experimental. Please let us know if it works for you. Azure OpenAI API support can be enabled by setting the [`llm.azure_openai_endpoint` config key or `ZEP_LLM_AZURE_OPENAI_ENDPOINT`](config) environment variable. Your Azure OpenAI API key should be set as described above. ## Anthropic Service > **Info:** Anthropic does not support embeddings > > If configuring Zep to use the Anthropic LLM service, you must configure Zep to use the local embeddings service. To configure Zep to use the Anthropic LLM service: 1. Set the [`ZEP_LLM_ANTHROPIC_API_KEY`](./config) environment variable to your Anthropic API key. 2. Set the [`llm.service` config key or `ZEP_LLM_SERVICE`](./config) environment variable to `anthropic`. 3. Set the [`llm.model` config key or `ZEP_LLM_MODEL`](./config) environment variable to a supported Anthropic model. ## Custom OpenAI-compatible API Endpoint > **Warning:** Zep's prompts are not optimized for all LLMs > > Your mileage may vary on how well Zep's default summarization and entity extraction prompts work with LLMs other than those explicitly supported. The OpenAI API Endpoint URL can be customized to allow Zep to connect to alternative OpenAI-compatible APIs. # Data Management > Understanding soft-deletion, purging, and configuration in Zep You are viewing the Zep Open Source v0.x documentation. This version is no longer supported, and documentation is provided as a reference only. The current documentation for Zep Community Edition is [available here](/ce/quickstart). ## Soft-deletion and Purging When records are deleted in Zep, they are initially marked as soft-deleted by updating their `deleted_at` field with the deletion datetime. These records remain in the database but are considered deleted for application purposes. By default, Zep executes a purge process every 60 minutes to perform hard deletes on these soft-deleted records. This means that soft-deleted records will be permanently removed from the `MessageStore`. ## Purge Configuration Administrators can modify the purge interval or disable the purge process entirely by editing `config.yaml` or setting the `ZEP_DATA_PURGE_EVERY` [environment variable](config). * Set `purge_every` to the desired number of minutes between each purge. For example, to change the interval to 120 minutes, set the purge\_every value to 120. * To disable the process altogether, set `purge_every` to 0 or leave undefined. In this case, the purging process will not run, and soft-deleted records will not be hard-deleted automatically. # Returns a fact by UUID ```http GET https://api.getzep.com/api/v2/facts/{factUUID} ``` get fact by uuid ## Path Parameters - FactUuid (required): Fact UUID ## Response Body - 200: The fact with the specified UUID. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/facts/factUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_fact( fact_uuid="factUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getFact("factUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetFact( context.TODO(), "factUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/facts/:factUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_fact( fact_uuid="factUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getFact("factUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetFact( context.TODO(), "factUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/facts/:factUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_fact( fact_uuid="factUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getFact("factUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetFact( context.TODO(), "factUUID", ) ``` # Delete a fact for the given UUID ```http DELETE https://api.getzep.com/api/v2/facts/{factUUID} ``` delete a fact ## Path Parameters - FactUuid (required): Fact UUID ## Response Body - 200: Deleted - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/facts/factUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.delete_fact( fact_uuid="factUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.deleteFact("factUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.DeleteFact( context.TODO(), "factUUID", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/facts/:factUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.delete_fact( fact_uuid="factUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.deleteFact("factUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.DeleteFact( context.TODO(), "factUUID", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/facts/:factUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.delete_fact( fact_uuid="factUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.deleteFact("factUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.DeleteFact( context.TODO(), "factUUID", ) ``` # Add a session ```http POST https://api.getzep.com/api/v2/sessions Content-Type: application/json ``` Create New Session ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"fact_rating_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:FactRatingInstruction"}}}},"description":"Optional instruction to use for fact rating."},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}},"description":"The metadata associated with the session."},{"key":"session_id","valueShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"description":"The unique identifier of the session."},{"key":"user_id","valueShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"description":"The unique identifier of the user associated with the session"}]} ``` ## Response Body - 200: The added session. - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_id": "session_id", "user_id": "user_id" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add_session( session_id="session_id", user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.addSession({ sessionId: "session_id", userId: "user_id" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.AddSession( context.TODO(), &v2.CreateSessionRequest{ SessionID: "session_id", UserID: "user_id", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_id": "string", "user_id": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add_session( session_id="session_id", user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.addSession({ sessionId: "session_id", userId: "user_id" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.AddSession( context.TODO(), &v2.CreateSessionRequest{ SessionID: "session_id", UserID: "user_id", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_id": "string", "user_id": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add_session( session_id="session_id", user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.addSession({ sessionId: "session_id", userId: "user_id" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.AddSession( context.TODO(), &v2.CreateSessionRequest{ SessionID: "session_id", UserID: "user_id", }, ) ``` # Returns all sessions in a specified order ```http GET https://api.getzep.com/api/v2/sessions-ordered ``` Get all sessions with optional page number, page size, order by field and order direction for pagination. ## Query Parameters - PageNumber (optional): Page number for pagination, starting from 1 - PageSize (optional): Number of sessions to retrieve per page - OrderBy (optional): Field to order the results by: created_at, updated_at, user_id, session_id - Asc (optional): Order direction: true for ascending, false for descending ## Response Body - 200: List of sessions - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions-ordered \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.list_sessions() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.listSessions(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.ListSessions( context.TODO(), &v2.MemoryListSessionsRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions-ordered \ -H "Authorization: Api-Key " \ -d page_number=0 \ -d page_size=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.list_sessions() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.listSessions(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.ListSessions( context.TODO(), &v2.MemoryListSessionsRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions-ordered \ -H "Authorization: Api-Key " \ -d page_number=0 \ -d page_size=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.list_sessions() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.listSessions(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.ListSessions( context.TODO(), &v2.MemoryListSessionsRequest{}, ) ``` # End multiple sessions. (cloud only) ```http POST https://api.getzep.com/api/v2/sessions/end Content-Type: application/json ``` End multiple sessions by their IDs. ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}},{"key":"session_ids","valueShape":{"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}]} ``` ## Response Body - 200: OK - 400: Bad Request - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_ids": [ "session_ids" ] }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_sessions( session_ids=["session_ids"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSessions({ sessionIds: ["session_ids"] }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSessions( context.TODO(), &v2.EndSessionsRequest{ SessionIDs: []string{ "session_ids", }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_ids": [ "string" ] }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_sessions( session_ids=["session_ids"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSessions({ sessionIds: ["session_ids"] }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSessions( context.TODO(), &v2.EndSessionsRequest{ SessionIDs: []string{ "session_ids", }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_ids": [ "string" ] }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_sessions( session_ids=["session_ids"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSessions({ sessionIds: ["session_ids"] }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSessions( context.TODO(), &v2.EndSessionsRequest{ SessionIDs: []string{ "session_ids", }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "session_ids": [ "string" ] }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_sessions( session_ids=["session_ids"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSessions({ sessionIds: ["session_ids"] }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSessions( context.TODO(), &v2.EndSessionsRequest{ SessionIDs: []string{ "session_ids", }, }, ) ``` # Search sessions for the specified query. ```http POST https://api.getzep.com/api/v2/sessions/search Content-Type: application/json ``` Search sessions for the specified query. ## Query Parameters - Limit (optional): The maximum number of search results to return. Defaults to None (no limit). ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"min_fact_rating","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}},"description":"The minimum fact rating to filter on. Only supported on cloud. Will be ignored on Community Edition."},{"key":"min_score","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}},"description":"The minimum score for search results. Only supported on cloud. Will be ignored on Community Edition."},{"key":"mmr_lambda","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}},"description":"The lambda parameter for the MMR Reranking Algorithm. Only supported on cloud. Will be ignored on Community Edition."},{"key":"record_filter","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}},"description":"Record filter on the metadata. Only supported on cloud. Will be ignored on Community Edition."},{"key":"search_scope","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:SearchScope"}}}},"description":"Search scope. Only supported on cloud. On Community Edition the search scope is always \"facts\"."},{"key":"search_type","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:SearchType"}}}},"description":"Search type. Only supported on cloud. Will be ignored on Community Edition."},{"key":"session_ids","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}},"description":"the session ids to search"},{"key":"text","valueShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"description":"The search text."},{"key":"user_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"User ID used to determine which sessions to search. Required on Community Edition."}]} ``` ## Response Body - 200: A SessionSearchResponse object representing the search results. - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/search \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "text": "text" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.search_sessions( text="text", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.searchSessions({ text: "text" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.SearchSessions( context.TODO(), &v2.SessionSearchQuery{ Text: "text", }, ) ``` ```shell curl -X POST "https://api.getzep.com/api/v2/sessions/search?limit=0" \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "text": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.search_sessions( text="text", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.searchSessions({ text: "text" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.SearchSessions( context.TODO(), &v2.SessionSearchQuery{ Text: "text", }, ) ``` # Returns a session by ID ```http GET https://api.getzep.com/api/v2/sessions/{sessionId} ``` get session by id ## Path Parameters - SessionId (required): Session ID ## Response Body - 200: The session with the specified ID. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSession( context.TODO(), "sessionId", ) ``` ```shell curl https://api.getzep.com/api/v2/sessions/:sessionId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSession( context.TODO(), "sessionId", ) ``` ```shell curl https://api.getzep.com/api/v2/sessions/:sessionId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSession( context.TODO(), "sessionId", ) ``` # Update a session ```http PATCH https://api.getzep.com/api/v2/sessions/{sessionId} Content-Type: application/json ``` Update Session Metadata ## Path Parameters - SessionId (required): Session ID ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"fact_rating_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:FactRatingInstruction"}}}},"description":"Optional instruction to use for fact rating.\nFact rating instructions can not be unset."},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}},"description":"The metadata to update"}]} ``` ## Response Body - 200: The updated session. - 400: Bad Request - 404: Not Found - 409: Conflict - 500: Internal Server Error ## Examples ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/sessionId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "metadata": { "key": "value" } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_session( session_id="sessionId", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateSession("sessionId", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateSession( context.TODO(), "sessionId", &v2.UpdateSessionRequest{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/:sessionId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "metadata": { "string": {} } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_session( session_id="sessionId", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateSession("sessionId", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateSession( context.TODO(), "sessionId", &v2.UpdateSessionRequest{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/:sessionId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "metadata": { "string": {} } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_session( session_id="sessionId", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateSession("sessionId", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateSession( context.TODO(), "sessionId", &v2.UpdateSessionRequest{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/:sessionId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "metadata": { "string": {} } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_session( session_id="sessionId", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateSession("sessionId", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateSession( context.TODO(), "sessionId", &v2.UpdateSessionRequest{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/:sessionId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "metadata": { "string": {} } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_session( session_id="sessionId", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateSession("sessionId", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateSession( context.TODO(), "sessionId", &v2.UpdateSessionRequest{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` # Classify a session (cloud only) ```http POST https://api.getzep.com/api/v2/sessions/{sessionId}/classify Content-Type: application/json ``` classify a session by session id. ## Path Parameters - SessionId (required): Session ID ## Request Body ```json {"type":"alias","value":{"type":"id","id":"type_:ClassifySessionRequest"}} ``` ## Response Body - 200: A response object containing the name and classification result. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/sessionId/classify \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "classes": [ "classes" ], "name": "name" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.classify_session( session_id="sessionId", classes=["classes"], name="name", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.classifySession("sessionId", { classes: ["classes"], name: "name" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.ClassifySession( context.TODO(), "sessionId", &v2.ClassifySessionRequest{ Classes: []string{ "classes", }, Name: "name", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/classify \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "classes": [ "string" ], "name": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.classify_session( session_id="sessionId", classes=["classes"], name="name", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.classifySession("sessionId", { classes: ["classes"], name: "name" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.ClassifySession( context.TODO(), "sessionId", &v2.ClassifySessionRequest{ Classes: []string{ "classes", }, Name: "name", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/classify \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "classes": [ "string" ], "name": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.classify_session( session_id="sessionId", classes=["classes"], name="name", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.classifySession("sessionId", { classes: ["classes"], name: "name" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.ClassifySession( context.TODO(), "sessionId", &v2.ClassifySessionRequest{ Classes: []string{ "classes", }, Name: "name", }, ) ``` # End a session (cloud only) ```http POST https://api.getzep.com/api/v2/sessions/{sessionId}/end Content-Type: application/json ``` End a session by ID. ## Path Parameters - SessionId (required): Session ID ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"classify","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:ClassifySessionRequest"}}}}},{"key":"instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}]} ``` ## Response Body - 200: OK - 400: Bad Request - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/sessionId/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSession( context.TODO(), "sessionId", &v2.EndSessionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSession( context.TODO(), "sessionId", &v2.EndSessionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSession( context.TODO(), "sessionId", &v2.EndSessionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/end \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.end_session( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.endSession("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.EndSession( context.TODO(), "sessionId", &v2.EndSessionRequest{}, ) ``` # Returns all facts for a session by ID (cloud only) ```http GET https://api.getzep.com/api/v2/sessions/{sessionId}/facts ``` get facts for a session ## Path Parameters - SessionId (required): Session ID ## Query Parameters - MinRating (optional): Minimum rating by which to filter facts (Zep Cloud only) ## Response Body - 200: The facts for the session. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_facts( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionFacts("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionFacts( context.TODO(), "sessionId", &v2.MemoryGetSessionFactsRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/facts \ -H "Authorization: Api-Key " \ -d minRating=1 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_facts( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionFacts("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionFacts( context.TODO(), "sessionId", &v2.MemoryGetSessionFactsRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/facts \ -H "Authorization: Api-Key " \ -d minRating=1 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_facts( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionFacts("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionFacts( context.TODO(), "sessionId", &v2.MemoryGetSessionFactsRequest{}, ) ``` # Adds facts to a session (cloud only) ```http POST https://api.getzep.com/api/v2/sessions/{sessionId}/facts Content-Type: application/json ``` Adds facts to a session ## Path Parameters - SessionId (required): Session ID ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"facts","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"id","id":"type_:NewFact"}}}}}}}]} ``` ## Response Body - 200: OK - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/sessionId/facts \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add_session_facts( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.addSessionFacts("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.AddSessionFacts( context.TODO(), "sessionId", &v2.AddFactsRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/facts \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add_session_facts( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.addSessionFacts("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.AddSessionFacts( context.TODO(), "sessionId", &v2.AddFactsRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/facts \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add_session_facts( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.addSessionFacts("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.AddSessionFacts( context.TODO(), "sessionId", &v2.AddFactsRequest{}, ) ``` # Get session memory ```http GET https://api.getzep.com/api/v2/sessions/{sessionId}/memory ``` Returns a memory (latest summary, list of messages and facts) for a given session ## Path Parameters - SessionId (required): The ID of the session for which to retrieve memory. ## Query Parameters - Lastn (optional): The number of most recent memory entries to retrieve. - MinRating (optional): The minimum rating by which to filter facts ## Response Body - 200: OK - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId/memory \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.get("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Get( context.TODO(), "sessionId", &v2.MemoryGetRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/memory \ -H "Authorization: Api-Key " \ -d lastn=0 \ -d minRating=1 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.get("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Get( context.TODO(), "sessionId", &v2.MemoryGetRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/memory \ -H "Authorization: Api-Key " \ -d lastn=0 \ -d minRating=1 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.get("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Get( context.TODO(), "sessionId", &v2.MemoryGetRequest{}, ) ``` # Add memory to the specified session. ```http POST https://api.getzep.com/api/v2/sessions/{sessionId}/memory Content-Type: application/json ``` Add memory to the specified session. ## Path Parameters - SessionId (required): The ID of the session to which memory should be added. ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"fact_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"Additional instruction for generating the facts. Zep Cloud Only, will be ignored on Community Edition."},{"key":"messages","valueShape":{"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"id","id":"type_:Message"}}}},"description":"A list of message objects, where each message contains a role and content."},{"key":"return_context","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"boolean"}}}}},"description":"Optionally return memory context relevant to the most recent messages."},{"key":"summary_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"Additional instruction for generating the summary. Zep Cloud Only, will be ignored on Community Edition."}]} ``` ## Response Body - 200: An object, optionally containing memory context retrieved for the last message - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/sessionId/memory \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "content": "content", "role_type": "norole" } ] }' ``` ```python from zep_cloud import Message from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add( session_id="sessionId", messages=[ Message( content="content", role_type="norole", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.add("sessionId", { messages: [{ content: "content", roleType: "norole" }] }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Add( context.TODO(), "sessionId", &v2.AddMemoryRequest{ Messages: []*v2.Message{ &v2.Message{ Content: "content", RoleType: v2.RoleTypeNoRole, }, }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/sessions/:sessionId/memory \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "content": "string", "role_type": "norole" } ] }' ``` ```python from zep_cloud import Message from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.add( session_id="sessionId", messages=[ Message( content="content", role_type="norole", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.add("sessionId", { messages: [{ content: "content", roleType: "norole" }] }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Add( context.TODO(), "sessionId", &v2.AddMemoryRequest{ Messages: []*v2.Message{ &v2.Message{ Content: "content", RoleType: v2.RoleTypeNoRole, }, }, }, ) ``` # Delete memory messages for a given session ```http DELETE https://api.getzep.com/api/v2/sessions/{sessionId}/memory ``` delete memory messages by session id ## Path Parameters - SessionId (required): The ID of the session for which memory should be deleted. ## Response Body - 200: OK - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/sessions/sessionId/memory \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.delete( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.delete("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Delete( context.TODO(), "sessionId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/sessions/:sessionId/memory \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.delete( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.delete("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Delete( context.TODO(), "sessionId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/sessions/:sessionId/memory \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.delete( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.delete("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Delete( context.TODO(), "sessionId", ) ``` # Lists messages for a session ```http GET https://api.getzep.com/api/v2/sessions/{sessionId}/messages ``` Lists messages for a session, specified by limit and cursor. ## Path Parameters - SessionId (required): Session ID ## Query Parameters - Limit (optional): Limit the number of results returned - Cursor (optional): Cursor for pagination ## Response Body - 200: OK - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId/messages ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_messages( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionMessages("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionMessages( context.TODO(), "sessionId", &v2.MemoryGetSessionMessagesRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/messages \ -d limit=0 \ -d cursor=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_messages( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionMessages("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionMessages( context.TODO(), "sessionId", &v2.MemoryGetSessionMessagesRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/messages \ -d limit=0 \ -d cursor=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_messages( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionMessages("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionMessages( context.TODO(), "sessionId", &v2.MemoryGetSessionMessagesRequest{}, ) ``` # Gets a specific message from a session ```http GET https://api.getzep.com/api/v2/sessions/{sessionId}/messages/{messageUUID} ``` Gets a specific message from a session ## Path Parameters - SessionId (required): The ID of the session. - MessageUuid (required): The UUID of the message. ## Response Body - 200: The message. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId/messages/messageUUID ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_message( session_id="sessionId", message_uuid="messageUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionMessage("sessionId", "messageUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionMessage( context.TODO(), "sessionId", "messageUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/sessions/:sessionId/messages/:messageUUID ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_message( session_id="sessionId", message_uuid="messageUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionMessage("sessionId", "messageUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionMessage( context.TODO(), "sessionId", "messageUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/sessions/:sessionId/messages/:messageUUID ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_session_message( session_id="sessionId", message_uuid="messageUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSessionMessage("sessionId", "messageUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSessionMessage( context.TODO(), "sessionId", "messageUUID", ) ``` # Updates the metadata of a message. ```http PATCH https://api.getzep.com/api/v2/sessions/{sessionId}/messages/{messageUUID} Content-Type: application/json ``` Updates the metadata of a message. ## Path Parameters - SessionId (required): The ID of the session. - MessageUuid (required): The UUID of the message. ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"metadata","valueShape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}},"description":"The metadata to update"}]} ``` ## Response Body - 200: The updated message. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/sessionId/messages/messageUUID \ -H "Content-Type: application/json" \ -d '{ "metadata": { "key": "value" } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_message_metadata( session_id="sessionId", message_uuid="messageUUID", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateMessageMetadata("sessionId", "messageUUID", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateMessageMetadata( context.TODO(), "sessionId", "messageUUID", &v2.ModelsMessageMetadataUpdate{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/:sessionId/messages/:messageUUID \ -H "Content-Type: application/json" \ -d '{ "metadata": { "string": {} } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_message_metadata( session_id="sessionId", message_uuid="messageUUID", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateMessageMetadata("sessionId", "messageUUID", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateMessageMetadata( context.TODO(), "sessionId", "messageUUID", &v2.ModelsMessageMetadataUpdate{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/sessions/:sessionId/messages/:messageUUID \ -H "Content-Type: application/json" \ -d '{ "metadata": { "string": {} } }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.update_message_metadata( session_id="sessionId", message_uuid="messageUUID", metadata={"key": "value"}, ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.updateMessageMetadata("sessionId", "messageUUID", { metadata: { "key": "value" } }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.UpdateMessageMetadata( context.TODO(), "sessionId", "messageUUID", &v2.ModelsMessageMetadataUpdate{ Metadata: map[string]interface{}{ "key": "value", }, }, ) ``` # Search memory for the specified session (cloud only) ```http POST https://api.getzep.com/api/v2/sessions/{sessionId}/search Content-Type: application/json ``` Search memory for the specified session. Deprecated, please use search_sessions method instead ## Path Parameters - SessionId (required): The ID of the session for which memory should be searched. ## Query Parameters - Limit (optional): The maximum number of search results to return. Defaults to None (no limit). ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}},"description":"Metadata Filter"},{"key":"min_fact_rating","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}}},{"key":"min_score","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}}},{"key":"mmr_lambda","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}}},{"key":"search_scope","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:SearchScope"}}}}},{"key":"search_type","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:SearchType"}}}}},{"key":"text","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}]} ``` ## Response Body - 200: A list of SearchResult objects representing the search results. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/sessions/sessionId/search \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.search( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.search("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Search( context.TODO(), "sessionId", &v2.MemorySearchPayload{}, ) ``` ```shell curl -X POST "https://api.getzep.com/api/v2/sessions/:sessionId/search?limit=0" \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.search( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.search("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Search( context.TODO(), "sessionId", &v2.MemorySearchPayload{}, ) ``` ```shell curl -X POST "https://api.getzep.com/api/v2/sessions/:sessionId/search?limit=0" \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.search( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.search("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.Search( context.TODO(), "sessionId", &v2.MemorySearchPayload{}, ) ``` # Returns a session's summaries by ID (cloud only) ```http GET https://api.getzep.com/api/v2/sessions/{sessionId}/summary ``` Get session summaries by ID ## Path Parameters - SessionId (required): Session ID ## Response Body - 200: OK - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId/summary \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_summaries( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSummaries("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSummaries( context.TODO(), "sessionId", ) ``` ```shell curl https://api.getzep.com/api/v2/sessions/:sessionId/summary \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_summaries( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSummaries("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSummaries( context.TODO(), "sessionId", ) ``` ```shell curl https://api.getzep.com/api/v2/sessions/:sessionId/summary \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.get_summaries( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.getSummaries("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.GetSummaries( context.TODO(), "sessionId", ) ``` # Synthesize a question (cloud only) ```http GET https://api.getzep.com/api/v2/sessions/{sessionId}/synthesize_question ``` Synthesize a question from the last N messages in the chat history. ## Path Parameters - SessionId (required): The ID of the session. ## Query Parameters - LastNMessages (optional): The number of messages to use for question synthesis. ## Response Body - 200: The synthesized question. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/sessions/sessionId/synthesize_question \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.synthesize_question( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.synthesizeQuestion("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.SynthesizeQuestion( context.TODO(), "sessionId", &v2.MemorySynthesizeQuestionRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/synthesize_question \ -H "Authorization: Api-Key " \ -d lastNMessages=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.synthesize_question( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.synthesizeQuestion("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.SynthesizeQuestion( context.TODO(), "sessionId", &v2.MemorySynthesizeQuestionRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/sessions/:sessionId/synthesize_question \ -H "Authorization: Api-Key " \ -d lastNMessages=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.memory.synthesize_question( session_id="sessionId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.memory.synthesizeQuestion("sessionId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Memory.SynthesizeQuestion( context.TODO(), "sessionId", &v2.MemorySynthesizeQuestionRequest{}, ) ``` # Add a user. ```http POST https://api.getzep.com/api/v2/users Content-Type: application/json ``` Add a user. ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"email","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The email address of the user."},{"key":"fact_rating_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:FactRatingInstruction"}}}},"description":"Optional instruction to use for fact rating."},{"key":"first_name","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The first name of the user."},{"key":"last_name","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The last name of the user."},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}},"description":"The metadata associated with the user."},{"key":"user_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The unique identifier of the user."}]} ``` ## Response Body - 200: The user that was added. - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/users \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.add() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.add(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Add( context.TODO(), &v2.CreateUserRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/users \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.add() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.add(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Add( context.TODO(), &v2.CreateUserRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/users \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.add() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.add(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Add( context.TODO(), &v2.CreateUserRequest{}, ) ``` # List all users ```http GET https://api.getzep.com/api/v2/users-ordered ``` List all users with pagination. ## Query Parameters - PageNumber (optional): Page number for pagination, starting from 1 - PageSize (optional): Number of users to retrieve per page ## Response Body - 200: Successfully retrieved list of users - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/users-ordered \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.list_ordered() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.listOrdered(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.ListOrdered( context.TODO(), &v2.UserListOrderedRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/users-ordered \ -H "Authorization: Api-Key " \ -d pageNumber=0 \ -d pageSize=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.list_ordered() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.listOrdered(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.ListOrdered( context.TODO(), &v2.UserListOrderedRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/users-ordered \ -H "Authorization: Api-Key " \ -d pageNumber=0 \ -d pageSize=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.list_ordered() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.listOrdered(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.ListOrdered( context.TODO(), &v2.UserListOrderedRequest{}, ) ``` # Get a user. ```http GET https://api.getzep.com/api/v2/users/{userId} ``` Get a user. ## Path Parameters - UserId (required): The user_id of the user to get. ## Response Body - 200: The user that was retrieved. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/users/userId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.get("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Get( context.TODO(), "userId", ) ``` ```shell curl https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.get("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Get( context.TODO(), "userId", ) ``` ```shell curl https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.get("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Get( context.TODO(), "userId", ) ``` # Delete a user ```http DELETE https://api.getzep.com/api/v2/users/{userId} ``` delete user by id ## Path Parameters - UserId (required): User ID ## Response Body - 200: OK - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/users/userId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.delete( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.delete("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Delete( context.TODO(), "userId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.delete( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.delete("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Delete( context.TODO(), "userId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.delete( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.delete("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Delete( context.TODO(), "userId", ) ``` # Update a user. ```http PATCH https://api.getzep.com/api/v2/users/{userId} Content-Type: application/json ``` Update a user. ## Path Parameters - UserId (required): User ID ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"email","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The email address of the user."},{"key":"fact_rating_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:FactRatingInstruction"}}}},"description":"Optional instruction to use for fact rating."},{"key":"first_name","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The first name of the user."},{"key":"last_name","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The last name of the user."},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}},"description":"The metadata to update"}]} ``` ## Response Body - 200: The user that was updated. - 400: Bad Request - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X PATCH https://api.getzep.com/api/v2/users/userId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.update( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.update("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Update( context.TODO(), "userId", &v2.UpdateUserRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.update( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.update("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Update( context.TODO(), "userId", &v2.UpdateUserRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.update( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.update("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Update( context.TODO(), "userId", &v2.UpdateUserRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/users/:userId \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.update( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.update("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.Update( context.TODO(), "userId", &v2.UpdateUserRequest{}, ) ``` # Get user facts. ```http GET https://api.getzep.com/api/v2/users/{userId}/facts ``` Get user facts. ## Path Parameters - UserId (required): The user_id of the user to get. ## Response Body - 200: The user facts. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/users/userId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get_facts( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.getFacts("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.GetFacts( context.TODO(), "userId", ) ``` ```shell curl https://api.getzep.com/api/v2/users/:userId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get_facts( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.getFacts("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.GetFacts( context.TODO(), "userId", ) ``` ```shell curl https://api.getzep.com/api/v2/users/:userId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get_facts( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.getFacts("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.GetFacts( context.TODO(), "userId", ) ``` # List all sessions for a user ```http GET https://api.getzep.com/api/v2/users/{userId}/sessions ``` list all sessions for a user by user id ## Path Parameters - UserId (required): User ID ## Response Body - 200: OK - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/users/userId/sessions \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get_sessions( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.getSessions("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.GetSessions( context.TODO(), "userId", ) ``` ```shell curl https://api.getzep.com/api/v2/users/:userId/sessions \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.user.get_sessions( user_id="userId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.user.getSessions("userId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.User.GetSessions( context.TODO(), "userId", ) ``` # Gets a list of DocumentCollections (cloud only) ```http GET https://api.getzep.com/api/v2/collections ``` Returns a list of all DocumentCollections. ## Response Body - 200: OK - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/collections \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.list_collections() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.listCollections(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.ListCollections( context.TODO(), ) ``` ```shell curl https://api.getzep.com/api/v2/collections \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.list_collections() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.listCollections(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.ListCollections( context.TODO(), ) ``` ```shell curl https://api.getzep.com/api/v2/collections \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.list_collections() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.listCollections(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.ListCollections( context.TODO(), ) ``` # Gets a DocumentCollection (cloud only) ```http GET https://api.getzep.com/api/v2/collections/{collectionName} ``` Returns a DocumentCollection if it exists. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/collections/collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.get_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetCollection( context.TODO(), "collectionName", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.get_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetCollection( context.TODO(), "collectionName", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.get_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetCollection( context.TODO(), "collectionName", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.get_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetCollection( context.TODO(), "collectionName", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.get_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetCollection( context.TODO(), "collectionName", ) ``` # Creates a new DocumentCollection ```http POST https://api.getzep.com/api/v2/collections/{collectionName} Content-Type: application/json ``` If a collection with the same name already exists, an error will be returned. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"description","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string","maxLength":1000}}}}}},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}}}]} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/collections/collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddCollection( context.TODO(), "collectionName", &v2.CreateDocumentCollectionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddCollection( context.TODO(), "collectionName", &v2.CreateDocumentCollectionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddCollection( context.TODO(), "collectionName", &v2.CreateDocumentCollectionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddCollection( context.TODO(), "collectionName", &v2.CreateDocumentCollectionRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddCollection( context.TODO(), "collectionName", &v2.CreateDocumentCollectionRequest{}, ) ``` # Deletes a DocumentCollection ```http DELETE https://api.getzep.com/api/v2/collections/{collectionName} ``` If a collection with the same name already exists, it will be overwritten. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteCollection( context.TODO(), "collectionName", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteCollection( context.TODO(), "collectionName", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteCollection( context.TODO(), "collectionName", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteCollection( context.TODO(), "collectionName", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteCollection( context.TODO(), "collectionName", ) ``` # Updates a DocumentCollection ```http PATCH https://api.getzep.com/api/v2/collections/{collectionName} Content-Type: application/json ``` Updates a DocumentCollection ## Path Parameters - CollectionName (required): Name of the Document Collection ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"description","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string","maxLength":1000}}}}}},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}}}]} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.update_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updateCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdateCollection( context.TODO(), "collectionName", &v2.UpdateDocumentCollectionRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.update_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updateCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdateCollection( context.TODO(), "collectionName", &v2.UpdateDocumentCollectionRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.update_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updateCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdateCollection( context.TODO(), "collectionName", &v2.UpdateDocumentCollectionRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.update_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updateCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdateCollection( context.TODO(), "collectionName", &v2.UpdateDocumentCollectionRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.update_collection( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updateCollection("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdateCollection( context.TODO(), "collectionName", &v2.UpdateDocumentCollectionRequest{}, ) ``` # Creates Multiple Documents in a DocumentCollection (cloud only) ```http POST https://api.getzep.com/api/v2/collections/{collectionName}/documents Content-Type: application/json ``` Creates Documents in a specified DocumentCollection and returns their UUIDs. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Request Body ```json {"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"id","id":"type_:CreateDocumentRequest"}}}} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/collections/collectionName/documents \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "content": "content" } ]' ``` ```python from zep_cloud import CreateDocumentRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_documents( collection_name="collectionName", request=[ CreateDocumentRequest( content="content", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addDocuments("collectionName", [{ content: "content" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddDocuments( context.TODO(), "collectionName", []*v2.CreateDocumentRequest{ &v2.CreateDocumentRequest{ Content: "content", }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "content": "string" } ]' ``` ```python from zep_cloud import CreateDocumentRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_documents( collection_name="collectionName", request=[ CreateDocumentRequest( content="content", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addDocuments("collectionName", [{ content: "content" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddDocuments( context.TODO(), "collectionName", []*v2.CreateDocumentRequest{ &v2.CreateDocumentRequest{ Content: "content", }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "content": "string" } ]' ``` ```python from zep_cloud import CreateDocumentRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_documents( collection_name="collectionName", request=[ CreateDocumentRequest( content="content", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addDocuments("collectionName", [{ content: "content" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddDocuments( context.TODO(), "collectionName", []*v2.CreateDocumentRequest{ &v2.CreateDocumentRequest{ Content: "content", }, }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "content": "string" } ]' ``` ```python from zep_cloud import CreateDocumentRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.add_documents( collection_name="collectionName", request=[ CreateDocumentRequest( content="content", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.addDocuments("collectionName", [{ content: "content" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.AddDocuments( context.TODO(), "collectionName", []*v2.CreateDocumentRequest{ &v2.CreateDocumentRequest{ Content: "content", }, }, ) ``` # Batch Deletes Documents from a DocumentCollection by UUID (cloud only) ```http POST https://api.getzep.com/api/v2/collections/{collectionName}/documents/batchDelete Content-Type: application/json ``` Deletes specified Documents from a DocumentCollection. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Request Body ```json {"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/collections/collectionName/documents/batchDelete \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ "string" ]' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_delete_documents( collection_name="collectionName", request=["string"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchDeleteDocuments("collectionName", ["string"]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchDeleteDocuments( context.TODO(), "collectionName", []string{ "string", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents/batchDelete \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ "string" ]' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_delete_documents( collection_name="collectionName", request=["string"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchDeleteDocuments("collectionName", ["string"]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchDeleteDocuments( context.TODO(), "collectionName", []string{ "string", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents/batchDelete \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ "string" ]' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_delete_documents( collection_name="collectionName", request=["string"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchDeleteDocuments("collectionName", ["string"]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchDeleteDocuments( context.TODO(), "collectionName", []string{ "string", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents/batchDelete \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ "string" ]' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_delete_documents( collection_name="collectionName", request=["string"], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchDeleteDocuments("collectionName", ["string"]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchDeleteDocuments( context.TODO(), "collectionName", []string{ "string", }, ) ``` # Batch Gets Documents from a DocumentCollection (cloud only) ```http POST https://api.getzep.com/api/v2/collections/{collectionName}/documents/batchGet Content-Type: application/json ``` Returns Documents from a DocumentCollection specified by UUID or ID. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"document_ids","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}}},{"key":"uuids","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}}}]} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/collections/collectionName/documents/batchGet \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_get_documents( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchGetDocuments("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchGetDocuments( context.TODO(), "collectionName", &v2.GetDocumentListRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents/batchGet \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_get_documents( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchGetDocuments("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchGetDocuments( context.TODO(), "collectionName", &v2.GetDocumentListRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents/batchGet \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_get_documents( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchGetDocuments("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchGetDocuments( context.TODO(), "collectionName", &v2.GetDocumentListRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/collections/:collectionName/documents/batchGet \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_get_documents( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchGetDocuments("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchGetDocuments( context.TODO(), "collectionName", &v2.GetDocumentListRequest{}, ) ``` # Batch Updates Documents in a DocumentCollection (cloud only) ```http PATCH https://api.getzep.com/api/v2/collections/{collectionName}/documents/batchUpdate Content-Type: application/json ``` Updates Documents in a specified DocumentCollection. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Request Body ```json {"type":"alias","value":{"type":"list","itemShape":{"type":"alias","value":{"type":"id","id":"type_:UpdateDocumentListRequest"}}}} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/collectionName/documents/batchUpdate \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "uuid": "uuid" } ]' ``` ```python from zep_cloud import UpdateDocumentListRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_update_documents( collection_name="collectionName", request=[ UpdateDocumentListRequest( uuid_="uuid", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchUpdateDocuments("collectionName", [{ uuid: "uuid" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchUpdateDocuments( context.TODO(), "collectionName", []*v2.UpdateDocumentListRequest{ &v2.UpdateDocumentListRequest{ UUID: "uuid", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/batchUpdate \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "uuid": "string" } ]' ``` ```python from zep_cloud import UpdateDocumentListRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_update_documents( collection_name="collectionName", request=[ UpdateDocumentListRequest( uuid_="uuid", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchUpdateDocuments("collectionName", [{ uuid: "uuid" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchUpdateDocuments( context.TODO(), "collectionName", []*v2.UpdateDocumentListRequest{ &v2.UpdateDocumentListRequest{ UUID: "uuid", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/batchUpdate \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "uuid": "string" } ]' ``` ```python from zep_cloud import UpdateDocumentListRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_update_documents( collection_name="collectionName", request=[ UpdateDocumentListRequest( uuid_="uuid", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchUpdateDocuments("collectionName", [{ uuid: "uuid" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchUpdateDocuments( context.TODO(), "collectionName", []*v2.UpdateDocumentListRequest{ &v2.UpdateDocumentListRequest{ UUID: "uuid", }, }, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/batchUpdate \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '[ { "uuid": "string" } ]' ``` ```python from zep_cloud import UpdateDocumentListRequest from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.batch_update_documents( collection_name="collectionName", request=[ UpdateDocumentListRequest( uuid_="uuid", ) ], ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.batchUpdateDocuments("collectionName", [{ uuid: "uuid" }]); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.BatchUpdateDocuments( context.TODO(), "collectionName", []*v2.UpdateDocumentListRequest{ &v2.UpdateDocumentListRequest{ UUID: "uuid", }, }, ) ``` # Gets a Document from a DocumentCollection by UUID (cloud only) ```http GET https://api.getzep.com/api/v2/collections/{collectionName}/documents/uuid/{documentUUID} ``` Returns specified Document from a DocumentCollection. ## Path Parameters - CollectionName (required): Name of the Document Collection - DocumentUuid (required): UUID of the Document to be updated ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/collections/collectionName/documents/uuid/documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.gets_a_document_from_a_document_collection_by_uuid_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getsADocumentFromADocumentCollectionByUuidCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetsADocumentFromADocumentCollectionByUUIDCloudOnly( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.gets_a_document_from_a_document_collection_by_uuid_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getsADocumentFromADocumentCollectionByUuidCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetsADocumentFromADocumentCollectionByUUIDCloudOnly( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.gets_a_document_from_a_document_collection_by_uuid_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getsADocumentFromADocumentCollectionByUuidCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetsADocumentFromADocumentCollectionByUUIDCloudOnly( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.gets_a_document_from_a_document_collection_by_uuid_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.getsADocumentFromADocumentCollectionByUuidCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.GetsADocumentFromADocumentCollectionByUUIDCloudOnly( context.TODO(), "collectionName", "documentUUID", ) ``` # Delete Document from a DocumentCollection by UUID (cloud only) ```http DELETE https://api.getzep.com/api/v2/collections/{collectionName}/documents/uuid/{documentUUID} ``` Delete specified Document from a DocumentCollection. ## Path Parameters - CollectionName (required): Name of the Document Collection - DocumentUuid (required): UUID of the Document to be deleted ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 404: Document Not Found - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/collectionName/documents/uuid/documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_document( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteDocument("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteDocument( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_document( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteDocument("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteDocument( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_document( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteDocument("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteDocument( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_document( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteDocument("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteDocument( context.TODO(), "collectionName", "documentUUID", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.delete_document( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.deleteDocument("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.DeleteDocument( context.TODO(), "collectionName", "documentUUID", ) ``` # Updates a Document (cloud only) ```http PATCH https://api.getzep.com/api/v2/collections/{collectionName}/documents/uuid/{documentUUID} Content-Type: application/json ``` Updates a Document in a DocumentCollection by UUID ## Path Parameters - CollectionName (required): Name of the Document Collection - DocumentUuid (required): UUID of the Document to be updated ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"document_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string","maxLength":40}}}}}},{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}}}]} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/collectionName/documents/uuid/documentUUID \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.updates_a_document_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updatesADocumentCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdatesADocumentCloudOnly( context.TODO(), "collectionName", "documentUUID", &v2.UpdateDocumentRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.updates_a_document_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updatesADocumentCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdatesADocumentCloudOnly( context.TODO(), "collectionName", "documentUUID", &v2.UpdateDocumentRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.updates_a_document_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updatesADocumentCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdatesADocumentCloudOnly( context.TODO(), "collectionName", "documentUUID", &v2.UpdateDocumentRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.updates_a_document_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updatesADocumentCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdatesADocumentCloudOnly( context.TODO(), "collectionName", "documentUUID", &v2.UpdateDocumentRequest{}, ) ``` ```shell curl -X PATCH https://api.getzep.com/api/v2/collections/:collectionName/documents/uuid/:documentUUID \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.updates_a_document_cloud_only( collection_name="collectionName", document_uuid="documentUUID", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.updatesADocumentCloudOnly("collectionName", "documentUUID"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.UpdatesADocumentCloudOnly( context.TODO(), "collectionName", "documentUUID", &v2.UpdateDocumentRequest{}, ) ``` # Searches Documents in a DocumentCollection (cloud only) ```http POST https://api.getzep.com/api/v2/collections/{collectionName}/search Content-Type: application/json ``` Searches over documents in a collection based on provided search criteria. One of text or metadata must be provided. Returns an empty list if no documents are found. ## Path Parameters - CollectionName (required): Name of the Document Collection ## Query Parameters - Limit (optional): Limit the number of returned documents ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"metadata","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"map","keyShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"valueShape":{"type":"alias","value":{"type":"unknown"}}}}}},"description":"Document metadata to filter on."},{"key":"min_score","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}}},{"key":"mmr_lambda","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}},"description":"The lambda parameter for the MMR Reranking Algorithm."},{"key":"search_type","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:SearchType"}}}},"description":"The type of search to perform. Defaults to \"similarity\". Must be one of \"similarity\" or \"mmr\"."},{"key":"text","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"The search text."}]} ``` ## Response Body - 200: OK - 400: Bad Request - 401: Unauthorized - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/collections/collectionName/search \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.search( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.search("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.Search( context.TODO(), "collectionName", &v2.DocumentSearchPayload{}, ) ``` ```shell curl -X POST "https://api.getzep.com/api/v2/collections/:collectionName/search?limit=0" \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.search( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.search("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.Search( context.TODO(), "collectionName", &v2.DocumentSearchPayload{}, ) ``` ```shell curl -X POST "https://api.getzep.com/api/v2/collections/:collectionName/search?limit=0" \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.search( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.search("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.Search( context.TODO(), "collectionName", &v2.DocumentSearchPayload{}, ) ``` ```shell curl -X POST "https://api.getzep.com/api/v2/collections/:collectionName/search?limit=0" \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.document.search( collection_name="collectionName", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.document.search("collectionName"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Document.Search( context.TODO(), "collectionName", &v2.DocumentSearchPayload{}, ) ``` # Add Data ```http POST https://api.getzep.com/api/v2/graph Content-Type: application/json ``` Add data to the graph ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"data","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}},{"key":"group_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}},{"key":"type","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:GraphDataType"}}}}},{"key":"user_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}]} ``` ## Response Body - 200: Data added - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/graph \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.add() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.add(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Add( context.TODO(), &v2.AddDataRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/graph \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.add() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.add(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Add( context.TODO(), &v2.AddDataRequest{}, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/graph \ -H "Content-Type: application/json" \ -d '{}' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.add() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.add(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Add( context.TODO(), &v2.AddDataRequest{}, ) ``` # Search Graph ```http POST https://api.getzep.com/api/v2/graph/search Content-Type: application/json ``` Perform a graph search query. ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"center_node_uuid","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"Node to rerank around for node distance reranking"},{"key":"group_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"one of user_id or group_id must be provided"},{"key":"limit","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"integer"}}}}},"description":"The maximum number of facts to retrieve. Defaults to 10. Limited to 50."},{"key":"min_score","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}},"description":"minimum similarity score for a result to be returned"},{"key":"mmr_lambda","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"double"}}}}},"description":"weighting for maximal marginal relevance"},{"key":"query","valueShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}},"description":"The string to search for (required)"},{"key":"reranker","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:Reranker"}}}},"description":"Defaults to RRF"},{"key":"scope","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:GraphSearchScope"}}}},"description":"Defaults to Edges. Communities will be added in the future."},{"key":"user_id","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}},"description":"one of user_id or group_id must be provided"}]} ``` ## Response Body - 200: Graph search results - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/graph/search \ -H "Content-Type: application/json" \ -d '{ "query": "query" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.search( query="query", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.search({ query: "query" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Search( context.TODO(), &v2.GraphSearchQuery{ Query: "query", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/graph/search \ -H "Content-Type: application/json" \ -d '{ "query": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.search( query="query", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.search({ query: "query" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Search( context.TODO(), &v2.GraphSearchQuery{ Query: "query", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/graph/search \ -H "Content-Type: application/json" \ -d '{ "query": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.search( query="query", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.search({ query: "query" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Search( context.TODO(), &v2.GraphSearchQuery{ Query: "query", }, ) ``` # Get Group Edges ```http GET https://api.getzep.com/api/v2/graph/edge/group/{group_id} ``` Get all edges for a group ## Path Parameters - GroupId (required): Group ID ## Response Body - 200: Edges - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/edge/group/group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.getByGroupId("group_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.GetByGroupID( context.TODO(), "group_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/group/:group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.getByGroupId("group_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.GetByGroupID( context.TODO(), "group_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/group/:group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.getByGroupId("group_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.GetByGroupID( context.TODO(), "group_id", ) ``` # Get User Edges ```http GET https://api.getzep.com/api/v2/graph/edge/user/{user_id} ``` Get all edges for a user ## Path Parameters - UserId (required): User ID ## Response Body - 200: Edges - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/edge/user/user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.getByUserId("user_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.GetByUserID( context.TODO(), "user_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/user/:user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.getByUserId("user_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.GetByUserID( context.TODO(), "user_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/user/:user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.getByUserId("user_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.GetByUserID( context.TODO(), "user_id", ) ``` # Get Edge ```http GET https://api.getzep.com/api/v2/graph/edge/{uuid} ``` Get a specific edge by its UUID ## Path Parameters - Uuid (required): Edge UUID ## Response Body - 200: Edge - 400: Bad Request - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/edge/uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/edge/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Get( context.TODO(), "uuid", ) ``` # Delete Edge ```http DELETE https://api.getzep.com/api/v2/graph/edge/{uuid} ``` Delete an edge by UUID ## Path Parameters - Uuid (required): Edge UUID ## Response Body - 200: Edge deleted - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/graph/edge/uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.delete( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.delete("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Delete( context.TODO(), "uuid", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/graph/edge/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.delete( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.delete("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Delete( context.TODO(), "uuid", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/graph/edge/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.edge.delete( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.edge.delete("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Edge.Delete( context.TODO(), "uuid", ) ``` # Get Group Episodes ```http GET https://api.getzep.com/api/v2/graph/episodes/group/{group_id} ``` Get episodes by Group ID ## Path Parameters - GroupId (required): Group ID ## Query Parameters - Lastn (optional): The number of most recent episodes to retrieve. ## Response Body - 200: Episodes - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/episodes/group/group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.getByGroupId("group_id"); ``` ```go import ( context "context" graph "github.com/getzep/zep-go/v2/graph" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.GetByGroupID( context.TODO(), "group_id", &graph.EpisodeGetByGroupIDRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/graph/episodes/group/:group_id \ -d lastn=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.getByGroupId("group_id"); ``` ```go import ( context "context" graph "github.com/getzep/zep-go/v2/graph" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.GetByGroupID( context.TODO(), "group_id", &graph.EpisodeGetByGroupIDRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/graph/episodes/group/:group_id \ -d lastn=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.getByGroupId("group_id"); ``` ```go import ( context "context" graph "github.com/getzep/zep-go/v2/graph" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.GetByGroupID( context.TODO(), "group_id", &graph.EpisodeGetByGroupIDRequest{}, ) ``` # Get User Episodes ```http GET https://api.getzep.com/api/v2/graph/episodes/user/{user_id} ``` Get episodes by User ID ## Path Parameters - UserId (required): User ID ## Query Parameters - Lastn (optional): The number of most recent episodes entries to retrieve. ## Response Body - 200: Episodes - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/episodes/user/user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.getByUserId("user_id"); ``` ```go import ( context "context" graph "github.com/getzep/zep-go/v2/graph" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.GetByUserID( context.TODO(), "user_id", &graph.EpisodeGetByUserIDRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/graph/episodes/user/:user_id \ -d lastn=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.getByUserId("user_id"); ``` ```go import ( context "context" graph "github.com/getzep/zep-go/v2/graph" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.GetByUserID( context.TODO(), "user_id", &graph.EpisodeGetByUserIDRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/graph/episodes/user/:user_id \ -d lastn=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.getByUserId("user_id"); ``` ```go import ( context "context" graph "github.com/getzep/zep-go/v2/graph" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.GetByUserID( context.TODO(), "user_id", &graph.EpisodeGetByUserIDRequest{}, ) ``` # Get Episode ```http GET https://api.getzep.com/api/v2/graph/episodes/{uuid} ``` Get episode by UUID ## Path Parameters - Uuid (required): Episode UUID ## Response Body - 200: Episode - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/episodes/uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/episodes/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/episodes/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.episode.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.episode.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Episode.Get( context.TODO(), "uuid", ) ``` # Get Group Nodes ```http GET https://api.getzep.com/api/v2/graph/node/group/{group_id} ``` Get all nodes for a group ## Path Parameters - GroupId (required): Group ID ## Response Body - 200: Nodes - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/node/group/group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.getByGroupId("group_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.GetByGroupID( context.TODO(), "group_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/group/:group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.getByGroupId("group_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.GetByGroupID( context.TODO(), "group_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/group/:group_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get_by_group_id( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.getByGroupId("group_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.GetByGroupID( context.TODO(), "group_id", ) ``` # Get User Nodes ```http GET https://api.getzep.com/api/v2/graph/node/user/{user_id} ``` Get all nodes for a user ## Path Parameters - UserId (required): User ID ## Response Body - 200: Nodes - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/node/user/user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.getByUserId("user_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.GetByUserID( context.TODO(), "user_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/user/:user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.getByUserId("user_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.GetByUserID( context.TODO(), "user_id", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/user/:user_id ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get_by_user_id( user_id="user_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.getByUserId("user_id"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.GetByUserID( context.TODO(), "user_id", ) ``` # Get Node ```http GET https://api.getzep.com/api/v2/graph/node/{uuid} ``` Get a specific node by its UUID ## Path Parameters - Uuid (required): Node UUID ## Response Body - 200: Node - 400: Bad Request - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/graph/node/uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.Get( context.TODO(), "uuid", ) ``` ```shell curl https://api.getzep.com/api/v2/graph/node/:uuid ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.graph.node.get( uuid_="uuid", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.graph.node.get("uuid"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Graph.Node.Get( context.TODO(), "uuid", ) ``` # Create a new user group ```http POST https://api.getzep.com/api/v2/groups Content-Type: application/json ``` Create a new user group ## Request Body ```json {"type":"object","extends":[],"properties":[{"key":"description","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}},{"key":"fact_rating_instruction","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"id","id":"type_:FactRatingInstruction"}}}},"description":"UserIDs []string `json:\"user_ids\"`"},{"key":"group_id","valueShape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}},{"key":"name","valueShape":{"type":"alias","value":{"type":"optional","shape":{"type":"alias","value":{"type":"primitive","value":{"type":"string"}}}}}}]} ``` ## Response Body - 200: The added group - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl -X POST https://api.getzep.com/api/v2/groups \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "group_id": "group_id" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.add( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.add({ groupId: "group_id" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Add( context.TODO(), &v2.CreateGroupRequest{ GroupID: "group_id", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/groups \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "group_id": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.add( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.add({ groupId: "group_id" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Add( context.TODO(), &v2.CreateGroupRequest{ GroupID: "group_id", }, ) ``` ```shell curl -X POST https://api.getzep.com/api/v2/groups \ -H "Authorization: Api-Key " \ -H "Content-Type: application/json" \ -d '{ "group_id": "string" }' ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.add( group_id="group_id", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.add({ groupId: "group_id" }); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Add( context.TODO(), &v2.CreateGroupRequest{ GroupID: "group_id", }, ) ``` # List all groups ```http GET https://api.getzep.com/api/v2/groups-ordered ``` List all groups with pagination. ## Query Parameters - PageNumber (optional): Page number for pagination, starting from 1 - PageSize (optional): Number of groups to retrieve per page ## Response Body - 200: Successfully retrieved list of groups - 400: Bad Request - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/groups-ordered \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.list_all_groups() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.listAllGroups(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.ListAllGroups( context.TODO(), &v2.GetGroupsOrderedRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/groups-ordered \ -H "Authorization: Api-Key " \ -d pageNumber=0 \ -d pageSize=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.list_all_groups() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.listAllGroups(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.ListAllGroups( context.TODO(), &v2.GetGroupsOrderedRequest{}, ) ``` ```shell curl -G https://api.getzep.com/api/v2/groups-ordered \ -H "Authorization: Api-Key " \ -d pageNumber=0 \ -d pageSize=0 ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.list_all_groups() ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.listAllGroups(); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2 "github.com/getzep/zep-go/v2" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.ListAllGroups( context.TODO(), &v2.GetGroupsOrderedRequest{}, ) ``` # Get a group. ```http GET https://api.getzep.com/api/v2/groups/{groupId} ``` Get a group. ## Path Parameters - GroupId (required): The group_id of the group to get. ## Response Body - 200: The group that was retrieved. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/groups/groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.get_a_group( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.getAGroup("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.GetAGroup( context.TODO(), "groupId", ) ``` ```shell curl https://api.getzep.com/api/v2/groups/:groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.get_a_group( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.getAGroup("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.GetAGroup( context.TODO(), "groupId", ) ``` ```shell curl https://api.getzep.com/api/v2/groups/:groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.get_a_group( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.getAGroup("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.GetAGroup( context.TODO(), "groupId", ) ``` # Delete group ```http DELETE https://api.getzep.com/api/v2/groups/{groupId} ``` Delete group ## Path Parameters - GroupId (required): Group ID ## Response Body - 200: Deleted - 400: Bad Request - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl -X DELETE https://api.getzep.com/api/v2/groups/groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.delete( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.delete("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Delete( context.TODO(), "groupId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/groups/:groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.delete( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.delete("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Delete( context.TODO(), "groupId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/groups/:groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.delete( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.delete("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Delete( context.TODO(), "groupId", ) ``` ```shell curl -X DELETE https://api.getzep.com/api/v2/groups/:groupId \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.delete( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.delete("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.Delete( context.TODO(), "groupId", ) ``` # Get group facts. ```http GET https://api.getzep.com/api/v2/groups/{groupId}/facts ``` Get group facts. ## Path Parameters - GroupId (required): The group_id of the group to get. ## Response Body - 200: The group facts. - 404: Not Found - 500: Internal Server Error ## Examples ```shell curl https://api.getzep.com/api/v2/groups/groupId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.get_facts( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.getFacts("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.GetFacts( context.TODO(), "groupId", ) ``` ```shell curl https://api.getzep.com/api/v2/groups/:groupId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.get_facts( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.getFacts("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.GetFacts( context.TODO(), "groupId", ) ``` ```shell curl https://api.getzep.com/api/v2/groups/:groupId/facts \ -H "Authorization: Api-Key " ``` ```python from zep_cloud.client import Zep client = Zep( api_key="YOUR_API_KEY", ) client.group.get_facts( group_id="groupId", ) ``` ```typescript import { ZepClient } from "zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); await client.group.getFacts("groupId"); ``` ```go import ( context "context" option "github.com/getzep/zep-go/v2/option" v2client "github.com/getzep/zep-go/v2/client" ) client := v2client.NewClient( option.WithAPIKey( "", ), ) response, err := client.Group.GetFacts( context.TODO(), "groupId", ) ``` # Overview > Temporal Knowledge Graphs for Agentic Applications Graphiti helps you create and query Knowledge Graphs that evolve over time. A knowledge graph is a network of interconnected facts, such as *“Kendra loves Adidas shoes.”* Each fact is a *“triplet”* represented by two entities, or nodes (*”Kendra”, “Adidas shoes”*), and their relationship, or edge (*”loves”*).
Knowledge Graphs have been explored extensively for information retrieval. What makes Graphiti unique is its ability to autonomously build a knowledge graph while handling changing relationships and maintaining historical context.
![graphiti intro slides](file:2a438f52-a4fc-4849-a62f-0f6649592d4d) Graphiti builds dynamic, temporally-aware knowledge graphs that represent complex, evolving relationships between entities over time. It ingests both unstructured and structured data, and the resulting graph may be queried using a fusion of time, full-text, semantic, and graph algorithm approaches. With Graphiti, you can build LLM applications such as: * Assistants that learn from user interactions, fusing personal knowledge with dynamic data from business systems like CRMs and billing platforms. * Agents that autonomously execute complex tasks, reasoning with state changes from multiple dynamic sources. Graphiti supports a wide range of applications in sales, customer service, health, finance, and more, enabling long-term recall and state-based reasoning for both assistants and agents. ## Graphiti and Zep Memory Graphiti powers the core of [Zep's memory layer](https://www.getzep.com) for LLM-powered Assistants and Agents. We're excited to open-source Graphiti, believing its potential reaches far beyond memory applications. ## Why Graphiti? We were intrigued by Microsoft’s GraphRAG, which expanded on RAG text chunking by using a graph to better model a document corpus and making this representation available via semantic and graph search techniques. However, GraphRAG did not address our core problem: It's primarily designed for static documents and doesn't inherently handle temporal aspects of data. Graphiti is designed from the ground up to handle constantly changing information, hybrid semantic and graph search, and scale: * **Temporal Awareness:** Tracks changes in facts and relationships over time, enabling point-in-time queries. Graph edges include temporal metadata to record relationship lifecycles. * **Episodic Processing:** Ingests data as discrete episodes, maintaining data provenance and allowing incremental entity and relationship extraction. * **Hybrid Search:** Combines semantic and BM25 full-text search, with the ability to rerank results by distance from a central node e.g. “Kendra”. * **Scalable:** Designed for processing large datasets, with parallelization of LLM calls for bulk processing while preserving the chronology of events. * **Supports Varied Sources:** Can ingest both unstructured text and structured JSON data. ![graphiti demo slides](file:09f32c10-b9aa-48a1-b884-ce795712241b) # Installation > How to install Graphiti Requirements: * Python 3.10 or higher * Neo4j 5.21 or higher * OpenAI API key (for LLM inference and embedding) Optional: * Anthropic or Groq API key (for alternative LLM providers) The simplest way to install Neo4j is via [Neo4j Desktop](https://neo4j.com/download/). It provides a user-friendly interface to manage Neo4j instances and databases. ``` pip install graphiti-core ``` or ``` poetry add graphiti-core ``` # Quick Start > Getting started with Graphiti Graphiti uses OpenAI for LLM inference and embedding. Ensure that an `OPENAI_API_KEY` is set in your environment. Support for Anthropic and Groq LLM inferences is available, too. ### Initialize graphiti Before running this cell, ensure that you have [Neo4j Desktop](https://neo4j.com/download/) open, a Project created, a Local DBMS added within that Project, and that the DBMS is started. ```python from graphiti_core import Graphiti from graphiti_core.nodes import EpisodeType from datetime import datetime graphiti = Graphiti("bolt://localhost:7687", "neo4j", "password") # Initialize the graph database with graphiti's indices. This only needs to be done once. await graphiti.build_indices_and_constraints() ``` ### Add Episodes ```python episodes = [ "Kamala Harris is the Attorney General of California. She was previously " "the district attorney for San Francisco.", "As AG, Harris was in office from January 3, 2011 – January 3, 2017", ] for i, episode in enumerate(episodes): await graphiti.add_episode( name=f"Freakonomics Radio {i}", episode_body=episode, source=EpisodeType.text, source_description="podcast", reference_time=datetime.now() ) ``` ### Search the graph Execute a hybrid search combining semantic similarity and BM25 retrieval Results are combined and reranked using Reciprocal Rank Fusion ```python results = await graphiti.search('Who was the California Attorney General?') [ EntityEdge( │ uuid='3133258f738e487383f07b04e15d4ac0', │ source_node_uuid='2a85789b318d4e418050506879906e62', │ target_node_uuid='baf7781f445945989d6e4f927f881556', │ created_at=datetime.datetime(2024, 8, 26, 13, 13, 24, 861097), │ name='HELD_POSITION', # the fact reflects the updated state that Harris is # no longer the AG of California │ fact='Kamala Harris was the Attorney General of California', │ fact_embedding=[ │ │ -0.009955154731869698, │ ... │ │ 0.00784289836883545 │ ], │ episodes=['b43e98ad0a904088a76c67985caecc22'], │ expired_at=datetime.datetime(2024, 8, 26, 20, 18, 1, 53812), # These dates represent the date this edge was true. │ valid_at=datetime.datetime(2011, 1, 3, 0, 0, tzinfo=), │ invalid_at=datetime.datetime(2017, 1, 3, 0, 0, tzinfo=) ) ] ``` ### Rerank search results based on graph distance Provide a node UUID to prioritize results closer to that node in the graph. Results are weighted by their proximity, with distant edges receiving lower scores. ```python await client.search('Who was the California Attorney General?', center_node_uuid) ``` ### Close the connection ```python graphiti.close() ``` # Adding Episodes > How to add data to your Graphiti graph ### Adding Episodes Episodes represent a single data ingestion event. An `episode` is itself a node, and any nodes identified while ingesting the episode are related to the episode via `MENTIONS` edges. Episodes enable querying for information at a point in time and understanding the provenance of nodes and their edge relationships. Supported episode types: * `text`: Unstructured text data * `message`: Conversational messages of the format `speaker: message...` * `json`: Structured data, processed distinctly from the other types The graph below was generated using the code in the [Quick Start](quick-start). Each **podcast** is an individual episode. ![Simple Graph Visualization](https://raw.githubusercontent.com/getzep/graphiti/main/images/simple_graph.svg) #### Adding a `text` or `message` Episode Using the `EpisodeType.text` type: ```python await graphiti.add_episode( name="tech_innovation_article", episode_body=( "MIT researchers have unveiled 'ClimateNet', an AI system capable of predicting " "climate patterns with unprecedented accuracy. Early tests show it can forecast " "major weather events up to three weeks in advance, potentially revolutionizing " "disaster preparedness and agricultural planning." ), source=EpisodeType.text, # A description of the source (e.g., "podcast", "news article") source_description="Technology magazine article", # The timestamp for when this episode occurred or was created reference_time=datetime(2023, 11, 15, 9, 30), ) ``` Using the `EpisodeType.message` type supports passing in multi-turn conversations in the `episode_body`. The text should be structured in `{role/name}: {message}` pairs. ```python await graphiti.add_episode( name="Customer_Support_Interaction_1", episode_body=( "Customer: Hi, I'm having trouble with my Allbirds shoes. " "The sole is coming off after only 2 months of use.\n" "Support: I'm sorry to hear that. Can you please provide your order number?" ), source=EpisodeType.message, source_description="Customer support chat", reference_time=datetime(2024, 3, 15, 14, 45), ) ``` #### Adding an Episode using structured data in JSON format JSON documents can be arbitrarily nested. However, it's advisable to keep documents compact, as they must fit within your LLM's context window. For large data imports, consider using the `add_episode_bulk` API to efficiently add multiple episodes at once. ```python product_data = { "id": "PROD001", "name": "Men's SuperLight Wool Runners", "color": "Dark Grey", "sole_color": "Medium Grey", "material": "Wool", "technology": "SuperLight Foam", "price": 125.00, "in_stock": True, "last_updated": "2024-03-15T10:30:00Z" } # Add the episode to the graph await graphiti.add_episode( name="Product Update - PROD001", episode_body=product_data, # Pass the Python dictionary directly source=EpisodeType.json, source_description="Allbirds product catalog update", reference_time=datetime.now(), ) ``` #### Loading Episodes in Bulk Graphiti offers `add_episode_bulk` for efficient batch ingestion of episodes, significantly outperforming `add_episode` for large datasets. This method is highly recommended for bulk loading. Use `add_episode_bulk` only for populating empty graphs or when edge invalidation is not required. The bulk ingestion pipeline does not perform edge invalidation operations. ```python product_data = [ { "id": "PROD001", "name": "Men's SuperLight Wool Runners", "color": "Dark Grey", "sole_color": "Medium Grey", "material": "Wool", "technology": "SuperLight Foam", "price": 125.00, "in_stock": true, "last_updated": "2024-03-15T10:30:00Z" }, ... { "id": "PROD0100", "name": "Kids Wool Runner-up Mizzles", "color": "Natural Grey", "sole_color": "Orange", "material": "Wool", "technology": "Water-repellent", "price": 80.00, "in_stock": true, "last_updated": "2024-03-17T14:45:00Z" } ] # Prepare the episodes for bulk loading bulk_episodes = [ RawEpisode( name=f"Product Update - {product['id']}", content=json.dumps(product), source=EpisodeType.json, source_description="Allbirds product catalog update", reference_time=datetime.now() ) for product in product_data ] await graphiti.add_episode_bulk(bulk_episodes) ``` ``` ``` # Communities > How to create and update communities In Graphiti, communities (represented as `CommunityNode` objects) represent groups of related entity nodes. Communities can be generated using the `build_communities` method on the graphiti class. ```python await graphiti.build_communities() ``` Communities are determined using the Leiden algorithm, which groups strongly connected nodes together. Communities contain a summary field that collates the summaries held on each of its member entities. This allows Graphiti to provide high-level synthesized information about what the graph contains in addition to the more granular facts stored on edges. Once communities are built, they can also be updated with new episodes by passing in `update_communities=True` to the `add_episode` method. If a new node is added to the graph, we will determine which community it should be added to based on the most represented community of the new node's surrounding nodes. This updating methodology is inspired by the label propagation algorithm for determining communities. However, we still recommend periodically rebuilding communities to ensure the most optimal grouping. Whenever the `build_communities` method is called it will remove any existing communities before creating new ones. # Searching the Graph > How to retrieve information from your Graphiti graph The examples below demonstrate two search approaches in the Graphiti library: 1. **Hybrid Search:** ```python await graphiti.search(query) ``` Combines semantic similarity and BM25 retrieval, reranked using Reciprocal Rank Fusion. Example: Does a broad retrieval of facts related to Allbirds Wool Runners and Jane's purchase. 2. **Node Distance Reranking:** ```python await graphiti.search(query, focal_node_uuid) ``` Extends Hybrid Search above by prioritizing results based on proximity to a specified node in the graph. Example: Focuses on Jane-specific information, highlighting her wool allergy. Node Distance Reranking is particularly useful for entity-specific queries, providing more contextually relevant results. It weights facts by their closeness to the focal node, emphasizing information directly related to the entity of interest. This dual approach allows for both broad exploration and targeted, entity-specific information retrieval from the knowledge graph. ```python query = "Can Jane wear Allbirds Wool Runners?" jane_node_uuid = "123e4567-e89b-12d3-a456-426614174000" def print_facts(edges): print("\n".join([edge.fact for edge in edges])) # Hybrid Search results = await graphiti.search(query) print_facts(results) > The Allbirds Wool Runners are sold by Allbirds. > Men's SuperLight Wool Runners - Dark Grey (Medium Grey Sole) has a runner silhouette. > Jane purchased SuperLight Wool Runners. # Hybrid Search with Node Distance Reranking await client.search(query, jane_node_uuid) print_facts(results) > Jane purchased SuperLight Wool Runners. > Jane is allergic to wool. > The Allbirds Wool Runners are sold by Allbirds. ``` ## Configurable Search Strategies Graphiti also provides a low-level search method that is more configurable than the out-of-the-box search. This search method can be called using `graphiti._search()` and passing in an additional config parameter of type `SearchConfig`. `SearchConfig` contains 4 fields: one for the limit, and three more configs for each of edges, nodes, and communities. The `graphiti._search()` method returns a `SearchResults` object containing a list of nodes, edges, and communities. The `graphiti._search()` method is quite configurable and can be complicated to work with at first. As such, we also have a `search_config_recipes.py` file that contains a few prebuilt `SearchConfig` recipes for common use cases. The 15 recipes are the following: | Search Type | Description | | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | COMBINED\_HYBRID\_SEARCH\_RRF | Performs a hybrid search with RRF reranking over edges, nodes, and communities. | | COMBINED\_HYBRID\_SEARCH\_MMR | Performs a hybrid search with MMR reranking over edges, nodes, and communities. | | COMBINED\_HYBRID\_SEARCH\_CROSS\_ENCODER | Performs a full-text search, similarity search, and BFS with cross\_encoder reranking over edges, nodes, and communities. | | EDGE\_HYBRID\_SEARCH\_RRF | Performs a hybrid search over edges with RRF reranking. | | EDGE\_HYBRID\_SEARCH\_MMR | Performs a hybrid search over edges with MMR reranking. | | EDGE\_HYBRID\_SEARCH\_NODE\_DISTANCE | Performs a hybrid search over edges with node distance reranking. | | EDGE\_HYBRID\_SEARCH\_EPISODE\_MENTIONS | Performs a hybrid search over edges with episode mention reranking. | | EDGE\_HYBRID\_SEARCH\_CROSS\_ENCODER | Performs a hybrid search over edges with cross encoder reranking. | | NODE\_HYBRID\_SEARCH\_RRF | Performs a hybrid search over nodes with RRF reranking. | | NODE\_HYBRID\_SEARCH\_MMR | Performs a hybrid search over nodes with MMR reranking. | | NODE\_HYBRID\_SEARCH\_NODE\_DISTANCE | Performs a hybrid search over nodes with node distance reranking. | | NODE\_HYBRID\_SEARCH\_EPISODE\_MENTIONS | Performs a hybrid search over nodes with episode mentions reranking. | | NODE\_HYBRID\_SEARCH\_CROSS\_ENCODER | Performs a hybrid search over nodes with cross encoder reranking. | | COMMUNITY\_HYBRID\_SEARCH\_RRF | Performs a hybrid search over communities with RRF reranking. | | COMMUNITY\_HYBRID\_SEARCH\_MMR | Performs a hybrid search over communities with MMR reranking. | | COMMUNITY\_HYBRID\_SEARCH\_CROSS\_ENCODER | Performs a hybrid search over communities with cross encoder reranking. | ## Supported Reranking Approaches **Reciprocal Rank Fusion (RRF)** enhances search by combining results from different algorithms, like BM25 and semantic search. Each algorithm's results are ranked, converted to reciprocal scores (1/rank), and summed. This aggregated score determines the final ranking, leveraging the strengths of each method for more accurate retrieval. **Maximal Marginal Relevance (MMR)** is a search strategy that balances relevance and diversity in results. It selects results that are both relevant to the query and diverse from already chosen ones, reducing redundancy and covering different query aspects. MMR ensures comprehensive and varied search results by iteratively choosing results that maximize relevance while minimizing similarity to previously selected results. A **Cross-Encoder** is a model that jointly encodes a query and a result, scoring their relevance by considering their combined context. This approach often yields more accurate results compared to methods that encode query and a text separately. Graphiti supports two cross encoders: * `OpenAIRerankerClient` (the default) and `BGERerankerClient`. Rather than use a cross-encoder model, the `OpenAIRerankerClient` uses an OpenAI model to classify relevance and the resulting `logprobs` are used to rerank results. * The `BGERerankerClient` uses the `BAAI/bge-reranker-v2-m3` model and requires `sentence_transformers` be installed. # CRUD Operations > How to access and modify Nodes and Edges The Graphiti library uses 8 core classes to add data to your graph: * `Node` * `EpisodicNode` * `EntityNode` * `Edge` * `EpisodicEdge` * `EntityEdge` * `CommunityNode` * `CommunityEdge` The generic `Node` and `Edge` classes are abstract base classes, and the other 4 classes inherit from them. Each of `EpisodicNode`, `EntityNode`, `EpisodicEdge`, and `EntityEdge` have fully supported CRUD operations. The save method performs a find or create based on the uuid of the object, and will add or update any other data from the class to the graph. A driver must be provided to the save method. The Entity Node save method is shown below as a sample. ```python async def save(self, driver: AsyncDriver): result = await driver.execute_query( """ MERGE (n:Entity {uuid: $uuid}) SET n = {uuid: $uuid, name: $name, name_embedding: $name_embedding, summary: $summary, created_at: $created_at} RETURN n.uuid AS uuid""", uuid=self.uuid, name=self.name, summary=self.summary, name_embedding=self.name_embedding, created_at=self.created_at, ) logger.info(f'Saved Node to neo4j: {self.uuid}') return result ``` Graphiti also supports hard deleting nodes and edges using the delete method, which also requires a driver. ```python async def delete(self, driver: AsyncDriver): result = await driver.execute_query( """ MATCH (n:Entity {uuid: $uuid}) DETACH DELETE n """, uuid=self.uuid, ) logger.info(f'Deleted Node: {self.uuid}') return result ``` Finally, Graphiti also provides class methods to get nodes and edges by uuid. Note that because these are class methods they are called using the class rather than an instance of the class. ```python async def get_by_uuid(cls, driver: AsyncDriver, uuid: str): records, _, _ = await driver.execute_query( """ MATCH (n:Entity {uuid: $uuid}) RETURN n.uuid As uuid, n.name AS name, n.created_at AS created_at, n.summary AS summary """, uuid=uuid, ) nodes: list[EntityNode] = [] for record in records: nodes.append( EntityNode( uuid=record['uuid'], name=record['name'], labels=['Entity'], created_at=record['created_at'].to_native(), summary=record['summary'], ) ) logger.info(f'Found Node: {uuid}') return nodes[0] ``` # Adding Fact Triples > How to add fact triples to your Graphiti graph A "fact triple" consists of two nodes and an edge between them, where the edge typically contains some fact. You can manually add a fact triple of your choosing to the graph like this: ```python from graphiti_core.nodes import EpisodeType, EntityNode from graphiti_core.edges import EntityEdge import uuid from datetime import datetime source_name = "Bob" target_name = "bananas" source_uuid = "some existing UUID" # This is an existing node, so we use the existing UUID obtained from Neo4j Desktop target_uuid = str(uuid.uuid4()) # This is a new node, so we create a new UUID edge_name = "LIKES" edge_fact = "Bob likes bananas" source_node = EntityNode( uuid=source_uuid, name=source_name, group_id="" ) target_node = EntityNode( uuid=target_uuid, name=target_name, group_id="" ) edge = EntityEdge( group_id="", source_node_uuid=source_uuid, target_node_uuid=target_uuid, created_at=datetime.now(), name=edge_name, fact=edge_fact ) await graphiti.add_triplet(source_node, edge, target_node) ``` When you add a fact triple, Graphiti will attempt to deduplicate your passed in nodes and edge with the already existing nodes and edges in the graph. If there are no duplicates, it will add them as new nodes and edges. Also, you can avoid constructing `EntityEdge` or `EntityNode` objects manually by using the results of a Graphiti search (see [Searching the Graph](/graphiti/graphiti/searching)). # Using LangGraph and Graphiti > Building an agent with LangChain's LangGraph and Graphiti A Jupyter notebook version of this example is available [on GitHub](https://github.com/getzep/graphiti/blob/main/examples/langgraph-agent/agent.ipynb). Looking for a managed Graphiti service? Check out [Zep Cloud](https://www.getzep.com). * Designed as a self-improving memory layer for Agents. * No need to run Neo4j or other dependencies. * Additional features for startups and enterprises alike. * Fast and scalable. The following example demonstrates building an agent using LangGraph. Graphiti is used to personalize agent responses based on information learned from prior conversations. Additionally, a database of products is loaded into the Graphiti graph, enabling the agent to speak to these products. The agent implements: * persistance of new chat turns to Graphiti and recall of relevant Facts using the most recent message. * a tool for querying Graphiti for shoe information * an in-memory `MemorySaver` to maintain agent state. ## Install dependencies ```shell pip install graphiti-core langchain-openai langgraph ipywidgets ``` Ensure that you've followed the [Graphiti installation instructions](installation). In particular, installation of `neo4j`. ```python import asyncio import json import logging import os import sys import uuid from contextlib import suppress from datetime import datetime from pathlib import Path from typing import Annotated import ipywidgets as widgets from dotenv import load_dotenv from IPython.display import Image, display from typing_extensions import TypedDict load_dotenv() ``` ```python def setup_logging(): logger = logging.getLogger() logger.setLevel(logging.ERROR) console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging.INFO) formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s') console_handler.setFormatter(formatter) logger.addHandler(console_handler) return logger logger = setup_logging() ``` ## Configure Graphiti Ensure that you have `neo4j` running and a database created. You'll need the following environment variables configured: ```bash NEO4J_URI= NEO4J_USER= NEO4J_PASSWORD= ``` ```python # Configure Graphiti from graphiti_core import Graphiti from graphiti_core.edges import EntityEdge from graphiti_core.nodes import EpisodeType from graphiti_core.utils.bulk_utils import RawEpisode from graphiti_core.utils.maintenance.graph_data_operations import clear_data neo4j_uri = os.environ.get('NEO4J_URI', 'bolt://localhost:7687') neo4j_user = os.environ.get('NEO4J_USER', 'neo4j') neo4j_password = os.environ.get('NEO4J_PASSWORD', 'password') client = Graphiti( neo4j_uri, neo4j_user, neo4j_password, ) ``` ## Generating a database schema The following is only required for the first run of this notebook or when you'd like to start your database over. `clear_data` is destructive and will wipe your entire database. ```python # Note: This will clear the database await clear_data(client.driver) await client.build_indices_and_constraints() ``` ## Load Shoe Data into the Graph Load several shoe and related products into the Graphiti. This may take a while. This only needs to be done once. If you run `clear_data` you'll need to rerun this step. ```python async def ingest_products_data(client: Graphiti): script_dir = Path.cwd().parent json_file_path = script_dir / 'data' / 'manybirds_products.json' with open(json_file_path) as file: products = json.load(file)['products'] episodes: list[RawEpisode] = [ RawEpisode( name=product.get('title', f'Product {i}'), content=str({k: v for k, v in product.items() if k != 'images'}), source_description='ManyBirds products', source=EpisodeType.json, reference_time=datetime.now(), ) for i, product in enumerate(products) ] await client.add_episode_bulk(episodes) await ingest_products_data(client) ``` ## Create a user node in the Graphiti graph In your own app, this step could be done later once the user has identified themselves and made their sales intent known. We do this here so we can configure the agent with the user's `node_uuid`. ```python user_name = 'jess' await client.add_episode( name='User Creation', episode_body=(f'{user_name} is interested in buying a pair of shoes'), source=EpisodeType.text, reference_time=datetime.now(), source_description='SalesBot', ) # let's get Jess's node uuid nl = await client.get_nodes_by_query(user_name) user_node_uuid = nl[0].uuid # and the ManyBirds node uuid nl = await client.get_nodes_by_query('ManyBirds') manybirds_node_uuid = nl[0].uuid ``` ## Helper Functions and LangChain Imports ```python def edges_to_facts_string(entities: list[EntityEdge]): return '-' + '\n- '.join([edge.fact for edge in entities]) ``` ```python from langchain_core.messages import AIMessage, SystemMessage from langchain_core.tools import tool from langchain_openai import ChatOpenAI from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import END, START, StateGraph, add_messages from langgraph.prebuilt import ToolNode ``` ## `get_shoe_data` Tool The agent will use this to search the Graphiti graph for information about shoes. We center the search on the `manybirds_node_uuid` to ensure we rank shoe-related data over user data. ```python @tool async def get_shoe_data(query: str) -> str: """Search the graphiti graph for information about shoes""" edge_results = await client.search( query, center_node_uuid=manybirds_node_uuid, num_results=10, ) return edges_to_facts_string(edge_results) tools = [get_shoe_data] tool_node = ToolNode(tools) ``` ## Initialize the LLM and bind tools ```python llm = ChatOpenAI(model='gpt-4o-mini', temperature=0).bind_tools(tools) ``` ### Test the tool node ```python await tool_node.ainvoke({'messages': [await llm.ainvoke('wool shoes')]}) ``` ```json { "messages": [ { "content": "-The product 'Men's SuperLight Wool Runners - Dark Grey (Medium Grey Sole)' is made of Wool.\n- Women's Tree Breezers Knit - Rugged Beige (Hazy Beige Sole) has sizing options related to women's move shoes half sizes.\n- TinyBirds Wool Runners - Little Kids - Natural Black (Blizzard Sole) is a type of Shoes.\n- The product 'Men's SuperLight Wool Runners - Dark Grey (Medium Grey Sole)' belongs to the category Shoes.\n- The product 'Men's SuperLight Wool Runners - Dark Grey (Medium Grey Sole)' uses SuperLight Foam technology.\n- TinyBirds Wool Runners - Little Kids - Natural Black (Blizzard Sole) is sold by Manybirds.\n- Jess is interested in buying a pair of shoes.\n- TinyBirds Wool Runners - Little Kids - Natural Black (Blizzard Sole) has the handle TinyBirds-wool-runners-little-kids.\n- ManyBirds Men's Couriers are a type of Shoes.\n- Women's Tree Breezers Knit - Rugged Beige (Hazy Beige Sole) belongs to the Shoes category.", "name": "get_shoe_data", "tool_call_id": "call_EPpOpD75rdq9jKRBUsfRnfxx" } ] } ``` ## Chatbot Function Explanation The chatbot uses Graphiti to provide context-aware responses in a shoe sales scenario. Here's how it works: 1. **Context Retrieval**: It searches the Graphiti graph for relevant information based on the latest message, using the user's node as the center point. This ensures that user-related facts are ranked higher than other information in the graph. 2. **System Message**: It constructs a system message incorporating facts from Graphiti, setting the context for the AI's response. 3. **Knowledge Persistence**: After generating a response, it asynchronously adds the interaction to the Graphiti graph, allowing future queries to reference this conversation. This approach enables the chatbot to maintain context across interactions and provide personalized responses based on the user's history and preferences stored in the Graphiti graph. ```python class State(TypedDict): messages: Annotated[list, add_messages] user_name: str user_node_uuid: str async def chatbot(state: State): facts_string = None if len(state['messages']) > 0: last_message = state['messages'][-1] graphiti_query = f'{"SalesBot" if isinstance(last_message, AIMessage) else state["user_name"]}: {last_message.content}' # search graphiti using Jess's node uuid as the center node # graph edges (facts) further from the Jess node will be ranked lower edge_results = await client.search( graphiti_query, center_node_uuid=state['user_node_uuid'], num_results=5 ) facts_string = edges_to_facts_string(edge_results) system_message = SystemMessage( content=f"""You are a skillfull shoe salesperson working for ManyBirds. Review information about the user and their prior conversation below and respond accordingly. Keep responses short and concise. And remember, always be selling (and helpful!) Things you'll need to know about the user in order to close a sale: - the user's shoe size - any other shoe needs? maybe for wide feet? - the user's preferred colors and styles - their budget Ensure that you ask the user for the above if you don't already know. Facts about the user and their conversation: {facts_string or 'No facts about the user and their conversation'}""" ) messages = [system_message] + state['messages'] response = await llm.ainvoke(messages) # add the response to the graphiti graph. # this will allow us to use the graphiti search later in the conversation # we're doing async here to avoid blocking the graph execution asyncio.create_task( client.add_episode( name='Chatbot Response', episode_body=f"{state['user_name']}: {state['messages'][-1]}\nSalesBot: {response.content}", source=EpisodeType.message, reference_time=datetime.now(), source_description='Chatbot', ) ) return {'messages': [response]} ``` ## Setting up the Agent This section sets up the Agent's LangGraph graph: 1. **Graph Structure**: It defines a graph with nodes for the agent (chatbot) and tools, connected in a loop. 2. **Conditional Logic**: The `should_continue` function determines whether to end the graph execution or continue to the tools node based on the presence of tool calls. 3. **Memory Management**: It uses a MemorySaver to maintain conversation state across turns. This is in addition to using Graphiti for facts. ```python graph_builder = StateGraph(State) memory = MemorySaver() # Define the function that determines whether to continue or not async def should_continue(state, config): messages = state['messages'] last_message = messages[-1] # If there is no function call, then we finish if not last_message.tool_calls: return 'end' # Otherwise if there is, we continue else: return 'continue' graph_builder.add_node('agent', chatbot) graph_builder.add_node('tools', tool_node) graph_builder.add_edge(START, 'agent') graph_builder.add_conditional_edges('agent', should_continue, {'continue': 'tools', 'end': END}) graph_builder.add_edge('tools', 'agent') graph = graph_builder.compile(checkpointer=memory) ``` Our LangGraph agent graph is illustrated below. ```python with suppress(Exception): display(Image(graph.get_graph().draw_mermaid_png())) ``` ![LangGraph Illustration](file:196640cf-0721-4f6b-b9ec-3f42425bbf93) ## Running the Agent Let's test the agent with a single call ```python await graph.ainvoke( { 'messages': [ { 'role': 'user', 'content': 'What sizes do the TinyBirds Wool Runners in Natural Black come in?', } ], 'user_name': user_name, 'user_node_uuid': user_node_uuid, }, config={'configurable': {'thread_id': uuid.uuid4().hex}}, ) ``` ```json { "messages": [ { "content": "What sizes do the TinyBirds Wool Runners in Natural Black come in?", "id": "6a940637-70a0-4c95-a4d7-4c4846909747", "type": "HumanMessage" }, { "content": "The TinyBirds Wool Runners in Natural Black are available in the following sizes for little kids: 5T, 6T, 8T, 9T, and 10T. \n\nDo you have a specific size in mind, or are you looking for something else? Let me know your needs, and I can help you find the perfect pair!", "additional_kwargs": { "refusal": null }, "response_metadata": { "token_usage": { "completion_tokens": 76, "prompt_tokens": 314, "total_tokens": 390 }, "model_name": "gpt-4o-mini-2024-07-18", "system_fingerprint": "fp_f33667828e", "finish_reason": "stop", "logprobs": null }, "id": "run-d2f79c7f-4d41-4896-88dc-476a8e38bea8-0", "usage_metadata": { "input_tokens": 314, "output_tokens": 76, "total_tokens": 390 }, "type": "AIMessage" } ], "user_name": "jess", "user_node_uuid": "186a845eee4849619d1e625b178d1845" } ``` ## Viewing the Graph At this stage, the graph would look something like this. The `jess` node is `INTERESTED_IN` the `TinyBirds Wool Runner` node. The image below was generated using Neo4j Desktop. ![Graph State](file:b6cb85e7-d0ba-4fef-a36d-1aca9956ca78) ## Running the Agent interactively The following code will run the agent in a Jupyter notebook event loop. You can modify the code to suite your own needs. Just enter a message into the box and click submit. ```python conversation_output = widgets.Output() config = {'configurable': {'thread_id': uuid.uuid4().hex}} user_state = {'user_name': user_name, 'user_node_uuid': user_node_uuid} async def process_input(user_state: State, user_input: str): conversation_output.append_stdout(f'\nUser: {user_input}\n') conversation_output.append_stdout('\nAssistant: ') graph_state = { 'messages': [{'role': 'user', 'content': user_input}], 'user_name': user_state['user_name'], 'user_node_uuid': user_state['user_node_uuid'], } try: async for event in graph.astream( graph_state, config=config, ): for value in event.values(): if 'messages' in value: last_message = value['messages'][-1] if isinstance(last_message, AIMessage) and isinstance( last_message.content, str ): conversation_output.append_stdout(last_message.content) except Exception as e: conversation_output.append_stdout(f'Error: {e}') def on_submit(b): user_input = input_box.value input_box.value = '' asyncio.create_task(process_input(user_state, user_input)) input_box = widgets.Text(placeholder='Type your message here...') submit_button = widgets.Button(description='Send') submit_button.on_click(on_submit) conversation_output.append_stdout('Asssistant: Hello, how can I help you find shoes today?') display(widgets.VBox([input_box, submit_button, conversation_output])) ```