Skip to content

feat(delegation): per-child fallback chain via delegation.fallback_providers - #81072

Open
devatnull wants to merge 3 commits into
NousResearch:mainfrom
devatnull:feat/delegation-fallback-providers
Open

feat(delegation): per-child fallback chain via delegation.fallback_providers#81072
devatnull wants to merge 3 commits into
NousResearch:mainfrom
devatnull:feat/delegation-fallback-providers

Conversation

@devatnull

Copy link
Copy Markdown
Contributor

What

Subagents currently inherit the parent's fallback_providers chain with no way to override it. This PR adds delegation.fallback_providers to config.yaml, supporting three modes:

Value Behavior
Not set / "inherit" Child inherits parent's fallback_providers (default, backward compatible)
[] No fallback — child fails on primary model error
[{provider, model}, ...] Custom per-child chain

Why

When running multiple providers with different cost/quota profiles, you often want subagents to fail over to cheaper models than the primary conversation. For example:

# Primary conversation fallbacks to expensive models
fallback_providers:
  - provider: zai
    model: glm-5.2
  - provider: xai-oauth
    model: grok-4.5

# Subagents fall back to cheaper models
delegation:
  model: gpt-5.6-luna
  provider: openai-codex
  fallback_providers:
    - provider: zai
      model: glm-5.2
    - provider: opencode-go
      model: deepseek-v4-flash

How

The resolution reuses the existing _iter_fallback_entries parser from hermes_cli/fallback_config.py — same entry shape, same dedup logic.

Resolution order in _build_child_agent:

  1. Read delegation.fallback_providers from config
  2. If "inherit" or "parent" → use parent's _fallback_chain
  3. If []None (no fallback)
  4. If [{...}] → parse and use custom chain
  5. If not set at all → inherit parent (backward compatible)

Files changed

  • tools/delegate_tool.py — three-mode fallback resolution + tool description update
  • hermes_cli/config_defaults.py — new fallback_providers key in delegation section
  • website/docs/user-guide/features/delegation.md — new Fallback Chain subsection + Key Properties bullet
  • tests/tools/test_delegate_fallback_providers.py — 5 tests covering all three modes + parent string alias

Testing

tests.tools.test_delegate_fallback_providers — 5/5 pass
tests.tools.test_delegate.TestFallbackModelInheritance — 2/2 pass (no regression)
tests.hermes_cli.test_fallback_config — all pass

Pre-existing failure test_child_inherits_runtime_credentials is unrelated (fails on clean main — credential masking assertion).

Backward compatibility

When delegation.fallback_providers is absent from config, behavior is identical to before — child inherits parent's _fallback_chain.

…oviders

Subagents currently inherit the parent's fallback_providers chain with
no way to override it. This adds three modes for
delegation.fallback_providers in config.yaml:

  Not set / inherit  → child inherits parent's fallback_providers (default)
  []                   → no fallback; child fails on primary error
  [{provider, model}]  → custom per-child chain

Use case: route subagent failures to cheaper providers (e.g. GLM-5.2 →
DeepSeek V4 Flash) while keeping the primary conversation on a more
expensive chain (e.g. Grok 4.5 → GLM-5.2).

The resolution reuses the existing _iter_fallback_entries parser from
hermes_cli/fallback_config.py — same entry shape, same dedup logic.

Changes:
- tools/delegate_tool.py: resolve child fallback chain before building
  child agent; three-mode dispatch (inherit / none / custom)
- hermes_cli/config_defaults.py: add fallback_providers key to
  delegation section with inline docs
- website/docs/user-guide/features/delegation.md: new Fallback Chain
  subsection + Key Properties bullet
- tests/tools/test_delegate_fallback_providers.py: 5 tests covering
  all three modes + parent string alias

Backward compatible: when delegation.fallback_providers is absent,
behavior is identical to before (inherits parent chain).
Copilot AI lite review requested due to automatic review settings August 7, 2026 13:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for configuring a separate fallback provider/model chain for delegated subagents via delegation.fallback_providers, so subagent failover behavior can differ from the parent conversation while reusing the existing fallback parsing/dedup logic.

Changes:

  • Adds child fallback-chain resolution in delegate_task child-agent construction.
  • Documents the new delegation.fallback_providers behavior and examples.
  • Adds tests intended to cover inherit/none/custom modes for child fallback chains.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
tools/delegate_tool.py Implements per-child fallback-chain resolution and updates tool description text.
hermes_cli/config_defaults.py Adds a delegation.fallback_providers default/config documentation entry.
website/docs/user-guide/features/delegation.md Documents the new fallback-chain override behavior for subagents.
tests/tools/test_delegate_fallback_providers.py Adds tests for the new delegation fallback-chain configuration modes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/delegate_tool.py Outdated
Comment on lines +1581 to +1583
_del_cfg = _load_config()
_del_cfg_root = _del_cfg.get("delegation", {}) if isinstance(_del_cfg, dict) else {}
_del_fb_raw = _del_cfg_root.get("fallback_providers") if isinstance(_del_cfg_root, dict) else None
Comment on lines +39 to +43
@patch("tools.delegate_tool._load_config")
def test_inherit_when_not_set(self, mock_cfg):
"""When delegation.fallback_providers is absent, inherit parent chain."""
mock_cfg.return_value = {"delegation": {}}
parent = self._make_parent_agent(
Comment thread hermes_cli/config_defaults.py Outdated
# [] → no fallback (child fails on primary error)
# [{provider, model}] → custom per-child chain
# Same entry shape as the top-level fallback_providers key.
"fallback_providers": [], # e.g. [{"provider":"zai","model":"glm-5.2"}]
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have tool/delegate Subagent delegation comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 7, 2026
Three issues found by Copilot review:

1. delegate_tool.py: _load_config() returns the delegation sub-dict
   directly, but code did .get('delegation', {}).get('fallback_providers')
   — double-wrapping meant the key was never read. Fixed to read
   .get('fallback_providers') directly.

2. config_defaults.py: fallback_providers: [] in defaults made the key
   always present after merge, which would be interpreted as 'disable
   fallback' — breaking the documented inherit-by-default behavior.
   Removed the default value; key is now absent unless user sets it.

3. Tests: re-implemented resolution logic inline but mocked
   _load_config returning a full config dict (with delegation wrapper)
   instead of the delegation sub-dict directly. Tests now match the
   real return shape. Added two regression tests for both bugs.
hermes config set stores complex values as JSON strings in config.yaml.
_iter_fallback_entries only handled dict/list, not str — so setting
fallback_providers via CLI silently broke the fallback chain (parsed
as empty, no fallback fired on 429/rate-limit).

Add str branch that JSON-parses then recurses. Affects both top-level
fallback_providers and delegation.fallback_providers.
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/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/delegate Subagent delegation type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants