hermes - 💡(How to fix) Fix OpenViking plugin: 403 with API key auth + env vars not reloaded after /reload [2 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

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.


Error Message

Client error '403 Forbidden' for url 'http://host:31933/api/v1/fs/tree' {"error":{"code":"PERMISSION_DENIED","message":"X-OpenViking-Account cannot override the account for ADMIN/USER API keys."}}

Root Cause

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 Action

Fixed

Code Example

Client error '403 Forbidden' for url 'http://host:31933/api/v1/fs/tree'

---

{"error":{"code":"PERMISSION_DENIED","message":"X-OpenViking-Account cannot override the account for ADMIN/USER API keys."}}

---

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
RAW_BUFFERClick to expand / collapse

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

  1. Set memory.provider: openviking in config.yaml
  2. Configure .env with OPENVIKING_ENDPOINT and OPENVIKING_API_KEY
  3. 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

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING