Skip to content

fix(delegation): honor delegation.fallback_providers for child agents - #80421

Open
andrexibiza wants to merge 4 commits into
NousResearch:mainfrom
andrexibiza:fix/delegation-fallback-providers-65038
Open

andrexibiza wants to merge 4 commits into
NousResearch:mainfrom
andrexibiza:fix/delegation-fallback-providers-65038

Conversation

@andrexibiza

@andrexibiza andrexibiza commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Honor a delegation.fallback_providers chain for delegated children so a worker explicitly routed via delegation.* 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-oauth so subagents run on xAI. When the child hit a retryable error, Hermes still walked the head agent's fallback_providers list — which often put ollama-cloud first — 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 as delegation.fallback_providers > parent inheritance. Key absent/null → inherit parent _fallback_chain; [] → no child fallback; malformed → warn + inherit (mirrors reasoning_effort). Normalization reuses hermes_cli.fallback_config.get_fallback_chain().
  • hermes_cli/config_defaults.pydelegation.fallback_providers: None (null sentinel = inherit; no _config_version bump).
  • cli-config.yaml.example + docs — document the key and the three-way semantic.
  • Tests — 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 main with DCO + green local suite. Prior PR had no reported checks; this branch is a clean rebase of that design onto 6e9cae6ac4b.

How to test

scripts/run_tests.sh tests/tools/test_delegate.py tests/tools/test_async_delegation.py

Local result: 89 passed, 0 failed.

Minimal config repro from #65038:

delegation:
  provider: xai-oauth
  model: grok-composer-2.5-fast
  fallback_providers:
    - provider: xai-oauth
      model: grok-composer-2.5-fast

Platforms

  • Windows (native) + git-bash test runner via scripts/run_tests.sh

Interlock

Part of #65038

Part of #80450

@andrexibiza

Copy link
Copy Markdown
Contributor Author

Interlock receipt

Local: 89/89 green on tests/tools/test_delegate.py + tests/tools/test_async_delegation.py.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/delegate Subagent delegation area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades duplicate This issue or pull request already exists labels Aug 6, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Duplicate of #65052, which is the earlier open implementation of the same child fallback-chain resolution.

@andrexibiza

Copy link
Copy Markdown
Contributor Author

ci: force re-trigger — queued run never associated; reopening immediately

andrexibiza and others added 4 commits August 17, 2026 12:01
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>
@andrexibiza
andrexibiza force-pushed the fix/delegation-fallback-providers-65038 branch from 6e5be8c to 2ec23e8 Compare August 17, 2026 17:04
@andrexibiza

Copy link
Copy Markdown
Contributor Author

Rebased onto current origin/main and resolved the conflict that was blocking mergeability.

What changed:

  • Rebased fix/delegation-fallback-providers-65038 onto origin/main (4323c67dcc6).
  • Resolved two merge conflicts in tools/delegate_tool.py and cli-config.yaml.example that had arisen because main already landed the #80450 pinned-provider fallback behavior while this PR adds delegation.fallback_providers.
  • Semantic merge: explicit delegation.fallback_providers (declared child chain, [] disables) now takes precedence; when unset, children inherit the parent chain subject to the #80450 exception (an explicit delegation.provider pin fails loudly rather than silently rerouting onto parent fallback models). Malformed fallback_providers entries log a warning and fall back to parent inheritance, matching the PR's own test contract.
  • Kept the newer child_session_db ownership-transfer pattern from main (the PR branch predated that refactor).
  • Preserved the additive doc comments from both sides in cli-config.yaml.example.

Verification: tests/tools/test_delegate.py + tests/tools/test_async_delegation.py → 98 passed; tests/hermes_cli/test_fallback_config.py → 5 passed; attribution audit clean; git diff --check clean. All commits carry andrexibiza's GitHub noreply identity.

PR is now mergeable; CI is re-running on the new head.

@andrexibiza

Copy link
Copy Markdown
Contributor Author

@ayushnangia retains all credit for this fix. Freshly rebased.

djagya pushed a commit to djagya/hermes-agent that referenced this pull request Aug 26, 2026
…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).
djagya pushed a commit to djagya/hermes-agent that referenced this pull request Aug 26, 2026
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>
ayushnangia added a commit to ayushnangia/hermes-agent that referenced this pull request Aug 28, 2026
…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).
ayushnangia added a commit to ayushnangia/hermes-agent that referenced this pull request Aug 28, 2026
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>
andrexibiza added a commit to andrexibiza/hermes-agent that referenced this pull request Sep 7, 2026
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>
ayushnangia added a commit to ayushnangia/hermes-agent that referenced this pull request Sep 7, 2026
…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).
ayushnangia added a commit to ayushnangia/hermes-agent that referenced this pull request Sep 7, 2026
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>
kshitijk4poor pushed a commit that referenced this pull request Sep 7, 2026
…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).
kshitijk4poor pushed a commit that referenced this pull request Sep 7, 2026
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>
andrexibiza added a commit to andrexibiza/hermes-agent that referenced this pull request Sep 9, 2026
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>
andrexibiza added a commit to andrexibiza/hermes-agent that referenced this pull request Sep 9, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/delegate Subagent delegation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

delegation.fallback_providers is ignored; delegated workers inherit the parent fallback chain

2 participants