Summary
Two bugs in plugins/memory/openviking/__init__.py prevent the OpenViking memory plugin from working with API-key-authenticated servers and with late .env loading.
Bug 1: X-OpenViking-Account header conflicts with API key auth
Severity: Blocker — all viking_* tools return 403 when API key is configured.
Symptom:
Client error '403 Forbidden' for url 'http://host:31933/api/v1/fs/tree'
Server response:
{"error":{"code":"PERMISSION_DENIED","message":"X-OpenViking-Account cannot override the account for ADMIN/USER API keys."}}
Root cause: _VikingClient._headers() unconditionally sends X-OpenViking-Account, X-OpenViking-User, and X-OpenViking-Agent headers alongside X-API-Key. When using API key authentication, the account is embedded in the key itself — the server rejects explicit tenant header overrides.
Fix: Only send tenant headers in local-dev mode (no API key). When self._api_key is set, omit them.
def _headers(self) -> dict:
h = {
"Content-Type": "application/json",
- "X-OpenViking-Account": self._account,
- "X-OpenViking-User": self._user,
- "X-OpenViking-Agent": self._agent,
}
if self._api_key:
h["X-API-Key"] = self._api_key
+ else:
+ h["X-OpenViking-Account"] = self._account
+ h["X-OpenViking-User"] = self._user
+ h["X-OpenViking-Agent"] = self._agent
return h
Bug 2: Env vars captured once in initialize(), not re-read after /reload
Severity: Medium — requires process restart to pick up env changes.
Symptom: User adds OPENVIKING_* vars to .env after hermes starts, runs /reload, but viking tools still fail because initialize() already cached the empty values.
Root cause: initialize() snapshots os.environ.get("OPENVIKING_API_KEY", "") into self._api_key and creates _VikingClient once. /reload updates os.environ but the provider instance is not re-initialized.
Fix: Add _ensure_client() method that re-reads os.environ on every tool call and recreates the client if the API key or endpoint changed: replace if not self._client: with if not self._ensure_client(): in handle_tool_call() and system_prompt_block().
Reproduction
- Set
memory.provider: openviking in config.yaml
- Configure
.env with OPENVIKING_ENDPOINT and OPENVIKING_API_KEY
- Start hermes — viking_search/viking_browse return 403
Verified Fix
- viking_browse: 50 entries OK
- viking_search: 10 results with scores OK
- viking_read: L0 abstract content OK
/reload + tool call works without restart OK
Summary
Two bugs in
plugins/memory/openviking/__init__.pyprevent the OpenViking memory plugin from working with API-key-authenticated servers and with late.envloading.Bug 1:
X-OpenViking-Accountheader conflicts with API key authSeverity: Blocker — all viking_* tools return 403 when API key is configured.
Symptom:
Server response:
{"error":{"code":"PERMISSION_DENIED","message":"X-OpenViking-Account cannot override the account for ADMIN/USER API keys."}}Root cause:
_VikingClient._headers()unconditionally sendsX-OpenViking-Account,X-OpenViking-User, andX-OpenViking-Agentheaders alongsideX-API-Key. When using API key authentication, the account is embedded in the key itself — the server rejects explicit tenant header overrides.Fix: Only send tenant headers in local-dev mode (no API key). When
self._api_keyis set, omit them.def _headers(self) -> dict: h = { "Content-Type": "application/json", - "X-OpenViking-Account": self._account, - "X-OpenViking-User": self._user, - "X-OpenViking-Agent": self._agent, } if self._api_key: h["X-API-Key"] = self._api_key + else: + h["X-OpenViking-Account"] = self._account + h["X-OpenViking-User"] = self._user + h["X-OpenViking-Agent"] = self._agent return hBug 2: Env vars captured once in
initialize(), not re-read after/reloadSeverity: Medium — requires process restart to pick up env changes.
Symptom: User adds
OPENVIKING_*vars to.envafter hermes starts, runs/reload, but viking tools still fail becauseinitialize()already cached the empty values.Root cause:
initialize()snapshotsos.environ.get("OPENVIKING_API_KEY", "")intoself._api_keyand creates_VikingClientonce./reloadupdatesos.environbut the provider instance is not re-initialized.Fix: Add
_ensure_client()method that re-readsos.environon every tool call and recreates the client if the API key or endpoint changed: replaceif not self._client:withif not self._ensure_client():inhandle_tool_call()andsystem_prompt_block().Reproduction
memory.provider: openvikingin config.yaml.envwithOPENVIKING_ENDPOINTandOPENVIKING_API_KEYVerified Fix
/reload+ tool call works without restart OK