tencentdb-agent-memory

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

tencentdb-agent-memory

tencentdb-agent-memory

Skill by ara.so — AI Agent Skills collection.
ara.so开发的Skill — AI Agent技能合集。

What It Does

功能介绍

TencentDB Agent Memory provides fully local long-term memory for AI agents through a 4-tier progressive pipeline:
  • L0 Conversation: Raw dialogue logs
  • L1 Atom: Atomic facts extracted from conversations
  • L2 Scenario: Scene blocks aggregated from atoms
  • L3 Persona: User profile distilled from scenarios
It combines symbolic short-term memory (Mermaid canvas offloading) with layered long-term memory (persona/scenario pyramid) to:
  • Cut token usage by up to 61.38% (WideSearch benchmark)
  • Improve task success by up to 51.52% relative (WideSearch)
  • Boost PersonaMem accuracy from 48% to 76%
Zero external API dependencies — runs entirely on local SQLite + sqlite-vec.
TencentDB Agent Memory 通过四层渐进式管道为AI Agent提供完全本地化的长期记忆:
  • L0 对话层:原始对话日志
  • L1 原子层:从对话中提取的原子事实
  • L2 场景层:由原子信息聚合而成的场景模块
  • L3 角色层:从场景中提炼的用户画像
它结合符号化短期记忆(Mermaid画布卸载)与分层长期记忆(角色/场景金字塔),实现:
  • 最多减少**61.38%**的Token使用量(WideSearch基准测试)
  • 任务成功率相对提升最高51.52%(WideSearch测试)
  • PersonaMem准确率从48%提升至76%
无外部API依赖 — 完全基于本地SQLite + sqlite-vec运行。

Installation

安装方法

For OpenClaw

适用于OpenClaw

bash
undefined
bash
undefined

Install the plugin

安装插件

openclaw plugins install @tencentdb-agent-memory/memory-tencentdb
openclaw plugins install @tencentdb-agent-memory/memory-tencentdb

Restart the gateway

重启网关

openclaw gateway restart
undefined
openclaw gateway restart
undefined

For Hermes (Docker)

适用于Hermes(Docker部署)

bash
undefined
bash
undefined

Build the image

构建镜像

docker build -f Dockerfile.hermes -t hermes-memory .
docker build -f Dockerfile.hermes -t hermes-memory .

Run with your LLM credentials

配置LLM凭证后运行

docker run -d
--name hermes-memory
--restart unless-stopped
-p 8420:8420
-e MODEL_API_KEY="${YOUR_API_KEY}"
-e MODEL_BASE_URL="https://api.lkeap.cloud.tencent.com/v1"
-e MODEL_NAME="deepseek-v3.2"
-e MODEL_PROVIDER="custom"
-v hermes_data:/opt/data
hermes-memory
undefined
docker run -d
--name hermes-memory
--restart unless-stopped
-p 8420:8420
-e MODEL_API_KEY="${YOUR_API_KEY}"
-e MODEL_BASE_URL="https://api.lkeap.cloud.tencent.com/v1"
-e MODEL_NAME="deepseek-v3.2"
-e MODEL_PROVIDER="custom"
-v hermes_data:/opt/data
hermes-memory
undefined

As a Standalone Library

作为独立库使用

bash
npm install @tencentdb-agent-memory/memory-tencentdb
typescript
import { TencentDBMemory } from '@tencentdb-agent-memory/memory-tencentdb';

const memory = new TencentDBMemory({
  storage: {
    type: 'sqlite',
    dbPath: './data/memory.db'
  }
});

await memory.initialize();
bash
npm install @tencentdb-agent-memory/memory-tencentdb
typescript
import { TencentDBMemory } from '@tencentdb-agent-memory/memory-tencentdb';

const memory = new TencentDBMemory({
  storage: {
    type: 'sqlite',
    dbPath: './data/memory.db'
  }
});

await memory.initialize();

Configuration

配置说明

OpenClaw Zero-Config (Minimal)

OpenClaw极简零配置

jsonc
// ~/.openclaw/openclaw.json
{
  "memory-tencentdb": {
    "enabled": true
  }
}
jsonc
// ~/.openclaw/openclaw.json
{
  "memory-tencentdb": {
    "enabled": true
  }
}

Enable Short-Term Compression

启用短期压缩

jsonc
{
  "memory-tencentdb": {
    "enabled": true,
    "config": {
      "offload": {
        "enabled": true
      }
    }
  },
  "plugins": {
    "slots": {
      "contextEngine": "openclaw-context-offload"
    }
  }
}
Then apply the runtime patch:
bash
bash scripts/openclaw-after-tool-call-messages.patch.sh
jsonc
{
  "memory-tencentdb": {
    "enabled": true,
    "config": {
      "offload": {
        "enabled": true
      }
    }
  },
  "plugins": {
    "slots": {
      "contextEngine": "openclaw-context-offload"
    }
  }
}
然后应用运行时补丁:
bash
bash scripts/openclaw-after-tool-call-messages.patch.sh

Full Configuration Schema

完整配置 Schema

jsonc
{
  "memory-tencentdb": {
    "enabled": true,
    "config": {
      // Storage backend
      "storage": {
        "type": "sqlite",  // or "postgres"
        "dbPath": "./data/memory.db",
        // For PostgreSQL:
        // "host": "localhost",
        // "port": 5432,
        // "database": "agent_memory",
        // "user": "postgres",
        // "password": "${POSTGRES_PASSWORD}"
      },
      
      // LLM for memory extraction
      "llm": {
        "provider": "custom",
        "apiKey": "${LLM_API_KEY}",
        "baseURL": "https://api.lkeap.cloud.tencent.com/v1",
        "model": "deepseek-v3.2"
      },
      
      // Embedding model (local by default)
      "embedding": {
        "provider": "local",  // or "openai"
        "model": "Xenova/all-MiniLM-L6-v2",
        "dimension": 384
      },
      
      // Memory extraction control
      "memory": {
        "autoExtract": true,
        "extractInterval": 10,  // Extract every 10 messages
        "personaUpdateThreshold": 50  // Update persona after 50 atoms
      },
      
      // Short-term offload
      "offload": {
        "enabled": true,
        "maxContextTokens": 100000,
        "compressionRatio": 0.3
      },
      
      // Recall settings
      "recall": {
        "topK": 5,
        "similarityThreshold": 0.6,
        "includePersona": true,
        "includeScenarios": true
      }
    }
  }
}
jsonc
{
  "memory-tencentdb": {
    "enabled": true,
    "config": {
      // 存储后端
      "storage": {
        "type": "sqlite",  // 或 "postgres"
        "dbPath": "./data/memory.db",
        // PostgreSQL配置:
        // "host": "localhost",
        // "port": 5432,
        // "database": "agent_memory",
        // "user": "postgres",
        // "password": "${POSTGRES_PASSWORD}"
      },
      
      // 用于记忆提取的LLM
      "llm": {
        "provider": "custom",
        "apiKey": "${LLM_API_KEY}",
        "baseURL": "https://api.lkeap.cloud.tencent.com/v1",
        "model": "deepseek-v3.2"
      },
      
      // 嵌入模型(默认本地)
      "embedding": {
        "provider": "local",  // 或 "openai"
        "model": "Xenova/all-MiniLM-L6-v2",
        "dimension": 384
      },
      
      // 记忆提取控制
      "memory": {
        "autoExtract": true,
        "extractInterval": 10,  // 每10条消息提取一次
        "personaUpdateThreshold": 50  // 累计50条原子信息后更新用户画像
      },
      
      // 短期记忆卸载
      "offload": {
        "enabled": true,
        "maxContextTokens": 100000,
        "compressionRatio": 0.3
      },
      
      // 召回设置
      "recall": {
        "topK": 5,
        "similarityThreshold": 0.6,
        "includePersona": true,
        "includeScenarios": true
      }
    }
  }
}

Core Concepts

核心概念

Memory Layers

记忆分层

L3 Persona (user profile, preferences)
    ↑ aggregates from
L2 Scenario (scene blocks, common patterns)
    ↑ extracts from
L1 Atom (atomic facts)
    ↑ distills from
