Deduplication, observability, and CLI settings

Settings and constructs that sit outside MemorySettings for Configuration reference: the DeduplicationConfig dataclass and how it follows ResolutionConfig, the observability factory, and CLI configuration — plus how invalid values are validated.

Deduplication configuration

DeduplicationConfig is a dataclass from neo4j_agent_memory.memory.long_term. It belongs to the bolt LongTermMemory constructor; it is not a MemorySettings group or a MemoryClient constructor argument. There is no DeduplicationStrategy enum and no NAM_DEDUPLICATION__…​ environment family; variables with that prefix are ignored.

Since 0.7 the thresholds live on ResolutionConfig (Resolution configuration), and both write paths use them:

  • Message ingestion resolves extracted mentions with OntologyResolver, the resolver strategy="composite" builds on bolt, and bands them with auto_merge_threshold and review_threshold.

  • MemoryClient builds its long-term store with DeduplicationConfig.from_resolution_config(settings.resolution), which copies auto_merge_threshold, review_threshold (as flag_threshold), fuzzy_threshold, and candidate_limit (as max_candidates). When the configured resolver is an OntologyResolver, add_entity delegates its duplicate check to that resolver, so it bands exactly like ingestion. The dataclass thresholds drive the embedding-similarity check only with any other resolver.

Construct the dataclass yourself only when you build a LongTermMemory directly. Derive it from resolution settings so the two paths cannot drift:

from neo4j_agent_memory.config.settings import ResolutionConfig
from neo4j_agent_memory.memory.long_term import DeduplicationConfig, LongTermMemory

config = DeduplicationConfig.from_resolution_config(
    ResolutionConfig(auto_merge_threshold=0.95, review_threshold=0.88)
)
# Use only when constructing a store explicitly with your connected graph client.
store = LongTermMemory(graph_client, embedder=embedder, deduplication=config)

add_entity checks only when an embedder is configured; add_entity(…​, deduplicate=False) disables checking for that call. Per-entity-type thresholds belong on the ontology: EntityTypeDef.resolution_threshold and EntityTypeDef.review_threshold. See Deduplication and provenance for all fields and review/merge operations.

Observability configuration

There is no ObservabilityConfig on MemorySettings and no NAM_OBSERVABILITY__…​ family. Use the observability factory and provider SDK settings.

Install the extra for the provider you use: opentelemetry adds the OpenTelemetry API, SDK and OTLP exporter, and opik adds Opik. See Python extras.

pip install 'neo4j-agent-memory[opentelemetry]==0.7.0'
# Or: pip install 'neo4j-agent-memory[opik]==0.7.0'

This fragment assumes a connected MemoryClient named client and a query string, inside an async function:

from neo4j_agent_memory.observability import get_tracer

tracer = get_tracer(
    provider="opentelemetry", service_name="my-agent-memory",
    endpoint="http://localhost:4317",
)
# Or: get_tracer(provider="opik", project_name="my-agent-memory")

async with tracer.async_span("entity-search") as span:
    span.set_attribute("query_length", len(query))
    result = await client.long_term.search_entities(query)

get_tracer accepts auto, opentelemetry, opik, and noop; auto-detection depends on installed libraries. Instrument the operations you intend to trace. OpenTelemetry export requires an explicit endpoint and an installed OTLP exporter; merely setting OTEL_EXPORTER_OTLP_ENDPOINT does not install an exporter on this tracer. Use tracer.span for a synchronous context manager or tracer.async_span for an async one.

CLI configuration

The CLI exposes command-specific Click options and environment aliases; see CLI reference. It does not automatically read .neo4j-memory.yaml, nor does it implement NAM_CLI__…​. An extraction --schema argument is a YAML EntitySchemaConfig file path, not a CLI settings file or named built-in schema; use --gliner-schema for a built-in template name and --ontology for an ontology document.

Validation

Numeric constraints appear in each field table. Invalid enum values or unknown constructor/nested fields raise Pydantic ValidationError, and so does a ResolutionConfig whose review_threshold exceeds its auto_merge_threshold. Missing optional provider packages may instead fail during provider construction; connection and model requests have their own errors.

from pydantic import ValidationError
from neo4j_agent_memory.config.settings import ResolutionConfig

try:
    ResolutionConfig(semantic_threshold=1.5)
except ValidationError as exc:
    print(exc.errors()[0]["type"])  # less_than_equal