File: README.md
Latest: Team Memory Beta is evolving quickly — install it and start exploring in minutes.
Installation
Start all three services in one go (memory-core + memory-hub + proxy):
git clone https://github.com/Tencent/TencentDB-Agent-Memory.git
cd TencentDB-Agent-Memory/deploy/global-images
cp .env.example .env
$EDITOR .env # Fill in two sets of LLM parameters (memory group + proxy group)
./start-all.sh # Launch everything with one command; when finished, it prints a one-liner you can paste directly into ClaudeOpen the panel: http://localhost:8125.
Complete installation documentation (standalone Memory Hub deployment, Proxy + Claude Code / CodeBuddy usage, stop and cleanup, port reference, etc.) is available in INSTALL.md (中文: INSTALL_CN.md).
Migrating data from an older version
If you're already on an older release (v1.x / v0.x) and want to bring your existing data over to v2.0.0+, we provide a migration tool:
See Data Migration Tool (v2 → v3) for full usage and flags. New installations can skip this.
All Agents Share the Same Memory Server
One Proxy, unchanged protocol, zero-code integration — point the Agent's base URL to the Proxy and it's done. No plugin, hook, or MCP server is required.
| DeepSeek Harness | Claude Code | Codex | CodeBuddy |
|---|---|---|---|
| WorkBuddy | Hermes | OpenClaw | More frameworks coming soon... |
See INSTALL.md for the exact configuration steps of each client.
Don't see your favorite Agent? You can try adapting it yourself with the Generic integration guide — and we'd love a PR adding native support for it. See CONTRIBUTING.md to get started.
What is TencentDB Agent Memory?
We started from a practical question: How do you reduce repetitive work when using Agents?
If project context has already been explained, it shouldn't need to be repeated in a new session. If documents have already been read, every Agent shouldn't have to start again from page one. A workflow that already works shouldn't have to be rediscovered next time.
Memory here means more than just "remembering conversations." Any information that helps the next Agent avoid reinventing the wheel should be saved, organized, and reused.
Existing information → Reusable memory assets → Fewer turns → Less rework → More stable results and higher efficiencyLet experience accumulate, flow, and pass on to the next Agent
Memory Hub for Agent teams closes the loop across the entire experience lifecycle: work produces assets, assets circulate through the team, and new members can load the team's save file on day one.
- Automatic asset extraction: Extract Chat Memory and Skills from conversations and tasks; convert documents and code into Wiki and CodeGraph; then manage, review, and route them consistently.
- Portable & multi-Agent compatible: Memory assets are decoupled from Agent frameworks — they can move across frameworks and be shared and maintained by multiple Agents and team members.
- Cold-start friendly: Import existing documents, codebases, and Agent conversation sessions. New Agent teams can start from existing experience instead of learning from scratch.
🧠 A brain that remembers people and context
- Chat Memory retains preferences, facts, decisions, and interaction history.
- Each Agent automatically gets its own memory when created — no need to re-introduce yourself next time.
- L0 Conversation → L1 Atom → L2 Scenario → L3 Persona — raw conversations are distilled layer by layer.
"Don't refactor the old auth module — mobile is still using it." — Context this costly shouldn't depend on humans repeating it every time.
⚡ A Skill library that accumulates expertise
- After completing complex work, Agents can extract and manage reusable Skills from conversations and tool calls, and import them into the context of a designated Agent when needed.
- A Skill isn't just a prompt snippet; it has versions, resource files, trigger boundaries, execution steps, and validation rules.
- Personal Skills are private by default; after review, they can be shared with the team and assigned to other Agents.
Troubleshooting, code review, release checklists — learn it once, and the whole team can use it.
📖 A knowledge map that reads both docs and code
Wiki turns product docs, design specs, and ops runbooks into structured pages with a link graph. (Inspired by Karpathy's LLM knowledge base.)
CodeGraph indexes code symbols, files, call relationships, and impact paths.
Agents can search, read, inspect callers/callees, and perform impact analysis before modifying code.
Wiki keeps Agents from reading every file list before getting to work. CodeGraph doesn't just tell them "the code is here" — it tells them "changing this might affect those."
🛡️ A team memory panel controlled by humans
- Create teams and Agents in Memory Hub; review, share, and equip memory assets.
- Manage ownership, versions, status, visibility, usage counts, and Agent bindings in one place.
privatebelongs strictly to the Owner;teamis visible to all team members;restrictedgrants precise access via User / Role / Agent ACLs.- Two role layers: global System Admin manages users and teams (creating teams, adding members) and can also use Wiki, CodeGraph, Skill, and other asset management features; Team-level roles include Admin (team manager) and Member (regular member), responsible for asset collaboration and access control within a team. Asset ownership is tracked via Owner — the Owner automatically has management permissions for their assets.
Cold Start: Load the Save File, Then Get to Work
Most Agents' first task is re-learning your project. TencentDB Agent Memory turns the learning cost you've already paid into a save file:
Specifically, these existing assets can be imported directly and processed automatically in the panel:
- Codebases: Import existing repositories — CodeGraph automatically indexes symbols, files, call relationships, and impact paths.
- Documents & files: Import relevant docs and files — Wiki automatically generates structured pages with a link graph.
- Conversation sessions: Import past Agent conversation sessions — Skills and Chat Memory are automatically extracted as reusable assets.
Stop retraining every Agent. Give it the save file.
One Play Style: Build a Growing Agent Team for a One-Person Company
Open Memory Hub and create a team:
Tiny but Serious Inc.
├── 👤 You · Set goals / Make decisions
├── 🔭 Scout · Research / Find opportunities
├── 🛠 Builder · Write code / Build products
├── 🧪 Reviewer · Test / Find issues
└── 🧠 Agent Memory · Preserve the team's experienceYou're not opening four disconnected chat windows — you're assembling a squad with different roles that can inherit the team's accumulated experience.
Recruit first, then equip
🔭 Scout
├── User interview Chat Memory
├── Market research Wiki
└── Competitive analysis Skill
🛠 Builder
├── Product Wiki
├── Project CodeGraph
└── Feature Delivery Skill
🧪 Reviewer
├── Historical incident Chat Memory
├── Project CodeGraph
└── Release Checklist SkillDifferent roles, different loadouts. Less noise — give each Agent the memory assets it actually needs to get work done.
The company can be tiny. Experience can compound forever.
Memory Assets, Not a Chat Log Warehouse
RAG answers "what can be found?" Team Memory also answers "who can use it, which version is valid, and which Agent should receive it."
| Chat History | Standard RAG | TencentDB Agent Memory | |
|---|---|---|---|
| Cross-session user understanding | △ | △ | ✅ Chat Memory |
| Distilled executable experience | — | — | ✅ Skill |
| Document structure & relationships | — | △ Chunk retrieval | ✅ Wiki + Link Graph |
| Code call graphs & impact scope | — | △ Text match | ✅ CodeGraph |
| Ownership / Version / Status | — | — | ✅ |
| Team sharing & Agent loadout | — | — | ✅ |
| Private / Team / ACL | — | △ | ✅ |
Memory Hub Is Not a Display Board — It's a Control Panel
| Play Style | What you do in the Hub |
|---|---|
| Team Up | Create teams, add people and Agents, define sharing boundaries |
| Asset Library | Browse, search, review, and manage Chat Memory, Skills, Wiki, and CodeGraph |
| Agent Loadout | Bind different memory assets to different Agents; adjust priority and usage mode |
| Knowledge Workshop | Build Wiki and CodeGraph; monitor processing status and asset metadata |
| Access Control | Switch between private, team, and ACL-based access; revoke sharing when needed |
When you open an asset, what matters is not just "what it says," but also "where it came from, which version it is, who it's assigned to, and whether it's been used recently."
Every Loop Gains Experience
Memory doesn't run the Agent loop; it ensures the next iteration inherits the previous one's results: valuable interactions stay in Chat Memory, proven workflows are distilled into Skills, and document/code changes are updated through Wiki ingest and CodeGraph sync.
Without Memory, loops may just repeat faster. With inherited memory, each iteration has the chance to be better than the last.
One Agent Team: Shared Experience, Not Shared Privacy
New Chat Memory and Skills are private by default. Sharing is an explicit action, not a default leak.
| Visibility | Semantics |
|---|---|
private |
Only the Owner can read — not even team admins |
team |
Team members can read; the Owner / Admin can manage |
restricted |
Precise access via User / Role / Agent ACL |
agent |
For targeted equipping of Agents within the same team |
You can assign the "Release Skill" to the Release Agent, the "Architecture Wiki" to all development Agents, and CodeGraph to Coder and Reviewer.
Technical Implementation
TencentDB Agent Memory doesn't aim to "store everything." It solves three problems: what's worth keeping, who can use it, and how to retrieve less while retrieving the right things next time.
1. Memory isn't flat records — it grows in layers
Conversations are first saved as L0, then refined by an async pipeline into multiple levels of granularity:
| Layer | What it stores | Primary use |
|---|---|---|
| L0 Conversation | Raw conversations with full context | Verify exact wording, timestamps, and sources |
| L1 Atom | Facts, preferences, constraints, and events extracted from conversations | Precise recall of actionable information |
| L2 Scenario | Knowledge blocks organized around projects or scenarios | Quickly restore a working context |
| L3 Core / Persona | Long-term profiles, stable patterns, and high-level cognition | Let Agents rapidly enter a user's and team's context |
Both generation and retrieval are layered: normally, L2/L3 provide a quick context bootstrap; when specific facts are needed, BM25 + vector retrieval + RRF fall back to L1/L0. Results are further capped by item count, character budget, and timeout limits to prevent memory from overwhelming the context window.
2. Memory isn't a global prompt — it's the Agent's loadout
Chat Memory, Skills, Wiki, and CodeGraph are all registered uniformly as Memory Assets. Memory Hub uses Fixed Binding + ACL to determine which assets a given Agent can use: first narrow the permission scope by Team, User, Agent, and visibility, then retrieve based on the current query.
This lets teams share experience without exposing all their private information; switching Agents or frameworks only requires re-equipping, not retraining.
3. Knowledge isn't injected wholesale — it's called on demand
Documents are organized into searchable Wiki pages that support link-graph drill-down; codebases are indexed into CodeGraph assets containing files, symbols, and call relationships. Agents first discover capabilities via /v3/tools/list, then use /v3/tools/call to read relevant pages, source code, or impact paths.
This makes documents and code part of memory as well — but they remain available tools that only enter context when truly needed.
Benchmark
| Benchmark | Without TencentDB Agent Memory | With it enabled | Relative improvement |
|---|---|---|---|
| PersonaMem | 48% | 76% | +59% |
PersonaMem tests whether an Agent can correctly understand and apply user information after extended interactions.
Notes
- Wiki and CodeGraph are built asynchronously; allow some processing time before they reach
readystatus. - CodeGraph currently prioritizes public HTTPS repositories; support for private repositories and SSH credentials is still being refined.
- The Hub supports manual asset binding; fully automated memory routing is still under iteration.
Related Documentation
- Roadmap (what we're building next)
- Full Installation Guide (Memory Core + Hub + Proxy one-click deployment)
- Roadmap (what we're building next; 中文: ROADMAP_CN.md)
- Data Migration Tool (v2 → v3) (if you're on an older release and want to migrate existing data)
- Knowledge OpenAPI
- Contributing Guide
Agent Memory doesn't have a settled standard yet. Bug reports, documentation, benchmarks, new framework adapters, and more creative Memory Hub use cases are all welcome.
Roadmap
Current release is v2.0.0. Next up (v2.0.1): zero-config cold start, faster Wiki generation, user/team custom prompts, Skill export, and Codex (IDE Plan mode) support.
👉 See the full plan in ROADMAP.md (中文: ROADMAP_CN.md).
Acknowledgements
TencentDB Agent Memory stands on the shoulders of the open-source community:
- CodeGraph — our CodeGraph asset module uses code from this project. Its design of a pre-indexed code graph is the foundation of our implementation.
- Hermes Agent (Nous Research) — our Skill asset management uses part of the Skill-related code from Hermes Agent and builds further optimizations base on it.
- "LLM Wiki" by Andrej Karpathy — the idea of treating documentation as an LLM-maintained, incrementally growing knowledge artifact directly informed how our Wiki layer is built and kept up to date.
We are grateful to the authors and contributors of these projects.
Community & Contributing
We welcome contributions of all kinds — bug reports, feature suggestions, documentation fixes, benchmark reproductions, ecosystem integrations, or pull requests. Agent memory is far from settled, and we hope to build it together with the community.
- 🐞 Found a bug or have a question? Open an issue in GitHub Issues — we respond within 24 hours.
- 💡 Have an idea to share? Start a thread in GitHub Discussions.
- 🛠️ Want to contribute code? Please read CONTRIBUTING.md first.
- 💬 Want to chat with us? Join our Discord community and talk to the core developers directly.
✨ Contributors
💡 Thanks to the following contributors building with us — you make TencentDB Agent Memory better.
| If TencentDB Agent Memory has been helpful to you, please consider starring the project.
If you have any suggestions, feel free to open an issue for discussion. | |
| --- | --- |
Star History
MIT © TencentDB Agent Memory Team
File: docker/opensource/README-hermes.md
Hermes + TDAI Memory — 一体化开源镜像
预装 Hermes Agent + TDAI Memory 插件,单容器同时运行两个服务。
只需配置一个 API Key 即可启用 Hermes 对话 + 四层记忆系统。
架构
┌──────────────────────────────────────────────────────┐
│ 容器内部 │
│ │
│ ┌──────────────────────┐ ┌─────────────────────┐ │
│ │ Hermes Agent │ │ TDAI Memory │ │
│ │ (Python) │───▶│ Gateway (Node.js) │ │
│ │ │HTTP│ :8420 │ │
│ │ memory_tencentdb │ │ │ │
│ │ plugin (内置) │ │ SQLite 本地存储 │ │
│ └──────────────────────┘ └─────────────────────┘ │
│ │
│ 统一模型配置(Hermes + TDAI 共用一套 MODEL_* 变量) │
└──────────────────────────────────────────────────────┘快速开始
# 构建(不依赖项目源码,任意目录均可)
docker build -f Dockerfile.hermes -t hermes-memory .
# 运行(后台常驻,Gateway 自动启动)
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
# 验证 Gateway
curl http://localhost:8420/health
# 进入 Hermes 对话
docker exec -it hermes-memory hermes镜像内置了腾讯云 DeepSeek-V3.2 的默认值,如果你使用该模型,
MODEL_BASE_URL/MODEL_NAME/MODEL_PROVIDER可以省略,只传MODEL_API_KEY即可。
工作原理
容器启动时(CMD)自动执行以下步骤:
- 将
MODEL_*环境变量同步到 Gateway(export TDAI_LLM_*) - 生成
/opt/data/config.yaml(Hermes 配置,含模型参数和memory.provider: memory_tencentdb) - 生成
/opt/data/.env(写入OPENAI_API_KEY,供 Hermes 读取) - 前台启动 TDAI Memory Gateway(Node.js,监听 :8420,保持容器常驻)
通过 docker exec -it hermes-memory hermes 进入对话时,Hermes 从 $HERMES_HOME(/opt/data)读取上述配置文件,自动连接已运行的 Gateway。memory_tencentdb 插件通过 HTTP 与本地 Gateway 通信,完成对话采集、记忆提取、场景构建和用户画像生成(L0→L1→L2→L3 四层 pipeline)。
环境变量
统一模型配置(Hermes + TDAI 共用)
| 变量 | 默认值 | 说明 |
|---|---|---|
MODEL_API_KEY |
- | LLM API Key(必填,运行时通过 -e 传入) |
MODEL_BASE_URL |
https://api.lkeap.cloud.tencent.com/v1 |
LLM API 地址 |
MODEL_NAME |
deepseek-v3.2 |
模型名称 |
MODEL_PROVIDER |
custom |
模型 provider: custom/openrouter/anthropic/openai/gemini |
用户只需配置上述 MODEL_* 变量,容器启动时自动同步到 Hermes(config.yaml + .env)和 Gateway(TDAI_LLM_* 环境变量)。
服务配置
| 变量 | 默认值 | 说明 |
|---|---|---|
TDAI_GATEWAY_PORT |
8420 |
Gateway 端口 |
TDAI_GATEWAY_HOST |
0.0.0.0 |
Gateway 绑定地址 |
TDAI_DATA_DIR |
/opt/data/tdai-memory |
记忆数据目录 |
HERMES_HOME |
/opt/data |
Hermes 数据目录 |
数据持久化
所有数据存储在 /opt/data volume 中:
/opt/data/
├── tdai-memory/ # TDAI 记忆数据 (SQLite + 场景文件)
│ ├── memories.sqlite # L0/L1 数据
│ ├── scene_blocks/ # L2 场景文件
│ ├── persona.md # L3 用户画像
│ └── checkpoint.json # Pipeline 状态
├── sessions/ # Hermes 会话记录
├── skills/ # Hermes 技能
├── config.yaml # Hermes 配置(启动时自动生成)
├── .env # 环境变量(启动时自动生成)
└── gateway.log # Gateway 日志故障排查
# 查看 Gateway 日志
docker exec hermes-memory cat /opt/data/tdai-memory/gateway.log
# 查看 Gateway 健康状态
docker exec hermes-memory curl -s http://localhost:8420/health | python3 -m json.tool
# 手动测试记忆召回
docker exec hermes-memory curl -s -X POST http://localhost:8420/recall \
-H "Content-Type: application/json" \
-d '{"query":"test","session_key":"debug"}'
# 查看生成的 Hermes 配置
docker exec hermes-memory cat /opt/data/config.yaml
# 查看环境变量同步结果
docker exec hermes-memory env | grep -E '(MODEL_|TDAI_LLM_)'
# 进入容器调试
docker exec -it hermes-memory bash构建说明
Dockerfile 不依赖本地源码 COPY,也不依赖 root 用户:
- TDAI Memory Gateway:通过
npm install @tencentdb-agent-memory/memory-tencentdb@latest从 npm registry 获取 - Hermes Agent:通过官方安装脚本从 GitHub 获取,安装到
/usr/local/lib/hermes-agent/ - memory_tencentdb 插件:npm 包内已包含
hermes-plugin/目录,构建时自动 symlink 到 Hermes 内置插件路径(/usr/local/lib/hermes-agent/plugins/memory/)
容器内所有运行时路径均为绝对路径,不依赖 $HOME 或特定用户,可以非 root 用户运行。
File: hermes-plugin/memory/memory_tencentdb/README.md
memory-tencentdb Memory Provider (Hermes)
Hermes-side MemoryProvider
adapter for the memory-tencentdb four-layer memory system
(L0 conversation capture → L1 episodic extraction → L2 scene blocks → L3 persona synthesis).
The heavy lifting — capture, extraction, storage, recall, pipeline scheduling —
runs in a Node.js Gateway sidecar (shipped by the same package as the
OpenClaw plugin). This Python provider is a thin HTTP client + process
supervisor that plugs the Gateway into Hermes's lifecycle.
Architecture
Hermes Agent (Python)
└─ MemoryManager
└─ MemoryTencentdbProvider (this directory)
├─ GatewaySupervisor — starts / health-checks the sidecar
└─ MemoryTencentdbSdkClient — POST /recall, /capture, /search/*, /session/end
│
▼ HTTP (127.0.0.1:8420 by default)
memory-tencentdb Gateway (Node.js)
└─ memory-tencentdb Core
├─ L0 Conversation store (SQLite / TCVDB + JSONL)
├─ L1 Episodic extraction (LLM + vector dedup)
├─ L2 Scene blocks (Markdown under data dir)
├─ L3 Persona synthesis (persona.md)
└─ Storage backends: SQLite + sqlite-vec OR Tencent VectorDBHermes lifecycle → Gateway mapping:
| Hermes hook / call | Gateway endpoint | Behavior |
|---|---|---|
prefetch(query) |
POST /recall |
Synchronous. Returns <memory-context> text for injection |
sync_turn(user, assistant) |
POST /capture |
Fire-and-forget on a background daemon thread (max 4 in-flight) |
shutdown() / on_session_end |
POST /session/end |
Flush pending pipeline work |
get_tool_schemas() |
— | Advertises two LLM tools (see below) |
Reliability features baked into the provider:
- Circuit breaker — 5 consecutive Gateway failures → pause all calls for 60 s.
- Back-pressure on capture — at most 4 in-flight
sync_turnthreads; a 5th
waits up to 5 s for the oldest one before starting (Gateway hangs can't grow
threads unboundedly). - Supervised startup — if
MEMORY_TENCENTDB_GATEWAY_CMDis set (or the
provider auto-discoverssrc/gateway/server.ts, see below), it starts the
sidecar, polls/healthfor up to 30 s, and tailsgateway.stderr.logon
crash for diagnostics. - Zero-config auto-discovery — when
MEMORY_TENCENTDB_GATEWAY_CMDis
unset, the provider looks forsrc/gateway/server.tsnext to the plugin
checkout (in-tree) and, as a last resort, under~/.memory-tencentdb/tdai-memory-openclaw-plugin/(preferred),~/tdai-memory-openclaw-plugin/(legacy), and~/.hermes/plugins/tdai-memory-openclaw-plugin/.
A freshgit clonetherefore usually works without any extra env wiring —
override with the env var when you need a non-standard layout.
Installation Location
This directory (hermes-plugin/memory/memory_tencentdb/) is the source of
truth for the provider; Hermes does not load it from here. At startup
Hermes scans two locations for memory providers, in precedence order (seehermes-agent/plugins/memory/__init__.py):
- Bundled —
<hermes-agent-checkout>/plugins/memory/<name>/
This is the path memory_tencentdb ships under. It sits alongside the
other in-tree providers (byterover/,honcho/,mem0/,hindsight/,
…). Bundled entries take precedence over user-installed ones on name
collision. - User-installed —
$HERMES_HOME/plugins/<name>/, where$HERMES_HOMEdefaults to~/.hermes(seehermes_constants.get_hermes_home()). This path is used by the Windows
native.batinstaller and by third-party provider installs.
The trailing directory name must be exactly memory_tencentdb — Hermes
uses that directory name as the provider key; it must matchplugin.yaml::name and the value of memory.provider in config.yaml.
(The hyphenated form memory-tencentdb is a config-side alias, not a
valid directory name.)
Windows native install
On Windows, use the bundled batch script from the memory-tencentdb repository
root:
set TDAI_LLM_API_KEY=sk-...
set TDAI_LLM_BASE_URL=https://api.openai.com/v1
set TDAI_LLM_MODEL=gpt-4o
scripts\setup-hermes-memory-tencentdb.batPowerShell equivalent:
$env:TDAI_LLM_API_KEY="sk-..."
$env:TDAI_LLM_BASE_URL="https://api.openai.com/v1"
$env:TDAI_LLM_MODEL="gpt-4o"
.\scripts\setup-hermes-memory-tencentdb.batThe script performs the minimal native setup:
- checks
node,npm, Python, and the optionalhermescommand; - requires Node.js
>=22.16.0; - runs
npm install --omit=devwhennode_modulesis missing; - creates
%USERPROFILE%\.memory-tencentdb\memory-tdai; - sets
TDAI_LLM_*andMEMORY_TENCENTDB_GATEWAY_*in the current process
and writes them to%USERPROFILE%\.hermes\.env; - copies this provider to
%USERPROFILE%\.hermes\plugins\memory_tencentdb; - creates
%USERPROFILE%\.hermes\config.yamlwithmemory.provider: memory_tencentdbwhen the file does not exist, or prints
the exact YAML to add when it already exists; - starts the Gateway and polls
GET /health.
After it finishes, verify the sidecar directly:
curl.exe http://127.0.0.1:8420/healthPick one of the two installation styles:
Install A — symlink (recommended for developers working on both repos
simultaneously): keeps this repo as the single source of truth sogit pull in the plugin repo is immediately visible to Hermes.
# from the tdai-memory-openclaw-plugin checkout:
ln -s "$(pwd)/hermes-plugin/memory/memory_tencentdb" \
<hermes-agent-checkout>/plugins/memory/memory_tencentdbInstall B — copy (shipped alongside hermes-agent): freezes a specific
version of the provider inside the hermes-agent tree. This is how
memory_tencentdb is currently vendored in this repo pair — the two copies
under tdai-memory-openclaw-plugin/hermes-plugin/memory/memory_tencentdb/
and hermes-agent/plugins/memory/memory_tencentdb/ are kept in sync
manually.
cp -r tdai-memory-openclaw-plugin/hermes-plugin/memory/memory_tencentdb \
hermes-agent/plugins/memory/memory_tencentdbVerify Hermes sees the provider:
$ cd <hermes-agent-checkout>
$ python -c 'from plugins.memory import discover_memory_providers; \
[print(n, a) for n, _, a in discover_memory_providers()]'
memory_tencentdb True
...If the provider does not appear:
- confirm the target path is
hermes-agent/plugins/memory/memory_tencentdb/
(underscore, not hyphen); - confirm
__init__.pyandplugin.yamlsit directly inside that dir; - the discovery scan requires
__init__.pyto contain the literal stringMemoryProviderorregister_memory_provider— both are present in
this provider, so this is a non-issue as long as the file is the one
from this repo.
The Gateway source code (Node.js sidecar under
src/gateway/) stays
in thetdai-memory-openclaw-plugincheckout and does NOT need to be
copied into hermes-agent — the Python provider auto-discovers it via
the paths listed in Option A below, or viaMEMORY_TENCENTDB_GATEWAY_CMD.
Setup
1. Activate in Hermes (`~/.hermes/config.yaml`)
memory:
provider: memory_tencentdb # canonical name
# Aliases accepted for backward compatibility: `memory-tencentdb`, `tdai`2. Provide Gateway runtime + LLM credentials
At minimum the Gateway needs an OpenAI-compatible endpoint for L1/L2/L3
extraction. Set the Gateway-native variables in the Hermes process
environment:
export TDAI_LLM_API_KEY="sk-..."
export TDAI_LLM_BASE_URL="https://api.openai.com/v1" # optional
export TDAI_LLM_MODEL="gpt-4o" # optionalWhen the provider supervises the Gateway, it also accepts the legacy
Hermes-side aliases MEMORY_TENCENTDB_LLM_API_KEY,MEMORY_TENCENTDB_LLM_BASE_URL, and MEMORY_TENCENTDB_LLM_MODEL and mirrors
them into TDAI_LLM_* for the child process.
3. Start the Gateway
You have three options; pick whichever fits your deployment.
Option A — Auto-discovery (zero-config). If the plugin checkout sits at
one of the well-known paths, the provider will find src/gateway/server.ts
on its own and Popen() it as node --import tsx . Searched paths, in
order:
- In-tree:
/src/gateway/server.ts(when Hermes loads this
provider from a checkout of this repo). ~/.memory-tencentdb/tdai-memory-openclaw-plugin/src/gateway/server.ts(preferred install location)~/tdai-memory-openclaw-plugin/src/gateway/server.ts(legacy)~/.hermes/plugins/tdai-memory-openclaw-plugin/src/gateway/server.ts
No environment variables required beyond the LLM credentials above. A line
like
INFO plugins.memory.memory_tencentdb: memory-tencentdb Gateway command auto-discovered: /…/src/gateway/server.tswill appear in ~/.hermes/logs/agent.log on startup.
Option B — Explicit auto-start. Override or disable discovery by setting
the command yourself:
export MEMORY_TENCENTDB_GATEWAY_CMD="node --import tsx /abs/path/to/tdai-memory-openclaw-plugin/src/gateway/server.ts"The provider will Popen() this command on initialize(), wait forGET /health to report ok/degraded, and tail stderr on crash.
Option C — Run it yourself. Start the Gateway separately on the default
port (127.0.0.1:8420) before launching Hermes; the provider will detect it
via /health and skip the subprocess-launch path.
cd tdai-memory-openclaw-plugin
node --import tsx src/gateway/server.tsStorage backend (SQLite vs Tencent VectorDB), embedding config, pipeline
cadence, recall strategy, etc. are all Gateway-side settings. For
OpenClaw installs they live in~/.openclaw/openclaw.json; for standalone
Hermes deployments configure the Gateway via its own config file or env.
See the plugin's top-level README for the full
configuration schema.
Environment Variables
Gateway location
| Variable | Default | Description |
|---|---|---|
MEMORY_TENCENTDB_GATEWAY_HOST |
127.0.0.1 |
Gateway host |
MEMORY_TENCENTDB_GATEWAY_PORT |
8420 |
Gateway port (must be 1..65535; invalid values fall back) |
MEMORY_TENCENTDB_GATEWAY_CMD |
— | If set, the provider auto-starts the Gateway with this command. If unset, the provider auto-discovers src/gateway/server.ts next to the checkout or under $HOME (see Option A above) |
MEMORY_TENCENTDB_LOG_DIR |
~/.hermes/logs/memory_tencentdb |
Where the supervisor writes gateway.stdout.log / gateway.stderr.log |
Gateway data directory (owned by the Gateway, not this provider)
The L0~L3 data directory is resolved inside the Gateway (src/gateway/config.ts),
not here. Priority:
TDAI_DATA_DIRenv vardata.baseDirfrom atdai-gateway.yaml/tdai-gateway.jsonconfig file- Default:
~/.memory-tencentdb/memory-tdai
(Override the parent dir withMEMORY_TENCENTDB_ROOTif needed.) - Legacy fallback: if
~/.memory-tencentdb/memory-tdaidoes not exist but the
pre-0.4 location~/memory-tdaidoes, the Gateway keeps using the legacy
dir and prints a one-line deprecation warning to stderr. Runinstall_hermes_memory_tencentdb.shto migrate it automatically.
Hermes forwards the inherited environment to the Gateway subprocess, so
setting TDAI_DATA_DIR before launching Hermes is enough to override it.
The old MEMORY_TENCENTDB_DATA_DIR env var is no longer read — it was never
consumed by the Gateway anyway (names did not match), so removing it just
eliminates a silent no-op.
Gateway LLM (consumed by the Node sidecar)
| Variable | Default | Description |
|---|---|---|
TDAI_LLM_API_KEY |
— | LLM API key (required for L1/L2/L3) |
TDAI_LLM_BASE_URL |
https://api.openai.com/v1 |
OpenAI-compatible API base URL |
TDAI_LLM_MODEL |
gpt-4o |
Model name |
When the provider starts the Gateway subprocess, it mirrors the legacy
Hermes aliases below into the Gateway-native names above if the TDAI_*
variables are not already set:
| Alias | Mirrored to |
|---|---|
MEMORY_TENCENTDB_LLM_API_KEY |
TDAI_LLM_API_KEY |
MEMORY_TENCENTDB_LLM_BASE_URL |
TDAI_LLM_BASE_URL |
MEMORY_TENCENTDB_LLM_MODEL |
TDAI_LLM_MODEL |
Data-directory resolution is deliberately delegated to the Gateway via
TDAI_DATA_DIR(see above) so the provider and the Gateway can never
disagree about where L0~L3 live.
LLM Tools
This provider exposes two tools to the model via get_tool_schemas():
| Tool | Purpose | Args |
|---|---|---|
memory_tencentdb_memory_search |
Search L1 structured long-term memories | query (required), limit (1..20, default 5), type (persona/episodic/instruction) |
memory_tencentdb_conversation_search |
Search L0 raw conversation history | query (required), limit (1..20, default 5) |
Tool-call arguments are defensively coerced: limit accepts ints, numeric
strings, and floats, rejects bools, and is clamped to [1, 20] with a
warning on garbage input.
These are the only tool names registered with the LLM. The old
tdai_memory_search/tdai_conversation_searchnames are not served by
this provider — if older transcripts reference them,handle_tool_call
will return an "Unknown tool" error.
Plugin Metadata (`plugin.yaml`)
name: memory_tencentdb # canonical provider name
display_name: memory-tencentdb
hooks:
- on_memory_write # reserved; not yet mirrored to the Gateway
- on_session_end # triggers POST /session/end
aliases:
- tdai # legacy config value still resolves here
- memory-tencentdb # hyphenated form resolves here tooTroubleshooting
- "memory-tencentdb Gateway not available" on startup: either
MEMORY_TENCENTDB_GATEWAY_CMDis unset and auto-discovery did not findsrc/gateway/server.tsand nothing is listening on8420, or the
sidecar crashed. Check~/.hermes/logs/memory_tencentdb/gateway.stderr.log
(override withMEMORY_TENCENTDB_LOG_DIR). To confirm auto-discovery was
attempted, enableDEBUGlogging and look formemory-tencentdb Gateway auto-discovery found no server.ts under: …;
that log line enumerates every path that was searched. - Gateway starts from the wrong checkout: auto-discovery walks a fixed
preference list (in-tree first, then$HOME). If you want to pin a
specific path, setMEMORY_TENCENTDB_GATEWAY_CMDexplicitly — it always
wins over discovery. - Search tools silently missing from the LLM:
get_tool_schemas()
returns[]until either the Gateway is reachable or one ofMEMORY_TENCENTDB_GATEWAY_CMD/MEMORY_TENCENTDB_GATEWAY_PORTis set
in the environment. Set the env var so the tools are advertised
optimistically at registration time. - "circuit breaker tripped" warnings: five consecutive Gateway errors
were observed. Calls are paused for 60 s; check Gateway health and logs. - Capture backlog warnings: Gateway is slow or hung —
sync_turnis
tracking ≥ 4 in-flight threads. Inspect Gateway logs for stuck L1
extractions or LLM timeouts.
File: scripts/migrate-sqlite-to-tcvdb/README.md
SQLite → 腾讯云向量数据库迁移工具
离线迁移工具,用于将 memory-tdai 的数据从本地 SQLite 存储迁移到腾讯云向量数据库(TCVDB)。
前置条件
- Node.js >= 22.16.0
- 插件已通过
openclaw plugins install安装 - 迁移脚本已编译(见下方)
编译
迁移脚本使用 TypeScript 编写,运行前需要先编译:
npm run build:migrate-sqlite-to-vdb编译产物输出到 scripts/migrate-sqlite-to-tcvdb/dist/,可直接用 Node 运行。
使用方法
# 预检模式(仅查看源数据,不执行写入)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--dry-run
# 正式迁移
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--yes更多示例
# 直接传入 API Key(不通过环境变量)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key 'your-api-key-here' \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--yes# 指定自定义 SQLite 路径(数据库不在默认 vectors.db 位置时)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--sqlite-path /backup/2026-04/vectors-snapshot.db \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--yes# 只迁移 L1 记忆层(跳过 L0 原始消息和 Profile)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--layers l1 \
--yes# 只迁移 L0 和 L1(不迁移 Profile)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--layers l0,l1 \
--yes# 英文语料场景:使用英文 BM25 分词
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-en-v1.5 \
--bm25-language en \
--yes# 禁用 BM25 稀疏向量(仅使用密集向量检索)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--no-bm25-enabled \
--yes# 仅迁移数据,不自动更新 openclaw.json 和 manifest(手动管理配置)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--no-apply-config \
--no-rewrite-manifest \
--yes# 追加迁移:允许目标库已有数据,跳过非空检查
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--no-fail-if-target-nonempty \
--no-verify-counts \
--yes# 输出迁移摘要到 JSON 文件(适合 CI/自动化流水线)
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://127.0.0.1:80 \
--tcvdb-username root \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--summary-json-path ./migration-report.json \
--job-id "migrate-2026-04-13" \
--yes# 设置自定义超时和别名
npm run migrate:sqlite-to-tcvdb -- \
--plugin-data-dir ~/.openclaw/memory-tdai \
--openclaw-config-path ~/.openclaw/openclaw.json \
--tcvdb-url http://10.0.1.50:80 \
--tcvdb-username admin \
--tcvdb-api-key-env TCVDB_API_KEY \
--tcvdb-database agent_memory_prod \
--tcvdb-embedding-model bge-large-zh \
--tcvdb-alias "生产环境-主库" \
--tcvdb-timeout-ms 30000 \
--yes参数说明
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
--plugin-data-dir |
是 | — | 插件数据目录路径 |
--openclaw-config-path |
是 | — | openclaw.json 配置文件路径 |
--sqlite-path |
否 | /vectors.db |
SQLite 数据库文件路径(默认取数据目录下的 vectors.db) |
--plugin-id |
否 | memory-tencentdb |
写入配置时使用的插件 ID |
--tcvdb-url |
是 | — | TCVDB 服务地址 |
--tcvdb-username |
是 | — | TCVDB 用户名 |
--tcvdb-api-key |
* | — | TCVDB API 密钥(明文) |
--tcvdb-api-key-env |
* | — | 包含 API 密钥的环境变量名 |
--tcvdb-database |
是 | — | TCVDB 数据库名 |
--tcvdb-embedding-model |
是 | — | Embedding 模型名称 |
--tcvdb-alias |
否 | "" |
用户自定义别名 |
--tcvdb-timeout-ms |
否 | 10000 |
请求超时时间(毫秒) |
--layers |
否 | l0,l1,l2,l3 |
要迁移的层(逗号分隔) |
--dry-run |
否 | false |
仅预览,不执行写入 |
--yes |
否 | false |
跳过交互确认 |
--apply-config |
否 | true |
迁移后更新 openclaw.json |
--config-backup |
否 | true |
写入配置前先备份原配置文件 |
--rewrite-manifest |
否 | true |
将 manifest.json 更新为 tcvdb |
--fail-if-target-nonempty |
否 | true |
目标库非空时中止 |
--verify-counts |
否 | true |
迁移后校验记录数 |
--summary-json-path |
否 | — | 将迁移摘要写入此文件 |
--job-id |
否 | — | 迁移任务 ID(用于追踪) |
--bm25-enabled |
否 | true |
启用 BM25 稀疏向量 |
--bm25-language |
否 | zh |
BM25 语言(zh 或 en) |
* --tcvdb-api-key 和 --tcvdb-api-key-env 二选一,必须提供其中一个。
目录结构
scripts/migrate-sqlite-to-tcvdb/
├── cli-entry.ts # CLI 入口
├── sqlite-to-tcvdb.ts # 迁移核心逻辑(参数解析、预检、数据迁移)
├── config-write.ts # OpenClaw 配置更新(JSON5,自包含)
├── manifest-write.ts # Manifest 重写
├── *.test.ts # 就近放置的测试文件
├── tsconfig.json # 迁移脚本编译配置
├── dist/ # 编译产物(已 gitignore)
└── README.md # 本文件
bin/migrate-sqlite-to-tcvdb.mjs # 极薄 bin 包装 → dist/迁移脚本通过 ../../src/ 引用存储实现(VectorStore、TcvdbMemoryStore 等),但不依赖 openclaw/plugin-sdk。配置写回直接使用 json5。
File: scripts/README.memory-tencentdb-ctl.md
memory-tencentdb-ctl.sh — memory_tencentdb运维脚本
配合
install_hermes_memory_tencentdb.sh使用。
先跑安装脚本部署好插件 + Node 依赖,之后日常的启停 / 配置全部通过memory-tencentdb-ctl.sh完成。
1. 运行模式
脚本有两种模式,默认是独立模式,完全不触碰 ~/.hermes:
| 模式 | 激活方式 | 做什么 | 不做什么 |
|---|---|---|---|
standalone(默认) |
无需任何参数 | 启停 Gateway;写 $TDAI_DATA_DIR/tdai-gateway.json;日志落 $TDAI_DATA_DIR/logs/ |
不写 $HERMES_HOME/env.d/,不改 $HERMES_HOME/config.yaml,不读 hermes 相关 env |
hermes |
命令行追加 --hermes,或环境 MEMORY_TENCENTDB_MODE=hermes |
standalone 的全部 + config llm 同步写 $HERMES_HOME/env.d/memory-tencentdb-llm.sh;日志落 $HERMES_HOME/logs/memory_tencentdb/;开放 enable-hermes-memory 子命令 |
— |
为什么 hermes 模式要多写 env 文件?
因为 hermes 进程会托管式地把 Gateway 以子进程拉起来(supervisor 用os.environ.copy()传环境),此时 Gateway 读不到tdai-gateway.json所在的 shell 环境,必须通过$HERMES_HOME/env.d/*.sh让 hermes 自身source才能把凭据传进去。独立模式下 Gateway 自己读 JSON,无此需要。
2. 路径
路径变量约定:本节及后续示例统一用
$HERMES_HOME指代 hermes 的家目录,默认~/.hermes,但你可以通过环境变量覆盖(例如export HERMES_HOME=/srv/hermes),脚本和 hermes 自身都遵守这个变量。自 0.4.x 起,所有 tdai 相关数据/代码默认收纳到统一根目录
$MEMORY_TENCENTDB_ROOT(默认~/.memory-tencentdb)之下:
$TDAI_INSTALL_DIR默认$MEMORY_TENCENTDB_ROOT/tdai-memory-openclaw-plugin(即~/.memory-tencentdb/tdai-memory-openclaw-plugin)$TDAI_DATA_DIR默认$MEMORY_TENCENTDB_ROOT/memory-tdai(即~/.memory-tencentdb/memory-tdai)下文出现这些变量时先
export一份覆盖,再跑命令即可全局生效。
旧版本使用~/tdai-memory-openclaw-plugin与~/memory-tdai;install_hermes_memory_tencentdb.sh在升级时会自动迁移这两个旧目录到新位置。
| 路径 | standalone | hermes | 作用 |
|---|---|---|---|
$TDAI_INSTALL_DIR |
✅ | ✅ | 插件源码 + node_modules + src/gateway/server.ts |
$TDAI_DATA_DIR/tdai-gateway.json |
✅ | ✅ | Gateway 主配置:llm / memory.embedding / memory.tcvdb / memory.storeBackend,权限 0600 |
$TDAI_DATA_DIR/logs/ |
✅ 日志 | — | gateway.stdout.log / gateway.stderr.log / gateway.pid |
$HERMES_HOME/logs/memory_tencentdb/ |
— | ✅ 日志 | 同上,换目录 |
$HERMES_HOME/env.d/memory-tencentdb-llm.sh |
— | ✅ | hermes 启动前 source,给 supervisor 托管的 Gateway 子进程注入 LLM 凭据 |
$HERMES_HOME/config.yaml |
— | ✅ | enable-hermes-memory 修改其 memory.provider |
| Gateway 监听 | 127.0.0.1:8420 |
127.0.0.1:8420 |
可被 MEMORY_TENCENTDB_GATEWAY_HOST/PORT 覆盖 |
所有路径都能用同名环境变量覆盖(再次列出便于对照):MEMORY_TENCENTDB_ROOT(默认 ~/.memory-tencentdb)、TDAI_INSTALL_DIR(默认 $MEMORY_TENCENTDB_ROOT/tdai-memory-openclaw-plugin)、TDAI_DATA_DIR(默认 $MEMORY_TENCENTDB_ROOT/memory-tdai)、HERMES_HOME(默认 ~/.hermes)、MEMORY_TENCENTDB_LOG_DIR、MEMORY_TENCENTDB_GATEWAY_HOST/PORT。
依赖:bash、python3、node >= 22、npx、lsof 或 ss。
3. 安装 & 调用
脚本随 npm 包发布到 node_modules/.../scripts/ 下,但没有注册为 bin 命令。要用全局命令名调用,必须自己做一次软链。
3.1 从 npm 包里直接运行(无需任何配置)
npm install @tencentdb-agent-memory/memory-tencentdb
# 项目内安装,路径可由 npm root 动态算出
"$(npm root)/@tencentdb-agent-memory/memory-tencentdb/scripts/memory-tencentdb-ctl.sh" --help
# 全局安装则用 npm root -g
"$(npm root -g)/@tencentdb-agent-memory/memory-tencentdb/scripts/memory-tencentdb-ctl.sh" --helpnpm root / npm root -g 会在所有包管理器(npm / pnpm / yarn)和不同的 prefix 配置下返回正确目录,避免硬编码 node_modules/ 路径。适合一次性、临时使用的场景。
3.2 软链到 PATH(推荐给运维 / 长期使用)
不论脚本来源(git clone 出来的仓库 / npm install 装的包 / 自定义部署目录),先把脚本路径算出来存到一个变量里,再统一做软链。这样无需关心你把仓库放在 ~/code/、/opt/、还是别的什么地方。
# 第一步:定位 memory-tencentdb-ctl.sh 的真实路径(任选一种来源)
# (a) 从 git 仓库(在仓库根目录或任意子目录里执行)
SCRIPT="$(git -C "$(git rev-parse --show-toplevel)" ls-files | \
grep -E 'scripts/memory-tencentdb-ctl\.sh$' | head -1)"
SCRIPT="$(git rev-parse --show-toplevel)/$SCRIPT"
# (b) 从已 npm 全局安装的包
SCRIPT="$(npm root -g)/@tencentdb-agent-memory/memory-tencentdb/scripts/memory-tencentdb-ctl.sh"
# (c) 从项目本地的 node_modules
SCRIPT="$(npm root)/@tencentdb-agent-memory/memory-tencentdb/scripts/memory-tencentdb-ctl.sh"
# (d) 完全手写绝对路径(如部署到非标准位置)
SCRIPT="/opt/tdai/scripts/memory-tencentdb-ctl.sh"
# 第二步:验证路径正确,然后软链
test -f "$SCRIPT" && echo "ok: $SCRIPT" || { echo "not found"; exit 1; }
chmod +x "$SCRIPT"
sudo ln -sf "$SCRIPT" /usr/local/bin/memory-tencentdb-ctl
# 同样的办法把 install_hermes_memory_tencentdb.sh 链接成 install-memory-tencentdb(可选)
INSTALL_SCRIPT="$(dirname "$SCRIPT")/install_hermes_memory_tencentdb.sh"
test -f "$INSTALL_SCRIPT" && {
chmod +x "$INSTALL_SCRIPT"
sudo ln -sf "$INSTALL_SCRIPT" /usr/local/bin/install-memory-tencentdb
}之后直接 memory-tencentdb-ctl … / install-memory-tencentdb …。
为什么不直接用
npm bin注册? 这两个脚本是运维工具而不是包的核心 API,主仓库希望用户显式完成 PATH 注册(避免无意中污染全局命令空间,并避免 npm 卸载时静默移除运维入口)。
4. 生命周期管理(两种模式通用)
memory-tencentdb-ctl start # 若 :8420 已占用会直接返回;否则后台 spawn,等待 /health 通过
memory-tencentdb-ctl stop # 先 SIGTERM,5s 内未退则 SIGKILL
memory-tencentdb-ctl restart
memory-tencentdb-ctl status # 打印模式、端口、data/log 路径、进程状态
memory-tencentdb-ctl health # GET /health,纯 python3 实现,不要求 curl
memory-tencentdb-ctl logs # tail -f stdout + stderr
memory-tencentdb-ctl logs err 500 # 只看 stderr 最近 500 行启动命令解析顺序:
- 环境变量
MEMORY_TENCENTDB_GATEWAY_CMD(install_hermes_memory_tencentdb.sh写入/etc/profile.d/memory-tencentdb-env.sh的那条)。 - 回退到
sh -c 'cd $TDAI_INSTALL_DIR && exec npx tsx src/gateway/server.ts'。
启动时会自动 source 的环境文件:
- 两种模式:
/etc/profile.d/memory-tencentdb-env.sh - 仅 hermes 模式:
/etc/profile.d/hermes-env.sh以及$HERMES_HOME/env.d/*.sh
5. 配置 LLM / Embedding / VDB
三类凭据统一落到 $TDAI_DATA_DIR/tdai-gateway.json(0600,原子写)。config llm 在 --hermes 模式下会额外写一份 env 文件;Embedding / VDB 从不写 env。
5.1 LLM
# standalone 模式:只写 tdai-gateway.json
memory-tencentdb-ctl config llm \
--api-key "sk-xxxxxxxxxxxx" \
--base-url "https://api.openai.com/v1" \
--model "gpt-4o" \
--restart
# hermes 模式:tdai-gateway.json + $HERMES_HOME/env.d/memory-tencentdb-llm.sh
memory-tencentdb-ctl --hermes config llm \
--api-key "sk-xxxxxxxxxxxx" \
--base-url "https://api.openai.com/v1" \
--model "gpt-4o" \
--restart- JSON 写入点:
$.llm.{baseUrl, apiKey, model}。 - env 文件写入(仅
--hermes):TDAI_LLM_*及MEMORY_TENCENTDB_LLM_*别名(Python provider 的get_config_schema()会读后者)。
5.2 Embedding
默认关闭(provider=none)。启用远端 OpenAI 兼容服务:
memory-tencentdb-ctl config embedding \
--provider openai \
--api-key "sk-xxxx" \
--base-url "https://api.openai.com/v1" \
--model "text-embedding-3-small" \
--dimensions 1536 \
--restart
# 关闭 embedding(退化为 BM25/关键词召回)
memory-tencentdb-ctl config embedding --provider none --restart- JSON 写入点:
$.memory.embedding.{provider, baseUrl, apiKey, model, dimensions, enabled, proxyUrl?}。 qclawprovider 额外要求--proxy-url。- 校验规则与
src/config.ts的parseConfig()对齐:dimensions为正整数,非none必须带apiKey/baseUrl/model/dimensions;缺项直接报错不写半残 JSON。
5.3 VectorDB(Tencent Cloud VDB / tcvdb)
memory-tencentdb-ctl config vdb \
--url "http://xxx-vdb.tencentclb.com:8100" \
--username root \
--api-key "YOUR-VDB-API-KEY" \
--database "openclaw_memory" \
--alias "primary" \
--embedding-model "bge-large-zh" \
--ca-pem "/etc/ssl/vdb-ca.pem" \
--restart- JSON 写入点:
$.memory.tcvdb.{url, username, apiKey, database, alias?, caPemPath?, embeddingModel?}。 - 默认同时把
$.memory.storeBackend切到"tcvdb";只想预埋配置先不切,加--no-set-backend。 --ca-pem只写路径不复制文件;脚本会校验可读性。
5.4 退回本地 SQLite(关闭 VDB 后端)
# 默认:保留 memory.tcvdb 凭据(方便随时再切回去),仅把 storeBackend 改回 sqlite
memory-tencentdb-ctl config vdb-off --restart
# 同时把腾讯云 VDB 的 url / apiKey / database 等凭据从 JSON 中清掉
memory-tencentdb-ctl config vdb-off --purge-creds --restart- JSON 写入点:把
$.memory.storeBackend设为"sqlite";--purge-creds时额外删除整段$.memory.tcvdb。 $.llm/$.memory.embedding等其它顶级段完全保留,hermes 侧memory.provider不动(仍是memory_tencentdb,只是它内部存储退回 sqlite)。- 配置文件不存在时给出
warn并写入仅含{"memory":{"storeBackend":"sqlite"}}的最小配置。 - 与
config vdb完全镜像:可与--dry-run/--restart组合使用。
5.5 查看当前配置
memory-tencentdb-ctl config show- 打印
tdai-gateway.json,apiKey/password/token字段自动脱敏为<redacted:NN chars>。 - hermes 模式下额外打印
$HERMES_HOME/env.d/memory-tencentdb-*.sh(API key 也会脱敏),可直接贴工单。
6. 打通 hermes(仅 `--hermes` 模式)
memory-tencentdb-ctl --hermes enable-hermes-memory幂等:把 $HERMES_HOME/config.yaml 的 memory: 段的 provider: 改成 memory_tencentdb(不存在则新增整段)。改完后重启 hermes:
source "$HERMES_HOME/env.d/memory-tencentdb-llm.sh"
pkill -f hermes-agent || true
hermes关于写入策略:脚本采用"格式保真"双路径,永不重写整个 YAML:
- 首选:检测到
ruamel.yaml时走 round-trip,完整保留注释、键序、引号、缩进风格(推荐pip install --user ruamel.yaml享受最佳保真度,非必装);- 降级:未安装 ruamel 时走最小化原位行编辑——只重写
provider:那一行,缩进直接从同段已有兄弟键的前缀逐字符拷贝(零猜测、零格式破坏);- 若
memory:段不存在,则在文件末尾追加最小段,缩进从文档其它顶级段的子键拓印。实测对真实
~/.hermes/config.yaml做 byte-for-byte diff,除provider值本身外其余字节完全一致。
非 hermes 模式下调用该命令会直接报错退出。
想反过来"保留 hermes provider 不变,仅让 TDAI 内部存储退回 sqlite",用 §5.4 的
config vdb-off即可(不需要也不要改 hermes 的memory.provider)。
7. 典型使用流程
场景 A:Gateway 独立部署(不使用 hermes)
# 1) 安装
# INSTALL_SCRIPT 的取值方式见上文 3.2 节(git rev-parse / npm root / 手填均可)
# 例如从 git 仓库根:INSTALL_SCRIPT="$(git rev-parse --show-toplevel)/scripts/install_hermes_memory_tencentdb.sh"
# 从 npm 全局: INSTALL_SCRIPT="$(npm root -g)/@tencentdb-agent-memory/memory-tencentdb/scripts/install_hermes_memory_tencentdb.sh"
bash "$INSTALL_SCRIPT"
# 2) 只配 Gateway 所需凭据
memory-tencentdb-ctl config llm --api-key "sk-..." --base-url "https://api.openai.com/v1" --model gpt-4o
memory-tencentdb-ctl config embedding --provider openai --api-key "sk-..." --base-url "https://api.openai.com/v1" \
--model text-embedding-3-small --dimensions 1536
memory-tencentdb-ctl config vdb --url "http://xxx:8100" --api-key "..." --database openclaw_memory
# 3) 启动 + 自检
memory-tencentdb-ctl start
memory-tencentdb-ctl status
memory-tencentdb-ctl health # 预期: {"status":"ok",...}场景 B:集成 hermes
# 1) 安装(与场景 A 相同;INSTALL_SCRIPT 由上文 3.2 节算出)
bash "$INSTALL_SCRIPT"
# 2) 全程加 --hermes(或 export MEMORY_TENCENTDB_MODE=hermes 一次)
memory-tencentdb-ctl --hermes config llm --api-key "sk-..." --base-url "https://api.openai.com/v1" --model gpt-4o
memory-tencentdb-ctl --hermes config embedding --provider openai --api-key "sk-..." \
--base-url "https://api.openai.com/v1" \
--model text-embedding-3-small --dimensions 1536
memory-tencentdb-ctl --hermes config vdb --url "http://xxx:8100" --api-key "..." --database openclaw_memory
# 3) 启动 Gateway(通常由 hermes supervisor 托管,这里是手动兜底)
memory-tencentdb-ctl --hermes start
memory-tencentdb-ctl --hermes status
# 4) 在 hermes config 里启用 provider,并重启 hermes
memory-tencentdb-ctl --hermes enable-hermes-memory
source "$HERMES_HOME/env.d/memory-tencentdb-llm.sh"
pkill -f hermes-agent ; hermes如果嫌 --hermes 每次都要带,可以:
export MEMORY_TENCENTDB_MODE=hermes之后所有调用自动切到 hermes 模式,命令行无需再加 --hermes。
场景 C:临时把 TDAI 的存储退回 sqlite(保留 hermes 集成)
适用于 VDB 不可达 / 排障 / 离线开发等场景:希望 hermes 端 memory.provider 仍是 memory_tencentdb,但让 Gateway 改用本地 SQLite 落盘。
# (A) 默认:保留 memory.tcvdb 凭据,仅把 storeBackend 切回 sqlite
memory-tencentdb-ctl config vdb-off --restart
# (B) 排障结束想切回 vdb:当前需要重新跑一次 config vdb(必填项需重新提供,
# 即使 JSON 里凭据还在;脚本是基于必填校验的"重新声明"语义,不是 toggle)
memory-tencentdb-ctl config vdb \
--url "http://xxx-vdb.tencentclb.com:8100" \
--api-key "<你的 KEY>" \
--database "openclaw_memory" \
--restart
# (C) 彻底放弃 vdb:清掉凭据
memory-tencentdb-ctl config vdb-off --purge-creds --restart之所以 (B) 不提供"零参数 vdb-on",是因为原
config vdb子命令把--url/--api-key/--database设为强校验,避免用户拼装出半残配置;如果你希望把"已存的凭据重新激活"也做成单命令,告诉维护者补一个config vdb-on即可(实现方式与vdb-off完全镜像)。
不要为了"切回 sqlite"去改
~/.hermes/config.yaml的memory.provider!hermes 看到的依然是memory_tencentdbprovider,存储后端切换是 Gateway 内部的事,对 hermes 完全透明。
8. 全局选项 & 调试技巧
- 所有写操作支持
--dry-run(放在命令最前),会打印将要写入的内容但不落盘:bashmemory-tencentdb-ctl --dry-run config llm --api-key k --base-url https://x --model m - 敏感文件权限一律
0600;env.d/memory-tencentdb-llm.sh含明文 API key,不要 commit。 - 启动失败:
memory-tencentdb-ctl logs err 200查看 stderr;手动前台跑一遍更容易看到报错:bashcd "$TDAI_INSTALL_DIR" && npx tsx src/gateway/server.ts - 端口冲突:
MEMORY_TENCENTDB_GATEWAY_PORT=18420 memory-tencentdb-ctl restart。 - 验证 hermes 有没有吃到新 env(hermes 模式):bash
tr '\0' '\n' < /proc/$(pgrep -n hermes-agent)/environ | grep -E 'TDAI_|MEMORY_TENCENTDB_'
9. 退出码
| 码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 参数错误 / 业务校验失败(如 --base-url 非 http(s);在 standalone 下调 hermes 专属命令) |
| 2 | 写盘失败(磁盘满、权限不足等) |
| 127 | 依赖缺失(python3 / node / npx) |
要封装成 systemd unit,基于 memory-tencentdb-ctl start / memory-tencentdb-ctl stop 写 Type=forking 的 service 即可(Gateway 是无状态 HTTP sidecar,不依赖 systemd readiness 协议)。
File: src/cli/README.md
memory-tdai CLI
openclaw memory-tdai 命令空间,提供离线数据管理工具。
seed — 导入历史对话数据
将历史对话 JSON 文件导入到记忆管线中,完整执行 L0→L1→L2→L3 流程。适用于:
- 将已有对话数据灌入记忆系统
- 批量测试记忆提取效果
- 迁移/恢复记忆数据
用法
openclaw memory-tdai seed --input <file> [options]参数
| 参数 | 必填 | 说明 |
|---|---|---|
--input <file> |
✅ | 输入 JSON 文件路径 |
--output-dir <dir> |
— | 输出目录(默认自动生成带时间戳的目录) |
--session-key <key> |
— | 回退 session key(当输入数据缺少时使用) |
--config <file> |
— | 配置覆盖文件(JSON,与 openclaw.json 插件配置深度合并) |
--strict-round-role |
— | 严格校验每轮对话必须包含 user 和 assistant 消息 |
--yes |
— | 跳过交互确认(如时间戳自动填充确认) |
示例
# 基本用法
openclaw memory-tdai seed --input conversations.json
# 指定输出目录
openclaw memory-tdai seed --input data.json --output-dir ./seed-output
# 使用自定义配置覆盖(如调整 pipeline 参数)
openclaw memory-tdai seed --input data.json --config seed-config.json
# 跳过所有确认
openclaw memory-tdai seed --input data.json --yes
# 严格模式 + 自定义配置
openclaw memory-tdai seed --input data.json --config seed-config.json --strict-round-role --yes输入文件格式
支持两种 JSON 格式:
Format A:对象包装
{
"sessions": [
{
"sessionKey": "user-alice",
"sessionId": "conv-001",
"conversations": [
[
{ "role": "user", "content": "你好", "timestamp": 1711929600000 },
{ "role": "assistant", "content": "你好!有什么可以帮你?", "timestamp": 1711929601000 }
],
[
{ "role": "user", "content": "今天天气怎么样?" },
{ "role": "assistant", "content": "今天晴天,适合出门。" }
]
]
}
]
}Format B:顶层数组
[
{
"sessionKey": "user-alice",
"conversations": [
[
{ "role": "user", "content": "你好" },
{ "role": "assistant", "content": "你好!" }
]
]
}
]字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sessionKey |
string | ✅ | Session 标识(如用户 ID、频道名) |
sessionId |
string | — | 会话实例 ID(同一 sessionKey 下可有多个 sessionId) |
conversations |
message[][] | ✅ | 对话轮次数组,每个轮次是一组消息 |
role |
string | ✅ | 消息角色:user 或 assistant |
content |
string | ✅ | 消息内容 |
timestamp |
number | string | — | 时间戳:epoch 毫秒或 ISO 8601 字符串。缺失时 seed 会提示自动填充 |
配置覆盖
--config 接受一个 JSON 文件,与 openclaw.json 中的插件配置两级深度合并:
- 顶层 key 如果两边都是对象 → 浅合并(保留 base 中未覆盖的字段)
- 其他类型 → 直接覆盖
常见场景:seed 时使用更激进的 pipeline 参数以加速处理:
{
"pipeline": {
"everyNConversations": 3,
"enableWarmup": false,
"l1IdleTimeoutSeconds": 2,
"l2DelayAfterL1Seconds": 1,
"l2MinIntervalSeconds": 1,
"l2MaxIntervalSeconds": 10
}
}如果需要 seed 到独立的 TCVDB 数据库:
{
"storeBackend": "tcvdb",
"tcvdb": {
"database": "my_seed_test_db"
},
"pipeline": {
"everyNConversations": 3,
"enableWarmup": false,
"l1IdleTimeoutSeconds": 2
}
}输出目录结构
<output-dir>/
├── conversations/ — L0 JSONL 文件
├── records/ — L1 JSONL 文件
├── scene_blocks/ — L2 场景块
├── vectors.db — SQLite 向量数据库(仅 sqlite 后端)
├── .metadata/
│ ├── manifest.json — 元数据(store 绑定 + seed 运行记录)
│ └── checkpoint.json — 管线进度
└── .backup/ — 滚动备份Seed 完成后,manifest.json 会记录本次运行信息:
{
"version": 1,
"createdAt": "2026-04-01T22:00:00.000Z",
"store": {
"type": "sqlite",
"sqlite": { "path": "vectors.db" }
},
"seed": {
"inputFile": "conversations.json",
"sessions": 3,
"rounds": 42,
"messages": 128,
"startedAt": "2026-04-01T22:00:00.000Z",
"completedAt": "2026-04-01T22:05:30.000Z"
}
}File: README_CN.md
✨ 效果亮点
TencentDB Agent Memory = 符号化短期记忆 + 分层式长期记忆。
- 符号化短期记忆:将厚重的工具日志分层卸载,逐步总结成轻量级 Mermaid 结构符号,大幅降低 Token 消耗的同时提升任务成功率。
- 分层式长期记忆:把碎片化对话层层提炼,沉淀出有层次的画像与场景,不再是扁平的向量堆砌。
作为 OpenClaw 插件接入后:最高节省 61.38% Token,通过率相对提升 51.52%;PersonaMem 准确率从 48% 提升到 76%。
| 记忆能力 | Benchmark | OpenClaw 成功率 | 加插件后成功率 | 相对变化 | OpenClaw Token 消耗 | 加插件后 Token 消耗 | 相对变化 |
|---|---|---|---|---|---|---|---|
| 短期记忆 | WideSearch | 33% | 50% | +51.52% | 221.31M | 85.64M | −61.38% |
| 短期记忆 | SWE-bench | 58.4% | 64.2% | +9.93% | 3474.1M | 2375.4M | −33.09% |
| 短期记忆 | AA-LCR | 44.0% | 47.5% | +7.95% | 112.0M | 77.3M | −30.98% |
| 长期记忆 | PersonaMem | 48% | 76% | +59% | — | — | — |
超长 Session 评测不是单题清空上下文,而是把多个任务拼接到同一个 Session 中连续执行。例如 SWE-bench 每个 Session 连续执行 50 个任务,用来模拟真实长程 Agent 的上下文累积压力。
项目简介
Memory 不是为了让 AI 存下所有东西,而是为了让人不必重复所有事情。
在实际使用中,我们往往需要反复告诉 Agent 固定 SOP、项目背景、工具习惯和输出格式。这些信息不应该每次重新解释,但同时也不应该被无脑、扁平地全部塞进上下文。
TencentDB Agent Memory 帮助 Agent 学会你的流程、保留任务上下文、复用历史经验。但我们拒绝暴力的历史堆砌,也抛弃不可逆的暴力摘要。我们将记忆设计为一套极具层次感的系统,以符号化记忆解决单次长任务的信息过载,以记忆分层解决跨会话的经验沉淀。
让 Agent 记住该记的,让人把注意力留给判断、创造和真正有价值的工作。
核心技术:拒绝平铺,走向分层与符号化
TencentDB Agent Memory 的设计理念围绕两个核心展开:记忆分层 与 符号化记忆。这不仅让 Agent “记得更多”,更重要的是“想得更清”。
1. 记忆分层:渐进式披露与异构存储
传统的记忆系统往往将所有数据切片并平铺为向量,召回时如同在一堆毫无关联的便利贴中寻找线索,缺乏宏观视角的指引。
我们认为,不管是长期的知识、短期的任务,还是未来的经验能力,记忆都不应该平铺,生成和召回都必须有层次。TencentDB Agent Memory 将“分层”作为整个架构的统一设计哲学:
- 短期记忆(上下文卸载/任务)的分层:底层保留原始、厚重的工具调用结果(
refs/*.md),中层抽取步骤摘要(jsonl),高层则浓缩为一张极度轻量的 Mermaid 任务画布。Agent 在上下文中仅需关注高层结构,遇错时再沿着node_id下钻到底层查证。 - 长期个性化(用户理解)的分层:打破扁平的历史记录,建立 L0 Conversation(原始对话) → L1 Atom(结构化事实) → L2 Scenario(场景块) → L3 Persona(用户画像)的语义金字塔。平时靠高层 Persona 把握用户偏好,需要考证细节时再检索底层 Atom。
- 技能生成(Skill与动作沉淀,Roadmap)的分层:记忆不应仅限于“知道什么”,还应包括“会做什么”。我们正在将分层延伸至动作域:从底层的执行轨迹(Traces)与报错日志中,中层归纳出共性的解决模式,高层最终提炼出可直接挂载复用的 Skill 或标准 SOP 代码。
渐进式披露与异构存储:为了支撑这种无处不在的分层,我们设计了底层数据库与上层文件系统结合的存储方案。底层(海量事实、日志、轨迹)存入数据库或归档文件,确保稳定与全量检索;高层(画像、场景、画布、Skill)存入业务可读的文件系统(Markdown),确保高信息密度、逻辑清晰与白盒可调。低层保留证据,高层保留结构。
每一条信息都 100% 可找回、可恢复:压缩或抽象最大的风险是“丢失证据”。得益于严格的索引映射机制,系统内没有任何一段摘要是“不可逆”的黑盒。无论是短期记忆中被卸载的一段报错日志,还是长期记忆里总结出的一条用户偏好,Agent 或开发者都可以沿着“高层符号(Persona / 画布) → 中层索引(Scenario / JSONL) → 底层原文(L0 Conversation / refs)”的链路进行完美溯源与恢复。
2. 符号化记忆:用最少符号表达最多语义(Mermaid 画布)
长程任务中最消耗 Token 的往往是繁杂的过程日志(如搜索结果、代码、报错)。为此,我们结合 上下文卸载 (Context Offloading) 提出了 符号化记忆:
- Mermaid 符号图谱:取代冗长的自然语言或扁平的 JSON,我们使用高密度、强拓扑的 Mermaid 语法来描绘任务状态流转,既能被 LLM 精准理解,也方便人类阅览。
- 历史折叠与卸载:完整工具日志被卸载到外部文件系统,上下文仅保留轻量级的 Mermaid 任务地图。
- 基于
node_id的溯源:Agent 看着符号图谱推理,如需核对细节,直接 grep 图谱上的node_id即可瞬间找回完整原文,既大幅降本又保全了 100% 可追溯性。
graph LR
Log["繁杂冗长的过程日志(几十万 Token)"] -->|"1. 卸载完整原文"| FS[("外部文件系统(refs/xxx.md)")]
Log -->|"2. 提取关系"| MMD["Mermaid 符号图谱(带 node_id)"]
MMD -->|"3. 轻量级注入"| Agent(("Agent 上下文(几百 Token)"))
Agent -. "4. 随时按 node_id 下钻恢复原文" .-> FS
style Log fill:#f1f5f9,stroke:#94a3b8,stroke-dasharray: 5 5
style FS fill:#f8fafc,stroke:#cbd5e1
style MMD fill:#eff6ff,stroke:#3b82f6,stroke-width:2px
style Agent fill:#fffbeb,stroke:#f59e0b,stroke-width:2px快速开始
🎬 Demos
| OpenClaw × Agent Memory | Hermes × Agent Memory |
1. OpenClaw
1.1 安装插件
openclaw plugins install @tencentdb-agent-memory/memory-tencentdb
openclaw gateway restart升级插件请优先使用 OpenClaw 原生更新命令,该方式可以避免因语义化版本范围导致插件禁用:
bashopenclaw plugins update @tencentdb-agent-memory/memory-tencentdb
1.2 零配置启用
默认使用本地 SQLite + sqlite-vec 后端。
// ~/.openclaw/openclaw.json
{
"memory-tencentdb": {
"enabled": true
}
}启用后,TencentDB Agent Memory 会自动完成对话录制、记忆提取、场景归纳、用户画像生成和下一轮对话前召回。
1.3 启用短期记忆压缩(可选,要求版本 ≥ 0.3.4)
{
"memory-tencentdb": {
"config": {
"offload": {
"enabled": true
}
}
}
}步骤 1 —— 在插件配置中注册 slot
在 slots 字段中声明 contextEngine,让 OpenClaw 把上下文卸载请求路由到本插件:
{
"plugins": {
"slots": {
"contextEngine": "memory-tencentdb"
}
}
}步骤 2 —— 执行 patch 脚本
为保证最佳效果,请执行以下 patch 脚本。该脚本会注入 after-tool-call 消息钩子,让工具调用结果能被正确卸载与回溯:
bash scripts/openclaw-after-tool-call-messages.patch.sh💡 patch 每次 OpenClaw 安装只需执行一次。升级 OpenClaw 后建议重新执行以确保钩子生效。
2. Hermes
除 OpenClaw 外,本插件同样支持 Hermes Agent。根据部署场景选择安装路径:
| 你的场景 | 走哪条路 |
|---|---|
| 想从零启动一个带记忆能力的 Hermes(一条命令搞定) | 2.A Docker(下文) |
| 已经装好了Hermes,只想加上记忆能力 | 2.B 挂到已有 Hermes 上(再下文) |
2.A Docker(全新部署,需版本号 ≥ 0.3.4)
Docker 镜像把 hermes-agent 和 memory_tencentdb provider 聚合在一起,Gateway 监听 :8420:
# ============ 配置参数说明 ============
# MODEL_API_KEY 大模型 API Key(必填)—— 替换为你自己的凭证
# MODEL_BASE_URL 大模型接入地址,默认指向腾讯云大模型知识引擎(LKE)
# MODEL_NAME 模型名称,默认使用 DeepSeek-V3.2
# MODEL_PROVIDER 服务商类型:"custom" 适用于所有 OpenAI 兼容接口
MODEL_API_KEY="your-api-key"
MODEL_BASE_URL="https://api.lkeap.cloud.tencent.com/v1"
MODEL_NAME="deepseek-v3.2"
MODEL_PROVIDER="custom"
# ============ docker run 参数说明 ============
# -d 后台(detached)模式运行容器
# --name hermes-memory 容器命名,方便后续 docker exec / logs / stop
# --restart unless-stopped 崩溃或宿主机重启时自动拉起
# -p 8420:8420 宿主机端口 ↔ 容器端口(Hermes Gateway)
# -e MODEL_* 将上方配置参数注入容器环境变量
# -v hermes_data:/opt/data 记忆数据持久化到命名卷(容器重启后数据不丢)
# 进入 Docker 构建目录(已 clone 仓库并位于仓库根目录)
cd docker/opensource
# 构建
docker build -f Dockerfile.hermes -t hermes-memory .
# 运行
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
# 验证 Gateway
curl http://localhost:8420/health
# 进入 Hermes 对话
docker exec -it hermes-memory hermes镜像内置了腾讯云 DeepSeek-V3.2 的默认值,如果你使用该模型,
MODEL_BASE_URL/MODEL_NAME/MODEL_PROVIDER可以省略,只传MODEL_API_KEY即可。
2.B 挂到已有 Hermes 上(无 Docker)
如果宿主机上已经装好了 hermes-agent,只想加上记忆能力,不需要 Docker 镜像。
1. 下载插件包到统一目录:
mkdir -p ~/.memory-tencentdb
TEMP_DIR=$(mktemp -d)
cd "$TEMP_DIR"
npm init -y --silent
npm install @tencentdb-agent-memory/memory-tencentdb@latest --omit=dev
cp -r node_modules/@tencentdb-agent-memory/memory-tencentdb \
~/.memory-tencentdb/tdai-memory-openclaw-plugin
rm -rf "$TEMP_DIR"2. 安装 Gateway 依赖:
cd ~/.memory-tencentdb/tdai-memory-openclaw-plugin
npm install --omit=dev
npm install tsx3. 链接到 Hermes 插件目录:
rm -rf ~/.hermes/hermes-agent/plugins/memory/memory_tencentdb
ln -sf ~/.memory-tencentdb/tdai-memory-openclaw-plugin/hermes-plugin/memory/memory_tencentdb \
~/.hermes/hermes-agent/plugins/memory/memory_tencentdb此处目录名必须是
memory_tencentdb(下划线)—— Hermes 用它作为 provider key。memory-tencentdb(连字符)只是配置层面的别名,不能作为目录名。
4. 在 ~/.hermes/config.yaml 中声明 provider:
memory:
provider: memory_tencentdb5. 配置 Gateway 环境变量
编辑 ~/.hermes/.env,添加:
MEMORY_TENCENTDB_GATEWAY_CMD="sh -c 'cd ~/.memory-tencentdb/tdai-memory-openclaw-plugin && exec npx tsx src/gateway/server.ts'"
MEMORY_TENCENTDB_GATEWAY_HOST="127.0.0.1"
MEMORY_TENCENTDB_GATEWAY_PORT="8420"LLM 凭证请按需添加(Gateway 实际读取的是 TDAI_LLM_* 系列变量):
TDAI_LLM_API_KEY="sk-your-api-key-here"
TDAI_LLM_BASE_URL="https://api.openai.com/v1"
TDAI_LLM_MODEL="gpt-4o"也可改用 Gateway 配置文件 ~/.memory-tencentdb/memory-tdai/tdai-gateway.json:
{
"llm": {
"baseUrl": "https://your-api-endpoint/v1",
"apiKey": "your-api-key",
"model": "your-model-name"
}
}6. 启动 Gateway(两种方式任选其一):
- 对话时自动发现(推荐,零配置):不启动 Gateway,直接开始和 Hermes 对话。provider 会在第一条对话时自动检测到
~/.memory-tencentdb/tdai-memory-openclaw-plugin/src/gateway/server.ts并以Popen()拉起。首次对话会略有延迟。 - 手动运行:提前启动一个独立的 Gateway 进程:bash
cd ~/.memory-tencentdb/tdai-memory-openclaw-plugin npx tsx src/gateway/server.ts
7. 验证:
curl http://127.0.0.1:8420/health
# 应返回 {"status":"ok"} 或 {"status":"degraded"}Provider 的完整参考(环境变量、故障排查、LLM 工具 schema、supervisor 行为)见
hermes-plugin/memory/memory_tencentdb/README.md,调整 supervisor / circuit-breaker 默认值之前请先读它。
3. Hermes(Windows 原生安装)
Windows 原生 Hermes 环境下,在仓库根目录用 Command Prompt 或 PowerShell
运行内置批处理脚本:
$env:TDAI_LLM_API_KEY="your-api-key"
$env:TDAI_LLM_BASE_URL="https://api.openai.com/v1"
$env:TDAI_LLM_MODEL="gpt-4o"
.\scripts\setup-hermes-memory-tencentdb.bat脚本会检查 node、npm、Python 和 Hermes,要求 Node.js >=22.16.0;
当 Gateway 依赖缺失时执行 npm install --omit=dev,创建%USERPROFILE%\.memory-tencentdb\memory-tdai,复制插件到%USERPROFILE%\.hermes\plugins\memory_tencentdb,把 Gateway 环境变量写入%USERPROFILE%\.hermes\.env,随后启动 Gateway 并轮询:
curl.exe http://127.0.0.1:8420/health如果 %USERPROFILE%\.hermes\config.yaml 已存在,请确认包含:
memory:
provider: memory_tencentdb🔒 Gateway 安全配置(可选)
Hermes Gateway 监听 :8420,对外提供 capture / search / recall 的 HTTP 接口。新增两个开关,可以把它从“开放的本地 sidecar”切换为“需要鉴权的网络服务”。两个开关默认都关闭,已有部署的行为不变。
| 字段 | env | 默认值 | 说明 |
|---|---|---|---|
server.apiKey |
TDAI_GATEWAY_API_KEY |
(未设置) | 设置后,除 GET /health 外的所有接口都要求 Authorization: Bearer <apiKey>;缺失或错误的 token 返回 HTTP 401。Token 比较使用常量时间算法,避免时序侧信道。 |
server.corsOrigins |
TDAI_CORS_ORIGINS(逗号分隔) |
[] |
CORS 白名单。空列表表示不发送任何 Access-Control-Allow-* 响应头,浏览器同源策略会自动阻止跨域请求。["*"] 仅供本地开发,不要用于生产。 |
当 apiKey 未设置时,Gateway 启动时会打印一条 WARN;如果同时还绑定在非 loopback 地址(例如 0.0.0.0),还会再打印一条更醒目的告警。
客户端在启用鉴权后用 Bearer token 调用:
curl -H "Authorization: Bearer $TDAI_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"...","session_key":"..."}' \
http://127.0.0.1:8420/recallGET /health 永远无需 token,方便 docker healthcheck / kubectl liveness 等编排探针继续工作。
Hermes 插件侧的配置
Hermes memory_tencentdb 插件本身是 Gateway 的客户端。当 Gateway 开启了鉴权后,在 Hermes 进程上设置:
export MEMORY_TENCENTDB_GATEWAY_API_KEY="<与 Gateway 同一份密钥>"插件随后会在每一次发往 Gateway 的请求上附带 Authorization: Bearer <key>。该变量未设置时,插件不发送任何鉴权头,与 Gateway 维持开放模式的旧行为完全匹配——已有部署 0 影响。
需要明确的边界:插件只负责 client 一侧。Gateway 是否真的强制鉴权由 Gateway 端自己的 TDAI_GATEWAY_API_KEY / server.apiKey 决定。两端要使用相同的密钥才能匹配;插件不会把这个值传递给 Gateway——因为 Gateway 可能由 Docker、systemd 或其它独立机制拉起,插件没有也不应该去管这个。
若 MEMORY_TENCENTDB_GATEWAY_API_KEY 没设置,插件还会回退读取 TDAI_GATEWAY_API_KEY,方便两个进程共享同一个 env 文件、只设一个变量名的场景。Gateway 永远不会读 MEMORY_TENCENTDB_GATEWAY_API_KEY,那是插件侧专用名字。
🔧 可调参数
所有字段均有合理默认值,零配置即可跑。 如果要调优,可以按使用深度逐层展开。
🟢 Level 1 · 日常调参(覆盖 90% 使用场景)
| 字段 | 默认 | 说明 |
|---|---|---|
timezone |
"system" |
时区:"system"(跟随系统)/ IANA 名(Asia/Shanghai)/ offset 串(+08:00) |
storeBackend |
"sqlite" |
存储后端:sqlite |
recall.strategy |
"hybrid" |
召回策略:keyword / embedding / hybrid(RRF 融合,推荐) |
recall.maxResults |
5 |
每次召回条数 |
recall.maxCharsPerMemory |
0 |
单条 L1 记忆注入的最大字符数;0 表示不限制 |
recall.maxTotalRecallChars |
0 |
每轮 auto-recall 注入的 L1 记忆总字符预算;0 表示不限制 |
pipeline.everyNConversations |
5 |
每 N 轮对话触发一次 L1 记忆提取 |
extraction.maxMemoriesPerSession |
20 |
单次 L1 最多提取多少条 |
persona.triggerEveryN |
50 |
每 N 条新记忆触发用户画像生成 |
offload.enabled |
false |
是否启用短期记忆压缩 |
🟡 Level 2 · 进阶调优(长任务 / 长 Session 场景)
| 字段 | 默认 | 说明 |
|---|---|---|
pipeline.enableWarmup |
true |
Warm-up:新 session 从 1 轮起触发,每次翻倍至 N(1→2→4→…) |
pipeline.l1IdleTimeoutSeconds |
600 |
用户停止对话多久后触发 L1 |
pipeline.l2MinIntervalSeconds |
900 |
同 session 两次 L2 之间的最小间隔 |
recall.timeoutMs |
5000 |
召回超时阈值,超时跳过注入不阻塞对话 |
extraction.enableDedup |
true |
L1 向量去重 / 冲突检测 |
capture.excludeAgents |
[] |
Glob 模式排除特定 Agent(如 bench-judge-*) |
capture.l0l1RetentionDays |
0 |
L0/L1 本地文件保留天数,0 = 永不清理 |
offload.mildOffloadRatio |
0.5 |
温和压缩触发比例(占 context window) |
offload.aggressiveCompressRatio |
0.85 |
激进压缩触发比例 |
offload.mmdMaxTokenRatio |
0.2 |
MMD 注入 token 预算比例 |
bm25.language |
"zh" |
分词语言:zh(jieba) / en |
🔴 Level 3 · 完整参数表(运维 / 自定义模型 / 远程 embedding)
完整字段、类型、约束见 openclaw.plugin.json 。
embedding.*— 远程 embedding 服务(OpenAI 兼容 API)embedding.sendDimensions(默认true):是否在请求体中携带dimensions字段。OpenAItext-embedding-3-*系列依赖该字段做 Matryoshka 维度截断;但部分自托管 / 开源模型(如 BGE-M3)不支持自定义维度,会以 HTTP 400 报does not support matryoshka representation拒绝请求。此时请显式设为false,例如:json{ "embedding": { "enabled": true, "provider": "openai", "baseUrl": "http://your-host:your-port/v1", "apiKey": "<KEY>", "model": "bge-m3", "dimensions": 1024, "sendDimensions": false } }
llm.*— 独立 LLM 模式(绕过 OpenClaw 内置模型,用指定 API 跑 L1/L2/L3)offload.backendUrl / backendApiKey— 将 L1/L1.5/L2/L4 offload 流程卸载到后端服务report.*— 指标上报
🤔 方案特点
1. 宏观画像 + 微观事实:同一套下钻机制降低幻觉
压缩最大的风险是“省了 Token,也丢了证据”。因此 TencentDB Agent Memory 没有把历史压成一段不可恢复的 summary,而是保留了从高层摘要回到底层证据的路径。
| 问题类型 | 优先使用 | 继续下钻 |
|---|---|---|
| 日常偏好、表达风格、长期目标 | L3 Persona / L2 Scenario | 需要事实时查 L1 Atom / L0 Conversation |
| 具体事实、时间、项目细节 | L1 Atom / L0 Conversation | 命中不足时扩大时间范围或语义检索 |
| 当前长任务继续执行 | Active MMD 任务画布 | 摘要不够时查 JSONL,再读 refs/*.md 原文 |
| 历史任务恢复 | Metadata 任务入口 | 打开 MMD → 找 node_id → 追 result_ref |
上层负责“情商”和方向,下层负责“证据”和精度。短期压缩和长期记忆在这里合成一条闭环:能折叠,也能展开;能抽象,也能追证。
2. 白盒可调试:记忆不是黑盒向量
很多记忆系统的问题是:召回错了,你只能看到一串向量分数,很难判断到底哪里错。TencentDB Agent Memory 把关键中间产物保存在可读文件里:
- L2 Scenario 块是 Markdown,可以直接打开检查。
- L3 Persona 存放在
persona.md,可以追溯到对应的 Scenario。 - 短期任务画布是 Mermaid,既能给人看,也能给 Agent 读。
- 原文、摘要、节点之间有
result_ref和node_id关联。
这意味着调试不再是翻黑盒数据库,而是沿着“Persona → Scenario → Atom → Conversation”的链路逐层定位。
这些分层记忆产物都存放在 ~/.openclaw/memory-tdai/ 下,可以直接打开目录逐层查看。
3. 工程能力完整:不是 Demo,而是可接入的插件
| 能力 | 说明 |
|---|---|
| OpenClaw 插件 | 安装后即可自动捕获、提取、召回记忆 |
| Hermes Gateway 适配 | TdaiCore + HostAdapter 解耦宿主框架 |
| 本地后端 | SQLite + sqlite-vec,开箱即用 |
| 混合检索 | BM25 + 向量 + RRF,兼顾关键词和语义召回 |
| Agent 工具 | tdai_memory_search / tdai_conversation_search |
文档
| 文档 | 内容 |
|---|---|
scripts/README.memory-tencentdb-ctl.md |
运维管理工具说明 |
CHANGELOG.md |
版本变更记录 |
openclaw.plugin.json |
OpenClaw 插件声明与配置 Schema |
社区与贡献
我们欢迎一切形式的贡献——Bug 反馈、功能建议、文档勘误、Benchmark 复现、生态集成,或者一个 Pull Request 都可以。Agent 记忆这件事远未有定论,希望和大家一起把它做出来。
- 🐞 发现 Bug 或有疑问? 欢迎到 GitHub Issues 提交,我们会在 24 小时内响应。
- 💡 有想法想交流? 欢迎在 GitHub Discussions 发起讨论。
- 🛠️ 想贡献代码? 请先阅读 CONTRIBUTING.md。
- 💬 想加入交流群? 扫码加入 Agent Memory 微信社群,与早期开发者直接对话。
MIT © TencentDB Agent Memory Team