# NousResearch/hermes-agent · Noisy raft CLI warning logged when raft unused

## Open now

- Nothing open on GitHub.

Reports and a fix for an unconditional warning message about the raft CLI being logged repeatedly, even when the raft platform plugin is disabled or the CLI is not installed.

## TL;DR

- 3 member(s): 0 open issue(s), 2 closed issue(s), 0 open PR(s), 1 merged PR(s), 0 PR(s) closed without merging.
- A fix was merged to main in PR #49240. Verify it addresses your case.
- **Recommended:** read PR #49240 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `partially_resolved` · deciding PR(s): `pr-49240`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.45`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #49234: \[Bug\]: Raft platform plugin floods logs with WARNING every ~10s for users without raft CLI
- #49336: \[Bug\] Unconditional warning '\[raft\] raft CLI not found in PATH' logged even when Raft platform is disabled

## Prior & competing PRs

- **#49240: fix(plugins): silence raft check_fn log spam for users without raft CLI**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `plugins/platforms/raft/adapter.py`, `tests/plugins/test_raft_check_fn_silent.py`
  - fix hunks:
  - `plugins/platforms/raft/adapter.py`

    ```diff
    @@ -98,12 +98,20 @@
     
     
     def check_raft_requirements() -> bool:
    -    """Check if Raft channel dependencies are available."""
    +    """Check if Raft channel dependencies are available.
    +
    +    Intentionally silent on failure — this is a passive probe registered as
    +    the platform's ``check_fn``. It is called on every
    +    ``load_gateway_config()`` (message handling, display lookups, agent
    +    turns), so logging here floods the logs for every user without the
    +    ``raft`` CLI installed. The caller (``gateway/platform_registry.py``
    +    ``create_adapter()``) emits its own warning when requirements are not met
    +    and an adapter is actually requested. This matches the convention used by
    +    other platform adapters (e.g. ``teams/adapter.py``).
    +    """
         if not AIOHTTP_AVAILABLE:
    -        logger.warning("[raft] aiohttp is not installed — install with: pip install aiohttp")
             return False
         if not shutil.which("raft"):
    -        logger.warning("[raft] raft CLI not found in PATH — install from https://raft.build")
             return False
         return True
     
    ```
  - `tests/plugins/test_raft_check_fn_silent.py`

    ```diff
    @@ -0,0 +1,75 @@
    +"""Regression tests for the raft platform plugin's check_fn.
    +
    +The raft platform adapter's ``check_raft_requirements()`` is registered as
    +the platform's ``check_fn``. This function is invoked on every
    +``load_gateway_config()`` call (dozens of times during normal gateway
    +operation). It must therefore be a *silent* predicate — returning True/False
    +without logging — otherwise every user without the ``raft`` CLI installed
    +gets their logs flooded with WARNING messages every few seconds.
    +
    +See: https://github.com/NousResearch/hermes-agent/issues/49234
    +"""
    +
    +import logging
    +from unittest.mock import patch
    +
    +import pytest
    +
    +
    [redacted:email]
    +def raft_check():
    +    """Import check_raft_requirements fresh (adapter self-manages sys.path)."""
    +    from plugins.platforms.raft.adapter import check_raft_requirements
    +
    +    return check_raft_requirements
    +
    +
    +def test_check_returns_false_when_raft_cli_missing(raft_check):
    +    """check_fn returns False when raft CLI is not in PATH."""
    +    with patch("plugins.platforms.raft.adapter.shutil.which", return_value=None), \
    +         patch("plugins.platforms.raft.adapter.AIOHTTP_AVAILABLE", True):
    +        assert raft_check() is False
    +
    +
    +def test_check_returns_false_when_aiohttp_missing(raft_check):
    +    """check_fn returns False when aiohttp dependency is unavailable."""
    +    with patch("plugins.platforms.raft.adapter.AIOHTTP_AVAILABLE", False):
    +        assert raft_check() is False
    +
    +
    +def test_check_returns_true_when_all_deps_present(raft_check):
    +    """check_fn returns True when all dependencies are available."""
    +    with patch("plugins.platforms.raft.adapter.shutil.which", return_value="/usr/bin/raft"), \
    +         patch("plugins.platforms.raft.adapter.AIOHTTP_AVAILABLE", True):
    +        assert raft_check() is True
    +
    +
    +def test_check_silent_when_raft_cli_missing(raft_check, caplog):
    +    """check_fn must NOT log a WARNING when raft CLI is missing.
    +
    +    This is the regression guard for issue #49234 — logging inside check_fn
    +    causes log spam because the function is called on every config load.
    +    """
    +    with patch("plugins.platforms.raft.adapter.shutil.which", return_value=None), \
    +         patch("plugins.platforms.raft.adapter.AIOHTTP_AVAILABLE", True):
    +        with caplog.at_level(logging.WARNING, logger="plugins.platforms.raft.adapter"):
    +            raft_check()
    +
    +    warnings = [r for r in caplog.records if r.levelno >= logging.WARNING]
    +    assert warnings == [], (
    +        f"check_raft_requirements must be silent (no WARNING logs), "
    +        f"but emitted: {[r.getMessage() for r in warnings]}"
    +    )
    +
    +
    +def test_check_silent_when_aiohttp_missing(raft_check, caplog):
    +    """check_fn must NOT log a WARNING when aiohttp is missing."""
    +    with patch("plugins.platforms.raft.adapter.AIOHTTP_AVAILABLE", False):
    +        with caplog.at_level(logging.WARNING, logger="plugins.platforms.raft.adapter"):
    +            raft_check()
    +
    +    warnings = [r for r in caplog.records if r.levelno >= logging.WARNING]
    +    assert warnings == [], (
    +        f"check_raft_requirements must be silent (no WARNING logs), "
    +        f"but emitted: {[r.getMessage() for r in warnings]}"
    +    )
    ```

## Fix status

- Merged to main in PR #49240 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-20`.
- Subsystem: `agent`
