hermes - ✅(Solved) Fix Gateway config-backed Home Assistant / Mattermost / Signal adapters are blocked by env-only requirement checks [1 pull requests, 1 participants]

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…
GitHub stats
NousResearch/hermes-agent#13827Fetched 2026-04-23 07:48:46
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
labeled ×4cross-referenced ×1

GatewayRunner._create_adapter() rejects config-backed Home Assistant, Mattermost, and Signal adapters because its preflight checks only look at environment variables. Each adapter constructor already accepts PlatformConfig values, but the gateway never instantiates them unless duplicate env vars are also present.

Root Cause

Summary

GatewayRunner._create_adapter() rejects config-backed Home Assistant, Mattermost, and Signal adapters because its preflight checks only look at environment variables. Each adapter constructor already accepts PlatformConfig values, but the gateway never instantiates them unless duplicate env vars are also present.

Fix Action

Fixed

PR fix notes

PR #14053: fix(gateway): honor config-backed adapter requirements

Description (problem / solution / changelog)

Fixes #13827

Summary

  • let gateway preflight checks accept Signal, Home Assistant, and Mattermost credentials from PlatformConfig, not only env vars
  • pass the platform config into _create_adapter() requirement checks so config-only setups can instantiate adapters
  • add runner-level regression tests covering config-backed adapter creation without duplicate env vars

Repro

With HASS_TOKEN, MATTERMOST_TOKEN, MATTERMOST_URL, SIGNAL_HTTP_URL, and SIGNAL_ACCOUNT unset, _create_adapter() returned None for valid config-only platform definitions even though the adapters themselves already read from PlatformConfig.

Verification

  • python3 repro: config-only Home Assistant / Mattermost / Signal cases now return adapter instances instead of None
  • pytest -o addopts='' tests/gateway/test_runner_config_backed_adapters.py
  • pytest -o addopts='' tests/gateway/test_homeassistant.py::TestCheckRequirements
  • pytest -o addopts='' tests/gateway/test_mattermost.py::TestMattermostRequirements
  • pytest -o addopts='' tests/gateway/test_signal.py::TestSignalHelpers

Changed files

  • gateway/platforms/homeassistant.py (modified, +3/-1)
  • gateway/platforms/mattermost.py (modified, +4/-4)
  • gateway/platforms/signal.py (modified, +5/-2)
  • gateway/run.py (modified, +3/-3)
  • tests/gateway/test_runner_config_backed_adapters.py (added, +86/-0)

Code Example

import os
from types import SimpleNamespace
from gateway.run import GatewayRunner
from gateway.config import PlatformConfig, Platform

for key in [
    'HASS_TOKEN', 'HASS_URL',
    'MATTERMOST_TOKEN', 'MATTERMOST_URL',
    'SIGNAL_HTTP_URL', 'SIGNAL_ACCOUNT',
]:
    os.environ.pop(key, None)

fake_self = SimpleNamespace(
    config=SimpleNamespace(group_sessions_per_user=False, thread_sessions_per_user=False)
)

cases = [
    (Platform.HOMEASSISTANT, PlatformConfig(enabled=True, token='tok', extra={'url': 'http://ha.local'})),
    (Platform.MATTERMOST, PlatformConfig(enabled=True, token='tok', extra={'url': 'https://mm.example.com'})),
    (Platform.SIGNAL, PlatformConfig(enabled=True, extra={'http_url': 'http://127.0.0.1:8080', 'account': '+15551234567'})),
]

for platform, cfg in cases:
    print(platform.value, GatewayRunner._create_adapter(fake_self, platform, cfg))

---

HomeAssistant: aiohttp not installed or HASS_TOKEN not set
Mattermost: MATTERMOST_TOKEN or MATTERMOST_URL not set, or aiohttp missing
Signal: SIGNAL_HTTP_URL or SIGNAL_ACCOUNT not configured
homeassistant None
mattermost None
signal None
RAW_BUFFERClick to expand / collapse

Summary

GatewayRunner._create_adapter() rejects config-backed Home Assistant, Mattermost, and Signal adapters because its preflight checks only look at environment variables. Each adapter constructor already accepts PlatformConfig values, but the gateway never instantiates them unless duplicate env vars are also present.

Affected code

  • gateway/run.py:2111-2181
  • gateway/platforms/homeassistant.py:42-48
  • gateway/platforms/homeassistant.py:75-80
  • gateway/platforms/mattermost.py:53-68
  • gateway/platforms/mattermost.py:77-81
  • gateway/platforms/signal.py:130-149

