Back to blog

Hebbian Co-activation in External Memory Stores

researchmemoryhebbian-learningprior-art

Hebbian Co-activation in External Memory Stores: Implementing Associative Learning as a Runtime Algorithm on Persistent Databases for AI Agent Memory

Author: Rich Jeffries, Firebird Solutions

Date: March 2026

Contact: [email protected]


Abstract

Hebbian learning --- the principle that neurons which fire together wire together --- has been a foundational mechanism in neural network training since Hebb's original formulation in 1949. However, its application has been almost exclusively confined to adjustments of synaptic weights within neural network architectures during training or fine-tuning phases. This paper presents a fundamentally different application: implementing Hebbian co-activation as a runtime algorithm operating on persistent external memory stores, specifically PostgreSQL with the pgvector extension for dense vector similarity. We describe a complete system architecture in which AI agent memories are stored as structured records with associated vector embeddings, linked through typed directed edges whose strength values are dynamically adjusted based on co-activation patterns observed during agent operation. The system implements asymptotic reinforcement functions, time-based decay curves, automated consolidation pipelines, and vector-similarity-driven candidate generation for link formation. We provide concrete implementation details including database schemas, reinforcement algorithms, decay functions, API contracts, and a background consolidation daemon. Two production implementations are described: the original EchoMCP system (2025) using Dapper with raw SQL, and the successor Atamaia platform (2026) using Entity Framework Core with strongly-typed entities. The approach provides AI agents with a form of long-term associative memory that evolves independently of model weights, enabling usage-driven memory organization that more closely parallels biological memory consolidation than time-to-live or static-graph approaches used by existing AI memory systems.


1. Introduction

Large language models operate within a fundamental architectural constraint: their knowledge is frozen at training time, and their working memory is bounded by a fixed context window. While retrieval-augmented generation (RAG) addresses the knowledge-freshness problem by fetching relevant documents at query time, RAG systems treat external memory as a static store --- documents go in, documents come out, and the relationships between them are determined entirely by embedding similarity at retrieval time.

This creates a gap between how AI agents access memory and how biological memory systems work. In biological systems, memories are not isolated records retrieved by similarity search. They form dynamic associative networks where connections between memories strengthen through repeated co-activation and weaken through disuse. The hippocampus does not merely store and retrieve; it actively reorganizes memory traces through consolidation processes that run during sleep and rest states.

Current AI memory systems --- including Mem0, MemGPT/Letta, and Zep --- have made significant progress in providing agents with persistent memory across sessions. However, none of them implement the specific mechanism of Hebbian co-activation learning on their memory stores. They support temporal ordering, semantic similarity, and in some cases graph relationships, but the links between memories are either static (created at ingestion time and never modified) or managed through time-to-live (TTL) expiration policies that treat all memories uniformly based on age rather than usage patterns.

This paper describes a system that applies Hebbian learning principles as a runtime algorithm on an external persistent database. When two memories are accessed in temporal proximity during agent operation --- that is, when they "fire together" --- a typed link between them is either created or strengthened. Links that are repeatedly co-activated approach maximum strength asymptotically. Links that are never re-activated decay over time and are eventually pruned. The result is an associative memory graph that self-organizes based on actual usage patterns, providing agents with a form of long-term memory that is fundamentally different from static RAG retrieval.

1.1 Contributions

This paper makes the following contributions:

  1. A formal description of Hebbian co-activation applied to external database stores, distinguishing it from in-network Hebbian learning during training.
  2. Concrete implementation details including database schemas, reinforcement functions, decay algorithms, and API contracts, sufficient to reproduce the system.
  3. Two production implementations spanning different technology stacks (Dapper/raw SQL and Entity Framework Core), demonstrating the approach is framework-agnostic.
  4. Integration with a broader cognitive architecture including consolidation pipelines, forgetting mechanisms, and hydration systems that consume the Hebbian link graph.
  5. A typed link taxonomy that preserves semantic relationship categories while still permitting strength-based Hebbian dynamics.

2. Background and Related Work

2.1 Hebbian Learning in Neural Networks

Donald Hebb's postulate (1949) states: "When an axon of cell A is near enough to excite cell B and repeatedly or persistently takes part in firing it, some growth process or metabolic change takes place in one or both cells such that A's efficiency, as one of the cells firing B, is increased." This principle has been formalized in various ways within neural network training, most notably through the Hebbian learning rule:

$$\Delta w_{ij} = \eta \cdot x_i \cdot x_j$$

where $\Delta w_{ij}$ is the change in connection weight between neurons $i$ and $j$, $\eta$ is the learning rate, and $x_i$, $x_j$ are the activation values of the respective neurons.

Variations include Oja's rule (which adds normalization to prevent unbounded weight growth), competitive Hebbian learning (used in self-organizing maps), and spike-timing-dependent plasticity (STDP) in spiking neural networks. All of these operate on weights within a neural network during training or adaptation phases.

The critical distinction in this work is that we apply the Hebbian principle not to neural network weights but to explicit link structures in an external persistent database, operating at runtime rather than training time. The "neurons" in our system are discrete memory records; the "synapses" are typed database edges with mutable strength values; and "firing" corresponds to memory access events during agent operation.

2.2 External Memory Stores for AI Agents

Several systems have been developed to provide AI agents with persistent external memory. We summarize the most relevant ones and identify what distinguishes our approach.

