Skip to content

Consolidation Operations

This page documents the HTTP API endpoints for triggering and monitoring memory consolidation tasks. Consolidation is AutoMem’s background maintenance system that mimics biological memory processes — decay, creative association, clustering, and forgetting. An identity task also merges duplicate entities and synthesizes identity definitions for Entity nodes.

For information about the consolidation engine’s internal architecture and algorithms, see Consolidation Engine.


AutoMem provides two REST endpoints for consolidation operations:

EndpointMethodPurposeAuth
/consolidatePOSTManually trigger consolidation tasksAPI token
/consolidate/statusGETQuery scheduler state and last run timesAPI token

The consolidation system runs automatically on scheduled intervals (configurable via environment variables), but these endpoints allow manual triggers for testing, debugging, or forcing immediate execution.


graph TB
    subgraph "API Layer"
        PostConsolidate["/consolidate<br/>POST endpoint"]
        GetStatus["/consolidate/status<br/>GET endpoint"]
    end

    subgraph "Consolidation Module"
        Scheduler["ConsolidationScheduler<br/>(Background thread)"]
        Consolidator["MemoryConsolidator<br/>(Task executor)"]
    end

    subgraph "Data Stores"
        FalkorGraph[("FalkorDB Graph<br/>GRAPH_NAME")]
        QdrantVectors[("Qdrant Vectors<br/>COLLECTION_NAME")]
        ControlNode["ConsolidationControl node<br/>(Graph metadata)"]
        RunHistory["ConsolidationRun nodes<br/>(Execution logs)"]
    end

    PostConsolidate -->|"Trigger task"| Consolidator
    GetStatus -->|"Query state"| Scheduler
    GetStatus -->|"Read history"| ControlNode
    GetStatus -->|"Read history"| RunHistory

    Scheduler -->|"Periodic check"| Consolidator
    Consolidator -->|"Read memories"| FalkorGraph
    Consolidator -->|"Semantic search"| QdrantVectors
    Consolidator -->|"Update relevance"| FalkorGraph
    Consolidator -->|"Create edges"| FalkorGraph
    Consolidator -->|"Archive/delete"| FalkorGraph
    Consolidator -->|"Merge entities, synthesize identities"| FalkorGraph
    Consolidator -->|"Record runs"| ControlNode
    Consolidator -->|"Record runs"| RunHistory

Manually trigger one or more consolidation tasks.

ParameterTypeRequiredDefaultDescription
modestringNo"full"Task type to execute: decay, creative, cluster, forget, identity, or full
dry_runbooleanNotrueIf true, creative, cluster, forget, and identity report what they would do without writing. decay has no dry-run guard and always updates relevance scores, so mode="decay" and mode="full" write even with the default dry_run: true
TaskDefault IntervalDescriptionConfiguration Variable
decay86400s (24 hours)Apply exponential relevance decay to memoriesCONSOLIDATION_DECAY_INTERVAL_SECONDS
creative604800s (7 days)Discover hidden associations (REM-like)CONSOLIDATION_CREATIVE_INTERVAL_SECONDS
cluster2592000s (30 days)Group semantically similar memoriesCONSOLIDATION_CLUSTER_INTERVAL_SECONDS
forget0 (disabled)Archive/delete low-relevance memoriesCONSOLIDATION_FORGET_INTERVAL_SECONDS
identity604800s (7 days) when IDENTITY_SYNTHESIS_ENABLED is true, otherwise 0 (disabled)Merge duplicate entities and synthesize identity definitions for Entity nodes (requires an OpenAI client)CONSOLIDATION_IDENTITY_INTERVAL_SECONDS
fullN/AExecute decay, creative, cluster, identity (when IDENTITY_SYNTHESIS_ENABLED is true), then forget in sequenceN/A

mode="identity" runs whenever you request it. IDENTITY_SYNTHESIS_ENABLED only controls whether full includes the identity step and sets the default scheduled interval.

sequenceDiagram
    participant Client
    participant API as "POST /consolidate"
    participant Consolidator as MemoryConsolidator
    participant FalkorDB
    participant Qdrant

    Client->>API: "POST /consolidate<br/>{mode: 'decay', dry_run: false}"
    API->>API: "Validate API token"

    API->>Consolidator: "consolidate(mode=mode, dry_run=dry_run)"

    alt dry_run=true
        Consolidator-->>API: "Results (no writes, except decay scores)"
        API-->>Client: "200 {status: 'success', consolidation: {...}}"
    else dry_run=false
        Consolidator->>FalkorDB: "Read Memory nodes"
        Consolidator->>Qdrant: "Search vectors (if needed)"
        Consolidator->>FalkorDB: "Update nodes/edges"
        Consolidator-->>API: "Results + metrics"
        API->>FalkorDB: "persist_run() — Create ConsolidationRun node"
        API-->>Client: "200 {status: 'success', consolidation: {...}}"
    end

