Three-Column Working Memory for LLM-Based Agents

Author: Forrest Hosten, Aleq, Inc.
Email: forrest@aleq.com
Date: December 2025
Original Thesis: July 2025
Production Status: In production
arXiv Submission Status: Draft


Abstract

LLM-based agents struggle with working memory management. They either maintain too little context (forgetting recent interactions) or too much context (overwhelming the context window with irrelevant details). Traditional approaches use a single undifferentiated context buffer, forcing the agent to treat all information equally—active tasks, background notes, and ambient context are mixed together without structure.

We introduce a three-column working memory architecture that separates cognitive state into distinct functional regions: (1) Active Tasks—the 3-4 items currently being worked on, with full state and dependencies; (2) Notes—acknowledged items in a queue with time-to-live, representing things to address later; (3) Objects—ambient context including people (with relationship beliefs), entities, high-strength beliefs, and temporal context.

The key insight is that these columns serve different cognitive functions and require different management policies. Active Tasks need rich state tracking and explicit dependencies. Notes need TTL-based expiration and priority escalation. Objects need salience-based population from the knowledge graph, loading only items relevant to current context.

Critically, there are no explicit pointers between columns—the LLM reasons about relationships implicitly. This prevents brittle coupling and enables flexible cross-column reasoning (e.g., "This task involves Person X, who I noted earlier has a preference for detailed explanations"). The system is robust to deletions, renames, and changes without cascading pointer updates.

We demonstrate this architecture through a qualitative case study of a professional workflow agent. The design structurally guarantees bounded context usage by decoupling active work from ambient awareness, preventing the context overflow common in flat-buffer systems. The architecture is fully implemented in a production cognitive agent system.[^impl]

[^impl]: Implementation: Aleq MIND agent system (mars/src/aleq_mind/working_memory/). Code available upon request.


1. Introduction

Large language models have demonstrated remarkable capabilities in reasoning, planning, and natural language interaction. However, when deployed as autonomous agents that manage multiple concurrent tasks over extended periods, they face a fundamental challenge: working memory management.

1.1 The Working Memory Problem

Human working memory has well-documented capacity limits. Miller’s seminal work established the "7±2" rule [1]: humans can hold roughly 7 items in working memory simultaneously. Baddeley’s model further refined this, proposing functionally distinct regions [2]: a central executive for active processing, a phonological loop for verbal rehearsal, and a visuospatial sketchpad for spatial information.

LLM-based agents face analogous constraints. The context window—though measured in tokens rather than cognitive chunks—serves as the agent’s working memory. An agent interacting with users over hours or days must decide:

  • Which tasks are currently active vs. deferred?
  • What prior context is relevant to the current interaction?
  • Which relationships, preferences, and beliefs should inform responses?
  • When should previously mentioned items be proactively surfaced?

1.2 Existing Approaches and Their Limitations

Current LLM agent frameworks take one of three approaches:

Undifferentiated Context Buffers. Systems like LangChain [6] and Semantic Kernel [7] maintain a single message history buffer. All context—active tasks, mentioned entities, prior commitments—is stored in a flat chronological list. This creates two failure modes:

  1. Context overflow: The buffer grows unbounded, consuming the entire context window with irrelevant history.
  2. Premature truncation: To avoid overflow, systems truncate old messages, potentially dropping critical information (e.g., a task the user mentioned 20 messages ago but still expects completion).

External Memory Systems. Approaches like MemGPT [8] and ChatDB [9] store conversation history in external databases (vector stores, SQL) and retrieve relevant snippets on-demand. While this solves the capacity problem, it introduces high latency (vector search + retrieval) and relevance challenges (similarity-based retrieval may miss functionally important but semantically dissimilar information).

Task-Only Approaches. Systems like AutoGPT [10] and BabyAGI [11] maintain explicit task lists. However, they lack structured support for:

  • Acknowledged but deferred tasks ("I’ll look into that later")
  • Ambient context (people preferences, entity familiarity)
  • Relationship state across interactions

1.3 Our Contribution

We introduce a three-column working memory architecture that addresses these limitations by separating cognitive state into functionally distinct regions, each with appropriate management policies:

  1. Active Tasks (Column 1): 3-4 concurrent items with rich state, dependencies, and progress tracking. Slot-limited to prevent cognitive overload.
  2. Notes (Column 2): Acknowledged queue with time-to-live. Automatic priority escalation as deadlines approach. Prevents forgetting while avoiding constant interruption.
  3. Objects (Column 3): Salience-based ambient context. Dynamically populated with people (relationship beliefs), entities, relevant beliefs, and temporal context based on active tasks.

Critically, the columns are connected through implicit reasoning rather than explicit pointers. The LLM receives all three columns in natural language format and reasons about connections flexibly.

1.4 Key Results

In a qualitative case study of a professional workflow, the three-column architecture demonstrates:

  • Bounded Context Usage: Structurally prevents context overflow via slot limits and salience filtering.
  • Improved Task Persistence: TTL-based escalation prevents forgotten tasks.
  • Relationship Consistency: Implicit reasoning maintains awareness of stakeholder preferences.
  • Proactive Surfacing: Relevant context is brought to attention without explicit pointers.

The architecture is fully implemented in a production cognitive agent system.


2. Background: Working Memory in Cognitive Science

2.1 Baddeley’s Working Memory Model

Baddeley and Hitch [2] proposed that working memory comprises functionally distinct subsystems:

  • Central Executive: Attentional control, task coordination, strategic processing
  • Phonological Loop: Verbal and acoustic information storage
  • Visuospatial Sketchpad: Visual and spatial information storage
  • Episodic Buffer (added later [3]): Integration of information from multiple sources
graph TB
    subgraph "Baddeley's Model"
        CE[Central Executive]
        PL[Phonological Loop]
        VS[Visuospatial Sketchpad]
        EB[Episodic Buffer]
        CE --> PL
        CE --> VS
        CE --> EB
    end

    subgraph "Three-Column Mapping"
        AT[Active Tasks]
        NT[Notes]
        OB[Objects]
    end

    CE -.->|maps to| AT
    PL -.->|maps to| NT
    EB -.->|maps to| OB

Our three-column architecture adapts this model to LLM agents:

Baddeley Component Three-Column Equivalent Function
Central Executive Active Tasks What’s being processed now
Phonological Loop Notes Items to remember verbally
Episodic Buffer Objects Integrated contextual information

2.2 Miller’s Capacity Limits

Miller [1] found that human working memory capacity is approximately 7±2 items. Cowan [4] later refined this to 4±1 items for independent chunks.

We adopt a conservative 3-4 slot limit for Active Tasks, matching the lower bound of capacity research. This forces:

  1. Prioritization (can’t work on everything simultaneously)
  2. Decomposition (complex tasks must be broken into manageable steps)
  3. Delegation (low-priority items move to Notes, not Active)

2.3 Attention as Limited Resource

Kahneman [5] established that attention is a limited resource that must be allocated strategically. Our architecture operationalizes this through token budget allocation:

pie title Context Window Budget Allocation
    "Active Tasks (32%)" : 32
    "Notes (16%)" : 16
    "Objects (44%)" : 44
    "System (8%)" : 8
Column Budget Detail Level
Active Tasks 32% High detail, full state
Notes 16% Summary only
Objects 44% Ambient awareness
System 8% Prompts, metadata

3. Architecture

3.1 Three-Column Overview

graph LR
    subgraph "Column 1: Active Tasks"
        A1[Task 1<br/>Priority: 0.9<br/>State: executing]
        A2[Task 2<br/>Priority: 0.7<br/>State: blocked]
        A3[Task 3<br/>Priority: 0.6<br/>State: planning]
        A4[Slot 4<br/>empty]
    end

    subgraph "Column 2: Notes"
        N1[Note 1<br/>TTL: 4h<br/>Priority: 0.6]
        N2[Note 2<br/>TTL: 24h<br/>Priority: 0.4]
        N3[Note 3<br/>TTL: 2h<br/>Priority: 0.8]
        N4[...]
    end

    subgraph "Column 3: Objects"
        O1[People<br/>User, Vendor X]
        O2[Entities<br/>Project A, Client B]
        O3[Beliefs<br/>strength > 0.8]
        O4[Temporal<br/>Month-end]
    end

    A1 -.->|implicit reasoning| O1
    A1 -.->|implicit reasoning| O3
    N1 -.->|entity match| O2

3.2 Column 1: Active Tasks

Active Tasks represent items currently receiving the agent’s executive attention. Each task maintains:

@dataclass
class ActiveTask:
    task_id: str
    description: str  # Natural language summary
    state: Literal["planning", "executing", "blocked",
                   "awaiting_input", "complete"]
    dependencies: List[str]  # What this task depends on
    history: List[dict]  # What's happened so far
    started_at: datetime
    priority: float  # [0,1] urgency score
    blocking_reason: Optional[str] = None
    progress: float = 0.0  # [0,1] completion estimate

Slot Allocation Policy:

flowchart TD
    NEW[New Task Arrives] --> CHECK{Slots Available?}
    CHECK -->|Yes| PCHECK{Priority > 0.5?}
    PCHECK -->|Yes| ACTIVATE[Activate Task]
    PCHECK -->|No| TONOTES[Add to Notes]
    CHECK -->|No| COMPARE{New Priority ><br/>Lowest x 1.3?}
    COMPARE -->|Yes| DEMOTE[Demote Lowest to Notes]
    DEMOTE --> ACTIVATE
    COMPARE -->|No| TONOTES

Tasks are activated when:

  1. Slots are available and task priority > 0.5, or
  2. Task priority exceeds lowest active task priority by 30%

When all slots are full and a high-priority task arrives, the lowest-priority active task is demoted to Notes (not discarded), preserving work while freeing capacity.

3.3 Column 2: Notes

Notes represent acknowledged commitments not yet activated. Each note has:

@dataclass
class Note:
    note_id: str
    content: str  # Natural language description
    created_at: datetime
    ttl: timedelta  # Time to live
    priority: float  # [0,1] base priority
    source: Literal["user", "system", "inferred"]
    context: dict  # Relevant context when noted

TTL-Based Priority Escalation:

The effective priority is computed using a piecewise function:

p_{\text{effective}}(t) = p_{\text{base}} \times
\begin{cases}
2.0 & \text{if } r(t) < 0.05 \text{ (critical)} \\
1.5 & \text{if } 0.05 \leq r(t) < 0.20 \text{ (warning)} \\
1.0 & \text{otherwise (normal)}
\end{cases}

where r(t) = 1 - \frac{t - t_{\text{created}}}{\text{TTL}} is the remaining fraction of TTL at time t.

stateDiagram-v2
    [*] --> Normal: Note Created
    Normal --> Warning: TTL < 20% remaining
    Warning --> Critical: TTL < 5% remaining
    Critical --> Surfaced: Priority triggers notification
    Critical --> Expired: TTL = 0
    Normal --> Expired: TTL = 0 (low priority)
    Surfaced --> Activated: User engages
    Surfaced --> Expired: User ignores
    Expired --> [*]: Archived
    Activated --> [*]: Promoted to Active Task
TTL Remaining Escalation Factor Effect
< 5% 2.0x Critical — urgent notification
5% – 20% 1.5x Warning — gentle reminder
> 20% 1.0x Normal — no escalation

This creates automatic urgency: as a note approaches expiration, its effective priority increases, eventually triggering proactive surfacing ("Quick heads up—you asked me to review X, and that’s on my list with 90 minutes remaining").

3.4 Column 3: Objects

Objects provide ambient context—information relevant to active work but not itself a task. The column is dynamically populated via salience-based selection from the knowledge graph.

Object Categories:

graph TB
    subgraph "Objects Column"
        P[People]
        E[Entities]
        B[Beliefs]
        T[Temporal]
    end

    P --> P1[User: relationship=0.95]
    P --> P2[Vendor X: relationship=0.72]

    E --> E1[Project Cheyenne: salience=0.45]
    E --> E2[Client ABC: salience=0.88]

    B --> B1["Vendor X uses GL 5100"<br/>strength=0.88]
    B --> B2["User prefers detail"<br/>strength=0.92]

    T --> T1[Month-end: urgency=1.5x]
    T --> T2[Q3 close: urgency=1.2x]
