Skip to content

Documentation navigation

Memory and Recall

Choose what agents remember, how they recall it, and when it expires.

#Memory and Recall

A model on its own forgets everything once a conversation gets long enough. Memory is how mAIvn gives an agent a working recollection: it remembers what was said earlier, pulls back the parts that matter for the current question, and learns reusable lessons over time.

Concretely, memory keeps long-running conversations accurate by combining:

  • summarization when thread context grows too large
  • retrieval of relevant memory signals (vector, keyword, graph, skills, insights, resources)
  • asynchronous post-finalize indexing and extraction

#How It Works

Each invocation can include three core stages:

  1. Summarize: compacts history before execution when needed.
  2. Retrieve: injects relevant memory context into the current turn.
  3. Index: persists new memory after the response is returned.

Indexing is asynchronous by design, so latency-sensitive responses are not blocked by persistence work.

#Thread Recall vs Scope-Shared Assets

Memory is intentionally split into two layers:

  • Thread recall: summaries, vector hits, keyword hits, graph neighbors, and other transcript-like recall stay tied to the current thread_id.
  • Scope-shared assets: skills, bound resources, and promoted insights are reusable across future threads within their sharing scope (agent, swarm, project, or org).

This means future threads already benefit from scoped skills and resources. AI-generated insights are narrower by default: auto extraction only supports agent or swarm, and broader reuse happens through portal promotion to project or org.

#Memory Levels

MemoryConfig.level controls recall context size. It does not by itself select retrieval-only or vector-only persistence:

LevelSDK recall context budget
noneDisables ordinary memory processing
glimpse2,000 characters
focus6,000 characters
clarity12,000 characters

Use persistence_mode="persist_none" for retrieval without new persistence, "vector_only" to exclude graph extraction, or "vector_plus_graph" to permit it. Configured SDK memory defaults to enabled, clarity, and vector_plus_graph when those fields are omitted. The runtime and tenant policy can further restrict behavior. Explicit bound-resource access for a schema-bearing request has separate handling; see Structured Output.

#Quick Start

Use a stable thread_id and set scope defaults:

Python
from maivn import (
    Agent,
    MemoryConfig,
    MemoryInsightExtractionConfig,
    MemoryRetrievalConfig,
    MemorySkillExtractionConfig,
)
from maivn.messages import HumanMessage

agent = Agent(
    name="memory_demo",
    system_prompt="Use prior context when relevant.",
    api_key="your-api-key",
    memory_config=MemoryConfig(
        enabled=True,
        level="clarity",  # none | glimpse | focus | clarity
        persistence_mode="vector_plus_graph",
        retrieval=MemoryRetrievalConfig(
            top_k=4,
            skills_enabled=True,
            insights_enabled=True,
            resources_enabled=True,
        ),
        skill_extraction=MemorySkillExtractionConfig(
            enabled=True,
        ),
        insight_extraction=MemoryInsightExtractionConfig(
            enabled=True,
        ),
    ),
)

thread_id = "customer-success-q1"

agent.invoke(
    messages=[HumanMessage(content="Store this rollout plan and owners.")],
    thread_id=thread_id,
)

result = agent.invoke(
    messages=[HumanMessage(content="Who owns the rollout milestones?")],
    thread_id=thread_id,
)

#Scope Memory Assets

Agent and Swarm can define memory assets directly:

  • skills: user-defined reusable skill payloads
  • resources: bound resource payloads (inline content, file, URL, or document reference)

Use add_skill to register and attach a skill, or attach_skill for an existing ID. Constructor skills declarations are only stored locally in this SDK. Constructor resources are uploaded before first invocation; set binding_type to bind them to the scope. These paths do not transmit MemoryAssetsConfig.

Python
agent = Agent(
    name="deploy_agent",
    api_key="your-api-key",
    memory_config=MemoryConfig(
        level="clarity",
    ),
    resources=[
        {
            "name": "deploy-runbook.txt",
            "mime_type": "text/plain",
            "text_content": "Rollback immediately if canary validation fails.",
            "binding_type": "agent",
            "sharing_scope": "agent",
            "tags": ["deploy", "rollback"],
        }
    ],
)
agent.add_skill(
    name="deploy_with_health_checks",
    description="Deploy, run health checks, then cut over traffic.",
    steps=["Deploy the service.", "Check service health before switching traffic."],
)