Why this is a bug

The runtime contract is inconsistent:

  • HomeAssistantAdapter(config) reads config.token and config.extra["url"].
  • MattermostAdapter(config) reads config.token and config.extra["url"].
  • SignalAdapter(config) reads config.extra["http_url"] and config.extra["account"].

But GatewayRunner._create_adapter() blocks all three adapters behind check_*_requirements() helpers that only consult env vars (HASS_TOKEN, MATTERMOST_*, SIGNAL_*).

So a valid config.yaml setup can be loaded into PlatformConfig and still fail to start in the normal gateway path.

Minimal reproduction

Run from the repo root with env vars unset:

import os
from types import SimpleNamespace
from gateway.run import GatewayRunner
from gateway.config import PlatformConfig, Platform

for key in [
    'HASS_TOKEN', 'HASS_URL',
    'MATTERMOST_TOKEN', 'MATTERMOST_URL',
    'SIGNAL_HTTP_URL', 'SIGNAL_ACCOUNT',
]:
    os.environ.pop(key, None)

fake_self = SimpleNamespace(
    config=SimpleNamespace(group_sessions_per_user=False, thread_sessions_per_user=False)
)

cases = [
    (Platform.HOMEASSISTANT, PlatformConfig(enabled=True, token='tok', extra={'url': 'http://ha.local'})),
    (Platform.MATTERMOST, PlatformConfig(enabled=True, token='tok', extra={'url': 'https://mm.example.com'})),
    (Platform.SIGNAL, PlatformConfig(enabled=True, extra={'http_url': 'http://127.0.0.1:8080', 'account': '+15551234567'})),
]

for platform, cfg in cases:
    print(platform.value, GatewayRunner._create_adapter(fake_self, platform, cfg))

Observed output:

HomeAssistant: aiohttp not installed or HASS_TOKEN not set
Mattermost: MATTERMOST_TOKEN or MATTERMOST_URL not set, or aiohttp missing
Signal: SIGNAL_HTTP_URL or SIGNAL_ACCOUNT not configured
homeassistant None
mattermost None
signal None

Even though constructing the adapters directly with the same PlatformConfig works.

Expected behavior

If the required values are present in PlatformConfig, _create_adapter() should instantiate the adapter without requiring duplicate env vars.

Actual behavior

_create_adapter() returns None for config-backed Home Assistant / Mattermost / Signal setups unless equivalent env vars are also exported.

Suggested investigation

  • Make check_ha_requirements(), check_mattermost_requirements(), and check_signal_requirements() accept a PlatformConfig (or remove the env-only gate and let the adapter validate after construction).
  • Add a regression test that exercises _create_adapter() with config-only platform credentials.

extent analysis

TL;DR

Modify the check_*_requirements() functions to accept a PlatformConfig object, allowing _create_adapter() to instantiate adapters without requiring duplicate environment variables.

Guidance

  • Update the check_ha_requirements(), check_mattermost_requirements(), and check_signal_requirements() functions to take a PlatformConfig object as an argument, enabling them to validate the configuration without relying on environment variables.
  • Remove the environment variable checks from the _create_adapter() method, allowing it to instantiate adapters based solely on the provided PlatformConfig.
  • Add a regression test to ensure that _create_adapter() works correctly with config-only platform credentials.
  • Verify that the adapter constructors (HomeAssistantAdapter, MattermostAdapter, SignalAdapter) correctly handle the PlatformConfig object and its attributes.

Example

def check_ha_requirements(config: PlatformConfig) -> bool:
    return config.token and config.extra.get("url")

def check_mattermost_requirements(config: PlatformConfig) -> bool:
    return config.token and config.extra.get("url")

def check_signal_requirements(config: PlatformConfig) -> bool:
    return config.extra.get("http_url") and config.extra.get("account")

Notes

The proposed changes assume that the PlatformConfig object contains the necessary attributes for each adapter type. Additional validation may be required to ensure that the configuration is complete and valid.

Recommendation

Apply the suggested changes to the check_*_requirements() functions and the _create_adapter() method to fix the issue, as this approach aligns with the expected behavior and allows for more flexible configuration handling.

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…

FAQ

Expected behavior

If the required values are present in PlatformConfig, _create_adapter() should instantiate the adapter without requiring duplicate env vars.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING