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

name

Entity name

entity_type

Entity type (PERSON, OBJECT, LOCATION, EVENT, ORGANIZATION)

subtype

Optional subtype (e.g., VEHICLE for OBJECT)

description

Optional description

aliases

Optional list of alternative names

attributes

Optional additional attributes

resolve

Whether to resolve against existing entities

generate_embedding

Whether to generate embedding

deduplicate

Whether to check for duplicate entities

geocode

Whether to geocode LOCATION entities (requires geocoder)

enrich

Whether to queue for background enrichment

coordinates

Optional (latitude, longitude) tuple to set directly

metadata

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

name

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

query

Search query

entity_types

Optional filter by entity types

limit

Maximum results

threshold

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

Source entity or ID

target

Target entity or ID

relationship_type

Type of relationship

description

Optional description

confidence

Confidence score

valid_from

Start of validity

valid_until

End of validity

attributes

Optional additional attributes

message_id

Id of the message the relationship was asserted from, appended to r.source_message_ids (at most 25 ids are kept)

evidence

Evidence snippet, such as the sentence the relationship was read from, appended to r.evidence (at most 3 snippets are kept)

extractor

Name of the extractor or caller asserting the relationship, stored on r.extractor

derived

Whether the relationship is derived (for example an inverse mirror) rather than observed. Folded with AND across calls, so one call with derived=False clears it for that edge

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 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

Entity or ID to find relations for

relationship_types

Optional filter by relationship types

depth

Traversal depth

get_entity_relationships

Get relationships for an entity by name.

async def get_entity_relationships(entity_name: str) -> list[tuple[Entity, Relationship]]: ...
Parameter Description

entity_name

Name of the entity

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

id

UUID

new UUID

Unique identifier.

created_at

datetime

current UTC time

Creation time.

updated_at

datetime | None

None

Last update time, if updated.

embedding

list[float] | None

None

Embedding vector, if one was generated.

metadata

dict[str, Any]

{}

Arbitrary key-value metadata, stored as JSON.

name

str

required

Entity name

canonical_name

str | None

None

Resolved canonical name

type

str

required

Entity type (PERSON, OBJECT, LOCATION, EVENT, ORGANIZATION)

subtype

str | None

None

Entity subtype (e.g., VEHICLE for OBJECT)

description

str | None

None

Entity description

confidence

float

1.0

Confidence score

aliases

list[str]

[]

Alternative names

attributes

dict[str, Any]

{}

Additional entity attributes

source_id

UUID | None

None

Source message/document ID

Relationship

Pydantic model; inherited memory-entry fields are included.

Field Type Default Description

id

UUID

new UUID

Unique identifier.

created_at

datetime

current UTC time

Creation time.

updated_at

datetime | None

None

Last update time, if updated.

embedding

list[float] | None

None

Embedding vector, if one was generated.

metadata

dict[str, Any]

{}

Arbitrary key-value metadata, stored as JSON.

source_id

UUID

required

Source entity ID

target_id

UUID

required

Target entity ID

type

str

required

Relationship type

description

str | None

None

Relationship description

confidence

float

1.0

Confidence score

valid_from

datetime | None

None

Start of validity

valid_until

datetime | None

None

End of validity

attributes

dict[str, Any]

{}

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.