> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs-beta.getzep.com/v4/custom-instructions/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-beta.getzep.com/_mcp/server. # Custom instructions > **Info** > > Available to [Flex Plus and Enterprise](https://www.getzep.com/pricing) customers. ## Why use custom instructions Zep's graph extraction uses general-purpose logic by default. Custom instructions let you describe the domain your application operates in, including specialized terminology and concepts that Zep might not otherwise understand. This domain context helps Zep interpret data more accurately during extraction. > **Note** > > Custom instructions describe **your domain** — the terminology, concepts, and context Zep needs to understand your data. If you need to define specific **entity types or relationship types** for your graph, use [custom ontology](/customizing-graph-structure#custom-entity-and-edge-types) instead. ## How custom instructions work Custom instructions are applied **automatically in the background** whenever data is added to a graph. There is no parameter on `thread.add_messages`, `graph.episode.add`, or any other ingestion method to select which instructions to use — Zep fetches and applies the relevant instructions based on the target graph. ### Resolution order When data is ingested into a graph, Zep determines which instructions to use in the following order: 1. **Graph-specific instructions** — If the target graph has its own instructions, set with `graph.set_instructions`, those are used. 2. **Project-wide defaults** — If no graph-specific instructions exist, Zep falls back to project-wide default instructions. 3. **Built-in extraction logic** — If no custom instructions are defined at all, Zep uses its general-purpose extraction logic. This means you can set broad project-wide instructions as a baseline and override them for specific graphs when needed. ## Defining custom instructions ### Project-wide instructions Use `project.set_instructions` to set the project-wide defaults. These apply to all graphs that don't have their own graph-specific instructions. Each set call replaces the full set of instructions at that scope. ```python from zep_cloud import Zep, CustomInstruction client = Zep(api_key="YOUR_API_KEY") # Set the project-wide custom instructions client.project.set_instructions( instructions=[ CustomInstruction( name="legal_domain", text=( "This application operates in the legal domain. " "Common legal terminology includes: consideration, " "estoppel, tort, indemnification, force majeure, " "severability, arbitration clause, non-compete, " "and confidentiality. A 'party' refers to a person " "or organization involved in a legal agreement. " "'Clauses' are specific provisions within a contract." ) ) ] ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); // Set the project-wide custom instructions await client.project.setInstructions({ instructions: [ { name: "legal_domain", text: "This application operates in the legal domain. " + "Common legal terminology includes: consideration, " + "estoppel, tort, indemnification, force majeure, " + "severability, arbitration clause, non-compete, " + "and confidentiality. A 'party' refers to a person " + "or organization involved in a legal agreement. " + "'Clauses' are specific provisions within a contract." } ] }); ``` ```go import ( "context" "log" zep "github.com/getzep/zep-go/v4" zepclient "github.com/getzep/zep-go/v4/client" "github.com/getzep/zep-go/v4/graph" "github.com/getzep/zep-go/v4/option" ) client := zepclient.NewClient( option.WithAPIKey("YOUR_API_KEY"), ) // Set the project-wide custom instructions _, err := client.Project.SetInstructions( context.TODO(), &zep.Instructions{ Instructions: []*zep.CustomInstruction{ { Name: "legal_domain", Text: "This application operates in the legal domain. " + "Common legal terminology includes: consideration, " + "estoppel, tort, indemnification, force majeure, " + "severability, arbitration clause, non-compete, " + "and confidentiality. A 'party' refers to a person " + "or organization involved in a legal agreement. " + "'Clauses' are specific provisions within a contract.", }, }, }, ) if err != nil { log.Fatal("Error setting custom instructions:", err) } ``` When you add data to any graph, Zep automatically applies these project-wide instructions. No extra parameters are needed. The examples use the `uuid` that `graph.create` returns, which you store in your application database: **`Python`** ```python Python # Add data to a graph — the legal_domain instructions apply automatically client.graph.episode.add( zep_graph_uuid, type="text", data=( "The licensing agreement between Acme Corp and GlobalTech Inc " "includes a non-compete clause effective for 24 months and an " "arbitration clause requiring disputes be resolved in New York." ) ) ``` **`TypeScript`** ```typescript TypeScript // Add data to a graph — the legal_domain instructions apply automatically await client.graph.episode.add(zepGraphUuid, { type: "text", data: "The licensing agreement between Acme Corp and GlobalTech Inc " + "includes a non-compete clause effective for 24 months and an " + "arbitration clause requiring disputes be resolved in New York." }); ``` **`Go`** ```go Go // Add data to a graph — the legal_domain instructions apply automatically _, err = client.Graph.Episode.Add(context.TODO(), zepGraphUUID, &graph.AddEpisodeRequest{ Type: graph.V4AddEpisodeRequestTypeText.Ptr(), Data: "The licensing agreement between Acme Corp and GlobalTech Inc " + "includes a non-compete clause effective for 24 months and an " + "arbitration clause requiring disputes be resolved in New York.", }) if err != nil { log.Fatal("Error adding data:", err) } ``` ### Graph-specific instructions To set instructions for one graph, use `graph.set_instructions` with the UUID of the graph. For a user graph, use the `graph_uuid` that `user.create` returns. These instructions override any project-wide defaults for that graph. To apply the same instructions to more than one graph, send the call once for each graph. ```python from zep_cloud import Zep, CustomInstruction client = Zep(api_key="YOUR_API_KEY") # Set instructions for one user's graph. # zep_graph_uuid is the graph_uuid of the user, from your application database. client.graph.set_instructions( zep_graph_uuid, instructions=[ CustomInstruction( name="healthcare_domain", text=( "This application operates in the healthcare domain. " "Common medical terminology includes: prognosis (expected " "outcome), etiology (cause of a condition), contraindication " "(reason to avoid a treatment), comorbidity (co-occurring " "conditions), and differential diagnosis (distinguishing " "between conditions with similar symptoms). A 'prescription' " "refers to a specific medication, dosage, and schedule." ) ) ] ) ``` ```typescript import { ZepClient } from "@getzep/zep-cloud"; const client = new ZepClient({ apiKey: "YOUR_API_KEY" }); // Set instructions for one user's graph. // zepGraphUuid is the graph UUID of the user, from your application database. await client.graph.setInstructions(zepGraphUuid, { instructions: [ { name: "healthcare_domain", text: "This application operates in the healthcare domain. " + "Common medical terminology includes: prognosis (expected " + "outcome), etiology (cause of a condition), contraindication " + "(reason to avoid a treatment), comorbidity (co-occurring " + "conditions), and differential diagnosis (distinguishing " + "between conditions with similar symptoms). A 'prescription' " + "refers to a specific medication, dosage, and schedule." } ] }); ``` ```go import ( "context" "log" zep "github.com/getzep/zep-go/v4" zepclient "github.com/getzep/zep-go/v4/client" "github.com/getzep/zep-go/v4/option" ) client := zepclient.NewClient( option.WithAPIKey("YOUR_API_KEY"), ) // Set instructions for one user's graph. // zepGraphUUID is the graph UUID of the user, from your application database. _, err := client.Graph.SetInstructions( context.TODO(), zepGraphUUID, &zep.Instructions{ Instructions: []*zep.CustomInstruction{ { Name: "healthcare_domain", Text: "This application operates in the healthcare domain. " + "Common medical terminology includes: prognosis (expected " + "outcome), etiology (cause of a condition), contraindication " + "(reason to avoid a treatment), comorbidity (co-occurring " + "conditions), and differential diagnosis (distinguishing " + "between conditions with similar symptoms). A 'prescription' " + "refers to a specific medication, dosage, and schedule.", }, }, }, ) if err != nil { log.Fatal("Error setting custom instructions:", err) } ``` When you add messages to a thread of this user, Zep automatically applies the `healthcare_domain` instructions. No extra parameters are needed. The examples use the `uuid` that `thread.create` returns: **`Python`** ```python Python from zep_cloud import AddMessage # Add messages — the healthcare_domain instructions apply automatically response = client.thread.add_messages( zep_thread_uuid, messages=[ AddMessage( name="Dr. Patel", role="user", content="Patient shows signs of acute bronchitis with a secondary comorbidity of asthma. Prescribing azithromycin 500mg for 3 days.", ), AddMessage( name="Assistant", role="assistant", content="Noted. Should I flag any contraindications with the patient's existing medications?", ), AddMessage( name="Dr. Patel", role="user", content="Good point — check against the current prednisone prescription. The prognosis is good if we manage both conditions.", ), ] ) ``` **`TypeScript`** ```typescript TypeScript // Add messages — the healthcare_domain instructions apply automatically const response = await client.thread.addMessages(zepThreadUuid, { messages: [ { name: "Dr. Patel", role: "user", content: "Patient shows signs of acute bronchitis with a secondary comorbidity of asthma. Prescribing azithromycin 500mg for 3 days.", }, { name: "Assistant", role: "assistant", content: "Noted. Should I flag any contraindications with the patient's existing medications?", }, { name: "Dr. Patel", role: "user", content: "Good point — check against the current prednisone prescription. The prognosis is good if we manage both conditions.", }, ] }); ``` **`Go`** ```go Go // Add messages — the healthcare_domain instructions apply automatically response, err := client.Thread.AddMessages( context.TODO(), zepThreadUUID, &zep.AddMessagesRequest{ Messages: []*zep.AddMessage{ { Name: zep.String("Dr. Patel"), Role: zep.RoleTypeUser.Ptr(), Content: zep.String("Patient shows signs of acute bronchitis with a secondary comorbidity of asthma. Prescribing azithromycin 500mg for 3 days."), }, { Name: zep.String("Assistant"), Role: zep.RoleTypeAssistant.Ptr(), Content: zep.String("Noted. Should I flag any contraindications with the patient's existing medications?"), }, { Name: zep.String("Dr. Patel"), Role: zep.RoleTypeUser.Ptr(), Content: zep.String("Good point — check against the current prednisone prescription. The prognosis is good if we manage both conditions."), }, }, }, ) if err != nil { log.Fatal("Error adding messages:", err) } ``` ## Important behaviors ### Whole-set writes A set call replaces the full set of instructions at its scope. An instruction that is not in the request is removed from that scope. To add or change one instruction, read the current set, change the list, and write the full list back. To remove all instructions at a scope, write an empty list. `graph.get_instructions` returns the effective instructions of a graph. When the graph has no instructions of its own, the response contains the project-wide defaults and `inherited` is `true`. **`Python`** ```python Python # Change one project-wide instruction and keep the others. current = client.project.get_instructions() instructions = [i for i in current.instructions or [] if i.name != "legal_domain"] instructions.append(CustomInstruction(name="legal_domain", text="This application operates in the legal domain.")) client.project.set_instructions(instructions=instructions) ``` **`TypeScript`** ```typescript TypeScript // Change one project-wide instruction and keep the others. const current = await client.project.getInstructions(); const instructions = (current.instructions ?? []).filter((i) => i.name !== "legal_domain"); instructions.push({ name: "legal_domain", text: "This application operates in the legal domain." }); await client.project.setInstructions({ instructions }); ``` **`Go`** ```go Go // Change one project-wide instruction and keep the others. current, err := client.Project.GetInstructions(context.TODO()) if err != nil { log.Fatal("Error getting custom instructions:", err) } instructions := []*zep.CustomInstruction{} for _, i := range current.Instructions { if i.Name != "legal_domain" { instructions = append(instructions, i) } } instructions = append(instructions, &zep.CustomInstruction{ Name: "legal_domain", Text: "This application operates in the legal domain.", }) _, err = client.Project.SetInstructions(context.TODO(), &zep.Instructions{Instructions: instructions}) if err != nil { log.Fatal("Error setting custom instructions:", err) } ``` ## Limits | Limit | Value | | ------------------------ | ------------------ | | Instructions per request | 5 | | Instruction name length | 100 characters | | Instruction text length | 1-5,000 characters | > Describe your domain so Zep can better understand your data