fix(agent): notify gateway users when credential pool auth exhaustion causes provider switch - #10480
fix(agent): notify gateway users when credential pool auth exhaustion causes provider switch#10480aangelinsf wants to merge 2 commits into
Conversation
…th-exhausted When all credentials for a provider are exhausted due to 401/403 failures, emit a plain-language _emit_status() notification so gateway users (Telegram, Discord, etc.) know their primary AI has become unavailable and what to do. Same-provider key rotation remains silent — the message only fires when rotation itself fails and Hermes is forced to fall back. This is distinct from the cooldown duration change in PR NousResearch#10058 (which was closed). The notification half of that fix stands on its own: the configured fallback_model path already calls _emit_status() on provider switch, so this makes the credential pool exhaustion path consistent with that behavior. Closes NousResearch#10476
…rotation Two tests for TestAuthExhaustionNotification: - emits notification when all 401 credentials exhausted (rotate returns None) - stays silent when rotation to a next credential succeeds Matches the pattern of TestPoolRotationCycle in the same file.
🤖 Automated PR ReviewSecurity Scan✓ No security concerns Code Quality✓ Good UX - notifies users on auth failure SummaryStatus: APPROVE Clean fix. Good user experience improvement - gateway users now get clear notification when credential pool is exhausted. Reviewed by Hermes Agent |
|
Thanks for the focused notification fix. This is an automated hermes-sweeper review; current
The PR's original insertion point is now only a forwarder to |
What does this PR do?
When a provider fails with repeated 401/403 errors, Hermes marks its credentials as "exhausted"
in the credential pool and silently falls back to the next available provider — with no notification
to the user. In a gateway deployment (Telegram, Discord, etc.), this means the user unknowingly
receives responses from a completely different AI provider, potentially with different capabilities,
different privacy terms, and unexpected cost implications.
This is a behavioral inconsistency: the configured
fallback_modelpath already calls_emit_status()when it switches providers, which propagates to all gateway platforms. Thecredential pool exhaustion path — which produces the same end-user outcome — does not.
This PR fixes the inconsistency by calling
_emit_status()in_recover_with_credential_pool()when
mark_exhausted_and_rotate()returnsNone(all credentials exhausted, rotation impossible).Same-provider key rotation — where a new key for the same provider is swapped in transparently —
remains silent, as that is legitimately low-signal infrastructure behavior the user doesn't need
to know about.
The message is written in plain language: it names the failing provider, avoids exposing raw HTTP
status codes or internal jargon, and gives an actionable recovery command.
Related Issue
Fixes #10476
Type of Change
Changes Made
run_agent.py— In_recover_with_credential_pool(), added_emit_status()call in theFailoverReason.authbranch aftermark_exhausted_and_rotate()returnsNone. The messageincludes the provider label and the recovery command (
hermes auth reset <provider>). The callis placed after rotation fails, so same-provider key rotation (where
next_entryis notNone)continues silently.
tests/agent/test_credential_pool_routing.py— AddedTestAuthExhaustionNotificationclasswith two tests:
test_emits_notification_when_all_credentials_exhausted— verifies_emit_statusis calledonce with a message containing the provider name, HTTP status, and
hermes auth resetwhen rotation returns
Nonetest_silent_when_rotation_to_next_credential_succeeds— verifies_emit_statusis notcalled when rotation succeeds (same-provider key swap), preserving the silent behavior for
that path
How to Test
Unit tests (fast):
Manual gateway verification:
KIMI_API_KEY=sk-invalidin~/.hermes/.envwithprovider: kimi-codinginconfig.yaml)OPENROUTER_API_KEY)of the switch
with
hermes auth reset <provider>before testingChecklist
Code
fix(agent):,test(agent):)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — N/A (no user-visible features added)cli-config.yaml.exampleif I added/changed config keys — N/A (no new config keys)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/A (no architecture changes)Screenshots / Logs
Before (silent fallback — no notification sent to Telegram):
After (notification emitted to gateway before response):