Category Description Example
People Stakeholders with relationship_value and preference beliefs User (0.95), Vendor contact (0.72)
Entities Domain entities mentioned in active tasks Clients, projects, vendors
Beliefs High-strength beliefs (> 0.8) relevant to context "Vendor X uses GL code 5100"
Temporal Current period context Month-end, quarter-end, deadlines

Salience Computation:

s(e, t) = 0.4 \cdot r(e, t) + 0.3 \cdot f(e) + 0.3 \cdot i(e)

where:

  • r(e, t) = e^{-\Delta t / 60} — recency score (60-minute half-life)
  • f(e) = \min(1.0, \frac{\text{mentions}}{3}) — frequency score (mentions in active tasks + top notes)
  • i(e) = \max\{p_{\text{task}} : e \in \text{task}\} — importance score (max priority of linked tasks)
graph LR
    subgraph "Salience Formula"
        R[Recency<br/>weight: 0.4]
        F[Frequency<br/>weight: 0.3]
        I[Importance<br/>weight: 0.3]
    end

    R --> S[Salience Score]
    F --> S
    I --> S

    S --> FILTER{s > threshold?}
    FILTER -->|Yes| LOAD[Load to Objects]
    FILTER -->|No| SKIP[Skip]

Only the top k objects by salience are loaded (typically k=20), ensuring bounded context usage.

3.5 Implicit Cross-Column Reasoning

Unlike traditional memory systems with explicit pointers (foreign keys, references), the three columns are connected through the LLM’s natural language reasoning:

sequenceDiagram
    participant AT as Active Task
    participant LLM as LLM Reasoning
    participant OB as Objects

    AT->>LLM: "Process invoice from Vendor X"
    OB->>LLM: "Vendor X: belief='uses GL 5100' (0.88)"
    OB->>LLM: "User: prefers detailed explanations"

    Note over LLM: Entity matching:<br/>"Vendor X" appears in both

    LLM->>LLM: Infer connection implicitly
    LLM-->>AT: Apply GL 5100 with detailed reasoning

Active Task: "Process invoice from Vendor X"

Object (from Column 3): "Vendor X: salience=0.88, belief: ‘uses GL code 5100’ (strength: 0.88)"

LLM reasoning: "This task involves Vendor X, who I know uses GL 5100 based on past experience (88% confidence). I’ll assign that code."

No explicit pointer connects the task to the belief. The LLM infers the connection through entity matching ("Vendor X" appears in both). This provides:

  1. Robustness: Renaming "Vendor X" to "Vendor X Corp" doesn’t break the system
  2. Flexibility: LLM can discover novel connections ("Task mentions Seattle office, Person Y is based in Seattle")
  3. Simplicity: No complex graph traversal or join operations required

4. Implementation

4.1 State Schema

The three columns are represented in the agent’s state as follows (production code from Aleq MIND system[^code]):

[^code]: Implementation location: mars/src/aleq_mind/state.py:363-379

# Column 1: Active tasks (3-4 slots)
active_slots: List[Dict[str, Any]]

# Column 2: Notes (acknowledged queue)
noted_tasks: List[Dict[str, Any]]

# Column 3: Ambient context from Neo4j
objects: Dict[str, Any] | None

# Objects column components (populated from fetch_active_subgraph)
salient_people: List[Dict[str, Any]] | None  # From objects["people"]
salient_entities: List[str] | None  # From objects["entities"]
temporal_context: Dict[str, Any] | None  # From objects["temporal_context"]
detected_patterns: List[str] | None  # From objects["patterns"]

4.2 Column Population Logic

Column 1 (Active Tasks): Updated explicitly through task activation:

async def activate_task(
    task_id: str,
    priority_factors: TaskPriority,
    max_slots: int = 4
) -> WorkingMemorySlot | None:
    # If slots available, activate high-priority tasks
    if len(active_tasks) < max_slots:
        if priority_factors.urgency > 0.5:
            return allocate_slot(task_id, priority_factors)

    # If slots full, demote lowest priority if new task significantly higher
    lowest = min(active_tasks, key=lambda t: t.priority)
    if priority_factors.urgency > lowest.priority * 1.3:
        demote_to_notes(lowest)  # Preserve work
        return allocate_slot(task_id, priority_factors)

    # Otherwise, add to notes
    add_note(task_id, ttl=timedelta(hours=24))
    return None

