What Is the Memory Core Service in TencentDB Agent Memory?

The Memory Core service is the central pipeline engine that transforms raw conversation data (L0) into structured long-term memories (L1-L3) and exposes v3 RPC APIs that other TencentDB Agent Memory components use to read and write memory records.

The TencentDB-Agent-Memory repository provides a complete memory management system for AI agents. At its foundation lies the Memory Core service, which orchestrates the deterministic processing of ephemeral chat logs into persistent knowledge graphs, scenario files, and core persona definitions.

Architecture Overview: The L0-to-L3 Pipeline

The Memory Core implements a layered architecture where data flows sequentially from raw capture to abstract persona generation. This pipeline is coordinated by the MemoryPipelineManager class defined in MemoryCore/src/utils/pipeline-manager.ts (see lines 2-30 for the architectural overview).

L0 – Capture Layer

Raw chat messages enter the system via the /v3/conversation/add endpoint. The auto-capture mechanism immediately calls notifyConversation() to buffer messages and update session activity timestamps. This layer triggers instantly on each agent_end event.

L1 – Batch Extraction

Buffered messages are processed by the L1 runner (configured via setL1Runner()). This stage creates atomic memories—discrete episodic facts, persona traits, and instructions. Triggers include:

  • Conversation count reaching configurable thresholds (warm-up or steady-state)
  • Idle timeout expiration when a user stops chatting

L2 – Scene Extraction

Per-session L2 runners transform atomic memories into scenario files (knowledge graphs and wiki pages). The pipeline uses a downward-only timer (implemented in advanceL2Timer() and fired via onL2TimerFired()) that guarantees processing occurs after L1 completes while respecting min/max interval constraints.

L3 – Persona Generation

A global L3 runner synthesizes a core persona by aggregating all session scenes. The triggerL3() function enqueues this work automatically after each L2 completion, using a global mutex and deduplication flag to ensure only one L3 process runs system-wide at any time.

Core Responsibilities and Implementation

The Memory Core service manages stateful, asynchronous orchestration through three SerialQueue instances (L1, L2, L3) and a collection of ManagedTimer objects.

State Management and Persistence

The service maintains session state through the PipelineSessionState interface, tracking conversation counts, warm-up thresholds, and cursor positions. The persistStates() method writes periodic checkpoints to disk, while recoverPendingSessions() re-arms L2 timers during startup for sessions with pending work. This ensures the pipeline survives process restarts without data loss.

Graceful Shutdown

The destroy() method (lines 150-180 in pipeline-manager.ts) implements coordinated shutdown by:

  1. Flushing pending timers and queues with configurable timeouts
  2. Persisting final state checkpoints
  3. Releasing global mutexes

API Gateway

All data-plane endpoints (/v3/conversation/*, /v3/atomic/*, /v3/knowledge/*) are served by the Memory Core gateway. The API contract is documented in MemoryCore/v3-api-memorycore-doc.md, and the service typically runs behind the gateway configuration defined in MemoryCore/tdai-gateway.yaml on port 8420.

Practical Implementation Example

The following TypeScript demonstrates typical initialization of the pipeline manager with custom runners:

import { MemoryPipelineManager } from "./MemoryCore/src/utils/pipeline-manager";

// Initialize with extraction thresholds
const manager = new MemoryPipelineManager({
  everyNConversations: 5,
  enableWarmup: true,
  l1: { idleTimeoutSeconds: 60 },
  l2: {
    delayAfterL1Seconds: 90,
    minIntervalSeconds: 900,
    maxIntervalSeconds: 3600,
    sessionActiveWindowHours: 24,
  },
});

// Configure L1 runner for atomic memory extraction
manager.setL1Runner(async ({ sessionKey, msg }) => {
  await storeAtomicMemories(sessionKey, msg);
  return { processedCount: msg.length, profileScopes: [sessionKey] };
});

// Configure L2 runner for scenario generation
manager.setL2Runner(async (sessionKey, cursor) => {
  const result = await generateScenario(sessionKey, cursor);
  return { latestCursor: result.newCursor };
});

// Configure L3 runner for persona synthesis
manager.setL3Runner(async () => {
  await synthesizeCorePersona();
});

// Start pipeline (optionally restore from checkpoint)
manager.start();

// Ingest conversation batch via API
await manager.notifyConversation("sess_123", [
  { role: "user", content: "How to fix a null pointer?", timestamp: new Date().toISOString() },
]);

This initialization pattern mirrors the production gateway process, where runners typically interface with vector databases and LLM inference endpoints.

Key Source Files

Summary

  • The Memory Core service hosts the L0-to-L3 pipeline that converts raw chats into structured memories.
  • MemoryPipelineManager orchestrates layer transitions using SerialQueue instances and ManagedTimer objects for deterministic scheduling.
  • The service provides checkpoint persistence via PipelineSessionState and graceful recovery via recoverPendingSessions().
  • All memory operations are exposed through v3 RPC APIs served on port 8420, documented in v3-api-memorycore-doc.md.
  • The architecture separates concerns into capture (L0), atomic extraction (L1), scene building (L2), and persona synthesis (L3).

Frequently Asked Questions

What triggers the transition from L1 to L2 processing in the Memory Core service?

After the L1 runner completes batch extraction, the advanceL2Timer() method schedules the L2 runner using a downward-only timer. This timer fires based on either a configurable delay after L1 completion (delayAfterL1Seconds) or a maximum interval timeout, whichever comes first. The onL2TimerFired() callback then executes the L2 runner to generate scenario files.

How does the Memory Core service ensure no data is lost during a restart?

The service implements checkpoint persistence through the persistStates() method, which serializes PipelineSessionState objects containing conversation counts, cursor positions, and pending timers. During startup, recoverPendingSessions() reads these checkpoints and re-arms any active L2 timers, allowing the pipeline to resume exactly where it left off.

What is the difference between the L2 and L3 runners?

The L2 runner operates at the session level, processing atomic memories into scenario files (knowledge graphs) for individual user sessions. The L3 runner is global and singleton-protected; it aggregates completed scenarios across all sessions to synthesize a single core persona file. While multiple L2 processes may run concurrently for different sessions, the mutex-protected triggerL3() ensures only one L3 process executes system-wide at any time.

Which API endpoints does the Memory Core service expose?

The service exposes v3 RPC-style endpoints under /v3/conversation/* for raw message ingestion, /v3/atomic/* for atomic memory operations, and /v3/knowledge/* for knowledge graph queries. These are implemented in the gateway layer and documented in MemoryCore/v3-api-memorycore-doc.md, with the complete deployment specification available in MemoryCore/tdai-gateway.yaml.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →