Conversation
The background-review and curator forks spawn an AIAgent that fails over through run_conversation()'s _try_activate_fallback(), which consults only the constructor-provided chain. Neither fork passed fallback_model, so a configured auxiliary.<task>.fallback_chain was silently ignored and the review died with its primary provider (calls=0, no fallback attempts). Add resolve_aux_task_fallback_chain() to hermes_cli/fallback_config.py: per-task entries first, then the top-level chain as the last-resort safety net, deduplicated by backend identity. Entries are normalized to the exact shape agent_init expects, aliasing transport -> api_mode for parity with the call_llm fallback path. Wire it into both fork constructors. Fixes NousResearch#93592 Fixes NousResearch#78371
Contributor
Duplicate of #79750: both wire configured per-task and global fallback chains into the curator and background-review forks. |
4 tasks
Contributor
Author
|
Closing in favor of #79750, which implements the same fix and predates this PR by three weeks. Review notes posted there cover two things worth folding in: citing |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
When
auxiliary.background_review.providerfails, the per-taskfallback_chainconfigured underauxiliary.background_review.fallback_chainis never consulted: the review retries its primary 3 times and then dies
silently with
calls=0, even though working fallback entries are configured.Root cause:
_run_review_in_thread()spawns the review fork without afallback_modelargument, soagent._fallback_chainstarts empty and_try_activate_fallback()gives up immediately. Every other auxiliarysub-module goes through
call_llm()(_try_configured_fallback_chain)and honors its chain — the two
run_conversation()-based forks were theonly ones that ignored it.
This wires both forks through the same layering the rest of the aux tasks
get: per-task
auxiliary.<task>.fallback_chainentries first, then thetop-level chain as the last-resort safety net, deduplicated by backend
identity. The user-facing documentation already promises this behavior
("Each task can also declare its own
fallback_chain"), and #78371describes exactly this wiring for the curator.
Related Issue
Fixes #93592
Fixes #78371
Type of Change
Changes Made
hermes_cli/fallback_config.py: addresolve_aux_task_fallback_chain(task, config=None)— builds theeffective chain for an AIAgent-fork review task: normalized
auxiliary.<task>.fallback_chainentries first, top-level chain(
get_fallback_chain) appended as safety net, deduplicated by backendidentity (provider+model+base_url). Entry normalization preserves
base_url/key_env/api_keyand aliasestransport->api_modefor parity with the
call_llmfallback path, which accepts eitherspelling while
_try_activate_fallback()only readsapi_mode.agent/background_review.py: pass the resolved chain to the reviewfork's
AIAgent(...)constructor asfallback_model.agent/curator.py: same wiring for the curation-pass fork.tests/agent/test_aux_review_fallback_chain.py: behavior-contracttests — task-first ordering, cross-source dedupe (case-insensitive),
invalid-entry tolerance, fresh-dict guarantees, entry-field
preservation, live-config resolution, and construction-time wiring of
both forks.
Users with no
auxiliary.<task>.fallback_chainand no top-level chain getbyte-identical behavior (empty chain ->
None-> empty_fallback_chain,as before).
How to Test
Targeted suites (CI-parity wrapper):
-> 15 passed.
Regression proof (fails on code before this PR): revert the two
constructor hunks in
agent/background_review.py/agent/curator.py—
TestBackgroundReviewWiring::*andTestCuratorWiring::*fail;restore them and all pass.
Manual: configure
auxiliary.background_review.{provider,model}pointingat a failing provider plus a working
fallback_chainentry; trigger abackground review. Before:
Background review complete: calls=0 ... result=none. After: the loop walks the configured entries (and then thetop-level chain) exactly like the main agent does.
Note on the full suite: on this host,
scripts/run_tests.shshowsenvironment-dependent failures unrelated to this change (terminal-width and
env-gate tests such as
tests/cli/test_prompt_stash_cli.pyandtests/hermes_cli/test_ignore_user_config_flags.py). Both sets wereverified to fail identically on pristine
origin/mainwithout this branch(via stash / scratch-worktree runs); every suite touching the modified
subsystems passes.
Checklist
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/A(No new config keys and no behavior beyond what the existing fallback-providers
documentation already describes, so the documentation boxes are N/A.)
🛠️ Dev: Halldrix
🤖 Sidekick: Hermes Agent v0.20.5
🐞 Reproduction: ✅ Confirmed