# How Memory Decay and Auto-Forgetting Work in AgentMemory Using the Ebbinghaus Curve

> Understand how AgentMemory uses the Ebbinghaus curve for memory decay and auto-forgetting. Discover TTL-based decay, deduplication, and pruning for efficient memory management.

- Repository: [Rohit Ghumare/agentmemory](https://github.com/rohitg00/agentmemory)
- Tags: deep-dive
- Published: 2026-05-10

---

**AgentMemory approximates the Ebbinghaus forgetting curve through a configurable `auto-forget` function that performs three distinct sweeps—TTL-based decay, contradiction-driven deduplication, and low-value observation pruning—to automatically remove stale memories without manual intervention.**

The `rohitg00/agentmemory` repository encodes the psychology of human forgetting into its storage architecture. Rather than retaining all data indefinitely, the system implements a practical approximation of the Ebbinghaus forgetting curve that degrades and purges memories based on age, redundancy, and importance scores. This automatic decay ensures AI agents maintain compact, high-relevance working memory.

## TTL-Based Decay: The `forgetAfter` Timestamp

The first sweep of the auto-forget process handles **time-to-live (TTL) expiration**, mirroring how the Ebbinghaus curve predicts memory usefulness decaying to near-zero over time. Each `Memory` object in the schema can carry a `forgetAfter` field—a timestamp indicating when the memory should naturally expire.

When the auto-forget routine executes, it iterates through all memories and compares `mem.forgetAfter` against the current system time. If the current time exceeds this TTL, the memory is permanently deleted and an audit entry is recorded.

In [`src/functions/auto-forget.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/functions/auto-forget.ts), this logic is implemented at lines 24-45:

```typescript
// Conceptual implementation based on source analysis
for (const mem of memories) {
  if (mem.forgetAfter && new Date() > new Date(mem.forgetAfter)) {
    await deleteMemory(mem.id);
    await auditLog({ reason: "ttl-expired", memoryId: mem.id });
  }
}

```

To set a decay point when creating a memory:

```typescript
await sdk.trigger({
  function_id: "mem::remember",
  payload: {
    content: "Quarterly revenue projections",
    forgetAfter: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
  },
});

```

## Contradiction-Driven Forgetting: Similarity-Based Pruning

The Ebbinghaus curve indicates that memories are reinforced through distinct repetition, while highly similar inputs create redundancy. AgentMemory treats near-identical memories as contradictions that should collapse into a single authoritative entry.

The system calculates **token-level similarity** between memory pairs. If the similarity score exceeds the `CONTRADICTION_THRESHOLD` (hardcoded at **0.9**), the older memory is marked with `isLatest = false` and effectively forgotten, while the newer entry is preserved.

This sweep occurs at lines 94-140 of [`src/functions/auto-forget.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/functions/auto-forget.ts). The implementation:

1. Computes vector similarity between candidate memories
2. Compares against the 0.9 threshold
3. Updates the older memory’s status and creates an audit entry with reason `"auto-forget contradiction"`

```typescript
// Result structure for contradiction detection
{
  contradictions: [
    { memoryA: "mem-789", memoryB: "mem-101", similarity: 0.94 }
  ]
}

```

## Low-Value Observation Pruning: The Decay Tail

The final sweep targets the long tail of the Ebbinghaus curve—observations that have decayed to negligible relevance. AgentMemory deletes observations older than **180 days** with an `importance` score ≤ **2**, considering these to have reached the asymptotic bottom of the retention curve.

At lines 158-165 of [`src/functions/auto-forget.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/functions/auto-forget.ts), the system:

1. Filters observations by age (>`180` days) and importance (`≤ 2`)
2. Removes the observation entries
3. Dereferences any associated image files to prevent orphaned storage
4. Logs the action for audit trails

This aggressive pruning prevents the knowledge base from accumulating "memory noise"—trivial details that interfere with retrieval performance.

## Triggering the Auto-Forget Process

The decay mechanism runs through two primary invocation paths registered in the system core.

### Automatic Startup Execution

The auto-forget function is registered in [`src/index.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/index.ts) at lines 50-52 and executes automatically when the AgentMemory server initializes. This ensures the knowledge base is sanitized before processing new agent operations.

### REST API Endpoint

For manual maintenance or cron-scheduled execution, the system exposes an HTTP endpoint at `/agentmemory/auto-forget` defined in [`src/triggers/api.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/triggers/api.ts) (lines 991-1004). This allows external schedulers to trigger decay sweeps during low-traffic periods.

### Dry-Run Mode for Safe Testing

Both invocation methods support a `dryRun` flag that simulates the pruning process without performing destructive operations. When enabled, the function returns an `AutoForgetResult` object listing what would be deleted without removing actual data.

Execute a dry-run via curl:

```bash
curl -X POST http://localhost:3000/agentmemory/auto-forget \
     -H "Content-Type: application/json" \
     -d '{"dryRun": true}'

```

Or programmatically:

```typescript
const result = await sdk.trigger({
  function_id: "mem::auto-forget",
  payload: { dryRun: false },
});

// Result contains three arrays:
console.log(result.ttlExpired);      // ["mem-123", "mem-456"]
console.log(result.contradictions);  // Similarity conflicts
console.log(result.lowValueObs);     // ["obs-202"]

```

## Summary

- **TTL decay** uses the `forgetAfter` timestamp in [`src/functions/auto-forget.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/functions/auto-forget.ts) (lines 24-45) to delete memories at their predicted expiration point.
- **Contradiction detection** collapses redundant memories with >0.9 similarity, marking older entries as stale (lines 94-140).
- **Low-value pruning** removes observations older than 180 days with importance ≤ 2 (lines 158-165).
- **Invocation options** include automatic startup execution ([`src/index.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/index.ts) lines 50-52) and the `/agentmemory/auto-forget` REST endpoint ([`src/triggers/api.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/triggers/api.ts) lines 991-1004).
- **Dry-run mode** enables safe testing of decay policies without data loss.

## Frequently Asked Questions

### How does the Ebbinghaus curve relate to the `forgetAfter` field?

The `forgetAfter` field implements the curve's prediction that memory retention drops exponentially over time. By setting a TTL, developers encode the specific point at which a memory's retrieval strength falls below usable thresholds, allowing the system to automatically purge the data when the curve predicts it will be effectively forgotten.

### What is the `CONTRADICTION_THRESHOLD` and why is it set to 0.9?

The `CONTRADICTION_THRESHOLD` is a similarity constant (0.9) that determines when two memories are considered redundant reinforcement rather than distinct learning. When token-level similarity exceeds 90%, the system treats the memories as duplicates of the same fact and preserves only the most recent version, preventing the knowledge base from bloating with repetitive observations.

### Can auto-forget be run without deleting data?

Yes. The `dryRun` parameter, available in both the REST API and programmatic triggers, executes the full analysis sweep without performing deletions. It returns an `AutoForgetResult` object containing arrays of `ttlExpired`, `contradictions`, and `lowValueObs` IDs that would be removed, enabling administrators to preview the impact before committing changes.

### What happens to image references when observations are pruned?

During the low-value observation sweep (lines 158-165), the system dereferences associated image files while deleting the observation records. This prevents orphaned storage artifacts from accumulating in the backing file system or object storage, ensuring that visual memory attachments decay alongside their textual counterparts.