2.2.1 Mem0

Mem0 (mem0.ai) provides a memory infrastructure API for AI agents. It stores memories in a vector database with optional graph layers and supports time-to-live (TTL) expiration and relevance scoring. Mem0 raised $24M in Series A funding (October 2025) and secured a partnership as the exclusive memory provider for the AWS Agent SDK.

Key difference: Mem0 uses TTL-based decay, which is time-only --- all memories decay at the same rate regardless of access frequency. There is no mechanism for link strengthening based on co-activation. Memory importance is static or time-dependent, never usage-driven.

2.2.2 MemGPT / Letta

MemGPT (Packer et al., 2023) introduced a tiered memory architecture inspired by operating system virtual memory management. It distinguishes between a message buffer (analogous to RAM), core memory (editable context blocks), recall memory (searchable conversation history), and archival memory (long-term storage). Letta (letta.com) is the commercialization of MemGPT.

Key difference: MemGPT's innovation is context window management through memory tiering. External storage is used as an archive, not as an associative network. There is no mechanism for memories to form or strengthen connections based on co-access patterns. Compression is handled through recursive summarization, not through associative linking.

2.2.3 Zep: Temporal Knowledge Graphs

Zep (getzep.com, arXiv:2501.13956) implements temporal knowledge graphs for AI agent memory, focusing on cross-session synthesis and entity-relation extraction with embeddings.

Key difference: Zep extracts entities and relations from conversations and structures them as a knowledge graph. The graph topology is determined at extraction time by NLP analysis, not by access patterns. There is no mechanism for edge weights to change based on co-activation. The temporal dimension tracks when knowledge was learned, not when it was co-accessed.

2.2.4 MemoriesDB

MemoriesDB (arXiv:2511.06179, November 2025) is the closest prior work. It implements a unified temporal-semantic-relational database for AI memory with edge weights of the form $W_{ij} = (w_{\text{strength}}, w_{\text{confidence}})$ and coherence metrics that can trigger decay or reinforcement.

Key difference: While MemoriesDB has an architectural framework that could support Hebbian dynamics, it does not explicitly implement co-activation tracking. Its weights are metadata properties set at edge creation time and modified by coherence checks, not by observing runtime memory access patterns. The system lacks a mechanism to detect that two memories were accessed in temporal proximity and to strengthen their link as a result.

2.3 Summary of Related Work

System Temporal Semantic Relational Co-activation Tracking Dynamic Reinforcement Usage-Based Decay Typed Links
Mem0 Yes Yes Optional No No No (TTL only) No
MemGPT/Letta Yes Yes No No No Summarization No
Zep Yes Yes Yes No No No Extraction-based
MemoriesDB Yes Yes Yes No Coherence-triggered Coherence-triggered Yes
This work Yes Yes Yes Yes Yes Yes Yes

The central novelty of this work is the explicit co-activation tracking mechanism combined with Hebbian reinforcement on a persistent external store --- the closed loop from "these memories were accessed together" to "the link between them is now stronger" to "future retrievals will surface them as more strongly associated."


3. System Architecture

3.1 Overview

The system operates within a three-layer cognitive architecture for AI agents:

Interaction Layer:  REST API | MCP Adapter | CLI
Core Services:      Memory Service | Identity & Hydration | Cognitive Continuity
Autonomic Layer:    Consolidation Daemon | Decay Engine | Pruning
Database:           PostgreSQL + pgvector (single source of truth)

The Hebbian memory system spans the Core Services and Autonomic layers. The Core Services layer handles synchronous operations (memory CRUD, link creation, on-access strengthening), while the Autonomic layer handles asynchronous background processes (consolidation, decay, pruning, forgotten shape generation).

3.2 Data Model

The core data model consists of three primary entities:

3.2.1 Memory Record

A memory record stores a discrete unit of agent knowledge with associated metadata and a dense vector embedding for similarity search.

Memory
  id              : bigint (primary key, auto-increment)
  guid            : uuid (external reference)
  tenant_id       : bigint (multi-tenant isolation)
  identity_id     : bigint (FK -> identities, owning AI identity)
  project_id      : bigint? (FK -> projects, optional scope)
  title           : varchar(500)
  content         : text (encrypted at rest)
  type_id         : int (FK -> memory_types lookup)
  importance      : int [1-10]
  embedding       : vector(1024) (pgvector dense vector)
  search_vector   : tsvector (PostgreSQL full-text search)
  is_pinned       : boolean (exempt from decay)
  access_count    : int (total access events)
  token_estimate  : int (approximate token count)
  last_accessed   : timestamp? (most recent access)
  archived_at     : timestamp? (soft archive)
  created_at      : timestamp
  updated_at      : timestamp

Memory types are enumerated to support differentiated handling:

Type ID Name Description
1 Identity Core identity facts about the agent
2 Relationship Information about relationships with humans or other agents
3 Conversation Distilled conversation content
4 Reflection Self-generated reflections and insights
5 Milestone Significant events or achievements
6 Instruction Operational instructions and preferences
7 Session Session-scoped working context
8 Reference External reference material
9 ForgottenShape Semantic residue of archived memories

3.2.2 Hebbian Link

A Hebbian link is a directed, typed edge between two memory records with a mutable strength value and co-activation tracking.