#Bound Resource Versioning

Scope resource declarations are uploaded once per scope instance. Content hashes support server-side deduplication, but the upload still sends the bytes. Changing a file after registration does not make that same scope upload again.

For an explicit replacement version, use client.resources.upload with ResourceUploadOptions(resource_id=existing_id). The constructor path does not forward resource_id as a replacement request. See SDK Resource Configuration.

#Message Attachments

HumanMessage and RedactedMessage support attachments. Attachment payloads are normalized and sent as document candidates for registration.

Python
from maivn.messages import HumanMessage

message = HumanMessage(
    content="Use the attached runbook for this request.",
    attachments=[
        {
            "name": "runbook.txt",
            "mime_type": "text/plain",
            "text_content": "Escalate if error rate exceeds 2%.",
            "sharing_scope": "project",
            "tags": ["runbook", "ops"],
        }
    ],
)

Supported attachment inputs include content_base64, content_bytes, text_content, and file.

#Per-Invocation Overrides

Override scope defaults per call with memory_config:

Python
from maivn import MemoryConfig, MemoryRetrievalConfig

result = agent.invoke(
    messages=[HumanMessage(content="Use retrieval only for this turn.")],
    thread_id=thread_id,
    memory_config=MemoryConfig(
        level="glimpse",
        retrieval=MemoryRetrievalConfig(
            skills_enabled=True,
            insights_enabled=True,
            resources_enabled=True,
            skill_injection_max_count=3,
            insight_injection_max_count=2,
            resource_injection_max_count=2,
        ),
    ),
)

#Observe Memory and Resource Events

Use event streaming to inspect enrichment phases:

Python
events = []

def on_event(event: dict) -> None:
    if event.get("event") != "enrichment":
        return
    payload = event.get("payload") or {}
    phase = payload.get("phase")
    if isinstance(phase, str) and (
        phase.startswith("memory_") or phase.startswith("document_")
    ):
        events.append(
            {
                "phase": phase,
                "message": payload.get("message"),
                "memory": payload.get("memory"),
            }
        )

agent.events(include="enrichment", on_event=on_event).invoke(
    messages=[HumanMessage(content="Recall the project constraints.")],
    thread_id=thread_id,
)

Common memory phases:

  • memory_summarizing
  • memory_summarized
  • memory_retrieving
  • memory_retrieved
  • memory_indexing
  • memory_graph_extracting
  • memory_indexed
  • memory_skill_extracting
  • memory_insight_extracting

Common resource phases:

  • resource_registering
  • resource_registered
  • resource_dedup_reused
  • resource_version_superseded
  • resource_extracting
  • resource_extracted

payload.memory can include hit counts, per-signal counts (skill_hits, insight_hits, resource_hits), latency, and effective memory level.

#Async Post-Finalize Behavior

Memory extraction can finish after the response stream closes. An extraction-start event or a non-zero retrieval count does not prove that the latest invocation's assets were saved.

Use client.memory.enrichments.list(session_id) or its async alist counterpart to read persisted outcomes. A receipt reports completed or failed and skill, insight, and graph-edge counts. Completed can legitimately mean zero assets. An empty receipt list does not imply completion; if polling, use a bounded retry policy and retain a pending state when no receipt arrives.

#Configuration Reference

Active SDK controls include enabled, level, persistence_mode, retrieval signal toggles and injection counts, and extraction enabled/max_count. Graph retrieval and extraction controls are also available.

The compatibility fields summarization_enabled, candidate_limit, insight_relevance_floor, extraction sharing_scope, confidence_threshold, and min_relevance_score are accepted but not forwarded. Do not rely on them to change behavior. Nested per-call configuration replaces the corresponding nested scope configuration rather than merging each nested field.

See Session Config Models for exact fields, validation, and request behavior. Invocation metadata is ignored; it is not an alternate configuration channel.