tencentdb-agent-memory
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesetencentdb-agent-memory
tencentdb-agent-memory
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
undefinedbash
undefinedInstall the plugin
安装插件
openclaw plugins install @tencentdb-agent-memory/memory-tencentdb
openclaw plugins install @tencentdb-agent-memory/memory-tencentdb
Restart the gateway
重启网关
openclaw gateway restart
undefinedopenclaw gateway restart
undefinedFor Hermes (Docker)
适用于Hermes(Docker部署)
bash
undefinedbash
undefinedBuild 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
--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
undefineddocker 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
--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
undefinedAs a Standalone Library
作为独立库使用
bash
npm install @tencentdb-agent-memory/memory-tencentdbtypescript
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-tencentdbtypescript
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.shjsonc
{
"memory-tencentdb": {
"enabled": true,
"config": {
"offload": {
"enabled": true
}
}
},
"plugins": {
"slots": {
"contextEngine": "openclaw-context-offload"
}
}
}然后应用运行时补丁:
bash
bash scripts/openclaw-after-tool-call-messages.patch.shFull 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:
- Offloaded to external files ()
refs/*.md - Compressed into Mermaid graph nodes with
node_id - Recalled via lookup when needed
node_id
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长工具输出会被:
- 卸载到外部文件()
refs/*.md - 压缩为带的Mermaid图节点
node_id - 需要时通过查询召回
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.-> BUsage 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 texttypescript
// 大体积工具输出
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.jstypescript
// 每日夜间运行以更新用户画像
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.jsOffload 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.shDatabase 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.portstorage.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
undefinedbash
undefinedLLM 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
undefinedOPENAI_API_KEY=your-openai-key
undefinedLearn More
更多信息
- GitHub: https://github.com/Tencent/TencentDB-Agent-Memory
- Discord: https://discord.gg/kDtHb5RW2
- Benchmarks: See README for WideSearch, SWE-bench, AA-LCR, PersonaMem results
- Architecture: 4-tier pyramid (L0 Conversation → L1 Atom → L2 Scenario → L3 Persona)
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.
- GitHub: https://github.com/Tencent/TencentDB-Agent-Memory
- Discord: https://discord.gg/kDtHb5RW2
- 基准测试: 查看README获取WideSearch、SWE-bench、AA-LCR、PersonaMem测试结果
- 架构: 四层金字塔(L0对话 → L1原子 → L2场景 → L3角色)
核心优势:TencentDB Agent Memory让Agent能够跨会话记住用户偏好、任务上下文与解决方案模式 — 无需将所有内容塞入上下文。针对短期过载使用符号化压缩,针对长期知识使用分层记忆。