mirror of
https://github.com/TencentCloud/TencentDB-Agent-Memory
synced 2026-07-10 20:34:30 +00:00
473 lines
24 KiB
Markdown
473 lines
24 KiB
Markdown
|
|
<div align="center">
|
|||
|
|
|
|||
|
|
<img src="./assets/images/logo.png" alt="TencentDB Agent Memory" width="880" />
|
|||
|
|
|
|||
|
|
### Agents remember,Humans innovate.
|
|||
|
|
|
|||
|
|
[](https://www.npmjs.com/package/@tencentdb-agent-memory/memory-tencentdb)
|
|||
|
|
[](./LICENSE)
|
|||
|
|
[](https://nodejs.org/)
|
|||
|
|
[](https://github.com/openclaw/openclaw)
|
|||
|
|
[](https://hermes-agent.nousresearch.com/docs/)
|
|||
|
|
[](https://discord.gg/kDtHb5RW2)
|
|||
|
|
|
|||
|
|
[Highlights](#-highlights) · [Overview](#overview) · [Core Technology](#core-technology-reject-flat-storage-embrace-layering-and-symbolization) · [Features](#-features) · [Quick Start](#quick-start)
|
|||
|
|
|
|||
|
|
<div align="center">
|
|||
|
|
|
|||
|
|
[**English**](./README.md) · [简体中文](./README_CN.md)
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✨ Highlights
|
|||
|
|
|
|||
|
|
> **TencentDB Agent Memory = symbolic short-term memory + layered long-term memory.**
|
|||
|
|
>
|
|||
|
|
> - **Symbolic short-term memory** offloads heavy tool logs and condenses them into compact Mermaid symbols, cutting token usage and improving task success.
|
|||
|
|
> - **Layered long-term memory** distills fragmented conversations into structured personas and scenes, instead of flat vector piles.
|
|||
|
|
|
|||
|
|
When integrated with OpenClaw, it cuts token usage by up to **61.38%**, improves pass rate by **51.52%** (relative), and raises PersonaMem accuracy from **48%** to **76%**.
|
|||
|
|
|
|||
|
|
| Memory Capability | Benchmark | OpenClaw Success | With Plugin | Relative Δ | OpenClaw Tokens | With Plugin Tokens | Relative Δ |
|
|||
|
|
| :--- | :--- | :---: | :---: | :---: | :---: | :---: | :---: |
|
|||
|
|
| **Short-term** | WideSearch | 33% | **50%** | **+51.52%** | 221.31M | **85.64M** | **−61.38%** |
|
|||
|
|
| **Short-term** | SWE-bench | 58.4% | **64.2%** | **+9.93%** | 3474.1M | **2375.4M** | **−33.09%** |
|
|||
|
|
| **Short-term** | AA-LCR | 44.0% | **47.5%** | **+7.95%** | 112.0M | **77.3M** | **−30.98%** |
|
|||
|
|
| **Long-term** | PersonaMem | 48% | **76%** | **+59%** | — | — | — |
|
|||
|
|
|
|||
|
|
> These results are measured over continuous long-horizon sessions, not isolated turns. For example, SWE-bench runs 50 consecutive tasks per session to simulate the context-accumulation pressure of real-world long-horizon agents.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
**Memory is not about hoarding everything in the AI — it is about sparing humans from having to repeat themselves.**
|
|||
|
|
|
|||
|
|
In practice, we constantly re-explain the same SOPs, project background, tool conventions, and output formats to the Agent. Such information should not require repetition, nor should it be indiscriminately dumped into the context.
|
|||
|
|
|
|||
|
|
TencentDB Agent Memory helps the Agent learn your workflows, retain task context, and reuse past experience. We reject both brute-force history accumulation and irreversible lossy summarization. Instead, we design memory as a layered system: **symbolic memory** for in-task information overload, and **memory layering** for cross-session experience.
|
|||
|
|
|
|||
|
|
> **Let the Agent remember what should be remembered, so people can focus on judgment, creation, and work that truly matters.**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Core Technology: Reject Flat Storage, Embrace Layering and Symbolization
|
|||
|
|
|
|||
|
|
Our architecture rests on two pillars: **memory layering** and **symbolic memory**. Together they ensure Agents do not merely "remember more", but "reason better".
|
|||
|
|
|
|||
|
|
### 1. Memory Layering: Progressive Disclosure with Heterogeneous Storage
|
|||
|
|
|
|||
|
|
Traditional memory systems shred data into fragments and dump them into a flat vector store. Recall degenerates into a blind search across disconnected fragments, with no macro-level guidance.
|
|||
|
|
|
|||
|
|
Whether it is long-term knowledge, short-term tasks, or future skill capabilities, memory should never be flat — both its formation and its recall must be hierarchical. TencentDB Agent Memory adopts **layering** as its unified architectural paradigm:
|
|||
|
|
|
|||
|
|
* **Short-term context layering.** The bottom layer archives raw tool outputs (`refs/*.md`); the middle layer extracts step-level summaries (`jsonl`); the top layer condenses state into a lightweight Mermaid canvas. The Agent only needs to attend to the top-layer structure in context, and drills down to the lower layers via `node_id` when an error occurs.
|
|||
|
|
* **Long-term personalization layering.** In place of flat logs, we build a semantic pyramid: **L0 Conversation** (raw dialogue) → **L1 Atom** (atomic facts) → **L2 Scenario** (scene blocks) → **L3 Persona** (user profile). The Persona layer carries day-to-day preferences; the system drills down to Atoms only when details matter.
|
|||
|
|
* **Skill generation layering.** Layering also applies to actions. The middle layer derives common solution patterns (**Scenario**) from bottom-layer execution traces (**Conversation**), and the top layer distills reusable Skills or standard SOPs (**Persona**).
|
|||
|
|
|
|||
|
|
<p align="center">
|
|||
|
|
<img src="./assets/images/memory-pyramid-en.jpg" alt="TencentDB Agent Memory L0 to L3 semantic pyramid" width="860" />
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
**Heterogeneous storage and progressive disclosure.** A dual-layer storage strategy underpins this architecture. The bottom layer (facts, logs, traces) is persisted in databases for robust full-text retrieval; the top layer (personas, scenes, canvases) is stored as human-readable Markdown files for high information density and white-box inspection. **Lower layers preserve evidence; upper layers preserve structure.**
|
|||
|
|
|
|||
|
|
**Full traceability and lossless recovery.** Compression often sacrifices traceability. TencentDB Agent Memory avoids irreversible compression by maintaining a deterministic path from high-level abstractions back to ground-truth evidence. Whether it is an offloaded error log or a distilled user preference, the system guarantees a complete drill-down path: "top-layer symbol (Persona / canvas) → mid-layer index (Scenario / jsonl) → bottom-layer raw text (L0 Conversation / refs)".
|
|||
|
|
|
|||
|
|
<div align="center">
|
|||
|
|
<img src="assets/images/flowchart1.png" alt="Retrievable and Recoverable Drill-Down Chain" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
### 2. Symbolic Memory: Maximum Semantics in Minimum Symbols (Mermaid Canvas)
|
|||
|
|
|
|||
|
|
In long tasks, the largest token consumers are verbose intermediate logs (search results, code, error traces). To address this, we combine **context offloading** with **symbolic memory**:
|
|||
|
|
|
|||
|
|
* **Mermaid symbol graph.** Instead of verbose prose or flat JSON, we encode task state transitions in high-density Mermaid syntax — precise enough for LLMs to parse, concise enough for humans to read.
|
|||
|
|
* **History offloading.** Full tool logs are offloaded to external files; only a lightweight Mermaid task map remains in context.
|
|||
|
|
* **`node_id` tracing.** The Agent reasons over the symbol graph; to verify a detail, it greps for the `node_id` and instantly retrieves the full raw text — cutting token cost while preserving full traceability.
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
Log["Verbose Logs<br/>(hundreds of thousands of tokens)"] -->|"1. Offload full text"| FS[("External FS<br/>(refs/*.md)")]
|
|||
|
|
Log -->|"2. Extract relations"| MMD["Mermaid Canvas<br/>(with node_id)"]
|
|||
|
|
|
|||
|
|
MMD -->|"3. Light injection"| Agent(("Agent Context<br/>(a few hundred tokens)"))
|
|||
|
|
Agent -. "4. Recall via node_id" .-> FS
|
|||
|
|
|
|||
|
|
style Log fill:#f1f5f9,stroke:#94a3b8,stroke-dasharray: 5 5,color:#475569
|
|||
|
|
style FS fill:#f8fafc,stroke:#cbd5e1,stroke-width:2px,color:#334155
|
|||
|
|
style MMD fill:#eff6ff,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a
|
|||
|
|
style Agent fill:#fffbeb,stroke:#f59e0b,stroke-width:2px,color:#92400e
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Quick Start
|
|||
|
|
|
|||
|
|
This section covers **standalone local mode only**: the Memory Gateway runs locally (or inside the container), uses local `SQLite + BM25` by default, and does not depend on any cloud Memory service.
|
|||
|
|
|
|||
|
|
> By default, `TDAI_GATEWAY_API_KEY` is not set, so the Gateway does not enforce a fixed Bearer secret. The v2 SDK still sends non-empty `apiKey` and `serviceId` headers as part of the protocol; for standalone mode, use `apiKey = "local"` and `serviceId = "default"`.
|
|||
|
|
|
|||
|
|
### Option 1: Use the published standalone container images
|
|||
|
|
|
|||
|
|
The images are published on Docker Hub with multi-arch tags, so Docker automatically selects the correct architecture (amd64 / arm64). No local image build is required:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker pull agentmemory/hermes-memory:1.0.0-beta
|
|||
|
|
docker pull agentmemory/openclaw-memory:1.0.0-beta
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Hermes + Memory (standalone)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker run -d --name hermes-memory \
|
|||
|
|
--restart unless-stopped \
|
|||
|
|
-v hermes-memory-data:/opt/data \
|
|||
|
|
-e MODEL_API_KEY="<LLM_API_KEY>" \
|
|||
|
|
-e MODEL_BASE_URL="https://api.lkeap.cloud.tencent.com/v1" \
|
|||
|
|
-e MODEL_NAME="deepseek-v3.2" \
|
|||
|
|
-e MODEL_PROVIDER="custom" \
|
|||
|
|
agentmemory/hermes-memory:1.0.0-beta
|
|||
|
|
|
|||
|
|
# Enter Hermes chat
|
|||
|
|
docker exec -it hermes-memory hermes
|
|||
|
|
|
|||
|
|
# Check the in-container Memory Gateway
|
|||
|
|
docker exec hermes-memory curl -s http://127.0.0.1:8420/health
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> If you reuse an existing `hermes-memory-data` volume, the container keeps using `/opt/data/config.yaml` and `/opt/data/.env` from that volume. When changing `MODEL_API_KEY`, `MODEL_BASE_URL`, `MODEL_NAME`, or `MODEL_PROVIDER`, add `-e HERMES_CONFIG_OVERWRITE=1` to regenerate the config. Removing the volume also works, but it deletes local memory data.
|
|||
|
|
|
|||
|
|
#### OpenClaw + Memory (standalone)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker run --rm -it --name openclaw-memory \
|
|||
|
|
-p 18789:18789 \
|
|||
|
|
-v openclaw-memory-data:/home/node/.openclaw \
|
|||
|
|
-v openclaw-memory-store:/opt/data \
|
|||
|
|
-e MODEL_API_KEY="<LLM_API_KEY>" \
|
|||
|
|
-e MODEL_BASE_URL="<LLM_BASE_URL>" \
|
|||
|
|
-e MODEL_NAME="<MODEL_ID>" \
|
|||
|
|
-e OPENCLAW_CONFIG_OVERWRITE=1 \
|
|||
|
|
agentmemory/openclaw-memory:1.0.0-beta \
|
|||
|
|
openclaw-memory-tui
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Both OpenClaw and Hermes standalone containers run their own in-container Memory Gateway at `127.0.0.1:8420`. Normal usage does not require publishing port `8420` to the host. Only add a non-conflicting mapping such as `-p 8421:8420` when you want to debug the in-container Gateway from the host.
|
|||
|
|
|
|||
|
|
### Option 2: Start the standalone Memory service directly
|
|||
|
|
|
|||
|
|
If you only want to run the Memory Gateway and call it from SDKs or your own Agent:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git clone <this-repo>
|
|||
|
|
cd tdai-memory-openclaw-plugin
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
TDAI_GATEWAY_CONFIG="$PWD/tdai-gateway.standalone.yaml" \
|
|||
|
|
TDAI_GATEWAY_HOST=127.0.0.1 \
|
|||
|
|
TDAI_GATEWAY_PORT=8420 \
|
|||
|
|
TDAI_DATA_DIR="$HOME/.memory-tencentdb/memory-tdai" \
|
|||
|
|
TDAI_LLM_API_KEY="<LLM_API_KEY>" \
|
|||
|
|
TDAI_LLM_BASE_URL="https://api.openai.com/v1" \
|
|||
|
|
TDAI_LLM_MODEL="gpt-4o" \
|
|||
|
|
node --import tsx/esm src/gateway/server.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Verify the service:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl http://127.0.0.1:8420/health
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
By default, `TDAI_GATEWAY_API_KEY` is not configured, so standalone mode does not enforce a fixed shared secret. If you expose the Gateway to a network, set `TDAI_GATEWAY_API_KEY` explicitly and use the same value in clients.
|
|||
|
|
|
|||
|
|
This option is intended for users who want to build their own Agent Memory adapter: run only the Memory Gateway, then use the v2 SDK inside your Agent framework to write conversations, recall memories, and expose memory tools. This repository provides two adapter references:
|
|||
|
|
|
|||
|
|
- [OpenClaw adapter reference](./openclaw-plugin/README.md)
|
|||
|
|
- [Hermes v2 adapter reference](./hermes-plugin/memory/memory_tencentdb_v2/README.md)
|
|||
|
|
|
|||
|
|
Full SDK API and local package build references: [TypeScript SDK docs](./sdk/typescript/README.md) / [Python SDK docs](./sdk/python/README.md).
|
|||
|
|
|
|||
|
|
### Option 3: Node.js SDK
|
|||
|
|
|
|||
|
|
Install:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
npm install @tencentdb-agent-memory/memory-sdk-ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Example:
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
import { MemoryClient } from "@tencentdb-agent-memory/memory-sdk-ts";
|
|||
|
|
|
|||
|
|
const client = new MemoryClient({
|
|||
|
|
endpoint: "http://127.0.0.1:8420",
|
|||
|
|
apiKey: "local", // standalone default; if TDAI_GATEWAY_API_KEY is set, use that value
|
|||
|
|
serviceId: "default", // standalone default space
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
await client.addConversation({
|
|||
|
|
session_id: "quickstart-session",
|
|||
|
|
messages: [
|
|||
|
|
{ role: "user", content: "I prefer TypeScript for tool scripts." },
|
|||
|
|
{ role: "assistant", content: "Got it, I will remember that preference." },
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const conversations = await client.queryConversation({
|
|||
|
|
session_id: "quickstart-session",
|
|||
|
|
limit: 10,
|
|||
|
|
});
|
|||
|
|
console.log(conversations.messages);
|
|||
|
|
|
|||
|
|
// L1 memories are extracted asynchronously. After enough turns or after the
|
|||
|
|
// pipeline has run, you can search structured memories:
|
|||
|
|
const memories = await client.searchAtomic({ query: "TypeScript preference", limit: 5 });
|
|||
|
|
console.log(memories.items);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [Node.js SDK docs](./sdk/typescript/README.md)
|
|||
|
|
|
|||
|
|
### Option 4: Python SDK
|
|||
|
|
|
|||
|
|
Install:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
pip install tencentdb-agent-memory-sdk-python
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Example:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from tencentdb_agent_memory import MemoryClient
|
|||
|
|
|
|||
|
|
client = MemoryClient(
|
|||
|
|
endpoint="http://127.0.0.1:8420",
|
|||
|
|
api_key="local", # standalone default; if TDAI_GATEWAY_API_KEY is set, use that value
|
|||
|
|
service_id="default", # standalone default space
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
client.add_conversation(
|
|||
|
|
session_id="quickstart-session",
|
|||
|
|
messages=[
|
|||
|
|
{"role": "user", "content": "I prefer Python for data processing."},
|
|||
|
|
{"role": "assistant", "content": "Got it, I will remember that preference."},
|
|||
|
|
],
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
conversations = client.query_conversation(
|
|||
|
|
session_id="quickstart-session",
|
|||
|
|
limit=10,
|
|||
|
|
)
|
|||
|
|
print(conversations["messages"])
|
|||
|
|
|
|||
|
|
# L1 memories are extracted asynchronously. After enough turns or after the
|
|||
|
|
# pipeline has run, you can search structured memories:
|
|||
|
|
memories = client.search_atomic(query="Python preference", limit=5)
|
|||
|
|
print(memories["items"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [Python SDK docs](./sdk/python/README.md)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔒 Gateway Security (optional)
|
|||
|
|
|
|||
|
|
The Hermes Gateway listens on `:8420` and exposes capture / search / recall HTTP endpoints. Two opt-in switches let you turn it from "open localhost sidecar" into "authenticated network service". **Both default to off so existing deployments keep working unchanged.**
|
|||
|
|
|
|||
|
|
| Field | env | Default | Description |
|
|||
|
|
| :--- | :--- | :--- | :--- |
|
|||
|
|
| `server.apiKey` | `TDAI_GATEWAY_API_KEY` | _(unset)_ | When set, every route except `GET /health` requires `Authorization: Bearer <apiKey>`; missing or wrong tokens get HTTP 401. Comparison is constant-time. |
|
|||
|
|
| `server.corsOrigins` | `TDAI_CORS_ORIGINS` (comma-separated) | `[]` | CORS allow-list. Empty list emits **no** `Access-Control-Allow-*` headers — browsers then block all cross-origin requests. Use `["*"]` only for local development. |
|
|||
|
|
|
|||
|
|
When `apiKey` is unset, the gateway prints a startup `WARN`. If it is bound to a non-loopback host (e.g. `0.0.0.0`) without an apiKey, a second louder warning is emitted.
|
|||
|
|
|
|||
|
|
Clients call protected routes with a Bearer token:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -H "Authorization: Bearer $TDAI_GATEWAY_API_KEY" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"query":"...","session_key":"..."}' \
|
|||
|
|
http://127.0.0.1:8420/recall
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`GET /health` stays open without a token so orchestrator probes (`docker healthcheck`, `kubectl liveness`) keep working.
|
|||
|
|
|
|||
|
|
### Hermes plugin side
|
|||
|
|
|
|||
|
|
The Hermes `memory_tencentdb` plugin is a **client** of the Gateway. To make it talk to a Gateway that has auth enabled, set:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
export MEMORY_TENCENTDB_GATEWAY_API_KEY="<same-secret-as-gateway>"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The plugin will then attach `Authorization: Bearer <key>` to every request it sends to the Gateway. If the variable is unset, the plugin sends no auth header — which matches the Gateway's legacy default and is fine for a Gateway that has not opted into `TDAI_GATEWAY_API_KEY`.
|
|||
|
|
|
|||
|
|
Important: the plugin only handles the **client half**. Whether the Gateway actually enforces a Bearer check is decided on the Gateway side (`TDAI_GATEWAY_API_KEY` / `server.apiKey`). Configure the same secret on both ends — the plugin does not propagate the secret across, since the Gateway might be started by Docker, systemd, or any other means outside the plugin's control.
|
|||
|
|
|
|||
|
|
If `MEMORY_TENCENTDB_GATEWAY_API_KEY` is unset, the plugin also looks at `TDAI_GATEWAY_API_KEY` as a fallback — handy when both processes share an env file and the operator only wants to set one variable name. The Gateway never reads `MEMORY_TENCENTDB_GATEWAY_API_KEY`; that name is plugin-side only.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
|
|||
|
|
## 🔧 Configurable Parameters
|
|||
|
|
|
|||
|
|
**Every field has a sensible default — it runs with zero configuration.** When you want to tune, peel back the layers based on how deep you go.
|
|||
|
|
|
|||
|
|
<details>
|
|||
|
|
<summary><b>🟢 Level 1 · Daily tuning</b> (covers 90% of use cases)</summary>
|
|||
|
|
|
|||
|
|
| Field | Default | Description |
|
|||
|
|
| :--- | :--- | :--- |
|
|||
|
|
| `storeBackend` | `"sqlite"` | Storage backend: `sqlite` |
|
|||
|
|
| `recall.strategy` | `"hybrid"` | Recall strategy: `keyword` / `embedding` / `hybrid` (RRF fusion, recommended) |
|
|||
|
|
| `recall.maxResults` | `5` | Number of items returned per recall |
|
|||
|
|
| `recall.maxCharsPerMemory` | `0` | Max characters injected for one recalled L1 memory; `0` disables this guard |
|
|||
|
|
| `recall.maxTotalRecallChars` | `0` | Total character budget for auto-recalled L1 memories; `0` disables this guard |
|
|||
|
|
| `pipeline.everyNConversations` | `5` | Trigger an L1 memory extraction every N turns |
|
|||
|
|
| `extraction.maxMemoriesPerSession` | `20` | Max memories extracted per L1 pass |
|
|||
|
|
| `persona.triggerEveryN` | `50` | Generate the user persona every N new memories |
|
|||
|
|
| `offload.enabled` | `false` | Whether to enable short-term compression |
|
|||
|
|
|
|||
|
|
</details>
|
|||
|
|
|
|||
|
|
<details>
|
|||
|
|
<summary><b>🟡 Level 2 · Advanced tuning</b> (long task / long session)</summary>
|
|||
|
|
|
|||
|
|
| Field | Default | Description |
|
|||
|
|
| :--- | :--- | :--- |
|
|||
|
|
| `pipeline.enableWarmup` | `true` | Warm-up: a new session triggers from turn 1, doubling each time up to N (1→2→4→…) |
|
|||
|
|
| `pipeline.l1IdleTimeoutSeconds` | `600` | Trigger L1 after the user has been idle for this many seconds |
|
|||
|
|
| `pipeline.l2MinIntervalSeconds` | `900` | Minimum interval between two L2 passes within the same session |
|
|||
|
|
| `recall.timeoutMs` | `5000` | Recall timeout; on timeout, skip injection without blocking the conversation |
|
|||
|
|
| `extraction.enableDedup` | `true` | L1 vector dedup / conflict detection |
|
|||
|
|
| `capture.excludeAgents` | `[]` | Glob patterns to exclude specific agents (e.g. `bench-judge-*`) |
|
|||
|
|
| `capture.l0l1RetentionDays` | `0` | Local retention days for L0 / L1 files; `0` = never clean up |
|
|||
|
|
| `offload.mildOffloadRatio` | `0.5` | Mild compression trigger ratio (of context window) |
|
|||
|
|
| `offload.aggressiveCompressRatio` | `0.85` | Aggressive compression trigger ratio |
|
|||
|
|
| `offload.mmdMaxTokenRatio` | `0.2` | Token budget ratio for MMD injection |
|
|||
|
|
| `bm25.language` | `"zh"` | Tokenizer language: `zh` (jieba) / `en` |
|
|||
|
|
|
|||
|
|
</details>
|
|||
|
|
|
|||
|
|
<details>
|
|||
|
|
<summary><b>🔴 Level 3 · Full parameter reference</b> (ops / custom models / remote embedding)</summary>
|
|||
|
|
|
|||
|
|
For all fields, types, and constraints see [`openclaw.plugin.json`](./openclaw.plugin.json)。
|
|||
|
|
|
|||
|
|
- `embedding.*` — remote embedding service (OpenAI-compatible API)
|
|||
|
|
- `embedding.sendDimensions` (default `true`): whether to include the `dimensions` field in the request body. OpenAI `text-embedding-3-*` models rely on it for Matryoshka truncation, but some self-hosted / OSS models (e.g. **BGE-M3**) do not support custom dimensions and will reject the request with HTTP 400 `does not support matryoshka representation`. Set it to `false` for those backends, e.g.:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"embedding": {
|
|||
|
|
"enabled": true,
|
|||
|
|
"provider": "openai",
|
|||
|
|
"baseUrl": "http://your-host:your-port/v1",
|
|||
|
|
"apiKey": "<KEY>",
|
|||
|
|
"model": "bge-m3",
|
|||
|
|
"dimensions": 1024,
|
|||
|
|
"sendDimensions": false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
- `llm.*` — standalone LLM mode (bypass OpenClaw's built-in model and run L1/L2/L3 with a designated API)
|
|||
|
|
- `offload.backendUrl / backendApiKey` — offload the L1/L1.5/L2/L4 flow to a backend service
|
|||
|
|
- `report.*` — metrics reporting
|
|||
|
|
|
|||
|
|
</details>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🤔 Features
|
|||
|
|
|
|||
|
|
### 1. Macro Personas + Micro Facts: A Unified Drill-Down Mechanism
|
|||
|
|
|
|||
|
|
The biggest risk in compression is saving tokens at the cost of losing the evidence. TencentDB Agent Memory therefore does not collapse history into an irreversible summary — it preserves a clear path from high-level abstraction back to ground-truth evidence.
|
|||
|
|
|
|||
|
|
| Question type | First look at | Drill down to |
|
|||
|
|
| :--- | :--- | :--- |
|
|||
|
|
| Daily preferences, voice, long-term goals | L3 Persona / L2 Scenario | L1 Atom / L0 Conversation when facts are needed |
|
|||
|
|
| Specific facts, dates, project details | L1 Atom / L0 Conversation | Widen the time range, or fall back to semantic recall when results are sparse |
|
|||
|
|
| Continuing a long-running task | Active Mermaid task canvas | Check the JSONL when the summary lacks detail, then `refs/*.md` for raw text |
|
|||
|
|
| Resuming a historical task | Metadata task entry | Open the Mermaid canvas → locate the `node_id` → trace `result_ref` |
|
|||
|
|
|
|||
|
|
The upper layers carry judgment and direction; the lower layers carry evidence and precision. Short-term compression and long-term memory form a single closed loop: **collapsible and expandable, abstract yet auditable.**
|
|||
|
|
|
|||
|
|
### 2. White-Box Debuggability: Memory Is Not a Black Box
|
|||
|
|
|
|||
|
|
Most memory systems fall short here: when recall is wrong, all you see is a list of vector scores, with no way to tell where things went wrong. TencentDB Agent Memory keeps the key intermediates as readable files:
|
|||
|
|
|
|||
|
|
- L2 Scenario blocks are plain Markdown — open them and inspect.
|
|||
|
|
- L3 Persona lives in `persona.md` and traces back to the Scenarios that produced it.
|
|||
|
|
- Short-term task canvases are Mermaid — readable by both humans and Agents.
|
|||
|
|
- Raw payloads, summaries, and nodes are linked by `result_ref` and `node_id`.
|
|||
|
|
|
|||
|
|
Debugging no longer means probing an opaque database — it becomes a deterministic walk along the chain "Persona → Scenario → Atom → Conversation" until the root cause surfaces.
|
|||
|
|
|
|||
|
|
**All of these layered memory artifacts live under `~/.openclaw/memory-tdai/` — feel free to open the directory and inspect each layer for yourself.**
|
|||
|
|
|
|||
|
|
### 3. Production-Ready Engineering: Not a Demo
|
|||
|
|
|
|||
|
|
| Capability | Description |
|
|||
|
|
| :--- | :--- |
|
|||
|
|
| OpenClaw plugin | Automatically captures, extracts, and recalls memory once installed |
|
|||
|
|
| Hermes Gateway adapter | `TdaiCore + HostAdapter`, decoupled from the host framework |
|
|||
|
|
| Local backend | `SQLite + sqlite-vec`, ready to use out of the box |
|
|||
|
|
| Hybrid retrieval | BM25 + vector + RRF — supports both keyword and semantic recall |
|
|||
|
|
| Agent tools | `tdai_memory_search` / `tdai_conversation_search` |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Documentation
|
|||
|
|
|
|||
|
|
| Document | Contents |
|
|||
|
|
| :--- | :--- |
|
|||
|
|
| [`scripts/README.memory-tencentdb-ctl.md`](./scripts/README.memory-tencentdb-ctl.md) | Operations & management tooling |
|
|||
|
|
| [`CHANGELOG.md`](./CHANGELOG.md) | Release notes and version history |
|
|||
|
|
| [`openclaw.plugin.json`](./openclaw.plugin.json) | OpenClaw plugin manifest and configuration schema |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Community & Contributing
|
|||
|
|
|
|||
|
|
We welcome every kind of contribution — bug reports, feature ideas, doc fixes, benchmark reproductions, ecosystem integrations, or a Pull Request. Agent memory is far from a solved problem, and we'd love to figure it out together.
|
|||
|
|
|
|||
|
|
- 🐞 **Found a bug or have a question?** Open an issue at [GitHub Issues](https://github.com/Tencent/TencentDB-Agent-Memory/issues) — we respond within 24 hours.
|
|||
|
|
- 💡 **Have an idea to share?** Start a thread in [GitHub Discussions](https://github.com/Tencent/TencentDB-Agent-Memory/discussions).
|
|||
|
|
- 🛠️ **Want to contribute code?** Please read [CONTRIBUTING.md](./CONTRIBUTING.md) first.
|
|||
|
|
- 💬 **Want to chat with us?** Join our [Discord community](https://discord.gg/kDtHb5RW2) and talk to the early developers directly.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Roadmap
|
|||
|
|
|
|||
|
|
- [x] Long-term personalized memory (L0 → L3)
|
|||
|
|
- [x] Short-term context compression (Context Offload + Mermaid canvas)
|
|||
|
|
- [x] Local SQLite backend and Tencent Cloud Vector Database (TCVDB) backend
|
|||
|
|
- [x] OpenClaw plugin and Hermes Gateway integration
|
|||
|
|
- [ ] Portable memory: cross-Agent / cross-framework / cross-device import, export, and live migration
|
|||
|
|
- [ ] Automatic Skill generation
|
|||
|
|
- [ ] Visual debugging and memory observability dashboard
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
<table>
|
|||
|
|
<tr>
|
|||
|
|
<td width="68%">
|
|||
|
|
<b>If TencentDB Agent Memory has been useful to you, please give the project a ⭐ to support us.</b><br />
|
|||
|
|
For any suggestions, feel free to open an issue and start the discussion.
|
|||
|
|
</td>
|
|||
|
|
<td width="32%" align="right">
|
|||
|
|
<img src="./assets/images/star-helper.png" alt="Star TencentDB Agent Memory" width="260" />
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
[MIT](./LICENSE) © TencentDB Agent Memory Team
|