Entity and relationship operations
Entity CRUD, search, and relationship operations from LongTermMemory API reference. Signatures show types, keyword-only arguments (*), and defaults; they are reference declarations, not calls to execute directly.
Entity operations (bolt)
add_entity
On Bolt, entity writes merge by exact (name, type), including when deduplicate=False. As of SDK 0.6.0, on an existing-node match add_entity re-reads the matched node and returns the entity carrying its persisted id, so a manual Cypher readback is no longer needed before linking repeated entities. The one exception is a node written by something other than this library that has no id property; that node is left as-is and the call returns the freshly generated id instead, since it cannot be adopted safely. The document tutorial still reads back the exact name/type match, but to reject ambiguity across extraction results, not to work around an ID bug.
Add an entity and return (Entity, DeduplicationResult). Geocoding and enrichment flags default to True, but run only when their providers are configured. There is no confidence keyword; attributes and metadata are distinct fields.
The duplicate check runs when deduplicate=True and an embedding was generated. In 0.7.0, when the client’s resolver is an OntologyResolver (the Bolt default, resolution.strategy="composite"), the check delegates to it, so add_entity uses the same bands as message ingestion: merge at ResolutionConfig.auto_merge_threshold (0.90) and a pending SAME_AS review edge at review_threshold (0.85). See Tune entity resolution.
async def add_entity(
name: str,
entity_type: EntityType | str,
*,
subtype: str | None=None,
description: str | None=None,
aliases: list[str] | None=None,
attributes: dict[str, Any] | None=None,
resolve: bool=True,
generate_embedding: bool=True,
deduplicate: bool=True,
geocode: bool=True,
enrich: bool=True,
coordinates: tuple[float, float] | None=None,
metadata: dict[str, Any] | None=None,
) -> tuple[Entity, DeduplicationResult]: ...
| Parameter | Description |
|---|---|
|
Entity name |
|
Entity type (PERSON, OBJECT, LOCATION, EVENT, ORGANIZATION) |
|
Optional subtype (e.g., VEHICLE for OBJECT) |
|
Optional description |
|
Optional list of alternative names |
|
Optional additional attributes |
|
Whether to resolve against existing entities |
|
Whether to generate embedding |
|
Whether to check for duplicate entities |
|
Whether to geocode LOCATION entities (requires geocoder) |
|
Whether to queue for background enrichment |
|
Optional (latitude, longitude) tuple to set directly |
|
Optional metadata |
get_entity_by_name
Return an exact name match or None. This method does not accept an entity-type filter.
async def get_entity_by_name(name: str) -> Entity | None: ...
| Parameter | Description |
|---|---|
|
Entity name to search for (checks name, canonical_name, aliases) |
search_entities
Semantic search with entity-type and similarity-threshold controls.
async def search_entities(
query: str,
*,
entity_types: list[EntityType | str] | None=None,
limit: int=10,
threshold: float=0.7,
) -> list[Entity]: ...
| Parameter | Description |
|---|---|
|
Search query |
|
Optional filter by entity types |
|
Maximum results |
|
Minimum similarity threshold |
There are no public get_entity, update_entity, or delete_entity wrappers in these Python stores. For bolt, use an application-specific graph query when the supported operations do not cover a mutation. NAMS endpoint existence does not imply a Python wrapper; consult REST API mappings.
Relationships (bolt)
add_relationship
Create an entity relationship. source and target accept Entity models or UUIDs.
async def add_relationship(
source: Entity | UUID,
target: Entity | UUID,
relationship_type: str,
*,
description: str | None=None,
confidence: float=1.0,
valid_from: datetime | None=None,
valid_until: datetime | None=None,
attributes: dict[str, Any] | None=None,
message_id: str | None=None,
evidence: str | None=None,
extractor: str | None=None,
derived: bool=False,
) -> Relationship: ...
| Parameter | Description |
|---|---|
|
Source entity or ID |
|
Target entity or ID |
|
Type of relationship |
|
Optional description |
|
Confidence score |
|
Start of validity |
|
End of validity |
|
Optional additional attributes |
|
Id of the message the relationship was asserted from, appended to |
|
Evidence snippet, such as the sentence the relationship was read from, appended to |
|
Name of the extractor or caller asserting the relationship, stored on |
|
Whether the relationship is derived (for example an inverse mirror) rather than observed. Folded with AND across calls, so one call with |
The current implementation includes attributes on the returned model but does not pass them to the graph write. Do not depend on arbitrary relationship attributes surviving a later read through this method.
With validation_mode="strict", add_relationship raises ValidationError when the configured ontology does not declare relationship_type or does not permit it between the two endpoints' labels.
If source or target does not resolve to a persisted :Entity node — a stale id, or the freshly generated id add_entity falls back to for a matched node that has no id property (see add_entity above) — add_relationship raises NotFoundError rather than silently returning a Relationship the graph does not contain. Re-adding an already-stored (source, target, relationship_type) triple does not raise: the MERGE keeps the original edge, and the returned Relationship.id is the id already stored on that edge, not a newly generated one.
get_related_entities
Get entities related to a given entity.
async def get_related_entities(
entity: Entity | UUID,
*,
relationship_types: list[str] | None=None,
depth: int=1,
) -> list[tuple[Entity, Relationship]]: ...
| Parameter | Description |
|---|---|
|
Entity or ID to find relations for |
|
Optional filter by relationship types |
|
Traversal depth |
Models
Import these Pydantic models from neo4j_agent_memory.memory.long_term. IDs are UUIDs, and inherited memory fields are shown below.
Entity
Pydantic model; inherited memory-entry fields are included.
| Field | Type | Default | Description |
|---|---|---|---|
|
|
|
Unique identifier. |
|
|
|
Creation time. |
|
|
|
Last update time, if updated. |
|
|
|
Embedding vector, if one was generated. |
|
|
|
Arbitrary key-value metadata, stored as JSON. |
|
|
|
Entity name |
|
|
|
Resolved canonical name |
|
|
|
Entity type (PERSON, OBJECT, LOCATION, EVENT, ORGANIZATION) |
|
|
|
Entity subtype (e.g., VEHICLE for OBJECT) |
|
|
|
Entity description |
|
|
|
Confidence score |
|
|
|
Alternative names |
|
|
|
Additional entity attributes |
|
|
|
Source message/document ID |
Relationship
Pydantic model; inherited memory-entry fields are included.
| Field | Type | Default | Description |
|---|---|---|---|
|
|
|
Unique identifier. |
|
|
|
Creation time. |
|
|
|
Last update time, if updated. |
|
|
|
Embedding vector, if one was generated. |
|
|
|
Arbitrary key-value metadata, stored as JSON. |
|
|
|
Source entity ID |
|
|
|
Target entity ID |
|
|
|
Relationship type |
|
|
|
Relationship description |
|
|
|
Confidence score |
|
|
|
Start of validity |
|
|
|
End of validity |
|
|
|
Additional relationship attributes |
Entity.display_name prefers its canonical name; Entity.full_type returns type plus optional subtype. Entity.entity_type resolves a known enum value or None for custom types.