The consolidation object is the engine’s result. It echoes mode and dry_run, adds started_at and completed_at timestamps plus a success flag, and nests each task’s statistics under steps, keyed by task name. Per-task statistics are not returned at the top level of the object.

{
"status": "success",
"consolidation": {
"mode": "decay",
"dry_run": false,
"started_at": "2025-01-15T08:00:00+00:00",
"steps": {
"decay": {
"processed": 42,
"avg_relevance_before": 0.61,
"avg_relevance_after": 0.59,
"distribution": { "high": 30, "medium": 9, "low": 2, "archive": 1 }
}
},
"completed_at": "2025-01-15T08:00:01+00:00",
"success": true
}
}

For mode="full", steps contains one entry per task that ran. The tasks run in the order decay, creative, cluster, identity, forget, and each reports its own keys:

{
"status": "success",
"consolidation": {
"mode": "full",
"dry_run": false,
"started_at": "2025-01-15T08:00:00+00:00",
"steps": {
"decay": {
"processed": 42,
"avg_relevance_before": 0.61,
"avg_relevance_after": 0.59,
"distribution": { "high": 30, "medium": 9, "low": 2, "archive": 1 }
},
"creative": { "discovered": 8, "created": 8, "sample_associations": [] },
"cluster": { "clusters_found": 3, "meta_memories_created": 3, "sample_clusters": [] },
"identity": { "skipped": true, "reason": "Identity synthesis is disabled" },
"forget": { "examined": 120, "archived": [], "deleted": [], "preserved": 120, "protected": [] }
},
"completed_at": "2025-01-15T08:00:10+00:00",
"success": true
}
}

The sample_associations and sample_clusters arrays hold the first 3 associations and the first 2 clusters found. They are shown empty here to keep the example short.

A full run that completes always includes an identity entry. When IDENTITY_SYNTHESIS_ENABLED is false, it is reported as skipped, as shown above.

If the engine hits an internal failure, the endpoint still returns 200 OK, with success set to false and an error string inside consolidation. Only an exception raised outside the engine’s consolidate() call, such as a failure while persisting the run, returns the 500 shape below.

{
"error": "Consolidation failed",
"details": "Connection refused"
}

Trigger full consolidation:

Terminal window
curl -X POST https://your-automem-instance/consolidate \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode": "full", "dry_run": false}'

Trigger single task (decay):

Terminal window
curl -X POST https://your-automem-instance/consolidate \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode": "decay", "dry_run": false}'

Authentication: API token required

Query the current state of the consolidation scheduler and retrieve execution history.

The number of history records returned is controlled server-side by CONSOLIDATION_HISTORY_LIMIT (default: 20); this endpoint accepts no query parameters.

{
"status": "success",
"next_runs": {
"decay": "In 7 hour(s)",
"creative": "In 3 day(s)",
"cluster": "In 24 day(s)",
"forget": "Disabled",
"identity": "Disabled"
},
"history": [
{
"id": "3f2b8c1d4e5a4f6b9a7c0d1e2f3a4b5c",
"mode": "decay",
"task": "decay",
"success": true,
"dry_run": false,
"started_at": "2025-01-15T08:00:00+00:00",
"completed_at": "2025-01-15T08:00:01+00:00",
"result": "{\"mode\": \"decay\", \"dry_run\": false, \"started_at\": \"2025-01-15T08:00:00+00:00\", \"steps\": {\"decay\": {\"processed\": 42, \"avg_relevance_before\": 0.61, \"avg_relevance_after\": 0.59, \"distribution\": {\"high\": 30, \"medium\": 9, \"low\": 2, \"archive\": 1}}}, \"completed_at\": \"2025-01-15T08:00:01+00:00\", \"success\": true}"
}
],
"thread_alive": true,
"tick_seconds": 60
}
FieldTypeDescription
statusstringAlways "success"
next_runs.<task>stringHuman-readable time until the task is next due, not a timestamp: "Due now", "In N day(s)", "In N hour(s)" (whole hours, so under an hour reads "In 0 hour(s)"), or "Disabled" when the task’s interval is 0. Keys are decay, creative, cluster, forget, and identity
history[]objectThe properties of one ConsolidationRun node, newest started_at first
history[].idstringRun ID (UUID hex)
history[].modestringMode that was run
history[].taskstringSame value as mode
history[].successbooleanfalse when the engine reported an internal failure
history[].dry_runbooleanWhether the run was a dry run. Dry runs are not recorded by POST /consolidate, and scheduled runs are never dry runs, so records written by those paths show false
history[].started_atstring (ISO 8601)Run start time
history[].completed_atstring (ISO 8601)Run completion time
history[].resultstringThe full consolidation result object, serialized as a JSON string. Parse it to read per-task statistics under steps
thread_alivebooleanWhether the background scheduler thread is active
tick_secondsintegerPolling interval for the scheduler loop

