Created by @MicScalise
Native Hermes
MemoryProviderfor the OB1 governed memory system. Gives Hermes agents the same auto-recall, auto-writeback, and governance that OpenClaw agents get fromintegrations/openclaw-agent-memory.
Plugs Hermes Agent into the OB1 v1 Agent Memory API so every Hermes turn does three things automatically:
- Recall — Before the LLM call, recent and relevant memories are pulled from OB1 (filtered by
use_policy—[instruction]items are treated as binding rules,[evidence]as supporting context only). - Writeback — After the turn, a structured summary lands in
agent_memoriestagged withruntime=hermes, the actual model + provider that ran the turn, and thetask_idlinkage. - Govern — Memories default to
pending_reviewwithrequires_user_confirmation=trueso nothing is promoted to instruction-grade until a human (or theob1_review_memorytool) confirms it.
The same backend serves both runtimes — OpenClaw agents and Hermes agents share one governed memory.
- Working Open Brain setup (guide)
schemas/agent-memoryappliedintegrations/agent-memory-apideployed- Hermes Agent 0.13.0+ installed
- Python 3.11+
HERMES AGENT MEMORY -- CREDENTIAL TRACKER
-----------------------------------------
FROM OB1
Agent Memory API URL: ____________
MCP Access Key: ____________
HERMES
Plugin path (~/.hermes/plugins/ob1): ____________
Default workspace ID: ____________
Default project ID (optional): ____________
-----------------------------------------
Apply the schema and deploy the API.
Important
The Agent Memory API must be reachable on the URL you'll configure below. The provider does an HTTP GET /health probe on initialization and warns (non-fatally) if it fails.
Done when: GET /health on the Agent Memory API returns ok: true.
Hermes plugins live under $HERMES_HOME/plugins/<name>/. The default $HERMES_HOME is ~/.hermes.
mkdir -p ~/.hermes/plugins/ob1
cp plugin/__init__.py ~/.hermes/plugins/ob1/__init__.py
cp plugin/plugin.yaml ~/.hermes/plugins/ob1/plugin.yamlNote
The plugin uses Python's stdlib only — no pip install required. PyYAML ships with Hermes.
Done when: ls ~/.hermes/plugins/ob1/ shows both files.
The plugin reads non-secret config from ~/.hermes/ob1.json and the access key from the OPENBRAIN_KEY environment variable.
1. Write the config file:
cat > ~/.hermes/ob1.json <<'EOF'
{
"endpoint": "http://localhost:8000/functions/v1/agent-memory-api",
"workspace_id": "default",
"project_id": null,
"auto_recall": true,
"auto_capture": true,
"max_recall_results": 10,
"default_confidence": 0.7,
"require_review_by_default": true
}
EOF2. Set the access key in ~/.hermes/.env:
echo 'OPENBRAIN_KEY=<your-mcp-access-key>' >> ~/.hermes/.env
echo 'OPENBRAIN_URL=http://localhost:8000/functions/v1/agent-memory-api' >> ~/.hermes/.env3. Tell Hermes to use the provider:
hermes config set memory.provider ob1Tip
Environment variables override ob1.json — useful for switching workspaces per shell (OPENBRAIN_WORKSPACE_ID=staging hermes ...).
Done when: hermes -z "Tell me what memory provider is active." mentions OpenBrain in its response.
Drive a real turn and confirm the writeback lands:
hermes -z "Decision: we will use Postgres for the queue. Lesson: always run migrations off-hours."Then query the database:
SELECT runtime_name, model, provider, task_id,
substring(content, 1, 80) AS content
FROM agent_memories
WHERE runtime_name = 'hermes'
ORDER BY created_at DESC
LIMIT 5;Done when: You see rows with runtime_name=hermes, the model your Hermes is configured to use (e.g. anthropic/claude-opus-4.6), and content matching your test turn.
Once installed and configured:
- Every Hermes turn auto-recalls. When the LLM is reasoning, recent and similar OB1 memories are silently injected as
<ob1-context>in the system prompt. - Every meaningful turn auto-writes. The user's question + a summary of the assistant's response lands in
agent_memoriesas a turn-summaryoutput. Trivial messages (ok,thanks) and short replies are skipped. - Session end produces structured findings. When Hermes exits, conversation lines matching decision / lesson / constraint / next_step / question / failure patterns are extracted into OB1's structured payload categories.
- Compression preserves findings. When Hermes hits a context-compression boundary, structured findings from the about-to-be-compressed messages are extracted, written back to OB1, and folded into the compression summary.
- Seven tools are available to the agent for explicit memory ops:
ob1_recall— task-scoped recallob1_writeback— structured storeob1_search— alias for recallob1_report_usage— close the loop on which recalled memories were usefulob1_list_review_queue— what's pending reviewob1_review_memory— confirm / reject / annotateob1_get_recall_trace— debug what came back
The provider silently no-ops when OPENBRAIN_KEY is not set or the endpoint is empty. Verify both:
hermes config get memory.provider # must be: ob1
cat ~/.hermes/ob1.json | grep endpoint # must be your real Agent Memory API URL
grep OPENBRAIN_KEY ~/.hermes/.env # must be presentHermes' run_agent.py doesn't pass model to on_turn_start, so the provider falls back to reading ~/.hermes/config.yaml. Confirm the config has a real model:
grep -A2 '^model:' ~/.hermes/config.yamlIf the value is auto for the provider field, the plugin derives the provider from the model prefix (anthropic/... → anthropic, openrouter/... → openrouter). For provider-less model names, the column will read unknown — set an explicit model.provider in config.yaml if you need accuracy.
The OB1 Agent Memory API uses match_thoughts(threshold=0.7) against text-embedding-3-small, which is strict. Related items often score 0.4–0.6. If your fleet uses queries that are conceptually similar but not lexically close, lower the threshold in match_thoughts or override it in your fork of agent-memory-api/index.ts.
Almost always means the OB1 Edge Function rejected a payload shape. The provider sends the v1 schema_version literals (openbrain.agent_memory.recall.v1 / openbrain.agent_memory.writeback.v1) and a strict runtime: {name, version} shape — extra keys in runtime get rejected. If you're modifying the provider, run the test suite (pytest plugin/tests/) before installing.
The provider auto-disables writes when invoked with agent_context in ("subagent", "cron", "flush"). Hermes sets agent_context automatically for these cases — if you're driving the provider from a custom runner, set it yourself when calling initialize().
integrations/hermes-agent-memory/
├── README.md # this file
├── metadata.json # OB1 contribution metadata
├── CHANGELOG.md # release notes
└── plugin/
├── __init__.py # OB1MemoryProvider implementation
├── plugin.yaml # Hermes plugin metadata
└── tests/
├── __init__.py
└── test_ob1_provider.py
cd plugin
pytest tests/75 tests cover pure helpers, schema shapes on the wire, lifecycle, prefetch + cache TTL, sync_turn, session-end, pre-compress, and the seven tool handlers. Network is mocked at urllib.request.urlopen — tests run offline.