fix(delegation): honor delegation.fallback_providers for child agents - #80421
andrexibiza wants to merge 4 commits into
Conversation
Interlock receipt
Local: 89/89 green on |
Duplicate of #65052, which is the earlier open implementation of the same child fallback-chain resolution. |
|
ci: force re-trigger — queued run never associated; reopening immediately |
529f119 to
23e6927
Compare
When delegation.fallback_providers is set, delegated children use that chain instead of silently inheriting the head agent's top-level fallback_providers. Absent/null preserves parent inheritance (NousResearch#7481); [] disables child fallback. Closes the isolation hole where a worker pinned via delegation.provider could still escalate onto ollama-cloud (or any other head fallback) on the first retryable failure. Fixes NousResearch#65038 Co-authored-by: Ayush Nangia <ayushnangia@users.noreply.github.com> Signed-off-by: Axl Ibiza, MBA <andrexibiza@users.noreply.github.com>
Signed-off-by: Andrex Ibiza <andrexibiza@users.noreply.github.com>
Signed-off-by: Andrex Ibiza <andrexibiza@users.noreply.github.com>
Signed-off-by: Andrex Ibiza <andrexibiza@users.noreply.github.com>
6e5be8c to
2ec23e8
Compare
|
Rebased onto current origin/main and resolved the conflict that was blocking mergeability. What changed:
Verification: PR is now mergeable; CI is re-running on the new head. |
|
@ayushnangia retains all credit for this fix. Freshly rebased. |
…n x config matrix Composes NousResearch#80465's pin semantics with NousResearch#80438/NousResearch#80421's delegation.fallback_providers semantics (NousResearch#65038) and settles the composition cell the three PRs leave undefined (NousResearch#80450 map). _resolve_child_fallback_chain implements the whole decision table in one pure function: pinned children get no chain unless the delegation section declares one (a delegation-scoped chain honors both explicit intents; the silent drag in NousResearch#80450 is specifically the PARENT chain substituting a pin); an explicit empty list disables fallback; absent config preserves historical parent inheritance exactly. Malformed declared values log and fall back PIN-AWARE — never the parent chain on a pinned child, so the config-error path cannot reintroduce the drag. Entries normalize through the canonical get_fallback_chain. The two existing inheritance tests are made hermetic against the real user config (as NousResearch#80438 also did).
Adopted from PR NousResearch#80421 with the author's explicit go-ahead on NousResearch#80450 ('Please proceed!'): config_defaults entry, cli-config.yaml.example block, and user-guide docs for the delegation-scoped fallback chain. Co-authored-by: Andrex Ibiza, MBA <84248988+andrexibiza@users.noreply.github.com>
…n x config matrix Composes NousResearch#80465's pin semantics with NousResearch#80438/NousResearch#80421's delegation.fallback_providers semantics (NousResearch#65038) and settles the composition cell the three PRs leave undefined (NousResearch#80450 map). _resolve_child_fallback_chain implements the whole decision table in one pure function: pinned children get no chain unless the delegation section declares one (a delegation-scoped chain honors both explicit intents; the silent drag in NousResearch#80450 is specifically the PARENT chain substituting a pin); an explicit empty list disables fallback; absent config preserves historical parent inheritance exactly. Malformed declared values log and fall back PIN-AWARE — never the parent chain on a pinned child, so the config-error path cannot reintroduce the drag. Entries normalize through the canonical get_fallback_chain. The two existing inheritance tests are made hermetic against the real user config (as NousResearch#80438 also did).
Adopted from PR NousResearch#80421 with the author's explicit go-ahead on NousResearch#80450 ('Please proceed!'): config_defaults entry, cli-config.yaml.example block, and user-guide docs for the delegation-scoped fallback chain. Co-authored-by: Andrex Ibiza, MBA <84248988+andrexibiza@users.noreply.github.com>
Assemble the existing guided picker and pin/config fallback matrix on NousResearch/hermes-agent main e9bccc9. Expose default delegation provider/model and ordered backups together on the Models screen, using the same scoped editor for the Advanced entry. Keep partial selections local, preserve model-only overrides, pin catalog and config operations to one connection/profile, and confirm persisted writes. Negotiate backend support so older runtimes cannot accept inert fallback settings through the new editor. Port the worker fallback decision into the post-decomposition runtime owner. Declared chains work with explicit pins; [] disables recovery; absent/null retains pin-aware defaults. Explicit inherit/parent is opt-in, canonical empty suppresses aliases, and returned route metadata is deeply child-owned. Reuse the canonical normalizer and existing recovery loop. Source implementation and provenance: - webtecnica: NousResearch#67523, source head fd6e822; omit its unrelated runner change. - Ayush Nangia: NousResearch#80479, source head a0a8d8d; preserve the pin/config matrix and spfcraze's model-only-pin correction. - Earlier fallback work: Ayush Nangia NousResearch#65052, Axl Ibiza NousResearch#80421, wz-heng NousResearch#80438, and Teknium NousResearch#80465 pin protection already on main. - devatnull NousResearch#81072 supplies explicit inheritance semantics, not its incompatible automatic inheritance under a pin. - TurgutKural NousResearch#101017 supplies alias compatibility, not its [] default. - Reports/design: DavidMetcalfe NousResearch#67347, mlahatte NousResearch#65038, and ScotterMonk NousResearch#94629. This is a co-authored current-main recomposition, not an unchanged cherry-pick of the historical commits. Original branches and review threads remain untouched. Dashboard NousResearch#67557 remains a separate surface. Fixes NousResearch#65038 Refs NousResearch#94629 Refs NousResearch#67347 Refs NousResearch#80450 Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com> Co-authored-by: Ayush Nangia <ayushnangia16@gmail.com>
…n x config matrix Composes NousResearch#80465's pin semantics with NousResearch#80438/NousResearch#80421's delegation.fallback_providers semantics (NousResearch#65038) and settles the composition cell the three PRs leave undefined (NousResearch#80450 map). _resolve_child_fallback_chain implements the whole decision table in one pure function: pinned children get no chain unless the delegation section declares one (a delegation-scoped chain honors both explicit intents; the silent drag in NousResearch#80450 is specifically the PARENT chain substituting a pin); an explicit empty list disables fallback; absent config preserves historical parent inheritance exactly. Malformed declared values log and fall back PIN-AWARE — never the parent chain on a pinned child, so the config-error path cannot reintroduce the drag. Entries normalize through the canonical get_fallback_chain. The two existing inheritance tests are made hermetic against the real user config (as NousResearch#80438 also did).
Adopted from PR NousResearch#80421 with the author's explicit go-ahead on NousResearch#80450 ('Please proceed!'): config_defaults entry, cli-config.yaml.example block, and user-guide docs for the delegation-scoped fallback chain. Co-authored-by: Andrex Ibiza, MBA <84248988+andrexibiza@users.noreply.github.com>
…n x config matrix Composes #80465's pin semantics with #80438/#80421's delegation.fallback_providers semantics (#65038) and settles the composition cell the three PRs leave undefined (#80450 map). _resolve_child_fallback_chain implements the whole decision table in one pure function: pinned children get no chain unless the delegation section declares one (a delegation-scoped chain honors both explicit intents; the silent drag in #80450 is specifically the PARENT chain substituting a pin); an explicit empty list disables fallback; absent config preserves historical parent inheritance exactly. Malformed declared values log and fall back PIN-AWARE — never the parent chain on a pinned child, so the config-error path cannot reintroduce the drag. Entries normalize through the canonical get_fallback_chain. The two existing inheritance tests are made hermetic against the real user config (as #80438 also did).
Adopted from PR #80421 with the author's explicit go-ahead on #80450 ('Please proceed!'): config_defaults entry, cli-config.yaml.example block, and user-guide docs for the delegation-scoped fallback chain. Co-authored-by: Andrex Ibiza, MBA <84248988+andrexibiza@users.noreply.github.com>
Rebuild NousResearch#105250 directly on current main as the Desktop projection of the delegation runtime contract merged in NousResearch#105347. Add the Models/profile-scoped editor, provider/model catalog controls, atomic fallback-policy drafts, capability negotiation, and authoritative same-owner save read-back. Remove the duplicate runtime fallback implementation and its failing test owner. Preserve model-only overrides, direct-endpoint metadata, explicit default-profile scope, stale-write refusal, failed-save retry, and legacy fallback-alias migration. The primary model and top-level fallback chain remain untouched. Source implementation and provenance: webtecnica NousResearch#67523; kshitijk4poor NousResearch#105347; Ayush Nangia NousResearch#80479 and NousResearch#65052; Axl Ibiza NousResearch#80421; wz-heng NousResearch#80438; Teknium NousResearch#80465; devatnull NousResearch#81072; TurgutKural NousResearch#101017; DavidMetcalfe NousResearch#67347; mlahatte NousResearch#65038; ScotterMonk NousResearch#94629. Fixes NousResearch#65038 Refs NousResearch#94629 Refs NousResearch#67347 Refs NousResearch#80450 Refs NousResearch#105347 Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com> Co-authored-by: Ayush Nangia <ayushnangia16@gmail.com>
Rebuild NousResearch#105250 directly on current main as the Desktop projection of the delegation runtime contract merged in NousResearch#105347. Add the Models/profile-scoped editor, provider/model catalog controls, atomic fallback-policy drafts, capability negotiation, and authoritative same-owner save read-back. Remove the duplicate runtime fallback implementation and its failing test owner. Preserve model-only overrides, direct-endpoint metadata, explicit default-profile scope, stale-write refusal, failed-save retry, and legacy fallback-alias migration. The primary model and top-level fallback chain remain untouched. Source implementation and provenance: webtecnica NousResearch#67523; kshitijk4poor NousResearch#105347; Ayush Nangia NousResearch#80479 and NousResearch#65052; Axl Ibiza NousResearch#80421; wz-heng NousResearch#80438; Teknium NousResearch#80465; devatnull NousResearch#81072; TurgutKural NousResearch#101017; DavidMetcalfe NousResearch#67347; mlahatte NousResearch#65038; ScotterMonk NousResearch#94629. Fixes NousResearch#65038 Refs NousResearch#94629 Refs NousResearch#67347 Refs NousResearch#80450 Refs NousResearch#105347 Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com> Co-authored-by: Ayush Nangia <ayushnangia16@gmail.com>
Summary
Honor a
delegation.fallback_providerschain for delegated children so a worker explicitly routed viadelegation.*no longer silently escalates onto fallback models intended only for the head agent (Fixes #65038).Why this matters to users
Before: You set
delegation.provider: xai-oauthso subagents run on xAI. When the child hit a retryable error, Hermes still walked the head agent'sfallback_providerslist — which often putollama-cloudfirst — and burned through an exhausted Ollama quota while ignoring the provider you pinned.After: You can give workers their own fallback chain under
delegation.fallback_providers. Set[]to disable child fallback entirely. If you leave the key unset/null, children keep inheriting the parent chain (backward compatible with #7481).Changes
tools/delegate_tool.py—_build_child_agent()resolves child chain asdelegation.fallback_providers> parent inheritance. Key absent/null → inherit parent_fallback_chain;[]→ no child fallback; malformed → warn + inherit (mirrorsreasoning_effort). Normalization reuseshermes_cli.fallback_config.get_fallback_chain().hermes_cli/config_defaults.py—delegation.fallback_providers: None(null sentinel = inherit; no_config_versionbump).cli-config.yaml.example+ docs — document the key and the three-way semantic.TestDelegationFallbackChain(override / absent / null / empty / malformed / real config loader). Async capacity test drains blocker completions to kill a latent race.Credit / prior art
Supersedes/reimplements the approach in open PR #65052 (@ayushnangia) against current
mainwith DCO + green local suite. Prior PR had no reported checks; this branch is a clean rebase of that design onto6e9cae6ac4b.How to test
Local result: 89 passed, 0 failed.
Minimal config repro from #65038:
Platforms
scripts/run_tests.shInterlock
Part of #65038
Part of #80450