Check last run times and history:

Terminal window
curl "https://your-automem-instance/consolidate/status" \
-H "Authorization: Bearer YOUR_TOKEN"

Consolidation state is persisted in FalkorDB using two node types:

Properties correspond to the CONSOLIDATION_TASK_FIELDS mapping in automem/config.py. A single ConsolidationControl node (with ID controlled by CONSOLIDATION_CONTROL_NODE_ID, defaulting to "global") stores the last run timestamp for each task (decay, creative, cluster, forget, identity, and full).

Each recorded execution (scheduled runs and POST /consolidate calls with dry_run set to false) creates a ConsolidationRun node in FalkorDB. The /consolidate/status endpoint reads the most recent ConsolidationRun nodes ordered by started_at descending, up to the number configured by CONSOLIDATION_HISTORY_LIMIT (default 20).


Consolidation behavior is controlled via environment variables:

VariableDefaultDescription
CONSOLIDATION_TICK_SECONDS60Scheduler loop polling interval
CONSOLIDATION_DECAY_INTERVAL_SECONDS86400Minimum time between decay runs
CONSOLIDATION_CREATIVE_INTERVAL_SECONDS604800Minimum time between creative runs
CONSOLIDATION_CLUSTER_INTERVAL_SECONDS2592000Minimum time between cluster runs
CONSOLIDATION_FORGET_INTERVAL_SECONDS0Minimum time between forget runs (0 = disabled)
IDENTITY_SYNTHESIS_ENABLEDfalseInclude the identity step in full runs (accepts 1, true, or yes)
CONSOLIDATION_IDENTITY_INTERVAL_SECONDS604800 when IDENTITY_SYNTHESIS_ENABLED is true, otherwise 0Minimum time between identity runs (0 = disabled)
CONSOLIDATION_DECAY_IMPORTANCE_THRESHOLD0.3Scheduled decay runs only process memories whose importance is at or above this value; lower-importance memories are skipped. Only the background scheduler passes it. A manual POST /consolidate sends no threshold, so it decays all non-archived memories
CONSOLIDATION_PROTECTED_TYPES"Decision,Insight"Memory types exempt from forget task
CONSOLIDATION_GRACE_PERIOD_DAYS90Days before a memory is eligible for forgetting
CONSOLIDATION_DELETE_THRESHOLD0.0Relevance score below which memories are deleted
CONSOLIDATION_ARCHIVE_THRESHOLD0.0Relevance score below which memories are archived
CONSOLIDATION_HISTORY_LIMIT20Default number of history records to return
CONSOLIDATION_CONTROL_NODE_ID"global"ID of the ConsolidationControl node

Example configuration:

Terminal window
CONSOLIDATION_TICK_SECONDS=30
CONSOLIDATION_DECAY_INTERVAL_SECONDS=1800
CONSOLIDATION_CREATIVE_INTERVAL_SECONDS=3600
CONSOLIDATION_CLUSTER_INTERVAL_SECONDS=14400
CONSOLIDATION_FORGET_INTERVAL_SECONDS=43200
CONSOLIDATION_DECAY_IMPORTANCE_THRESHOLD=0.4

Both POST /consolidate and GET /consolidate/status require authentication using the AUTOMEM_API_TOKEN. Unlike /health, which is exempt from token checks, /consolidate/status is not a public endpoint. Three authentication methods are supported for authenticated endpoints:

  1. Bearer Token (recommended): Authorization: Bearer <token>
  2. Custom Header: X-API-Key: <token>
  3. Query Parameter (discouraged in production): ?api_key=<token>

Requests to authenticated endpoints without valid authentication receive a 401 Unauthorized response.


StatusConditionResponse
401 UnauthorizedMissing or invalid token{"status": "error", "code": 401, "message": "Unauthorized"}
StatusConditionResponse
500 Internal Server ErrorTask execution exception (POST){"error": "Consolidation failed", "details": "<exception message>"}
500 Internal Server ErrorStatus query failure (GET){"error": "Failed to get status", "details": "<exception message>"}
503 Service UnavailableFalkorDB is unavailable (both endpoints, before any work starts){"status": "error", "code": 503, "message": "FalkorDB is unavailable"}

The two 500 handlers log only the exception message at error level, not a stack trace.


The ConsolidationScheduler runs in a background thread started at application initialization. It periodically checks whether each task’s interval has elapsed and executes tasks automatically without manual triggers.

The /consolidate endpoint triggers immediate execution of consolidation tasks regardless of the scheduler’s last run times.