fix(agent): pass api_key_hint to mark_exhausted_and_rotate in credential pool recovery - #43755
fix(agent): pass api_key_hint to mark_exhausted_and_rotate in credential pool recovery#43755liuhao1024 wants to merge 2 commits into
Conversation
…ial pool recovery recover_with_credential_pool() called mark_exhausted_and_rotate() without api_key_hint, causing it to fall back to current() or _select_unlocked(). When a prior rotation left current() as None, _select_unlocked() returned the NEXT (healthy) entry instead of the one that actually failed — marking the wrong credential as exhausted (NousResearch#43747). Extract the current API key from agent.api_key (or pool.current().runtime_api_key as fallback) and pass it as api_key_hint to all 4 call sites.
|
Nice fix — and the One gap I'd flag before merge: the tests verify the hint is plumbed, but don't yet prove that it routes through the real pool selection logic. Both Suggest adding one regression against a real Minor: for parity with the auxiliary path ( |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for tracing the missing handoff. The current-main premise is valid: recover_with_credential_pool() still calls mark_exhausted_and_rotate() without a hint (agent/agent_runtime_helpers.py:798, :822, :846, :946), while the pool only selects the exact failed key when a hint is supplied (agent/credential_pool.py:1576-1586).
Problems
- The new keyword will break current strict pool doubles:
tests/run_agent/test_run_agent.py:5649,:5670,:5696,:5801,:5825, and:5902definemark_exhausted_and_rotate(..., error_context=None)withoutapi_key_hint. - The added tests use mocks that discard the hint, so they do not prove the reported routing guarantee through the real selector in
agent/credential_pool.py:1581-1586.
Suggested changes
- Update those current test doubles to accept and, where applicable, assert
api_key_hint. - Add one real multi-entry
CredentialPoolregression where the failed key differs from the fallback/current healthy entry, then assert only the failed entry is exhausted.
Automated hermes-sweeper review.
| @@ -657,7 +669,7 @@ def recover_with_credential_pool( | |||
|
|
|||
There was a problem hiding this comment.
These calls now pass api_key_hint, but current strict pool doubles in tests/run_agent/test_run_agent.py:5649, :5670, :5696, :5801, :5825, and :5902 do not accept that keyword. Update those fakes (and assert the forwarded hint where useful), otherwise their exercised recovery branches raise TypeError.
…egression Follow-up to the #43755 salvage: - Update the strict _Pool doubles in tests/run_agent/test_run_agent.py to accept api_key_hint and assert it carries the agent's failed key. - Add a real-CredentialPool regression (no mocks) proving the hint routes exhaustion to the entry whose key actually failed, not pool.current(), plus the no-hint baseline (#43747 wrong-entry marking).
|
Salvaged and merged in #69553 — your commit was cherry-picked onto current main with authorship preserved (rebase-merge). On top of it we updated the strict pool test doubles flagged in the earlier review and added a real-CredentialPool regression proving the hint routes exhaustion to the failed entry. Thanks for tracing the missing handoff, @liuhao1024! |
…egression Follow-up to the NousResearch#43755 salvage: - Update the strict _Pool doubles in tests/run_agent/test_run_agent.py to accept api_key_hint and assert it carries the agent's failed key. - Add a real-CredentialPool regression (no mocks) proving the hint routes exhaustion to the entry whose key actually failed, not pool.current(), plus the no-hint baseline (NousResearch#43747 wrong-entry marking).
What does this PR do?
Passes
api_key_hinttomark_exhausted_and_rotate()inrecover_with_credential_pool(), ensuring the correct pool entry is marked as exhausted during credential rotation. Without this hint, the pool falls back tocurrent()or_select_unlocked(), which can return the wrong (healthy) entry after a prior rotation.Related Issue
Fixes #43747
Type of Change
Changes Made
agent/agent_runtime_helpers.py: Extract current API key fromagent.api_key(with fallback topool.current().runtime_api_key) before any rotation; pass it asapi_key_hintto all 4mark_exhausted_and_rotatecall sites (billing, rate-limit pre-exhausted, rate-limit retry, auth refresh failed)tests/agent/test_credential_pool_routing.py: Update helper to setagent.api_keyandagent.provider/pool.provider; updateassert_called_once_withto includeapi_key_hint; addrotate()**kwargs for forward compatibility; addtest_api_key_hint_from_pool_current_when_agent_key_missingverifying the fallback pathHow to Test
pytest tests/agent/test_credential_pool_routing.py -v— all 11 tests passpytest tests/run_agent/test_codex_xai_oauth_recovery.py -k "recover_with_credential_pool" -v— all 5 tests passChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/ACode Intelligence
recover_with_credential_pool()inagent/agent_runtime_helpers.py(4 call sites tomark_exhausted_and_rotate, callers: agent error recovery path)api_key_hintis already an optional parameter with existing None-handlingauxiliary_client.pyalready passesapi_key_hint=hintcorrectly (lines 2774, 2786); this PR bringsagent_runtime_helpers.pyto parity