
Your agent's context is only as precise as your entity types
One broad entity type gives an agent no way to narrow its context. Many narrow types overlap and get applied inconsistently. Type hierarchies let a Zep context graph give each entity or fact a broad type and the most specific subtype that fits.
An agent is only as precise as the context that it retrieves. A dealership agent that answers "Which hybrids do we have in stock?" must retrieve only hybrid cars. The same agent that answers "Which vehicles did Ana look at?" must retrieve every vehicle. A flat ontology lets the agent do one of these tasks well, but not both.
A custom entity type tells Zep which kinds of things to extract from your data, such as a product, a patient, or a contract. Until now, the custom types in a Zep ontology were flat. Each node got the label Entity and at most one custom type label. With type hierarchies, you can now arrange custom entity types and edge types as types and subtypes, and Zep classifies each entity or fact into the most specific type that fits.
Why flat types give your agent imprecise context
A flat ontology makes you select one level of detail for each kind of thing. A dealership agent can use one broad type, Vehicle. With one broad type, an agent cannot filter the graph for electric cars only. The agent can also use many narrow types, such as ElectricCar, HybridCar, PickupTruck, and BoxTruck. With many narrow types, the agent cannot filter for all cars in one query, and every narrow type counts against the entity type limit of your plan.
Narrow types also make classification harder. Zep selects a type from the description of each type. When descriptions overlap, no single type is correct, and Zep can classify the same kind of item inconsistently. The custom ontology guide says to make the types at one level mutually exclusive. A long, flat list of similar types makes that rule difficult to follow.
Programming languages and schema.org solve this with a type hierarchy. In a type hierarchy, ElectricCar is a kind of Car, and Car is a kind of Vehicle. An item of a subtype is also an item of each parent type.
Define an entity type hierarchy
Every type in the hierarchy is an ordinary custom entity type, with its own name, description, and properties. The new optional field entity_type_hierarchy holds only the structure. Its value is a dictionary of dictionaries. Each key names an entity type in the same request, and {} marks a leaf type.
from zep_cloud.client import Zepfrom zep_cloud.types import EntityProperty, EntityType client = Zep(api_key="YOUR_API_KEY") details = [EntityProperty(name="details", type="text", description="Details about the vehicle.")] entity_types = [ EntityType(name="Vehicle", description="A vehicle for sale or in service, such as a car or a truck. Do not use for a part or an accessory.", properties=details), EntityType(name="Car", description="A passenger car, such as a sedan or an SUV. Do not use for a pickup truck or a van.", properties=details), EntityType(name="ElectricCar", description="A car with only a battery and an electric motor, such as a Tesla Model 3. Do not use for a hybrid.", properties=details), EntityType(name="HybridCar", description="A car with an engine and an electric motor, such as a Toyota Prius. Do not use for a car with only a battery.", properties=details), EntityType(name="Truck", description="A truck for cargo, such as a pickup truck or a box truck. Do not use for an SUV.", properties=details),] client.project.set_ontology( entity_types=entity_types, entity_type_hierarchy={ "Vehicle": { "Car": {"ElectricCar": {}, "HybridCar": {}}, "Truck": {}, }, },)Each type description gives a membership rule, an example, and a similar item that does not belong. The parent type Vehicle contains its subtypes by design. The siblings ElectricCar and HybridCar must not overlap.
A type can have up to 10 direct subtypes, and a hierarchy can have up to 4 subtype levels below a top-level type. Subtypes do not count against the entity type limit of your plan. One ontology can have up to 100 entity types in total. The entity type hierarchy guide has the TypeScript and Go versions and the full validation rules.
How Zep classifies an entity into a subtype
Zep classifies each entity in two stages.
- Top-level extraction. The extraction prompt shows only the top-level types. In the example, extraction sees
Vehicleand the other top-level types of the ontology, and it does not seeCarorElectricCar. The list of choices stays short. - Subtype classification. For each entity with a top-level type that has subtypes, Zep walks down the hierarchy. At each level, one LLM call selects one subtype, or "none" when no subtype fits. The walk stops at a leaf type or at "none".
The input to each call is the entity name, the chain selected so far, the candidate subtypes with their descriptions, and the episode text that the entity came from. For example, "the Prius that Ana test-drove" becomes Vehicle, then Car, then HybridCar. A mention of "a new car" with no other detail stops at Car, because no subtype fits.
Subtype classification runs before deduplication. Deduplication, attribute extraction, and summaries see the full chain. An entity whose top-level type has no subtypes makes no classification calls, and an ontology without a hierarchy adds no LLM calls.
Labels, filters, and properties
A classified node gets the label of every type in its chain. A HybridCar node has the labels Entity, Vehicle, Car, and HybridCar. A node never has a subtype label without the labels of all its parent types.
A label filter matches a node when any label of the node matches. A filter on Car returns Car, ElectricCar, and HybridCar nodes, and a filter on ElectricCar returns only electric cars:
cars = client.graph.node.list( "YOUR_GRAPH_UUID", filters={"node_labels": ["Car"]},)
A subtype does not inherit properties or identity properties from its parent type. A node uses the properties of the last type in its chain only. Declare every property that a subtype needs on the subtype itself. To match subtype nodes by an identity value, such as a vehicle identification number, set identity_properties on each subtype.
Edge type hierarchies
Facts get the same model. The optional field edge_type_hierarchy has the same shape as entity_type_hierarchy. For example, the edge type EMPLOYED_BY can have the subtypes WORKS_FULL_TIME_FOR and CONTRACTS_FOR. Extraction selects a top-level edge type, and then the subtype walk selects the most specific edge type that fits.
An edge has one type name, which is the name of the last type in its chain. Search expands an edge type filter through the hierarchy. A filter on EMPLOYED_BY returns EMPLOYED_BY, WORKS_FULL_TIME_FOR, and CONTRACTS_FOR edges. A filter on CONTRACTS_FOR returns only contract work. The exclude_edge_types filter expands in the same way.
| Behavior | Entity type hierarchy | Edge type hierarchy |
|---|---|---|
| Ontology field | entity_type_hierarchy | edge_type_hierarchy |
| Saved type | Every label in the chain | Last type in the chain |
| Filter on a parent type | Matches all subtypes | Matches all subtypes |
| Property inheritance | None | None |
Entity and edge type hierarchies classify the same way and store the result differently. Source: the Zep custom ontology guide.
Ontology changes and existing data
A change to a hierarchy applies to episodes that Zep processes after the change. Existing nodes and edges keep their labels and names, and Zep does not reclassify them. Each ontology write replaces the full ontology. A request without entity_type_hierarchy removes the stored hierarchy. A graph ontology replaces the project ontology for that graph, and Zep does not merge the two hierarchies.
Availability of type hierarchies
Entity and edge type hierarchies are in closed beta. They are on by default on BYOC deployments. For other accounts, Zep enables the feature for each account. Without access, the API rejects a non-empty hierarchy with HTTP 400. To ask for access, contact Zep.
To learn how types fit with the other kinds of context in a graph, read Zep context types. For facts that relate three or more entities, read about hyperedges.
FAQ
What is a type hierarchy in a knowledge graph?
A type hierarchy arranges entity types or relationship types as types and subtypes. Each item of a subtype is also an item of its parent types. In Zep, ElectricCar can be a subtype of Car, and Car can be a subtype of Vehicle. Zep classifies each entity into the most specific subtype that fits, and a filter on a parent type also returns the items of its subtypes.
Does a subtype inherit the properties of its parent type?
No. Each type in a Zep hierarchy declares its own properties and identity properties. A node uses the properties of the last type in its type chain only. A HybridCar node does not get a property that only Vehicle declares. Declare on each subtype every property that the subtype needs, and set identity_properties on each subtype when you match nodes by an identity value.
How many LLM calls does subtype classification add?
Subtype classification makes one LLM call for each level that Zep walks, for each entity or edge. A hierarchy has at most 4 subtype levels below a top-level type, so one entity makes at most four calls. Calls for different entities run in parallel. An entity whose top-level type has no subtypes makes no calls, and an ontology without a hierarchy adds no calls.
Does Zep reclassify existing nodes when I change a hierarchy?
No. A hierarchy change applies to episodes that Zep processes after the change. Existing nodes keep their labels, and existing edges keep their names. When a new extraction merges with an existing node, and the existing chain is a prefix of the new chain, the node gets the longer chain. For example, an existing Car node can become a HybridCar node.




