Follow-up hardening on the salvaged _ensure_client() (#21130 fix): - Failed-config cooldown: after a refresh attempt fails for a given resolved config, skip re-probing for 30s. Previously every provider access against a down endpoint paid a 3s health probe under _client_refresh_lock and emitted a warning (2+ per turn, some on user-facing threads: prefetch, tool calls, session end). Retries still happen after the cooldown or immediately when config changes, and the log message now says so instead of the false 'disabled until config changes'. - Atomic connection snapshot: _conn_snapshot (5-tuple, single assignment) is published only after a health check passes. _new_client() and on_memory_write's writer read it as one load, so background writers can no longer observe a torn mix of old/new identity fields mid-refresh or target an endpoint that never passed health. Field writes in _ensure_client_locked keep tracking the attempted config for the unchanged-config dedupe. - _env_refresh_enabled moves to the top of initialize(): an exception mid-initialize (swallowed by MemoryManager) can no longer leave the provider silently stuck in never-refresh mode. - _search_prefetch_context reuses _new_client() and degrades to '' on construction failure instead of propagating. Mutation-checked: neutering the cooldown or publishing the snapshot on failed health makes the new regression tests fail. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| plugin.yaml | ||
| README.md | ||
OpenViking Memory Provider
Context database by Volcengine (ByteDance) with filesystem-style knowledge hierarchy, tiered retrieval, and automatic memory extraction.
Requirements
- OpenViking installed with the
openviking-servercommand available - OpenViking server config initialized and validated (
openviking-server init, thenopenviking-server doctor) - OpenViking server running and reachable from Hermes
Setup
Prepare OpenViking first:
openviking-server init
openviking-server doctor
openviking-server
Then configure Hermes:
hermes memory setup # select "openviking"
The setup can link to an existing ~/.openviking/ovcli.conf, copy its current
connection values into Hermes, or create a minimal ovcli.conf when one does
not exist.
Or manually:
hermes config set memory.provider openviking
Add the connection settings to the active profile's .env file. For the
default profile that is ~/.hermes/.env; for a named profile use
~/.hermes/profiles/<profile>/.env.
OPENVIKING_ENDPOINT=http://127.0.0.1:1933
# OPENVIKING_API_KEY=...
# OPENVIKING_ACCOUNT=default
# OPENVIKING_USER=default
# OPENVIKING_AGENT=hermes
Config
OpenViking's server config is separate from Hermes:
ov.confconfigures OpenViking storage, embedding/VLM models, auth, and server behavior. OpenViking reads it from--config,OPENVIKING_CONFIG_FILE, or~/.openviking/ov.conf.ovcli.confstores client/CLI connection values such asurl,api_key,account, anduser. It is read fromOPENVIKING_CLI_CONFIG_FILEor~/.openviking/ovcli.conf.
Hermes-side provider config is read from environment variables in the active
profile's .env:
| Env Var | Default | Description |
|---|---|---|
OPENVIKING_ENDPOINT |
http://127.0.0.1:1933 |
Server URL |
OPENVIKING_API_KEY |
(none) | User/admin API key for authenticated servers |
OPENVIKING_ACCOUNT |
default |
Tenant account for local/trusted mode |
OPENVIKING_USER |
default |
Tenant user for local/trusted mode |
OPENVIKING_AGENT |
hermes |
Hermes peer ID in OpenViking, used for peer-scoped memories |
When OPENVIKING_API_KEY is set, Hermes lets OpenViking derive account/user
identity from the key. In local or trusted deployments without an API key,
Hermes sends OPENVIKING_ACCOUNT and OPENVIKING_USER as identity headers.
Tools
| Tool | Description |
|---|---|
viking_search |
Semantic search with fast/deep/auto modes |
viking_read |
Read content at a viking:// URI (abstract/overview/full) |
viking_browse |
Filesystem-style navigation (list/tree/stat) |
viking_remember |
Store a fact directly with OpenViking content/write |
viking_forget |
Delete one exact viking:// memory file URI |
viking_add_resource |
Ingest URLs/docs into the knowledge base |
Memory Writes And Deletes
viking_remember writes directly to OpenViking with POST /api/v1/content/write
and mode=create. It creates peer-scoped memory files under
viking://user/peers/${OPENVIKING_AGENT}/memories/...; OpenViking may return a
canonical user-scoped form such as
viking://user/default/peers/${OPENVIKING_AGENT}/memories/... in API-key mode.
Explicit remembers do not depend on session commit extraction.
Hermes built-in memory tool additions are mirrored to OpenViking after the
local memory operation succeeds:
| Hermes action | OpenViking operation |
|---|---|
add |
content/write with mode=create under the configured peer memory namespace |
Built-in replace and remove operations are not mirrored because Hermes
native memory entries do not yet carry stable OpenViking file URIs. Use
viking_forget when the user explicitly asks to delete a specific OpenViking
memory URI.
viking_forget is intentionally narrow. It only accepts concrete user memory
file URIs, such as
viking://user/peers/hermes/memories/preferences/mem_abc123.md or the canonical
viking://user/default/peers/hermes/memories/preferences/mem_abc123.md. Files
directly under memories/, such as viking://user/default/memories/profile.md,
are also allowed because OpenViking supports them. The tool rejects directories,
resources, skills, sessions, generated summary files, and URIs with query
strings or fragments. Use OpenViking's MCP, CLI, or admin APIs for broader
resource and directory cleanup.