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.
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 VectorDB
Hermes 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.
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 (see
hermes-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 for third-party providers; we don't use it for memory_tencentdb.
The trailing directory name must be exactly memory_tencentdb — Hermes
uses that directory name as the provider key; it must match
plugin.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.)
Pick 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 so
git 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.
memory:
provider: memory_tencentdb # canonical name
# Aliases accepted for backward compatibility: `memory-tencentdb`, `tdai`At minimum the Gateway needs an OpenAI-compatible endpoint for L1/L2/L3 extraction. Set these in the Hermes process environment:
export MEMORY_TENCENTDB_LLM_API_KEY="sk-..."
export MEMORY_TENCENTDB_LLM_BASE_URL="https://api.openai.com/v1" # optional
export MEMORY_TENCENTDB_LLM_MODEL="gpt-4o" # optionalYou 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 <path>. Searched paths, in
order:
- In-tree:
<plugin-root>/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.ts
will 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 for
GET /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.
| 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 |
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.
| Variable | Default | Description |
|---|---|---|
MEMORY_TENCENTDB_LLM_API_KEY |
— | LLM API key (required for L1/L2/L3) |
MEMORY_TENCENTDB_LLM_BASE_URL |
https://api.openai.com/v1 |
OpenAI-compatible API base URL |
MEMORY_TENCENTDB_LLM_MODEL |
gpt-4o |
Model name |
⚠️ OnlyMEMORY_TENCENTDB_*env vars are honored by this provider for the Gateway location and LLM credentials. Data-directory resolution is deliberately delegated to the Gateway viaTDAI_DATA_DIR(see above) so the provider and the Gateway can never disagree about where L0~L3 live.
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_callwill return an "Unknown tool" error.
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 too- "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.