agentmemory backend
Optional `Memory` trait backend that delegates to a locally-running agentmemory REST server, for users who self-host agentmemory across Claude Code, Cursor, Codex, OpenCode, and OpenHuman.
OpenHuman's default Memory trait backend is sqlite β the unified store documented in Memory Trees. For users who already self-host agentmemory β typically because they want a single durable memory shared across Claude Code, Cursor, Codex, OpenCode, and OpenHuman β OpenHuman exposes an opt-in backend that proxies every trait call through agentmemory's REST surface.
Selecting backend = "agentmemory" skips OpenHuman's SQLite + embedder path entirely. agentmemory owns the storage, embedding, and retrieval layers. OpenHuman becomes a thin REST client.
When to use this
Use the agentmemory backend if:
You already run
npx -y @agentmemory/agentmemoryfor one or more coding agents and want OpenHuman to share the same durable store.You want hybrid BM25 + vector + graph retrieval without provisioning a separate embedder on the OpenHuman side.
You prefer agentmemory's lifecycle (consolidation, retention scoring, auto-forget, graph extraction) over OpenHuman's unified store.
Keep the default sqlite backend if:
You want self-contained, single-process operation with no external daemon dependency.
You rely on OpenHuman-specific Memory Tree features (chunking, sealing, summary trees) that operate on top of the SQLite store. The Memory Tree pipeline is unaffected by the trait backend β it operates on the host's document store, orthogonally β but the agentmemory backend is most valuable when you've already standardised on agentmemory across other agents.
Quick start
Install + start agentmemory (one terminal):
npx -y @agentmemory/agentmemoryDefaults to
http://localhost:3111(REST) +ws://localhost:49134(engine). First boot generates an HMAC secret at~/.agentmemory/.hmacand prints it once.Point OpenHuman at it in your
config.toml:[memory] backend = "agentmemory" # Defaults below β set only when overriding. # agentmemory_url = "http://localhost:3111" # agentmemory_secret = "" # HMAC bearer token, optional # agentmemory_timeout_ms = 5000Restart OpenHuman. The factory short-circuits the SQLite path and logs
[memory::factory] using agentmemory backend at <url>.
That's it. Existing OpenHuman call sites (store, recall, get, list, forget, namespace_summaries, count, health_check) work unchanged.
Config keys
agentmemory_url
http://localhost:3111
Base URL for the agentmemory REST server
agentmemory_secret
none
Optional HMAC bearer token. Sent as Authorization: Bearer <secret>
agentmemory_timeout_ms
5000
Per-request reqwest timeout
When backend == "agentmemory", the following existing MemoryConfig fields are ignored β agentmemory owns its own embedding stack via ~/.agentmemory/.env:
embedding_providerembedding_modelembedding_dimensionssqlite_open_timeout_secs
Setting them on this path is a no-op. The local-AI Ollama health-gate also doesn't run on this path β agentmemory's daemon manages its own embedder lifecycle.
Field mapping
OpenHuman's MemoryEntry β agentmemory wire row:
namespace
project
Defaults to "default" when empty
key
title
content
content
id
id
agentmemory-generated (mem_<rand>)
category: Core
type: "fact"
category: Daily
type: "conversation"
category: Conversation
type: "conversation"
category: Custom(s)
type: "fact" + concepts: [s]
Custom tag rolled into the concepts array so it remains queryable
session_id
sessionIds: [...]
OpenHuman exposes a single id; agentmemory persists an array
timestamp
updatedAt (RFC3339)
Falls back to createdAt if updatedAt is absent
score (recall hits only)
smart-search score
Populated on recall responses, None on get / list
agentmemory carries additional fields β concepts (auto-extracted), files (path tags), strength (retention score), version, supersedes (the lifecycle chain) β that this backend leaves at defaults. They're internal to agentmemory's lifecycle layer and don't need to round-trip through OpenHuman's trait.
Trait method β endpoint
Memory method
agentmemory REST
Notes
store
POST /agentmemory/remember
{project, title, content, type, concepts, sessionIds}
recall
POST /agentmemory/smart-search
Hybrid BM25 + vector + graph
get
POST /agentmemory/smart-search
+ client-side exact-title filter
list
GET /agentmemory/memories?latest=true&project=<ns>
forget
get(ns, key) β POST /agentmemory/forget
Two-step: resolve id then forget
namespace_summaries
GET /agentmemory/projects
Returns [{name, count, lastUpdated}]
count
GET /agentmemory/health
Reads memories field
health_check
GET /agentmemory/livez
RecallOpts.category, RecallOpts.session_id, and RecallOpts.min_score are applied as client-side filters on the smart-search response. agentmemory's REST surface doesn't expose them as server-side filters today. For very large recall windows (limit > 100) prefer issuing a tighter query string to reduce server-side work over relying on client-side post-filtering.
Security
When agentmemory_secret is set, the client honours agentmemory's v0.9.12 plaintext-bearer guard contract:
Loopback hosts (
localhost,127.0.0.1,::1) overhttp://β allowed. Local dev path.https://to any host β allowed.Plaintext HTTP to a non-loopback host β emits a one-time stderr warning at construction time. The bearer is observable on the wire.
AGENTMEMORY_REQUIRE_HTTPS=1(process env, ASCII-case-insensitive matches1ortrue) β escalates the warning into a hard refusal at client construction. The backend fails to start rather than leak the bearer once.
Production deploys should set AGENTMEMORY_REQUIRE_HTTPS=1 so a misconfigured TLS terminator fails loud rather than silently leaking.
The plaintext-bearer guard mirrors the integration plugin guards in agentmemory's PR #315 so an operator who's seen the warning on Hermes / OpenClaw / pi will recognise the same message on OpenHuman.
Failure modes
Daemon unreachable at startup
from_config succeeds (URL parses), but health_check() returns false on first call. Trait methods bubble up reqwest transport errors
Network timeout
anyhow::Error per trait contract; surfaces to caller
4xx / 5xx response
anyhow::Error with status + body snippet
Bearer over plaintext non-loopback (no env)
One-time stderr warning, request proceeds
Bearer over plaintext non-loopback + AGENTMEMORY_REQUIRE_HTTPS=1
Hard refusal at construction time
Empty agentmemory_url
Hard refusal at construction time with hint to leave it unset for the default
Invalid URL syntax
Hard refusal at construction time with the parser error
No automatic fallback to SQLite. If the daemon is down at boot, the backend surfaces the transport error loudly. Operators flip back to backend = "sqlite" in config.toml to recover. Rationale: a silent SQLite fallback would hide a misconfigured daemon β "private, simple, predictable" wins over "magically tolerant".
Performance notes
The backend is a thin REST proxy β it adds one HTTP round-trip per trait call. Practical implications:
storeandforgetare single-RTT.recall,get,listare single-RTT.forgetagainst an unknown key is two-RTT (the implicitgetlookupa no-op confirmation). Caller can short-circuit this by checking the return value of a prior
list.
agentmemory's REST is
127.0.0.1by default β same-host latency is sub-millisecond. Over a managed deploy with HTTPS termination, expect ~10β30ms per RTT.The default per-request timeout is 5 seconds. Bump
agentmemory_timeout_msif you're seeing intermittent timeouts on cold-start of the iii engine; agentmemory's first-request latency after a long idle can stretch toward 3β5s depending on persistence state.
Migration: from SQLite to agentmemory
There's no in-place migration today. The recommended path:
Export your existing memories from the SQLite store via OpenHuman's existing export RPC (or by direct SQL).
Walk the export and POST each row to
/agentmemory/rememberwith the sameproject+title+content. agentmemory will assign new ids; the OpenHuman side picks them up on firstlist.Set
backend = "agentmemory"and restart.
A dedicated bulk import path is filed as a follow-up.
Implementation reference
In-tree files:
store/agentmemory/mod.rsβ module surfacestore/agentmemory/backend.rsβimpl Memory for AgentMemoryBackendstore/agentmemory/client.rsβ reqwest wrapper + plaintext-bearer guardstore/agentmemory/mapping.rsβMemoryEntryβ agentmemory JSONtests/agentmemory_backend.rsβ 12 axum-mock integration tests
Related upstream:
agentmemory repo β https://github.com/rohitg00/agentmemory
agentmemory REST contract β
~/.agentmemory/.envkeys + endpoint list in the agentmemory READMEv0.9.12 plaintext-bearer guard β agentmemory PR #315
Last updated