L0 Conversation (raw dialogue)
L3 角色层(用户画像、偏好)
    ↑ 由以下层级聚合
L2 场景层(场景模块、通用模式)
    ↑ 由以下层级提取
L1 原子层(原子事实)
    ↑ 由以下层级提炼
L0 对话层(原始对话)

Symbolic Memory (Mermaid Canvas)

符号化记忆(Mermaid画布)

Long tool outputs are:
  1. Offloaded to external files (
    refs/*.md
    )
  2. Compressed into Mermaid graph nodes with
    node_id
  3. Recalled via
    node_id
    lookup when needed
mermaid
graph LR
    A["Search Results (50k tokens)"] -->|offload| B[("refs/search-001.md")]
    A -->|symbolize| C["node_1234<br/>type: search<br/>summary: 3 key findings"]
    C -.recall via node_id.-> B
长工具输出会被:
  1. 卸载到外部文件(
    refs/*.md
  2. 压缩为带
    node_id
    的Mermaid图节点
  3. 需要时通过
    node_id
    查询召回
mermaid
graph LR
    A["搜索结果(50k tokens)"] -->|offload| B[("refs/search-001.md")]
    A -->|symbolize| C["node_1234<br/>type: search<br/>summary: 3 key findings"]
    C -.recall via node_id.-> B

Usage Examples

使用示例

Store a Conversation

存储对话

typescript
import { TencentDBMemory } from '@tencentdb-agent-memory/memory-tencentdb';

const memory = new TencentDBMemory({
  storage: { type: 'sqlite', dbPath: './memory.db' }
});

await memory.initialize();

// Store conversation turn
await memory.storeConversation({
  sessionId: 'session-123',
  userId: 'user-456',
  messages: [
    { role: 'user', content: 'I prefer tabs over spaces' },
    { role: 'assistant', content: 'Got it, I'll use tabs in code.' }
  ],
  metadata: { topic: 'coding-preferences' }
});
typescript
import { TencentDBMemory } from '@tencentdb-agent-memory/memory-tencentdb';

const memory = new TencentDBMemory({
  storage: { type: 'sqlite', dbPath: './memory.db' }
});

await memory.initialize();

// 存储对话轮次
await memory.storeConversation({
  sessionId: 'session-123',
  userId: 'user-456',
  messages: [
    { role: 'user', content: 'I prefer tabs over spaces' },
    { role: 'assistant', content: 'Got it, I'll use tabs in code.' }
  ],
  metadata: { topic: 'coding-preferences' }
});

Extract Atoms and Update Persona

提取原子信息并更新用户画像

typescript
// Auto-extract runs every N messages (configurable)
// Or trigger manually:
await memory.extractAtoms('session-123');

// Check extracted atoms
const atoms = await memory.getAtoms('user-456', { limit: 10 });
console.log(atoms);
// [
//   { id: 'atom-1', content: 'User prefers tabs over spaces', category: 'preference' }
// ]

// Persona updates automatically after threshold
const persona = await memory.getPersona('user-456');
console.log(persona);
// {
//   userId: 'user-456',
//   profile: 'Prefers tabs, uses TypeScript, likes functional patterns',
//   preferences: { coding_style: 'tabs', language: 'TypeScript' }
// }
typescript
// 自动提取每N条消息触发一次(可配置)
// 或手动触发:
await memory.extractAtoms('session-123');

// 查看提取的原子信息
const atoms = await memory.getAtoms('user-456', { limit: 10 });
console.log(atoms);
// [
//   { id: 'atom-1', content: 'User prefers tabs over spaces', category: 'preference' }
// ]

// 达到阈值后自动更新用户画像
const persona = await memory.getPersona('user-456');
console.log(persona);
// {
//   userId: 'user-456',
//   profile: 'Prefers tabs, uses TypeScript, likes functional patterns',
//   preferences: { coding_style: 'tabs', language: 'TypeScript' }
// }

Recall Relevant Memories

召回相关记忆

typescript
// Before agent turn, recall relevant context
const recalled = await memory.recall({
  userId: 'user-456',
  query: 'how should I format this code?',
  topK: 5,
  includePersona: true,
  includeScenarios: true
});

console.log(recalled);
// {
//   persona: { profile: '...', preferences: {...} },
//   scenarios: [{ title: 'Code formatting', steps: [...] }],
//   atoms: [{ content: 'User prefers tabs', score: 0.89 }]
// }
typescript
// Agent回复前,召回相关上下文
const recalled = await memory.recall({
  userId: 'user-456',
  query: 'how should I format this code?',
  topK: 5,
  includePersona: true,
  includeScenarios: true
});

console.log(recalled);
// {
//   persona: { profile: '...', preferences: {...} },
//   scenarios: [{ title: 'Code formatting', steps: [...] }],
//   atoms: [{ content: 'User prefers tabs', score: 0.89 }]
// }

Offload Tool Output (Short-Term Memory)

卸载工具输出(短期记忆)

typescript
// Large tool output
const toolOutput = {
  tool: 'search',
  result: '...(50,000 tokens of search results)...'
};

// Offload and get symbolic reference
const offloaded = await memory.offloadContext({
  sessionId: 'session-123',
  content: toolOutput.result,
  metadata: { tool: 'search', timestamp: Date.now() }
});

console.log(offloaded);
// {
//   nodeId: 'node-1234',
//   mermaidNode: 'node-1234["🔍 Search: 3 findings"]',
//   refPath: 'refs/search-001.md',
//   summary: 'Found 3 relevant papers on neural memory'
// }

// Later, recover if needed
const recovered = await memory.recoverContext('node-1234');
console.log(recovered.content);  // Full original text
typescript
// 大体积工具输出
const toolOutput = {
  tool: 'search',
  result: '...(50,000 tokens of search results)...'
};

// 卸载并获取符号化引用
const offloaded = await memory.offloadContext({
  sessionId: 'session-123',
  content: toolOutput.result,
  metadata: { tool: 'search', timestamp: Date.now() }
});

console.log(offloaded);
// {
//   nodeId: 'node-1234',
//   mermaidNode: 'node-1234["🔍 Search: 3 findings"]',
//   refPath: 'refs/search-001.md',
//   summary: 'Found 3 relevant papers on neural memory'
// }

// 需要时恢复完整内容
const recovered = await memory.recoverContext('node-1234');
console.log(recovered.content);  // 完整原始文本

Query Scenarios

查询场景

typescript
// Get common solution patterns
const scenarios = await memory.getScenarios('user-456', {
  topic: 'debugging',
  limit: 3
});

console.log(scenarios);
// [
//   {
//     id: 'scenario-1',
//     title: 'TypeScript type errors',
//     pattern: 'Check tsconfig, verify imports, run tsc --noEmit',
//     frequency: 12
//   }
// ]
typescript
// 获取通用解决方案模式
const scenarios = await memory.getScenarios('user-456', {
  topic: 'debugging',
  limit: 3
});

console.log(scenarios);
// [
//   {
//     id: 'scenario-1',
//     title: 'TypeScript type errors',
//     pattern: 'Check tsconfig, verify imports, run tsc --noEmit',
//     frequency: 12
//   }
// ]

Common Patterns

通用模式

Agent Loop with Memory

带记忆功能的Agent循环

typescript
async function agentLoop(userId: string, userMessage: string) {
  const sessionId = `session-${Date.now()}`;
  
  // 1. Recall relevant context
  const memory = await memorySystem.recall({
    userId,
    query: userMessage,
    topK: 5
  });
  
  // 2. Build prompt with persona + recalled facts
  const systemPrompt = `
User Profile: ${memory.persona?.profile || 'No profile yet'}

Relevant memories:
${memory.atoms.map(a => `- ${a.content}`).join('\n')}

Recent scenarios:
${memory.scenarios.map(s => `- ${s.title}: ${s.pattern}`).join('\n')}
  `.trim();
  
  // 3. Call LLM
  const response = await llm.chat({
    messages: [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: userMessage }
    ]
  });
  
  // 4. Store conversation
  await memorySystem.storeConversation({
    sessionId,
    userId,
    messages: [
      { role: 'user', content: userMessage },
      { role: 'assistant', content: response }
    ]
  });
  
  return response;
}
typescript
async function agentLoop(userId: string, userMessage: string) {
  const sessionId = `session-${Date.now()}`;
  
  // 1. 召回相关上下文
  const memory = await memorySystem.recall({
    userId,
    query: userMessage,
    topK: 5
  });
  
  // 2. 结合用户画像与召回事实构建提示词
  const systemPrompt = `
User Profile: ${memory.persona?.profile || 'No profile yet'}

Relevant memories:
${memory.atoms.map(a => `- ${a.content}`).join('\n')}

Recent scenarios:
${memory.scenarios.map(s => `- ${s.title}: ${s.pattern}`).join('\n')}
  `.trim();
  
  // 3. 调用LLM
  const response = await llm.chat({
    messages: [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: userMessage }
    ]
  });
  
  // 4. 存储对话
  await memorySystem.storeConversation({
    sessionId,
    userId,
    messages: [
      { role: 'user', content: userMessage },
      { role: 'assistant', content: response }
    ]
  });
  
  return response;
}

Periodic Persona Refresh

定期刷新用户画像

typescript
// Run nightly to update user personas
async function refreshPersonas() {
  const users = await memory.getAllUsers();
  
  for (const userId of users) {
    const atomCount = await memory.getAtomCount(userId);
    
    if (atomCount >= 50) {  // Threshold
      await memory.updatePersona(userId);
      console.log(`Updated persona for ${userId}`);
    }
  }
}

// Schedule with cron
// 0 2 * * * node refresh-personas.js
typescript
// 每日夜间运行以更新用户画像
async function refreshPersonas() {
  const users = await memory.getAllUsers();
  
  for (const userId of users) {
    const atomCount = await memory.getAtomCount(userId);
    
    if (atomCount >= 50) {  // 阈值
      await memory.updatePersona(userId);
      console.log(`Updated persona for ${userId}`);
    }
  }
}

// 通过Cron调度
// 0 2 * * * node refresh-personas.js

Offload Long Tool Outputs

卸载长工具输出

typescript
async function handleToolCall(tool: string, args: any) {
  const result = await executeTool(tool, args);
  
  // If result is large, offload
  const tokenCount = estimateTokens(result);
  
  if (tokenCount > 10000) {
    const offloaded = await memory.offloadContext({
      sessionId: currentSession,
      content: result,
      metadata: { tool, args }
    });
    
    return {
      summary: offloaded.summary,
      nodeId: offloaded.nodeId,
      // Agent sees only Mermaid node in context
      mermaid: offloaded.mermaidNode
    };
  }
  
  return result;  // Small results stay inline
}
typescript
async function handleToolCall(tool: string, args: any) {
  const result = await executeTool(tool, args);
  
  // 如果结果体积大,进行卸载
  const tokenCount = estimateTokens(result);
  
  if (tokenCount > 10000) {
    const offloaded = await memory.offloadContext({
      sessionId: currentSession,
      content: result,
      metadata: { tool, args }
    });
    
    return {
      summary: offloaded.summary,
      nodeId: offloaded.nodeId,
      // Agent在上下文中仅看到Mermaid节点
      mermaid: offloaded.mermaidNode
    };
  }
  
  return result;  // 小体积结果直接保留
}

Troubleshooting

故障排查

Memory not extracting

记忆未提取

Check extraction interval:
jsonc
{
  "memory": {
    "autoExtract": true,
    "extractInterval": 10  // Extracts every 10 messages
  }
}
Manually trigger:
typescript
await memory.extractAtoms('session-id');
检查提取间隔:
jsonc
{
  "memory": {
    "autoExtract": true,
    "extractInterval": 10  // 每10条消息提取一次
  }
}
手动触发:
typescript
await memory.extractAtoms('session-id');

Persona not updating

用户画像未更新

Check threshold:
jsonc
{
  "memory": {
    "personaUpdateThreshold": 50  // Needs 50+ atoms
  }
}
Force update:
typescript
await memory.updatePersona('user-id');
检查阈值:
jsonc
{
  "memory": {
    "personaUpdateThreshold": 50  // 需要50条以上原子信息
  }
}
强制更新:
typescript
await memory.updatePersona('user-id');

Low recall quality

召回质量低

Tune similarity threshold:
jsonc
{
  "recall": {
    "topK": 10,  // Return more results
    "similarityThreshold": 0.5  // Lower = more permissive
  }
}
Check embedding model:
jsonc
{
  "embedding": {
    "provider": "openai",  // Try external embeddings
    "model": "text-embedding-3-small"
  }
}
调整相似度阈值:
jsonc
{
  "recall": {
    "topK": 10,  // 返回更多结果
    "similarityThreshold": 0.5  // 阈值越低,召回范围越广
  }
}
检查嵌入模型:
jsonc
{
  "embedding": {
    "provider": "openai",  // 尝试使用外部嵌入模型
    "model": "text-embedding-3-small"
  }
}

Offload not compressing

未进行卸载压缩

Verify offload is enabled:
jsonc
{
  "offload": {
    "enabled": true,
    "maxContextTokens": 100000
  }
}
For OpenClaw, check slot registration:
jsonc
{
  "plugins": {
    "slots": {
      "contextEngine": "openclaw-context-offload"
    }
  }
}
Apply runtime patch:
bash
bash scripts/openclaw-after-tool-call-messages.patch.sh
确认卸载已启用:
jsonc
{
  "offload": {
    "enabled": true,
    "maxContextTokens": 100000
  }
}
对于OpenClaw,检查插槽注册:
jsonc
{
  "plugins": {
    "slots": {
      "contextEngine": "openclaw-context-offload"
    }
  }
}
应用运行时补丁:
bash
bash scripts/openclaw-after-tool-call-messages.patch.sh

Database errors

数据库错误

SQLite locked:
  • Ensure only one process accesses the DB
  • Check file permissions on
    dbPath
PostgreSQL connection failed:
  • Verify credentials and network access
  • Check
    storage.host
    ,
    storage.port
    ,
    storage.database
SQLite锁定:
  • 确保只有一个进程访问数据库
  • 检查
    dbPath
    的文件权限
PostgreSQL连接失败:
  • 验证凭证与网络访问权限
  • 检查
    storage.host
    storage.port
    storage.database
    配置

High memory usage

内存占用过高

Reduce embedding dimension:
jsonc
{
  "embedding": {
    "model": "Xenova/all-MiniLM-L6-v2",  // 384 dims (lighter)
    "dimension": 384
  }
}
Limit recall scope:
jsonc
{
  "recall": {
    "topK": 3,  // Fewer results
    "includeScenarios": false  // Skip scenario recall
  }
}
降低嵌入维度:
jsonc
{
  "embedding": {
    "model": "Xenova/all-MiniLM-L6-v2",  // 384维度(更轻量)
    "dimension": 384
  }
}
限制召回范围:
jsonc
{
  "recall": {
    "topK": 3,  // 减少返回结果数量
    "includeScenarios": false  // 跳过场景召回
  }
}

Environment Variables

环境变量

bash
undefined
bash
undefined

LLM API Key (required if using external LLM)

LLM API密钥(使用外部LLM时必填)

LLM_API_KEY=your-api-key-here
LLM_API_KEY=your-api-key-here

PostgreSQL password (if using postgres storage)

PostgreSQL密码(使用postgres存储时)

POSTGRES_PASSWORD=your-db-password
POSTGRES_PASSWORD=your-db-password

OpenAI API key (if using OpenAI embeddings)

OpenAI API密钥(使用OpenAI嵌入模型时)

OPENAI_API_KEY=your-openai-key
undefined
OPENAI_API_KEY=your-openai-key
undefined

Learn More

更多信息


Key Takeaway: TencentDB Agent Memory lets agents remember user preferences, task context, and solution patterns across sessions — without dumping everything into context. Use symbolic compression for short-term overload and layered memory for long-term knowledge.

核心优势:TencentDB Agent Memory让Agent能够跨会话记住用户偏好、任务上下文与解决方案模式 — 无需将所有内容塞入上下文。针对短期过载使用符号化压缩,针对长期知识使用分层记忆。