Skip to content

fix(delegate): read fresh config.yaml so delegation.model edits take effect (#11999)#12053

Closed
briandevans wants to merge 2 commits into
NousResearch:mainfrom
briandevans:fix/delegate-task-model-override
Closed

fix(delegate): read fresh config.yaml so delegation.model edits take effect (#11999)#12053
briandevans wants to merge 2 commits into
NousResearch:mainfrom
briandevans:fix/delegate-task-model-override

Conversation

@briandevans

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes #11999.

delegate_task silently ignored delegation.model / delegation.provider overrides in ~/.hermes/config.yaml — subagents kept running on the parent's model regardless of what the user configured, defeating the whole point of cost-tiered delegation (Sonnet subagents under an Opus parent, say). The reporter's exact scenario:

delegation:
  model: claude-sonnet-4-20250514
  provider: anthropic

Parent on claude-opus-4-6. Expected: child runs on Sonnet. Actual: child runs on Opus; result metadata confirms "model": "claude-opus-4-6". Reporter also observed "persists across /reset commands and config reloads" — an important symptom that points at the actual root cause.

Root cause

tools/delegate_tool.py::_load_config() short-circuited through cli.CLI_CONFIG, a dict populated once at module-import time:

def _load_config() -> dict:
    try:
        from cli import CLI_CONFIG
        cfg = CLI_CONFIG.get("delegation", {})
        if cfg:
            return cfg       # <-- returns stale CACHED value
    except Exception:
        pass
    try:
        from hermes_cli.config import load_config
        full = load_config()
        return full.get("delegation", {})    # <-- fresh read (never reached on CLI)
    except Exception:
        return {}

Two independent bugs in this short-circuit:

  1. Cache staleness. CLI_CONFIG is built by cli.load_cli_config() at module import and is never re-read. An edit to ~/.hermes/config.yaml after the CLI starts — including adding a new delegation: section — is invisible to delegate_task. /reset and config-reload commands don't re-run load_cli_config, which is exactly the reporter's "persists across /reset" symptom.

  2. Truthy-but-empty defaults always win. cli.py populates CLI_CONFIG["delegation"] with built-in defaults ({"max_iterations": 45, "default_toolsets": [...], "model": "", "provider": "", "base_url": "", "api_key": ""}) even when the user's config.yaml has no delegation section at all. That's a truthy dict (non-empty), so if cfg: return cfg fires and the persistent hermes_cli.config.load_config() path is never reached. Downstream, configured_model = str(cfg.get("model") or "").strip() or None resolves to None, _resolve_delegation_credentials sets provider: None (inherit-from-parent), and _build_child_agent does effective_model = model or parent_agent.model → the parent model wins.

Reproduced in a minimal sandbox:

At CLI startup, CLI_CONFIG['delegation'] = {'model': '', 'provider': '', ...}
After user edits config.yaml, delegation.model is claude-sonnet-4-20250514
_load_config() returned: {'model': '', 'provider': '', ...}
BUG REPRODUCED: _load_config returned stale model=''

Fix

Drop the stale CLI_CONFIG short-circuit. Always read fresh via hermes_cli.config.load_config():

def _load_config() -> dict:
    try:
        from hermes_cli.config import load_config
        full = load_config()
        delegation = full.get("delegation", {})
        return delegation if isinstance(delegation, dict) else {}
    except Exception:
        return {}

Also hardens against a malformed delegation: not-a-dict value — the old code returned the non-dict verbatim, which then crashed _resolve_delegation_credentials on .get("model"). Coerce to {} so callers safely fall back to inherit-from-parent defaults.

Precedence / compat table

Scenario Before After
Edit delegation.model after CLI startup silently ignored (stale CLI_CONFIG) picked up on next delegate_task
Gateway / cron (cli.py not imported) already read fresh (fallback path) read fresh (unchanged)
Startup with no delegation: section stale CLI_CONFIG defaults returned → inherit-from-parent fresh load_config() returns DEFAULT_CONFIG delegation → inherit-from-parent (same result)
delegation.model: "" explicitly inherit-from-parent inherit-from-parent (unchanged)
delegation: not-a-dict (malformed) non-dict leaks to .get() → AttributeError coerced to {} → inherit-from-parent
Runtime mutation of CLI_CONFIG["delegation"] picked up n/a (grep-verified: nothing in the codebase mutates this at runtime)

Narrow scope — explicitly not changed

  • _resolve_delegation_credentials — downstream of _load_config, already correct given a fresh config dict. No change needed.
  • _build_child_agent / AIAgent.__init__ — same; the bug is purely at the config-read layer.
  • cli.CLI_CONFIG — left as-is. Grep confirms no runtime writer to CLI_CONFIG["delegation"] anywhere, so dropping its use in _load_config loses no runtime-only data.
  • Performanceload_config() is a single YAML parse plus copy.deepcopy(DEFAULT_CONFIG), measured <1 ms. delegate_task is called at most once per user turn; the cost is negligible.

Pre-empt reviewer Q&A

Q: Why not just re-populate CLI_CONFIG on file-change or /reset?
That would solve this bug but introduces a much larger invariant to maintain (every mutation point of every config section would have to either poll or be hooked). Reading fresh per-call is simpler, has a localized fix, and matches how gateway/cron already operate — so we're unifying instead of diverging further.

Q: Could this regress any path that relied on CLI_CONFIG's import-time snapshot?
Grepped every reader of CLI_CONFIG["delegation"] — only tools/delegate_tool.py::_load_config(). Nothing else reads this section, nothing writes to it at runtime.

Q: load_config() calls ensure_hermes_home(). Side-effect concerns like #11983?
For delegate_task specifically: ensure_hermes_home() creates ~/.hermes subdirs and seeds SOUL.md if they don't exist. This is idempotent after first call. delegate_task is only invoked from an AIAgent tool-dispatch loop where the parent agent has already initialized ~/.hermes (it couldn't have gotten to tool-dispatch otherwise). So the side-effect is a confirmed no-op in this call context. Additionally, the pre-fix fallback path (which fires in gateway/cron) already used load_config(), so this side effect was already part of the function's behaviour on the only paths that mattered.

Q: Why coerce non-dict delegation to {} instead of raising?
_load_config is best-effort at all other exit points (catches any exception → {}). Keeping that contract means callers don't have to learn a new failure mode — they still fall through to inherit-from-parent. A warning-log could be nice follow-up but the behavioural contract is maintained.

Regression coverage

tests/tools/test_delegate.py gets TestLoadConfigFreshReads (5 tests):

  1. test_ignores_stale_cli_config_cache — plants a stale cli module with empty-default CLI_CONFIG in sys.modules, writes an override to config.yaml, asserts _load_config() returns the override. Fails on origin/main with the exact reporter symptom: AssertionError: '' != 'claude-sonnet-4-20250514'.
  2. test_picks_up_delegation_override_written_after_startup — end-user scenario: edit config.yaml, call _load_config, get the edit.
  3. test_non_dict_delegation_section_is_coerced_to_empty — hardens .get() callers downstream; also fails on origin/main (old code returned the non-dict string verbatim).
  4. test_returns_dict_when_config_missing_delegation_section — pins graceful handling when delegation: isn't configured at all.
  5. test_end_to_end_resolve_uses_fresh_config — integration through _resolve_delegation_credentials all the way to effective_model = creds["model"] or parent.model.

How to test

  1. Focused suite:

    source venv/bin/activate
    python -m pytest tests/tools/test_delegate.py tests/tools/test_delegate_toolset_scope.py -q
    

    77 passed (72 pre-existing + 5 new).

  2. Verify the regression is caught on origin/main:

    git stash push tools/delegate_tool.py
    python -m pytest tests/tools/test_delegate.py::TestLoadConfigFreshReads -v
    

    → 2 fail (test_ignores_stale_cli_config_cache, test_non_dict_delegation_section_is_coerced_to_empty). Restore with git stash pop.

  3. Manual repro (the sandbox script above), before & after.

  4. CI-aligned broad suite:

    python -m pytest tests/ -q --ignore=tests/integration --ignore=tests/e2e --tb=line -n auto
    

    → 12824 passed, 39 skipped, 15 pre-existing baseline failures (dingtalk ×N, matrix, wsl ×2, approve_deny ×2, file_staleness ×2, local_interrupt_cleanup, plus a couple of known flakes in tools/). All reproduce on clean origin/main; none in tools/delegate_tool.py or tests/tools/test_delegate.py.

Tested on: macOS 15 (Darwin 25.5.0), Python 3.11.15.

Related Issue

Fixes #11999

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • tools/delegate_tool.py: rewrite _load_config to always read fresh from hermes_cli.config.load_config(); add defensive dict-coercion against malformed config values.
  • tests/tools/test_delegate.py: add TestLoadConfigFreshReads — 5 regression tests (2 fail cleanly on origin/main).

Adjacent surfaces checked

  • _resolve_delegation_credentials — downstream; verified correct given fresh config. Unchanged.
  • _build_child_agent — receives creds["model"]; verified it correctly wins over parent_agent.model when present. Unchanged.
  • AIAgent.__init__ model resolution (run_agent.py:708, :772) — preserves user-supplied model. Unchanged.
  • All four preserve_dots=self._anthropic_preserve_dots() call sites — unrelated. Unchanged.
  • cli.CLI_CONFIG writers — grep-confirmed none for delegation. No data loss from dropping the short-circuit.

Checklist

Code

  • I've read the Contributing Guide
  • Commit messages follow Conventional Commits (fix(scope):)
  • Searched for existing PRs — none on delegate_task ignores subagent model config — always inherits parent model #11999
  • Only changes related to this fix
  • Ran the CI-aligned test command and classified failures baseline-vs-change
  • Added tests for my changes (5 new; 2 fail on origin/main without the fix)
  • Tested on macOS 15 (Darwin 25.5.0), Python 3.11.15

Documentation & Housekeeping

  • No docs changes needed — config-read internals, no public API surface
  • No config-key changes — existing delegation.model / delegation.provider keys behave as their docstrings already promised
  • No architecture/workflow changes
  • Cross-platform impact: none — pure Python, no OS-specific paths
  • No tool descriptions/schemas touched

Notes for reviewers

  • No standalone lint command is defined; CI runs python -m pytest tests/ -q --ignore=tests/integration --ignore=tests/e2e --tb=short -n auto (matches .github/workflows/tests.yml).
  • No hermes_cli/** changes — the Nix workflow should not trigger.

…effect (NousResearch#11999)

``tools.delegate_tool._load_config`` short-circuited through
``cli.CLI_CONFIG``, a dict that's populated **once** at module-import
time and is never re-read.  In long-lived CLI sessions this meant
``delegation.model`` / ``delegation.provider`` edits to
``~/.hermes/config.yaml`` after startup were silently ignored —
subagents kept running on the parent's model regardless of the user's
override, defeating the entire point of cost-tiered delegation
(Sonnet subagents under an Opus parent, say).

The reporter's exact scenario (NousResearch#11999): set

    delegation:
      model: claude-sonnet-4-20250514
      provider: anthropic

in config.yaml, run the parent on ``claude-opus-4-6``, call
``delegate_task`` — the child reports ``claude-opus-4-6`` and the
result metadata confirms ``"model": "claude-opus-4-6"``.

Root cause
----------
The short-circuit at the top of ``_load_config``:

    try:
        from cli import CLI_CONFIG
        cfg = CLI_CONFIG.get("delegation", {})
        if cfg:
            return cfg

misfires in two ways:

1. ``CLI_CONFIG`` is a module-level dict built by
   ``cli.load_cli_config()`` at import time.  Subsequent edits to
   ``config.yaml`` (including adding a new ``delegation:`` section) are
   never picked up by that process.  ``/reset`` and config-reload
   commands don't re-run ``load_cli_config``, which matches the
   reporter's observation that the bug "persists across /reset commands
   and config reloads".

2. The ``if cfg:`` check always fires because cli.py's delegation
   defaults already populate a truthy dict
   (``{"max_iterations": 45, "default_toolsets": [...], "model": "",
   "provider": "", "base_url": "", "api_key": ""}``) even when the user
   hasn't set any override.  That truthy-but-empty dict bypasses the
   persistent ``hermes_cli.config.load_config()`` path entirely, so
   ``configured_model = str(cfg.get("model") or "").strip() or None``
   resolves to ``None`` and ``_build_child_agent`` falls back to
   ``parent_agent.model``.

Fix
---
Drop the stale ``CLI_CONFIG`` short-circuit and always read fresh via
``hermes_cli.config.load_config()``.  That's the path gateway and cron
code already use, so unifying everyone on it also removes a subtle
CLI-only divergence.  Performance cost is a single YAML parse + deep-
copy of ``DEFAULT_CONFIG``, <1 ms in practice — and ``delegate_task``
is invoked at most once per user turn.

Also harden the function so a malformed
``delegation: not-a-dict`` value coerces to ``{}`` instead of
leaking a non-dict through to ``_resolve_delegation_credentials``
(which calls ``.get()`` on it).

Narrow scope — explicitly not changed
-------------------------------------
* ``_resolve_delegation_credentials`` — downstream of
  ``_load_config``.  Verified correct given a fresh config dict; no
  changes needed.
* ``_build_child_agent`` / ``AIAgent.__init__`` — same.
* ``cli.CLI_CONFIG`` — leave as-is.  Nothing else in the codebase
  writes to ``CLI_CONFIG["delegation"]`` at runtime (grep-verified),
  so dropping its use in ``_load_config`` loses no runtime-only data.

Regression coverage
-------------------
``tests/tools/test_delegate.py`` gets a new
``TestLoadConfigFreshReads`` class with 5 tests:

* ``test_ignores_stale_cli_config_cache`` — plants a stale CLI_CONFIG
  with empty-default delegation in ``sys.modules["cli"]`` and asserts
  ``_load_config()`` still reads the fresh user override from
  ``config.yaml``.  On unpatched ``origin/main`` this fails with the
  exact reporter symptom:
  ``AssertionError: '' != 'claude-sonnet-4-20250514'``.
* ``test_picks_up_delegation_override_written_after_startup`` —
  end-user scenario: edit config.yaml, call _load_config, get the
  edit.
* ``test_non_dict_delegation_section_is_coerced_to_empty`` — hardens
  ``.get()`` callers downstream; also fails on ``origin/main`` (the
  old code returned the non-dict string verbatim).
* ``test_returns_dict_when_config_missing_delegation_section`` —
  pins graceful handling when no delegation section is configured.
* ``test_end_to_end_resolve_uses_fresh_config`` — integration through
  ``_resolve_delegation_credentials`` confirming the config flows all
  the way to ``effective_model = creds["model"] or parent.model``.

Validation
----------
``source venv/bin/activate && python -m pytest
tests/tools/test_delegate.py tests/tools/test_delegate_toolset_scope.py
-q`` -> 77 passed.

CI-aligned broad suite: ``python -m pytest tests/ -q
--ignore=tests/integration --ignore=tests/e2e --tb=line -n auto``
-> 12824 passed, 39 skipped, 15 pre-existing baseline failures (all
reproduce on clean ``origin/main``; none in ``tools/delegate_tool.py``
or ``tests/tools/test_delegate.py``).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 18, 2026 07:44

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

Fixes delegation config staleness so delegate_task picks up delegation.model / delegation.provider edits from ~/.hermes/config.yaml during long-lived CLI sessions.

Changes:

  • Remove the cli.CLI_CONFIG short-circuit and always read delegation config via hermes_cli.config.load_config().
  • Harden _load_config() against malformed non-dict delegation: values by coercing to {}.
  • Add regression tests covering fresh reads, stale CLI cache behavior, and malformed delegation sections.

Reviewed changes

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

File Description
tools/delegate_tool.py Always loads delegation config fresh from disk and type-checks the delegation section.
tests/tools/test_delegate.py Adds regression tests for #11999 covering config freshness and malformed config handling.

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

Comment thread tools/delegate_tool.py Outdated
Comment on lines +1047 to +1048
the built-in defaults (empty-string ``model``/``provider`` and a
``max_iterations`` float): those produced a truthy-but-empty dict

Copilot AI Apr 18, 2026

Copy link

Choose a reason for hiding this comment

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

The docstring claims the defaults include a "max_iterations" float, but DEFAULT_CONFIG defines delegation.max_iterations as an int (e.g., hermes_cli/config.py:676). This is misleading documentation—please update the wording/type to match the actual config schema.

Suggested change
the built-in defaults (empty-string ``model``/``provider`` and a
``max_iterations`` float): those produced a truthy-but-empty dict
the built-in defaults (empty-string ``model``/``provider`` and an
integer ``max_iterations``): those produced a truthy-but-empty dict

Copilot uses AI. Check for mistakes.
Comment thread tests/tools/test_delegate.py Outdated
Comment on lines +1481 to +1514
prev_home = os.environ.get("HERMES_HOME")
prev_key = os.environ.get("ANTHROPIC_API_KEY")
os.environ["HERMES_HOME"] = hhome
os.environ.setdefault("ANTHROPIC_API_KEY", "sk-test")
try:
# User adds override
with open(os.path.join(hhome, "config.yaml"), "w") as fh:
import yaml as _yaml
_yaml.safe_dump({
"model": "claude-opus-4-6",
"delegation": {
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
},
}, fh)
cfg = _load_config()
creds = _resolve_delegation_credentials(cfg, parent)
self.assertEqual(creds["model"], "claude-sonnet-4-20250514")
# and ``_build_child_agent`` will later do:
# effective_model = creds["model"] or parent.model
# which must now land on the delegation model, not parent's.
effective = creds["model"] or parent.model
self.assertEqual(effective, "claude-sonnet-4-20250514")
finally:
if prev_home is None:
os.environ.pop("HERMES_HOME", None)
else:
os.environ["HERMES_HOME"] = prev_home
if prev_key is None:
os.environ.pop("ANTHROPIC_API_KEY", None)
else:
os.environ["ANTHROPIC_API_KEY"] = prev_key


Copilot AI Apr 18, 2026

Copy link

Choose a reason for hiding this comment

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

test_end_to_end_resolve_uses_fresh_config currently depends on real provider resolution (_resolve_delegation_credentials -> hermes_cli.runtime_provider.resolve_runtime_provider) and uses os.environ.setdefault("ANTHROPIC_API_KEY", ...), which won’t override an existing-but-empty value. This makes the test environment-dependent/flaky. Consider patching hermes_cli.runtime_provider.resolve_runtime_provider (or agent.anthropic_adapter.resolve_anthropic_token) to return a fixed credential bundle, and/or force-set ANTHROPIC_API_KEY within a patch.dict so the test is hermetic.

Suggested change
prev_home = os.environ.get("HERMES_HOME")
prev_key = os.environ.get("ANTHROPIC_API_KEY")
os.environ["HERMES_HOME"] = hhome
os.environ.setdefault("ANTHROPIC_API_KEY", "sk-test")
try:
# User adds override
with open(os.path.join(hhome, "config.yaml"), "w") as fh:
import yaml as _yaml
_yaml.safe_dump({
"model": "claude-opus-4-6",
"delegation": {
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
},
}, fh)
cfg = _load_config()
creds = _resolve_delegation_credentials(cfg, parent)
self.assertEqual(creds["model"], "claude-sonnet-4-20250514")
# and ``_build_child_agent`` will later do:
# effective_model = creds["model"] or parent.model
# which must now land on the delegation model, not parent's.
effective = creds["model"] or parent.model
self.assertEqual(effective, "claude-sonnet-4-20250514")
finally:
if prev_home is None:
os.environ.pop("HERMES_HOME", None)
else:
os.environ["HERMES_HOME"] = prev_home
if prev_key is None:
os.environ.pop("ANTHROPIC_API_KEY", None)
else:
os.environ["ANTHROPIC_API_KEY"] = prev_key
with patch.dict(
os.environ,
{"HERMES_HOME": hhome, "ANTHROPIC_API_KEY": "sk-test"},
clear=False,
):
# Ensure credential lookup is deterministic and does not
# depend on any real provider/token resolution in the test
# environment.
with patch(
"agent.anthropic_adapter.resolve_anthropic_token",
return_value="sk-test",
):
# User adds override
with open(os.path.join(hhome, "config.yaml"), "w") as fh:
import yaml as _yaml
_yaml.safe_dump({
"model": "claude-opus-4-6",
"delegation": {
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
},
}, fh)
cfg = _load_config()
creds = _resolve_delegation_credentials(cfg, parent)
self.assertEqual(creds["model"], "claude-sonnet-4-20250514")
# and ``_build_child_agent`` will later do:
# effective_model = creds["model"] or parent.model
# which must now land on the delegation model, not parent's.
effective = creds["model"] or parent.model
self.assertEqual(effective, "claude-sonnet-4-20250514")

Copilot uses AI. Check for mistakes.
…d-to-end test

Addresses both Copilot inline review points on PR NousResearch#12053:

1. Docstring typo fix.  The docstring said ``max_iterations`` was a
   ``float`` in the built-in defaults.  It's an ``int`` —
   ``DEFAULT_CONFIG["delegation"]["max_iterations"] = 50``.  Reworded
   the sentence and dropped the misleading type qualifier.

2. ``test_end_to_end_resolve_uses_fresh_config`` no longer depends on
   real provider resolution.  Replaced the ad-hoc
   ``os.environ.setdefault("ANTHROPIC_API_KEY", ...)`` (which doesn't
   override an existing empty value and still calls into the real
   ``resolve_runtime_provider`` pipeline) with:

   * ``patch.dict(os.environ, ...)`` to force-set
     ``ANTHROPIC_API_KEY`` and ``HERMES_HOME`` atomically inside the
     block, and
   * ``patch(hermes_cli.runtime_provider.resolve_runtime_provider)``
     returning a fixed credential bundle, so the test is hermetic
     and its outcome only depends on the code path under test —
     ``_load_config`` → ``_resolve_delegation_credentials`` →
     ``effective_model`` selection.

Validation: ``source venv/bin/activate && python -m pytest
tests/tools/test_delegate.py::TestLoadConfigFreshReads -q`` -> 5 passed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@briandevans

Copy link
Copy Markdown
Contributor Author

Addressed both Copilot review points in a7bb79c4:

1. Docstring type fix — reworded the sentence so the description of the built-in-defaults dict no longer labels max_iterations as a float. It's an int (DEFAULT_CONFIG["delegation"]["max_iterations"] = 50 in hermes_cli/config.py:676).

2. End-to-end test hermeticity — replaced the environment-dependent os.environ.setdefault("ANTHROPIC_API_KEY", "sk-test") + real resolve_runtime_provider() call with:

  • patch.dict(os.environ, {"HERMES_HOME": …, "ANTHROPIC_API_KEY": "sk-test"}, clear=False) so the env vars are force-set (not just set-if-missing) for the duration of the test, and
  • patch("hermes_cli.runtime_provider.resolve_runtime_provider", return_value={…fixed bundle…}) so the test outcome depends only on the code path under test (_load_config_resolve_delegation_credentialseffective_model), not on whatever auth state happens to be resident in the runtime-provider pipeline.

Validation: python -m pytest tests/tools/test_delegate.py::TestLoadConfigFreshReads -q → 5 passed.

The unrelated test CI failure in the previous run (tests/tools/test_accretion_caps.py::TestReadTrackerCaps::test_live_cap_applied_after_read_add - KeyError: 'read_timestamps') is a baseline flake — passes in isolation both on this branch and on clean origin/main:

$ python -m pytest tests/tools/test_accretion_caps.py::TestReadTrackerCaps::test_live_cap_applied_after_read_add -v
1 passed in 10.56s

That test exercises tools/file_tools.py read-tracker bookkeeping under concurrent state mutations and is unrelated to this PR's tools/delegate_tool.py change.

asphyksia pushed a commit to asphyksia/hermes-agent that referenced this pull request Apr 20, 2026
…xplicit provider

When a subagent is configured with a custom base_url but no explicit
provider, it should use 'custom' as the provider rather than inheriting
the parent's provider. This fixes credential resolution for subagents
using custom endpoints like NVIDIA NIM.

Also fixes _load_config() to always read fresh from config.yaml instead
of using the stale CLI_CONFIG cache. This ensures delegation config
changes are picked up without restarting the CLI.

Fixes subagent credential resolution when using custom base_url without
explicit provider (complements PR NousResearch#12053).
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists tool/delegate Subagent delegation comp/agent Core agent loop, run_agent.py, prompt builder area/config Config system, migrations, profiles labels Apr 24, 2026
@briandevans

Copy link
Copy Markdown
Contributor Author

Closing to keep the queue clean — happy to reopen if this is still useful.

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 loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists tool/delegate Subagent delegation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

delegate_task ignores subagent model config — always inherits parent model

3 participants