HebbianLink
  id                    : bigint (primary key)
  guid                  : uuid
  tenant_id             : bigint
  from_memory_id        : bigint (FK -> memories)
  to_memory_id          : bigint (FK -> memories)
  type_id               : int (FK -> link_types lookup)
  strength              : float [0.0 - 1.0]
  co_activation_count   : int (total co-activation events)
  last_co_activated_at  : timestamp?
  created_at            : timestamp
  updated_at            : timestamp

  UNIQUE(from_memory_id, to_memory_id)

Link types encode the semantic nature of the relationship:

Type ID Name Description
1 Related General topical relationship
2 Enables Source enables or supports target
3 Validates Source provides evidence for target
4 Contradicts Source conflicts with target
5 Extends Source builds upon target
6 Precedes Temporal ordering
7 CausallyLinked Causal relationship

The link type is set at creation time and does not change, while the strength value is the Hebbian-dynamic component that evolves through co-activation and decay.

3.2.3 Memory Tag

Tags provide an additional axis of association beyond Hebbian links, supporting categorical retrieval.

MemoryTag
  id          : bigint
  memory_id   : bigint (FK -> memories)
  tag         : varchar(100)

  UNIQUE(memory_id, tag)

3.3 Co-activation Detection

Co-activation occurs when two memories are accessed in temporal proximity during agent operation. We define three mechanisms for co-activation detection:

Mechanism 1: Explicit strengthening. An API consumer (the agent itself, a tool, or a human operator) explicitly invokes the strengthen endpoint for a pair of memories. This is the most direct form and is typically triggered when an agent recognizes that two memories are relevant to the same context.

Mechanism 2: Consolidation-time co-activation analysis. A background consolidation daemon examines recent cognitive interactions to identify memories that were referenced in the same interaction window. If memories A and B both appeared in the context of interactions within a configurable time window (default: the last 10 interactions), they are considered co-activated.

Mechanism 3: Search-result co-access. When a search query returns multiple results and the agent subsequently accesses two or more of those results, the accessed results are candidates for co-activation linking. (This mechanism is specified but not yet implemented in the current production system.)

3.4 Reinforcement Function

When a co-activation event is detected for a pair of memories that already share a Hebbian link, the link's strength is increased according to an asymptotic reinforcement function:

$$S_{new} = \min\left(1.0, S_{current} + (1.0 - S_{current}) \times \alpha\right)$$

where:

  • $S_{current}$ is the current link strength in $[0.0, 1.0]$
  • $S_{new}$ is the updated link strength
  • $\alpha$ is the reinforcement rate (learning rate)

This function has several desirable properties:

  1. Bounded growth: Strength can never exceed 1.0, preventing runaway reinforcement.
  2. Diminishing returns: Each successive reinforcement produces a smaller absolute increase, modeling the biological phenomenon where well-established connections require less modification.
  3. Rapid initial learning: Weak links strengthen quickly; the first reinforcement from the default strength of 0.5 with $\alpha = 0.1$ yields a 5-percentage-point increase, while strengthening from 0.9 yields only a 1-percentage-point increase.

Two reinforcement rates are used:

Context Rate ($\alpha$) Rationale
Explicit strengthening (API call) 0.1 Direct human/agent signal; higher confidence
Background consolidation 0.05 Automated detection; lower confidence to avoid noise

For a new pair of memories detected as co-activated where no link yet exists, a new HebbianLink is created with an initial strength of 0.5 and a co-activation count of 0. The initial strength of 0.5 (rather than 0.0 or 1.0) reflects that the existence of a co-activation event is meaningful evidence of association, but not yet strong enough to dominate retrieval.

3.5 Decay Functions

Two complementary decay mechanisms operate on different entities:

3.5.1 Link Strength Decay (via Pruning)

Links with strength below a threshold that have not been co-activated within a time window are pruned entirely rather than decayed gradually. This is a deliberate design choice: gradual link decay creates maintenance overhead for links that are likely noise, while pruning provides a clean signal.

Prune condition:
  strength < 0.1 AND
  (last_co_activated_at IS NULL OR last_co_activated_at < NOW() - INTERVAL '60 days')

This means a link must be both weak (below 10% strength) and stale (no co-activation in 60 days) before removal. A weak but recently activated link is preserved; a strong but stale link is preserved. Only links that are both weak and forgotten are pruned.

3.5.2 Memory Importance Decay

Memories that have not been accessed in 30 or more days have their importance score reduced by 1 (minimum 1). Pinned memories are exempt from decay.

Decay condition:
  NOT is_pinned AND
  archived_at IS NULL AND
  importance > 1 AND
  (last_accessed_at IS NULL OR last_accessed_at < NOW() - INTERVAL '30 days')

Action:
  importance = MAX(1, importance - 1)

This produces a staircase decay curve rather than an exponential one: a memory starts at importance 5, drops to 4 after 30 days of disuse, to 3 after 60 days, and so on. This is slower than exponential decay, reflecting the intuition that memories are more durable than neural-network-style weights but still subject to erosion.

3.5.3 Automatic Archival

Memories that have reached minimum importance (1), are not pinned, have never been accessed, and are older than 90 days are automatically archived. Archived memories are not deleted (soft delete only) but are excluded from search results and Hebbian graph traversal.

Archive condition:
  NOT is_pinned AND
  archived_at IS NULL AND
  importance <= 1 AND
  access_count = 0 AND
  created_at < NOW() - INTERVAL '90 days'

3.6 Forgotten Shapes

When memories are archived, the system generates a "ForgottenShape" --- a lightweight memory record that preserves the semantic residue of what was lost. This is analogous to the biological "tip of the tongue" phenomenon: the specific content is gone, but a structural trace remains indicating that something relevant once existed in this area of the memory space.

A ForgottenShape contains:

  • The titles of the archived memories
  • The date range they covered
  • The count of memories archived
  • The vector embedding of a representative archived memory (providing approximate semantic position in the embedding space)

ForgottenShapes have importance 3 (low but not minimal), ensuring they persist long enough to potentially resurface during relevant searches while still being subject to eventual decay themselves.

3.7 Vector Similarity for Candidate Generation

Dense vector embeddings (1024-dimensional, generated by a local embedding model) serve a dual purpose:

  1. Retrieval-time similarity search: Standard RAG functionality --- find memories semantically similar to a query.
  2. Link candidate generation: Identify pairs of memories whose embeddings have high cosine similarity as candidates for Hebbian linking, even if they have not yet been co-activated.

The hybrid search pipeline uses a two-stage approach:

  1. Full-text search shortlist: PostgreSQL tsvector with GIN index produces an initial candidate set (default: 200 candidates).
  2. Vector reranking: Cosine similarity between query embedding and candidate embeddings produces a blended score.

The blending formula is:

$$\text{score} = (0.2 \times \text{FTS_rank}) + (0.8 \times \text{cosine_similarity})$$

Additional configurable boost factors are applied:

Boost Type Formula Effect
Importance $1 + \frac{\text{importance}}{10}$ Higher-importance memories rank higher
Pinned $\times 1.5$ if pinned Pinned memories get a 50% boost
Recency Linear decay after 90 days, max 30% reduction Recent memories slightly preferred
Access Frequency $1 + \frac{\min(\text{count}, 50)}{50} \times 0.2$ Frequently accessed memories boosted
Hebbian Strength Weighted by link strength to query-adjacent memories Strongly linked memories boosted

The HebbianStrength boost is the key integration point: memories that are strongly linked (via the Hebbian graph) to memories that matched the query receive a retrieval boost, enabling the associative memory structure to directly influence search results.


4. Implementation

4.1 Database Schema (PostgreSQL)

The following DDL creates the core tables for the Hebbian memory system:

-- Memory records
CREATE TABLE memories (
    id              BIGSERIAL PRIMARY KEY,
    guid            UUID NOT NULL DEFAULT gen_random_uuid(),
    tenant_id       BIGINT NOT NULL REFERENCES tenants(id),
    identity_id     BIGINT NOT NULL REFERENCES identities(id) ON DELETE CASCADE,
    project_id      BIGINT REFERENCES projects(id) ON DELETE SET NULL,
    title           VARCHAR(500) NOT NULL,
    content         TEXT NOT NULL,
    type_id         INT NOT NULL DEFAULT 3,
    importance      INT NOT NULL DEFAULT 5 CHECK (importance BETWEEN 1 AND 10),
    embedding       vector(1024),
    search_vector   tsvector,
    is_pinned       BOOLEAN NOT NULL DEFAULT FALSE,
    access_count    INT NOT NULL DEFAULT 0,
    token_estimate  INT NOT NULL DEFAULT 0,
    last_accessed_at TIMESTAMPTZ,
    archived_at     TIMESTAMPTZ,
    is_deleted      BOOLEAN NOT NULL DEFAULT FALSE,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Hebbian links between memories
CREATE TABLE hebbian_links (
    id                      BIGSERIAL PRIMARY KEY,
    guid                    UUID NOT NULL DEFAULT gen_random_uuid(),
    tenant_id               BIGINT NOT NULL REFERENCES tenants(id),
    from_memory_id          BIGINT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
    to_memory_id            BIGINT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
    type_id                 INT NOT NULL DEFAULT 1,
    strength                REAL NOT NULL DEFAULT 0.5,
    co_activation_count     INT NOT NULL DEFAULT 0,
    last_co_activated_at    TIMESTAMPTZ,
    is_deleted              BOOLEAN NOT NULL DEFAULT FALSE,
    created_at              TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at              TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    UNIQUE(from_memory_id, to_memory_id)
);

-- Memory tags
CREATE TABLE memory_tags (
    id          BIGSERIAL PRIMARY KEY,
    guid        UUID NOT NULL DEFAULT gen_random_uuid(),
    tenant_id   BIGINT NOT NULL REFERENCES tenants(id),
    memory_id   BIGINT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
    tag         VARCHAR(100) NOT NULL,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    UNIQUE(memory_id, tag)
);

-- Indexes
CREATE INDEX idx_memories_identity_type ON memories(identity_id, type_id);
CREATE INDEX idx_memories_identity_importance ON memories(identity_id, importance);
CREATE INDEX idx_memories_project ON memories(project_id) WHERE project_id IS NOT NULL;
CREATE INDEX idx_memories_pinned ON memories(is_pinned) WHERE is_pinned = TRUE;
CREATE INDEX idx_memories_search_vector ON memories USING GIN(search_vector);

CREATE INDEX idx_hebbian_links_from ON hebbian_links(from_memory_id);
CREATE INDEX idx_hebbian_links_to ON hebbian_links(to_memory_id);
CREATE INDEX idx_hebbian_links_strength ON hebbian_links(strength);
CREATE INDEX idx_hebbian_links_last_coactivated ON hebbian_links(last_co_activated_at);

-- Auto-update search vector on insert/update
CREATE OR REPLACE FUNCTION update_memory_search_vector()
RETURNS TRIGGER AS $$
BEGIN
    NEW.search_vector := to_tsvector('english', COALESCE(NEW.title, '') || ' ' || COALESCE(NEW.content, ''));
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_memory_search_vector
    BEFORE INSERT OR UPDATE OF title, content ON memories
    FOR EACH ROW
    EXECUTE FUNCTION update_memory_search_vector();

4.2 Core Operations (Pseudocode)

4.2.1 Link Creation

FUNCTION CreateLink(fromMemoryId, toMemoryId, linkType):
    IF fromMemoryId == toMemoryId:
        RETURN error("self-links not permitted")

    fromMemory = DB.Find(memories, fromMemoryId)
    toMemory = DB.Find(memories, toMemoryId)
    IF fromMemory IS NULL OR toMemory IS NULL:
        RETURN error("memory not found")

    existing = DB.FindFirst(hebbian_links,
        WHERE from_memory_id = fromMemoryId AND to_memory_id = toMemoryId)
    IF existing IS NOT NULL:
        RETURN error("link already exists")

    link = HebbianLink {
        from_memory_id: fromMemoryId,
        to_memory_id: toMemoryId,
        type_id: linkType,
        strength: 0.5,          -- Initial strength
        co_activation_count: 0
    }
    DB.Insert(hebbian_links, link)
    RETURN link

4.2.2 Hebbian Strengthening

FUNCTION StrengthenLink(fromMemoryId, toMemoryId):
    -- Bidirectional lookup: strengthening is symmetric
    link = DB.FindFirst(hebbian_links,
        WHERE (from_memory_id = fromMemoryId AND to_memory_id = toMemoryId)
           OR (from_memory_id = toMemoryId AND to_memory_id = fromMemoryId))

    IF link IS NULL:
        RETURN  -- No link to strengthen

    link.co_activation_count += 1
    link.last_co_activated_at = NOW()

    -- Asymptotic reinforcement: S_new = min(1.0, S + (1.0 - S) * alpha)
    alpha = 0.1  -- Explicit strengthening rate
    link.strength = MIN(1.0, link.strength + (1.0 - link.strength) * alpha)

    DB.Update(link)

4.2.3 Consolidation Cycle

FUNCTION RunConsolidation():
    strengthened = StrengthenRecentLinks()
    pruned       = PruneWeakLinks()
    decayed      = DecayStaleMemories()
    archived     = ArchiveAbandonedMemories()
    shapes       = CreateForgottenShapes()
    LOG("Consolidation: {strengthened} links, {pruned} pruned, {decayed} decayed,
         {archived} archived, {shapes} shapes")

FUNCTION StrengthenRecentLinks():
    cutoff = NOW() - 24 HOURS
    links = DB.Query(hebbian_links,
        WHERE last_co_activated_at > cutoff AND strength < 0.95)
    FOR EACH link IN links:
        -- Background consolidation rate (lower than explicit)
        link.strength = MIN(1.0, link.strength + (1.0 - link.strength) * 0.05)
    DB.UpdateBatch(links)
    RETURN COUNT(links)

FUNCTION PruneWeakLinks():
    cutoff = NOW() - 60 DAYS
    weak = DB.Query(hebbian_links,
        WHERE strength < 0.1
          AND (last_co_activated_at IS NULL OR last_co_activated_at < cutoff))
    DB.DeleteBatch(weak)
    RETURN COUNT(weak)

FUNCTION DecayStaleMemories():
    cutoff = NOW() - 30 DAYS
    stale = DB.Query(memories,
        WHERE NOT is_pinned
          AND archived_at IS NULL
          AND importance > 1
          AND (last_accessed_at IS NULL OR last_accessed_at < cutoff))
    FOR EACH memory IN stale:
        memory.importance = MAX(1, memory.importance - 1)
    DB.UpdateBatch(stale)
    RETURN COUNT(stale)

4.3 REST API Contracts

The system exposes the following HTTP endpoints for Hebbian link management:

POST   /api/memories/{id}/links
  Body: { "targetMemoryId": 42, "type": "Related" }
  Response: HebbianLinkDto { id, fromMemoryId, toMemoryId, type, strength, coActivationCount }
  Creates a new Hebbian link with initial strength 0.5.

DELETE /api/memories/{id}/links/{targetId}
  Removes the Hebbian link between the specified memories.

POST   /api/memories/{id}/links/{targetId}/strengthen
  Response: { "message": "Link strengthened" }
  Increments co-activation count, updates last co-activated timestamp,
  and applies asymptotic reinforcement function.

GET    /api/memories/{id}
  Response: MemoryDetailDto (includes LinksFrom[] and LinksTo[])
  Automatically increments access_count and updates last_accessed_at.

GET    /api/identities/{identityId}/memories/search?q={query}&topK=20
  Response: MemorySearchResult { results[], totalCandidates, embeddingCoverage }
  Hybrid FTS + vector search with configurable Hebbian strength boosting.

4.4 Entity Configuration (Entity Framework Core)

The following C# configuration establishes the database mapping for EF Core:

public class HebbianLinkConfiguration : AtamaiaEntityConfiguration<HebbianLink>
{
    public override void Configure(EntityTypeBuilder<HebbianLink> builder)
    {
        base.Configure(builder);
        builder.ToTable("hebbian_links");

        builder.Property(e => e.Strength).HasDefaultValue(0.5f);
        builder.Property(e => e.CoActivationCount).HasDefaultValue(0);

        builder.HasOne(e => e.FromMemory)
            .WithMany(m => m.LinksFrom)
            .HasForeignKey(e => e.FromMemoryId)
            .OnDelete(DeleteBehavior.Cascade);

        builder.HasOne(e => e.ToMemory)
            .WithMany(m => m.LinksTo)
            .HasForeignKey(e => e.ToMemoryId)
            .OnDelete(DeleteBehavior.Cascade);

        builder.HasIndex(e => new { e.FromMemoryId, e.ToMemoryId }).IsUnique();
    }
}

4.5 Background Consolidation Daemon

The consolidation daemon runs as a background job on a configurable interval (default: 1 hour). It executes the following pipeline in sequence:

1. StrengthenRecentLinks    -- Reinforce links co-activated in last 24h
2. PruneWeakLinks           -- Remove links below threshold (strength < 0.1, stale > 60 days)
3. DecayStaleMemories       -- Reduce importance of unaccessed memories (30+ days)
4. ArchiveAbandonedMemories -- Archive zero-access, low-importance memories (90+ days)
5. CreateForgottenShapes    -- Generate semantic residue for archived memories

Each step operates independently and produces a count of affected records for observability. The pipeline is idempotent: running it multiple times within the same time window produces no additional changes beyond the first run (due to the cutoff-based queries).

4.6 Prior Implementation: EchoMCP (2025)

The original implementation in the EchoMCP system used raw SQL via Dapper rather than an ORM. Key differences from the current implementation:

  1. Link types as strings rather than enum-backed integers: "relates_to", "evolves_to", "annotates", "supersedes", "contradicts", "co-activated".
  2. Linear reinforcement rather than asymptotic: strength = MIN(1.0, strength + 0.1) (constant increment per co-activation, risk of rapid saturation).
  3. Co-activation tracking via access_history table: A separate access_history table recorded every memory access with session IDs, enabling temporal co-activation analysis by querying for memories accessed in the same session.
  4. SQLite origin with PostgreSQL migration: The system originally ran on SQLite with FTS5 and was later ported to PostgreSQL, demonstrating portability.

The consolidation pipeline in EchoMCP was part of a broader ConsolidationPipeline class that also handled episodic-to-semantic distillation (extracting facts from conversations), working memory updates, and ephemeral context pruning. The Hebbian strengthening component specifically:

// EchoMCP: StrengthenHebbianLinksAsync
var coActivatedIds = await _cognitive.GetRecentlyActivatedMemoryIdsAsync(
    identity.InstanceId, interactionLimit: 10, ct);

// Strengthen links between ALL pairs of co-activated memories
foreach (var sourceId in coActivatedIds)
{
    foreach (var targetId in coActivatedIds.Where(id => id != sourceId))
    {
        var existingLink = await _memoryRepo.GetLinkAsync(
            sourceId, targetId, "co_activated", ct);

        if (existingLink != null)
        {
            var newStrength = Math.Min(1.0f, existingLink.Strength + 0.1f);
            await _memoryRepo.UpdateLinkStrengthAsync(
                sourceId, targetId, "co_activated", newStrength, ct);
        }
        else
        {
            await _memoryRepo.AddLinkAsync(
                sourceId, targetId, "co_activated", null, ct);
        }
    }
}

The evolution from EchoMCP to Atamaia refined the reinforcement function from linear to asymptotic, added explicit co-activation counters, introduced typed links with enum-backed lookup tables, and moved from raw SQL to EF Core with strongly-typed navigation properties.


5. Design Rationale

5.1 Why External Stores, Not In-Network Learning

The decision to implement Hebbian co-activation on an external database rather than through fine-tuning, LoRA adapters, or other in-network weight modification techniques is driven by several considerations:

Persistence across model changes. The associative memory graph persists independently of which LLM is being used. When the underlying model is upgraded (e.g., from Claude 3 to Claude 4), the Hebbian memory graph is unaffected. In-network learning would be lost on model swap.

Multi-model compatibility. The same memory graph can be consumed by multiple models simultaneously. In a multi-agent system where different agents use different models (or the same agent uses different models for different tasks), the Hebbian associations are shared infrastructure.

Inspectability. External database links are directly queryable, auditable, and debuggable. An operator can examine the hebbian_links table to understand why certain memories are strongly associated. In-network weight changes are opaque.

Safety. Modifying model weights at runtime carries risks of catastrophic forgetting, mode collapse, or unintended behavioral changes. External Hebbian links affect only the retrieval and ranking of memories, not the model's fundamental capabilities or alignment.

Multi-tenancy. The tenant_id column on every table enables complete isolation between different organizations or users. Each tenant has its own independent Hebbian memory graph. In-network learning cannot easily provide this isolation.

Cost. External database operations are computationally trivial compared to model fine-tuning. A co-activation strengthening operation is a single SQL UPDATE; a LoRA adaptation requires a training loop.

5.2 Why Asymptotic Reinforcement

The asymptotic reinforcement function $S_{new} = \min(1.0, S + (1.0 - S) \times \alpha)$ was chosen over simpler alternatives for the following reasons:

vs. Linear reinforcement ($S_{new} = \min(1.0, S + \alpha)$): Linear reinforcement saturates too quickly. With $\alpha = 0.1$, a link reaches maximum strength in only 5 reinforcements from the default. Asymptotic reinforcement requires approximately 23 reinforcements at $\alpha = 0.1$ to reach $S = 0.9$ from $S = 0.5$, providing a much longer learning curve that better reflects the gradual nature of memory consolidation.

vs. Exponential reinforcement ($S_{new} = 1 - (1 - S) \times e^{-\alpha}$): While exponential approaches also provide asymptotic behavior, they are harder to reason about and parameterize. The linear-step-toward-ceiling formulation is equivalent in behavior but more transparent.

vs. Multiplicative reinforcement ($S_{new} = S \times (1 + \alpha)$): Multiplicative reinforcement is unbounded without clamping and produces different dynamics depending on the current strength. Our formulation always approaches 1.0 regardless of starting point.

5.3 Why Two Reinforcement Rates

The dual-rate system (0.1 for explicit, 0.05 for background) reflects an epistemic distinction: an explicit strengthening request from an agent or operator carries higher confidence that the association is meaningful, while automated co-activation detection in the consolidation pipeline may include false positives (two memories accessed in the same session window may be unrelated). The lower background rate ensures that automated reinforcement builds associations gradually, requiring more evidence before strong links form.

5.4 Why Pruning Instead of Gradual Link Decay

An alternative design would apply gradual strength decay to all links (analogous to weight decay in neural network training). We rejected this approach because:

  1. Maintenance cost: Decaying all links on every consolidation cycle requires touching every row in the hebbian_links table. Pruning only touches the small subset of weak, stale links.
  2. Signal clarity: A link with strength 0.5 that has been co-activated once 30 days ago is ambiguous under gradual decay --- is it weakening or stable? Under pruning, it is clearly stable (above the 0.1 threshold, within the 60-day window).
  3. Storage efficiency: Links that will never be strengthened again are removed entirely rather than decaying slowly toward zero, reducing table size.

6. Applications and Integration

6.1 Hydration Pipeline

The Hebbian link graph is consumed during agent hydration --- the process of reconstructing agent context at the start of a new session. The hydration system retrieves memories from multiple sources in parallel, and Hebbian link strengths influence which memories are included:

  1. Pinned memories are always included (immune to decay, bypassing Hebbian selection).
  2. Recent memories are retrieved by recency (last N memories).
  3. Search-relevant memories are retrieved by hybrid FTS + vector search, with Hebbian strength as a boost factor.
  4. Link-adjacent memories are surfaced by traversing strong Hebbian links from already-selected memories (graph expansion).

The graph expansion step is the key integration point: once the initial set of memories is selected, the system follows outgoing Hebbian links with strength above a threshold (default: 0.7) to include strongly associated memories that might not have matched the direct query.

6.2 Consolidation Pipeline Integration

The Hebbian strengthening phase is the first step of a five-phase consolidation pipeline:

Phase 1: Strengthen Hebbian links (co-activation reinforcement)
Phase 2: Distill episodic to semantic (extract facts from conversations)
Phase 3: Update working memory (infer current goals and active threads)
Phase 4: Prune ephemeral context (decay low-importance memories)
Phase 5: Capture cognitive state (serialize for next session)

The ordering is intentional: Hebbian strengthening runs first because it informs the distillation and pruning phases. Strongly linked memories are less likely to be pruned, and the link structure provides context for episodic-to-semantic distillation.

6.3 Forgetting Integration

The ForgottenShape mechanism described in Section 3.6 integrates with the Hebbian graph by preserving the approximate embedding-space position of archived memories. When a ForgottenShape is created, it does not inherit the Hebbian links of the archived memories, but it does inherit a representative embedding. This means that future searches in the same semantic neighborhood will encounter the ForgottenShape, which can trigger a "tip of the tongue" phenomenon --- the agent knows that relevant information once existed in this area, even if the specific content is gone.

6.4 Involuntary Recall

The system supports involuntary recall --- the random surfacing of memories during hydration for re-evaluation by the agent. When a memory is surfaced through involuntary recall and the agent engages with it (by producing a recall response), all Hebbian links from that memory receive a co-activation signal. This creates a mechanism by which old, weakening memories can be "rescued" from decay by being randomly re-encountered and found relevant.

6.5 Multi-Agent Memory Sharing

In multi-agent architectures, project-scoped memories are shared across agents working on the same project. The Hebbian links in this context reflect the collective access patterns of all agents, creating a shared associative structure that emerges from the group's collaborative activity. An individual agent's identity-scoped memories maintain their own Hebbian graph, while project-scoped memories have a graph shaped by all contributors.


7. Discussion

7.1 Limitations

No bidirectional link strengthening. The current implementation stores unidirectional links (from A to B) but performs bidirectional lookup during strengthening (either A->B or B->A). This means the directionality of links is partially semantic (the type indicates direction, e.g., "A enables B") but the Hebbian dynamics are symmetric. A more sophisticated implementation might maintain asymmetric strengths for directed relationships.

No cross-tenant link inference. The multi-tenant isolation model prevents any sharing of Hebbian patterns across tenants. A federated model where anonymized co-activation patterns are shared could benefit from collective intelligence, but this raises significant privacy concerns.

Consolidation timing. The fixed 1-hour consolidation interval means co-activation events are not immediately reflected in link strengths (for the background consolidation path). The explicit API path provides immediate reinforcement, but automated co-activation detection is batch-processed. A streaming architecture with change data capture could provide near-real-time Hebbian updates.

Link type immutability. Once a link is created with a type (e.g., "Related"), the type cannot change even if the nature of the relationship evolves. A future version could support type evolution based on the context of co-activation events.

Embedding model dependency. The vector similarity component depends on a specific embedding model (currently 1024-dimensional). Changing embedding models requires re-embedding all memories, and the Hebbian graph may not align with a new embedding space. The link structure itself is model-independent, but the candidate generation via similarity search is not.

7.2 Comparison to In-Network Hebbian Learning

Dimension In-Network (Training) External Store (This Work)
Timing Training/fine-tuning Runtime (continuous)
Persistence Saved with model weights Independent database
Inspectability Opaque (weight matrices) Transparent (SQL queryable)
Model coupling Tied to specific model Model-agnostic
Computational cost GPU-intensive SQL UPDATE operations
Granularity Sub-symbolic (weight adjustments) Symbolic (named memories, typed links)
Reversibility Difficult (catastrophic forgetting) Trivial (DELETE FROM hebbian_links)
Multi-tenancy Not applicable Native (tenant_id isolation)
Safety risk Model behavior changes Retrieval ranking changes only

7.3 Future Work

Negative Hebbian learning. Implementing anti-Hebbian dynamics for contradictory memories: when an agent accesses memory A and then explicitly rejects or contradicts memory B, the link between them could be negatively reinforced (strength reduced) or a "Contradicts" link created or strengthened.

Embedding-space link prediction. Using the vector embeddings to predict which memories should be linked (high cosine similarity but no existing link) and proactively creating candidate links with low initial strength for the consolidation pipeline to confirm or prune.

Temporal windowing. Implementing variable-width co-activation windows based on session context. Two memories accessed 5 seconds apart in a fast-paced coding session should have stronger co-activation signal than two memories accessed 5 seconds apart in a day-long planning session.

Hebbian-influenced retrieval ranking. More sophisticated integration of the Hebbian graph into the search pipeline, including multi-hop graph traversal (follow links from links) and PageRank-style authority scoring on the memory graph.

Comparative evaluation. Systematic comparison of retrieval quality and agent task performance between Hebbian-enhanced memory and static RAG baselines, measured through standard agent benchmarks.


8. Conclusion

This paper has presented a complete system for applying Hebbian co-activation learning to external persistent memory stores used by AI agents. The approach transfers the "fire together, wire together" principle from neural network weight adjustment to runtime operations on a PostgreSQL database with pgvector, creating an associative memory graph that self-organizes based on actual agent usage patterns.

The key technical contributions are: (1) an asymptotic reinforcement function that prevents link saturation while allowing rapid initial learning; (2) a dual-rate reinforcement system distinguishing explicit from automated co-activation signals; (3) integration with a broader cognitive architecture including consolidation pipelines, forgetting mechanisms, and hydration systems; and (4) two production implementations demonstrating the approach across different technology stacks.

The system has been in production use since 2025 (EchoMCP) and 2026 (Atamaia), managing memory associations for AI agents across multiple concurrent sessions. The approach provides a form of long-term associative memory that is persistent across model changes, inspectable through standard SQL queries, safe from model-weight modification risks, and naturally multi-tenant.

As AI agents become more capable and long-running, the gap between static memory retrieval and dynamic associative memory will become increasingly important. We believe that externalizing Hebbian dynamics to persistent stores represents a practical and scalable approach to bridging this gap.


References

  1. Hebb, D. O. (1949). The Organization of Behavior: A Neuropsychological Theory. Wiley.

  2. Oja, E. (1982). A simplified neuron model as a principal component analyzer. Journal of Mathematical Biology, 15(3), 267-273.

  3. Packer, C., Wooders, S., Lin, K., Fang, V., Patil, S. G., Stoica, I., & Gonzalez, J. E. (2023). MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560.

  4. MemoriesDB. (2025). A Unified Temporal-Semantic-Relational Database for AI Memory. arXiv:2511.06179.

  5. Zep. (2025). Temporal Knowledge Graph Architecture for AI Agent Memory. arXiv:2501.13956.

  6. Mem0. (2025). Memory Infrastructure for AI Agents. https://mem0.ai

  7. Letta. (2025). MemGPT Platform for AI Agent Memory. https://letta.com

  8. pgvector. (2024). Open-source vector similarity search for PostgreSQL. https://github.com/pgvector/pgvector

  9. Lewis, P., Perez, E., Piktus, A., et al. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS 2020.

  10. Bi, D., & Poo, M. (1998). Synaptic modifications in cultured hippocampal neurons: dependence on spike timing, synaptic strength, and postsynaptic cell type. Journal of Neuroscience, 18(24), 10464-10472.


This paper describes systems developed by Firebird Solutions. The EchoMCP implementation has been in production since 2025; the Atamaia implementation since early 2026. Source code and deployment artifacts for both systems exist and are available for verification.

Correspondence: Rich Jeffries, Firebird Solutions, [email protected]