Explore long-term memory
Finds facts in long-term memory and checks relationships and evidence.
Goal
Answer questions that depend on remembered history, decisions, states, people, projects, systems, incidents, or prior observations.
Long-term memory combines semantic retrieval with a graph. Use each tool for its specific job:
search_longterm_memoryfinds relevant entity and fact anchors.expand_longterm_memory_graphopens the local relational neighborhood.search_longterm_memory_structureranks entities by an explicit global metric.analyze_longterm_memory_subgraphmeasures a seed-bounded local graph.open_longterm_memory_evidenceopens the original episodes behind facts.
A plausible hit is evidence to inspect, not automatically the final answer.
When to Use Memory
Use memory when the request may depend on something previously observed, stored, decided, discussed, or changed. This includes historical questions, status reconstruction, summaries, diagnoses, dependencies, prior incidents, and source verification.
Do not use memory for general knowledge, pure rewriting, calculations whose input is already present, or tasks fully answerable from the visible chat.
Tool Selection
Semantic Search
Use search_longterm_memory as the normal entry point. Send all independent
search needs together in queries:
{
"queries": [
"Software",
"Module der Software"
],
"limit_per_query": 5
}
Each list item is one focused natural-language query. Multi-word names remain one
query. Do not use AND, OR, long keyword lists, or repeat the same weak query in
separate calls.
The output contains one results group per input query in the same order. Each
group repeats the compact query text so its matches remain unambiguous; no query
index is returned.
Matches are either:
kind: entity, with an entity UUID and optional structural profile;kind: fact, with complete source, relation, fact text, target, times, and evidence references.
There is no query target and no semantic score in the output. Decide relevance from the user question and the returned content. Episodes are not regular search matches.
cross_query_entities.query_coverage only counts in how many result groups an
entity occurred during this single tool call. It is not a relevance score and is
not persisted.
Local Expansion
Use expand_longterm_memory_graph after finding entity UUIDs when surrounding
relations matter. Expansion is undirected for traversal: both endpoints are
followed, while the stored source and target remain unchanged in the output.
Start with depth: 1. Use depth: 2 only when the first neighborhood leaves an
important gap. Depth greater than two is unsupported.
Depth counts complete entity-to-entity relation hops. Graphiti may physically store a fact as an intermediate node, but that storage node does not consume a public hop: depth one already returns entity, relation, and the connected entity.
Optional filters are exact:
edge_typesmatches exact relation names;node_labelsmatches available Graphiti entity labels.
There is no direction parameter and no time filter. If truncated is true and
the remaining graph matters, repeat the identical request with next_cursor.
Never edit or reuse a cursor with changed seeds, scope, depth, or filters.
Global Structural Search
Use search_longterm_memory_structure when the question concerns the graph as a
whole, such as highly connected entities, entities supported by many episodes, or
entities with varied relation types. Ask only for the metric that has a clear
meaning for the question:
{
"rankings": [
{
"metric": "distinct_neighbors",
"top_k": 10
},
{
"metric": "distinct_episode_count",
"top_k": 10
}
],
"filters": {
"relation_types": [],
"node_labels": [],
"minimum_relation_count": 0
}
}
Supported metrics are:
relation_count: adjacent fact edges;distinct_neighbors: directly connected entities;distinct_episode_count: distinct supporting episode UUIDs;relation_type_count: distinct exact relation names.
Rankings are separate. There is no balanced ranking or hidden combined score.
ranking_coverage only says that an entity appeared in several explicitly
requested top-k lists in this call.
Local Structural Analysis
Use analyze_longterm_memory_subgraph to measure the graph bounded by seeds and
depth. It separates:
local_metrics, calculated only inside the expanded subgraph;global_profile, calculated across the selected dataspace scope.
Local values include relation and neighbor counts, seed coverage, repeated relation types, and same-source or same-target patterns. They are measurements, not a declaration of importance.
Evidence
Use open_longterm_memory_evidence when the user asks for sources or original
wording, when facts conflict, when chronology matters, or when an important claim
needs verification.
Pass fact edge_uuids directly. The tool resolves and groups the supporting
episodes per edge. Limit episode count and excerpt size to what the answer needs.
An episode count is not a count of independent documents or sources.
Memory Creation
Use create_longterm_memory only for explicit durable-memory intent or a workflow
that clearly requires storage. Do not switch from retrieval into writing without
that intent.
Structural Profiles
An entity profile describes graph structure:
relation_countdistinct_neighborsdistinct_episode_countrelation_type_countrelation_histogramdataspace_percentiles
A percentile of 0.94 means the raw value is greater than that of about 94% of
entities in percentile_scope. It is not probability, relevance, truth, quality,
or confidence. Always interpret percentiles together with their raw metric and
scope.
Time Fields
Tools may return created_at, reference_time, valid_at, invalid_at, and
expired_at. They have different meanings. Do not infer automatically that a
fact is current, invalid, superseded, or causally relevant. A missing field means
unknown or null.
There are no structured time filters. For relative-time questions, resolve the calendar wording when possible, include a concise date or event phrase in a semantic query, then inspect returned fact and evidence times. If the time cannot be resolved, state the uncertainty rather than inventing a date.
Retrieval Procedure
- Extract concrete anchors and independent information needs from the request.
- Batch the focused needs into one semantic search call.
- Read each query-labeled result group and select relevant entity or edge UUIDs.
- For a narrow, exact, unambiguous lookup, answer if the evidence is sufficient.
- For summaries, history, causes, dependencies, diagnoses, or ambiguity, take at least one focused follow-up: local expansion, another genuinely different semantic query batch, local analysis, global ranking, or evidence.
- Open evidence selectively for claims whose source, wording, chronology, or conflict matters.
- Stop when the answer is supported and further graph work would be off-topic.
Sparse Results and Conflicts
If search is weak, try a genuinely simpler query such as the main entity name or the entity plus one event term. Do not issue cosmetic variations indefinitely.
If facts conflict:
- keep both visible;
- compare their raw time fields without assuming a lifecycle interpretation;
- open evidence for the relevant edges;
- explain the conflict and remaining uncertainty.
Never invent missing memory.
Answer Construction
Answer primarily from entities and facts. Use episode excerpts as supporting evidence. Separate directly stored facts from your inference. For summaries, group information into a few useful themes instead of reproducing raw YAML. For historical answers, mention known dates and clearly label unresolved chronology.
Anti-Patterns
Do not:
- treat graph metrics or percentiles as semantic relevance;
- request a balanced score;
- assume edge direction has domain meaning;
- invent time filters or interpret missing times as a status;
- use episodes as the default search surface;
- pass episode UUIDs to the evidence tool instead of edge UUIDs;
- assume query history or hit counters exist across calls;
- expand blindly when one focused search already answers a narrow lookup;
- stop at one plausible hit for a non-trivial historical or relational question.