Column 2 (Notes): Managed via TTL-based lifecycle:

def update_note_priorities(notes: List[Note], now: datetime):
    for note in notes:
        age = now - note.created_at
        remaining_fraction = 1.0 - (age / note.ttl)

        if remaining_fraction < 0:
            archive_note(note)  # Expired
        elif remaining_fraction < 0.05:
            note.effective_priority = note.priority * 2.0  # Critical
        elif remaining_fraction < 0.20:
            note.effective_priority = note.priority * 1.5  # Warning
        else:
            note.effective_priority = note.priority  # Normal

        # Proactive surfacing if urgent or contextually relevant
        if should_surface_note(note, current_context):
            surface_to_user(note)

Column 3 (Objects): Populated via salience-based selection from knowledge graph:

def populate_objects(
    active_tasks: List[ActiveTask],
    notes: List[Note],
    knowledge_graph: KnowledgeGraph,
    max_objects: int = 20
) -> Dict:
    # Extract entities mentioned in active tasks and top notes
    mentioned_entities = set()
    for task in active_tasks:
        mentioned_entities.update(extract_entities(task.description))
    for note in notes[:5]:  # Top 5 notes by priority
        mentioned_entities.update(extract_entities(note.content))

    # Compute salience for all entities
    entities = []
    for entity_id in mentioned_entities:
        entity = knowledge_graph.get_entity(entity_id)
        entity.salience = compute_salience(entity, active_tasks, notes)
        entities.append(entity)

    # Load related people and beliefs
    people = load_related_people(mentioned_entities)
    beliefs = [b for b in knowledge_graph.beliefs
               if b.strength > 0.8 and b.relevant_to(mentioned_entities)]

    # Sort by salience and limit to max_objects
    entities.sort(key=lambda e: e.salience, reverse=True)

    return {
        "people": people[:max_objects // 4],
        "entities": entities[:max_objects // 2],
        "beliefs": beliefs[:max_objects // 4],
        "temporal": get_temporal_context()
    }

4.3 Integration with Core Interaction Loop

flowchart TB
    subgraph "Core Interaction Loop"
        T[1. Trigger<br/>User input arrives]
        CA[2. Cognitive Activation<br/>Fetch active subgraph]
        AP[3. Appraisal<br/>Reason about situation]
        AC[4. Action<br/>Take action]
        OF[5. Outcome & Feedback<br/>Learn from results]
    end

    T --> CA
    CA --> AP
    AP --> AC
    AC --> OF
    OF -.-> T

    subgraph "Working Memory"
        C1[Column 1<br/>Active Tasks]
        C2[Column 2<br/>Notes]
        C3[Column 3<br/>Objects]
    end

    T -->|who is user?| C3
    CA -->|populate| C3
    AP -->|read| C1
    AP -->|read| C2
    AC -->|update| C1
    AC -->|create| C2
    OF -->|update beliefs| C3

The three-column architecture serves as the working memory substrate for the agent’s Core Interaction Loop:

  1. Trigger: User input arrives; Objects column provides context (who is this user? what temporal context applies?)
  2. Cognitive Activation: Fetch active subgraph from knowledge graph; populate Objects with salient entities/people/beliefs
  3. Appraisal: Reason about situation; Active Tasks show current work, Notes show commitments
  4. Action: Take action; update Active Task state, create new Notes if needed
  5. Outcome & Feedback: Learn from results; update Object beliefs based on outcomes

5. Worked Example: Invoice Processing

We illustrate the architecture through a representative scenario from professional workflow automation.

5.1 Initial State (9:00 AM)

graph TB
    subgraph "Column 1: Active Tasks"
        T1["Task 1: Process invoice from Vendor X<br/>State: Executing (awaiting GL code)<br/>Priority: 0.9<br/>Started: 8:58 AM"]
    end

    subgraph "Column 2: Notes"
        N1["Note 1: Review Cheyenne variance report<br/>TTL: 4h | Priority: 0.6"]
        N2["Note 2: Follow up on Q3 budget<br/>TTL: 24h | Priority: 0.4"]
    end

    subgraph "Column 3: Objects"
        P["People:<br/>- User (rel: 0.95, prefers detail)<br/>- Vendor X contact (0.72)"]
        E["Entities:<br/>- Vendor X (salience: 0.88)<br/>- Cheyenne (salience: 0.45)"]
        B["Beliefs:<br/>- 'Vendor X uses GL 5100' (0.88)"]
        TM["Temporal:<br/>- Month-end (urgency: 1.5x)"]
    end

Column 1 – Active Tasks:

Task State Priority Started
Process invoice from Vendor X Executing (awaiting GL code) 0.9 8:58 AM

Column 2 – Notes:

Note TTL Priority
Review Cheyenne variance report 4h 0.6
Follow up on Q3 budget 24h 0.4

Column 3 – Objects:

Category Contents
People User (relationship: 0.95, prefers detailed explanations), Vendor X contact (0.72)
Entities Vendor X (salience: 0.88), Cheyenne project (salience: 0.45)
Beliefs "Vendor X uses GL code 5100" (strength: 0.88)
Temporal Month-end period (urgency: 1.5x)

5.2 Interaction 1: Task Completion (9:05 AM)

Agent completes Task 1:

"I’ve assigned GL code 5100 to the Vendor X invoice because: (1) it’s office supplies, which typically use the 5100-5199 range, (2) we’ve used 5100 for similar invoices from this vendor in the past (belief strength: 88%), and (3) the amount is under $10K so no special approval needed."

sequenceDiagram
    participant T1 as Task 1
    participant LLM as LLM
    participant B as Belief (Column 3)
    participant R as Relationship (Column 3)

    T1->>LLM: Process Vendor X invoice
    B->>LLM: "Vendor X uses GL 5100" (0.88)
    R->>LLM: "User prefers detailed explanations"

    Note over LLM: Entity match: "Vendor X"<br/>Apply belief + relationship

    LLM->>T1: Assign GL 5100 with detailed reasoning
    T1->>T1: Mark complete, free slot

Note: The agent referenced the belief from Column 3 (Objects) without explicit pointer. The connection was inferred through entity matching ("Vendor X" in Task 1 description maps to "Vendor X" belief in Objects).

The agent also used the relationship belief ("prefers detailed explanations") to provide thorough reasoning rather than a terse response.

State Update:

  • Column 1: Task 1 marked complete, slot freed
  • Column 3: Vendor X salience decays (0.88 to 0.65, no longer in active task)

5.3 Interaction 2: Proactive Surfacing (9:10 AM)

User asks: "What’s the status on the Cheyenne project?"

Relevance Detection:

should_surface_note(
    note=Note1,  # "Review Cheyenne variance report"
    current_context={"mentioned_entities": ["Cheyenne"]},
    now=datetime.now()
)
# Returns: True (entity overlap detected)
sequenceDiagram
    participant U as User
    participant LLM as LLM
    participant N1 as Note 1 (Column 2)

    U->>LLM: "What's the status on Cheyenne?"

    Note over LLM: Entity detection:<br/>"Cheyenne" mentioned

    LLM->>N1: Check relevance
    N1-->>LLM: "Review Cheyenne variance report"<br/>Entity match: "Cheyenne"

    Note over LLM: Contextual trigger!

    LLM->>U: "Before I answer, you asked me<br/>to review the Cheyenne variance report..."

Agent response:

"Before I answer that, I wanted to mention—earlier today you asked me to review the Cheyenne variance report. Would you like me to pull that up now since we’re discussing Cheyenne?"

The agent proactively surfaced Note 1 because the user’s question mentioned "Cheyenne", which matched the note’s content. This demonstrates contextual relevance triggering without explicit pointers.

State Update:

  • Column 1: Note 1 promoted to Task 2 (activated)
  • Column 2: Note 1 removed
  • Column 3: Cheyenne salience increases (0.45 to 0.92, now in active task + mentioned by user)

5.4 Interaction 3: TTL Escalation (12:30 PM)

Note 2 state:

Property Value
Created Yesterday 2:00 PM (22.5 hours ago)
TTL 24 hours
Remaining 1.5 hours (6.25% of TTL)
Base Priority 0.4
Effective Priority 0.4 \times 2.0 = 0.8 (escalated to critical)
graph LR
    subgraph "TTL Escalation"
        T0["Created<br/>22.5h ago"]
        T1["Now<br/>6.25% remaining"]
        T2["Expires<br/>1.5h"]
    end

    T0 -->|"r(t) = 0.0625"| T1
    T1 -->|"< 0.05 threshold"| CRIT[CRITICAL<br/>2.0x multiplier]
    CRIT --> SURFACE[Proactive Surface]

Agent proactively surfaces:

"Quick heads up—you asked me yesterday to follow up on the Q3 budget, and that’s on my list with about 90 minutes left before I’d consider it overdue. Would you like me to prioritize that now?"

The agent surfaced the note automatically due to TTL escalation (r = 0.0625 < 0.05 triggers critical threshold), demonstrating temporal awareness without explicit scheduling.


6. Qualitative Case Study

6.1 Scenario Configuration

Disclosure: This case study illustrates the system's behavior in a representative professional workflow scenario. The architecture is fully implemented and deployed in production.

Scenario Parameters:

Parameter Value
Domain Professional administrative workflow
Workload Concurrent management of invoicing, scheduling, and project tracking
Knowledge graph 45 objects (15 people, 20 entities, 10 high-strength beliefs)

6.2 System Properties

The three-column architecture provides several structural guarantees that arise directly from the design.

6.2.1 Boundedness

Property: Context size is structurally bounded by slot limits.

graph TB
    subgraph "Bounded Structure"
        A[Active Tasks<br/>MAX: 4 slots]
        N[Notes<br/>MAX: 20 items]
        O[Objects<br/>MAX: 25 items]
    end

    TOTAL[Total Upper Bound:<br/>4 + 20 + 25 = 49 items]

    A --> TOTAL
    N --> TOTAL
    O --> TOTAL

    UNBOUNDED[Traditional Buffer<br/>Grows unbounded]

    style UNBOUNDED fill:#f99,stroke:#900
    style TOTAL fill:#9f9,stroke:#090

Guarantee: With 4 Active Task slots, 20 max Notes, and 25 max Objects, the working memory has a fixed upper bound regardless of total tasks in the system. Unlike undifferentiated buffers that grow with task count, three-column structure prevents context overflow.

Mechanism:

  • Active Tasks: Hard limit of 3-4 slots forces prioritization
  • Notes: TTL-based expiration automatically prunes stale items
  • Objects: Salience-based population loads only relevant items

6.2.2 Robustness to Changes

Property: The system handles entity deletions, renames, and modifications without cascading updates.

Guarantee: Because there are no explicit pointers between columns, deleting a Note doesn't break Tasks that reference it, and renaming an Entity doesn't require updates across all columns.

Mechanism: The LLM reasons about relationships through natural language descriptions, not object IDs. If an Entity is renamed, the Task description remains valid because it contains the semantic meaning, not a brittle pointer.

6.2.3 Proactive Surfacing via TTL Escalation

Property: Deferred items automatically surface before they become overdue.

Guarantee: The TTL mechanism ensures that no acknowledged task can be silently forgotten. Every note must eventually either expire (if low priority) or escalate to the point of surfacing (if high priority).

Mechanism: Priority is a function of time remaining:

p_{\text{effective}}(t) = p_{\text{base}} \times \text{escalation}(t)

This creates a "ticking clock" for every deferred item.


7. Discussion

7.1 Novel Contributions

1. Functional Separation by Cognitive Role:

Prior work treats working memory as undifferentiated storage. We introduce functional separation: Active (executive attention), Notes (deferred commitments), Objects (ambient awareness). Each column has appropriate management policies matching its cognitive role.

2. TTL-Based Automatic Escalation:

Traditional task queues use static priorities. Our TTL mechanism creates temporal urgency: as deadlines approach, notes automatically escalate in priority, triggering proactive surfacing without manual scheduling.

3. Salience-Based Dynamic Population:

Vector databases use similarity for retrieval. We introduce salience (s = 0.4r + 0.3f + 0.3i) combining recency, frequency, and importance, providing functionally relevant (not just semantically similar) context.

4. Implicit Cross-Column Reasoning:

Explicit pointers create brittleness (renaming breaks references). LLMs reason implicitly through natural language matching, providing robustness and flexibility without cascading updates.

7.2 Limitations and Future Work

Limitation Description Future Work
Salience Weight Tuning Weights (0.4, 0.3, 0.3) from pilot testing Domain-specific tuning
TTL Configuration Appropriate values depend on domain velocity Automated assignment from linguistic markers
Multi-Agent Current architecture is single-agent Shared Notes/Objects columns
Production Telemetry Ongoing deployment Comprehensive empirical validation

7.3 Comparison with Related Work

System Task Mgmt Deferred Items Ambient Ctx TTL Salience
LangChain No No No No No
AutoGPT Yes No No No No
BabyAGI Yes No No No No
MemGPT No No Yes (vector) No Yes (similarity)
Three-Column Yes Yes Yes (graph) Yes Yes (functional)

Table 1: Feature comparison with existing agent frameworks


8. Conclusion

We introduced a three-column working memory architecture for LLM-based agents that addresses fundamental limitations in current approaches to context management. By separating cognitive state into functionally distinct regions—Active Tasks (executive attention), Notes (acknowledged commitments), and Objects (ambient context)—and applying appropriate management policies to each, the architecture achieves structural guarantees of boundedness and robustness.

graph TB
    subgraph "Key Insights"
        I1[1. Functional Separation<br/>TTL for notes, salience for objects,<br/>rich state for tasks]
        I2[2. Implicit Reasoning<br/>No pointers = robustness + flexibility]
        I3[3. Cognitive Grounding<br/>Baddeley + Miller models]
    end

    I1 --> RESULT[Production-Ready<br/>Three-Column Architecture]
    I2 --> RESULT
    I3 --> RESULT

The key insights are:

  1. Functional separation enables specialized management (TTL for notes, salience for objects, rich state for tasks)
  2. Implicit reasoning (no pointers) provides robustness and flexibility
  3. Adaptation of human working memory models (Baddeley, Miller) provides cognitive grounding

The architecture is fully implemented in a production cognitive agent system and is ready for broader adoption in the LLM agent community.


Acknowledgments

This work emerged from the development of the Aleq MIND cognitive agent system. The author thanks the research community for foundational work on working memory, attention theory, and knowledge representation that informed this architecture.


References

[1] Miller, G. A. (1956). The magical number seven, plus or minus two: Some limits on our capacity for processing information. Psychological Review, 63(2), 81-97.

[2] Baddeley, A. D., & Hitch, G. (1974). Working memory. Psychology of Learning and Motivation, 8, 47-89.

[3] Baddeley, A. (2000). The episodic buffer: A new component of working memory? Trends in Cognitive Sciences, 4(11), 417-423.

[4] Cowan, N. (2001). The magical number 4 in short-term memory: A reconsideration of mental storage capacity. Behavioral and Brain Sciences, 24(1), 87-114.

[5] Kahneman, D. (1973). Attention and Effort. Prentice-Hall.

[6] LangChain. (2023). Building applications with LLMs through composability. https://github.com/langchain-ai/langchain

[7] Microsoft. (2023). Semantic Kernel: Integrate LLMs into apps. https://github.com/microsoft/semantic-kernel

[8] Packer, C., et al. (2023). MemGPT: Towards LLMs as Operating Systems. arXiv preprint arXiv:2310.08560.

[9] Hu, C., et al. (2023). ChatDB: Augmenting LLMs with Databases as Their Symbolic Memory. arXiv preprint arXiv:2306.03901.

[10] AutoGPT. (2023). An experimental open-source attempt to make GPT-4 fully autonomous. https://github.com/Significant-Gravitas/Auto-GPT

[11] BabyAGI. (2023). Task-driven autonomous agent framework. https://github.com/yoheinakajima/babyagi


Implementation: Aleq MIND agent system. Code available upon request.