# NousResearch/hermes-agent · NameError for _pool_may_recover_from_rate_limit in conversation_loop

## Open now

- Nothing open on GitHub.

Nearly all members concern a NameError caused by a missing _ra() prefix or import for _pool_may_recover_from_rate_limit in conversation_loop.py, which breaks rate-limit fallback behavior. One member proposes replacing the _ra() lazy-import pattern with explicit dependency injection.

## TL;DR

- 18 member(s): 0 open issue(s), 9 closed issue(s), 0 open PR(s), 1 merged PR(s), 8 PR(s) closed without merging.
- A fix was merged to main in PR #28345. Verify it addresses your case.
- **Recommended:** read PR #28345 (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: `unresolved`. 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.16`: 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

- #27370: \[Bug\] NameError: '_pool_may_recover_from_rate_limit' is not defined in conversation_loop.py
- #27402: NameError: '_pool_may_recover_from_rate_limit' is not defined in conversation_loop.py
- #27465: bug: NameError '_pool_may_recover_from_rate_limit' in conversation_loop.py on rate limit (v0.14.0)
- #27719: \[Bug\]: Fallback fails with NameError when primary provider (DeepSeek) runs out of tokens
- #28389: NameError: _pool_may_recover_from_rate_limit not imported into extracted agent/conversation_loop.py
- #28773: \`NameError: _pool_may_recover_from_rate_limit\` in \`agent/conversation_loop.py:2335\` — fallback chain never activates on HTTP 429
- #29202: NameError: _pool_may_recover_from_rate_limit is not defined — missing _ra() prefix in conversation_loop.py
- #29621: \[Bug\]: After main model 429, switch to fallback model and report an error.
- #30350: NameError: _pool_may_recover_from_rate_limit not defined in conversation_loop.py

## Prior & competing PRs

- **#27359: fix(agent): resolve NameError in rate-limit fallback decision**. closed without merge · fix tier `suggested`
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#27374`, `#27374`, `#27374`, `#27370`, `#27374`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#28345: fix(conversation_loop): _ra()._pool_may_recover_from_rate_limit (NameError) (#28159)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `agent/conversation_loop.py`, `tests/agent/test_gemini_fast_fallback.py`
  - fix hunks:
  - `agent/conversation_loop.py`

    ```diff
    @@ -2332,7 +2332,7 @@ def _stop_spinner():
                         # still recover.  See _pool_may_recover_from_rate_limit
                         # for the single-credential-pool and CloudCode-quota
                         # exceptions.  Fixes #11314 and #13636.
    -                    pool_may_recover = _pool_may_recover_from_rate_limit(
    +                    pool_may_recover = _ra()._pool_may_recover_from_rate_limit(
                             agent._credential_pool,
                             provider=agent.provider,
                             base_url=getattr(agent, "base_url", None),
    ```
  - `tests/agent/test_gemini_fast_fallback.py`

    ```diff
    @@ -5,8 +5,10 @@
     Gemini OAuth) the 429 is an account-wide throttle, so waiting for pool
     rotation is pointless — prefer fallback immediately.
     """
    +import inspect
     from unittest.mock import MagicMock
     
    +from agent import conversation_loop
     from run_agent import _pool_may_recover_from_rate_limit
     
     
    ```

    ```diff
    @@ -60,3 +62,17 @@ def test_exhausted_pool_skips_rotation():
     
     def test_no_pool_skips_rotation():
         assert _pool_may_recover_from_rate_limit(None) is False
    +
    +
    +def test_conversation_loop_resolves_pool_helper_through_run_agent_module():
    +    """Extracted conversation loop must honor tests/patches on run_agent.
    +
    +    conversation_loop intentionally lazy-loads run_agent via _ra().  If this
    +    call site uses a bare imported helper, monkeypatching run_agent in tests (and
    +    production wrappers that patch run_agent) will not propagate into the
    +    extracted loop; older code also hit NameError in this branch.
    +    """
    +    source = inspect.getsource(conversation_loop.run_conversation)
    +
    +    assert "_ra()._pool_may_recover_from_rate_limit(" in source
    +    assert "pool_may_recover = _pool_may_recover_from_rate_limit(" not in source
    ```
- **#27374: fix(agent): wrap _pool_may_recover_from_rate_limit with _ra() lazy import**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#28345`, `#28159`, `#27370`, `#27465`, `#27468`, `#27583`, `#27686`, `#27732`, `#27734`, `#27735`, `#27750`, `#27891`, `#27903`, `#28304`
- **#27468: fix(conversation_loop): NameError on rate limit — route _pool_may_recover_from_rate_limit through _ra() (#27465)**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#28345`, `#28159`, `#27370`, `#27465`, `#27468`, `#27583`, `#27686`, `#27732`, `#27734`, `#27735`, `#27750`, `#27891`, `#27903`, `#28304`
- **#27583: fix: prefix _pool_may_recover_from_rate_limit with module name**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#28345`, `#28159`, `#27370`, `#27465`, `#27468`, `#27583`, `#27686`, `#27732`, `#27734`, `#27735`, `#27750`, `#27891`, `#27903`, `#28304`
- **#27608: fix(conversation_loop): NameError on rate-limit — _pool_may_recover_from_rate_limit not in scope**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#27370`
- **#27732: fix(agent): import _pool_may_recover_from_rate_limit in conversation_loop (#27719)**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#28345`, `#28159`, `#27370`, `#27465`, `#27468`, `#27583`, `#27686`, `#27732`, `#27734`, `#27735`, `#27750`, `#27891`, `#27903`, `#28304`
- **#27750: fix(agent): add missing _ra() prefix to pool recovery call**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#28345`, `#28159`, `#27370`, `#27465`, `#27468`, `#27583`, `#27686`, `#27732`, `#27734`, `#27735`, `#27750`, `#27891`, `#27903`, `#28304`
- **#29210: fix(agent): add _ra() prefix to _pool_may_recover_from_rate_limit call**. closed without merge
  - maintainer direction: category `silent_close`; implication `active`

## Fix status

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