delegate_task per-call model and provider overrides

NousResearch/hermes-agent · cluster 609 · agent

Data as of

5 open items. Fix merged in #7360. Check it covers your case.

The short answer

4open issues
1open PR
105items grouped
Known?
Yes. 105 related items grouped here, 56 issues already closed.
Fix event
A fix was merged to main in PR #7360. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this partially resolved, deciding PRs #16894, #41730. That is separate from the fix event.
Still open
4 issues and 1 PR.

These issues and PRs concern adding per-call model, provider, and profile override parameters to the delegate_task tool, along with fixes for bugs where delegation ignores configuration and subagents inherit the parent model or incorrect credentials instead of the intended settings.

Open issues4

  • Issue#4928Feature: add named delegation capability profiles for subagents
  • Issue#41889Feature Request: Cross-profile subagent support in delegate_task
  • Issue#51540delegation.model ignored for opencode-go provider
  • Issue#67699feature request: delegate_task should pass env vars or accept a profile parameter

Open PRs1

  • PR#58337fix(delegate): keep child credential pools provider-scoped

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #7360 fix(delegate): salvage delegate PRs #6933 #6881

    merged to main

    files: run_agent.py, tests/run_agent/test_agent_guardrails.py, tests/tools/test_delegate.py, tools/delegate_tool.py

  • #16894 fix(delegate): clear acp_command when override_provider is set

    merged to main

    files: tools/delegate_tool.py

  • #19744 fix(delegation): clear parent OpenRouter filters when delegation.provider override is set

    merged to main

    files: tests/tools/test_delegate.py, tools/delegate_tool.py

    Show the diff
    • tests/tools/test_delegate.py
      @@ -980,6 +980,48 @@ def test_cross_provider_delegation(self, mock_creds, mock_cfg):
                   self.assertNotEqual(kwargs["base_url"], parent.base_url)
                   self.assertNotEqual(kwargs["api_key"], parent.api_key)
       
      +    @patch("tools.delegate_tool._load_config")
      +    @patch("tools.delegate_tool._resolve_delegation_credentials")
      +    def test_provider_override_clears_parent_openrouter_filters(
      +        self, mock_creds, mock_cfg
      +    ):
      +        """Delegated provider should not inherit parent provider-preference filters."""
      +        mock_cfg.return_value = {
      +            "max_iterations": 45,
      +            "model": "google/gemini-3-flash-preview",
      +            "provider": "openrouter",
      +        }
      +        mock_creds.return_value = {
      +            "model": "google/gemini-3-flash-preview",
      +            "provider": "openrouter",
      +            "base_url": "https://openrouter.ai/api/v1",
      +            "api_key": "sk-or-key",
      +            "api_mode": "chat_completions",
      +        }
      +        parent = _make_mock_parent(depth=0)
      +        parent.providers_allowed = ["anthropic/claude-3.5-sonnet"]
      +        parent.providers_ignored = ["openai/gpt-4o-mini"]
      +        parent.providers_order = ["google/gemini-2.5-pro"]
      +        parent.provider_sort = "price"
      +
      +        with patch("run_agent.AIAgent") as MockAgent:
      +            mock_child = MagicMock()
      +            mock_child.run_conversation.return_value = {
      +                "final_response": "done",
      +                "completed": True,
      +                "api_calls": 1,
      +            }
      +            MockAgent.return_value = mock_child
      +
      +            delegate_task(goal="Cross-provider test", parent_agent=parent)
      +
      +            _, kwargs = MockAgent.call_args
      +            self.assertEqual(kwargs["provider"], "openrouter")
      +            self.assertIsNone(kwargs["providers_allowed"])
      +            self.assertIsNone(kwargs["providers_ignored"])
      +            self.assertIsNone(kwargs["providers_order"])
      +            self.assertIsNone(kwargs["provider_sort"])
      +
           @patch("tools.delegate_tool._load_config")
           @patch("tools.delegate_tool._resolve_delegation_credentials")
           def test_direct_endpoint_credentials_reach_child_agent(self, mock_creds, mock_cfg):
    • tools/delegate_tool.py
      @@ -1032,6 +1032,23 @@ def _child_thinking(text: str) -> None:
           # fallback_model parameter (which handles both list and dict forms).
           parent_fallback = getattr(parent_agent, "_fallback_chain", None) or None
       
      +    # Inherit the parent's OpenRouter provider-preference filters by default
      +    # (so subagents routed to the same provider honour the same routing
      +    # constraints).  BUT: when `delegation.provider` is set the user is
      +    # explicitly asking the child to run on a different provider, and
      +    # parent-level OpenRouter filters (e.g. `only=["Anthropic"]`) would
      +    # silently force the child back onto the parent's provider. Clear the
      +    # filters in that case so the delegated provider is honoured.
      +    child_providers_allowed = getattr(parent_agent, "providers_allowed", None)
      +    child_providers_ignored = getattr(parent_agent, "providers_ignored", None)
      +    child_providers_order = getattr(parent_agent, "providers_order", None)
      +    child_provider_sort = getattr(parent_agent, "provider_sort", None)
      +    if override_provider:
      +        child_providers_allowed = None
      +        child_providers_ignored = None
      +        child_providers_order = None
      +        child_provider_sort = None
      +
           child = AIAgent(
               base_url=effective_base_url,
               api_key=[redacted:secret-assignment]
      @@ -1056,10 +1073,10 @@ def _child_thinking(text: str) -> None:
               thinking_callback=child_thinking_cb,
               session_db=getattr(parent_agent, "_session_db", None),
               parent_session_id=getattr(parent_agent, "session_id", None),
      -        providers_allowed=parent_agent.providers_allowed,
      -        providers_ignored=parent_agent.providers_ignored,
      -        providers_order=parent_agent.providers_order,
      -        provider_sort=parent_agent.provider_sort,
      +        providers_allowed=child_providers_allowed,
      +        providers_ignored=child_providers_ignored,
      +        providers_order=child_providers_order,
      +        provider_sort=child_provider_sort,
               tool_progress_callback=child_progress_cb,
               iteration_budget=None,  # fresh budget per subagent
           )
  • #41730 fix(delegate): resolve custom-endpoint subagent pools by endpoint identity

    merged to main

    files: agent/credential_pool.py, tests/tools/test_delegate.py, tools/delegate_tool.py

    Show the diff
    • agent/credential_pool.py
      @@ -374,7 +374,7 @@ def _iter_custom_providers(config: Optional[dict] = None):
               yield _normalize_custom_pool_name(name), entry
       
       
      -def get_custom_provider_pool_key(base_url: str, provider_name: Optional[str] = None) -> Optional[str]:
      +def get_custom_provider_pool_key(base_url: Optional[str], provider_name: Optional[str] = None) -> Optional[str]:
           """Look up the custom_providers list in config.yaml and return 'custom:<name>' for a matching base_url.
       
           When provider_name is given, prefer matching by name first (solving the case where
    • tests/tools/test_delegate.py
      @@ -1518,6 +1518,73 @@ def test_different_provider_load_failure_returns_none(self):
       
               self.assertIsNone(result)
       
      +    # --- Custom-endpoint identity resolution (issue #7833) ---
      +
      +    def test_custom_different_endpoint_does_not_inherit_parent_pool(self):
      +        """A child on custom endpoint B must not inherit the parent's custom
      +        endpoint A pool just because both normalize to provider='custom'."""
      +        parent = _make_mock_parent()
      +        parent.provider = "custom"
      +        parent.base_url = "https://endpoint-a.example.com/v1"
      +        parent._credential_pool = [redacted:secret-assignment]"parent_custom_a_pool")
      +
      +        child_pool = MagicMock(name="endpoint_b_pool")
      +        child_pool.has_credentials.return_value = True
      +
      +        def fake_key(base_url, provider_name=None):
      +            return {
      +                "https://endpoint-a.example.com/v1": "custom:endpoint-a",
      +                "https://endpoint-b.example.com/v1": "custom:endpoint-b",
      +            }.get(base_url)
      +
      +        with patch("agent.credential_pool.get_custom_provider_pool_key", side_effect=fake_key), \
      +             patch("agent.credential_pool.load_pool", return_value=child_pool) as load_mock:
      +            result = _resolve_child_credential_pool(
      +                "custom", parent, "https://endpoint-b.example.com/v1"
      +            )
      +
      +        # Loaded the child's OWN endpoint pool, not the parent's.
      +        load_mock.assert_called_once_with("custom:endpoint-b")
      +        self.assertIs(result, child_pool)
      +        self.assertIsNot(result, parent._credential_pool)
      +
      +    def test_custom_same_endpoint_shares_parent_pool(self):
      +        """A child on the SAME custom endpoint as the parent reuses the parent's
      +        pool so rotation/cooldown state stays synchronized."""
      +        parent = _make_mock_parent()
      +        parent.provider = "custom"
      +        parent.base_url = "https://endpoint-a.example.com/v1"
      +        parent._credential_pool = [redacted:secret-assignment]"parent_custom_a_pool")
      +
      +        with patch(
      +            "agent.credential_pool.get_custom_provider_pool_key",
      +            return_value="custom:endpoint-a",
      +        ):
      +            result = _resolve_child_credential_pool(
      +                "custom", parent, "https://endpoint-a.example.com/v1"
      +            )
      +
      +        self.assertIs(result, parent._credential_pool)
      +
      +    def test_custom_unregistered_endpoint_returns_none(self):
      +        """A raw delegation.base_url with no matching custom_providers entry
      +        must NOT inherit the parent's pool — return None so the child keeps its
      +        fixed delegated credential."""
      +        parent = _make_mock_parent()
      +        parent.provider = "custom"
      +        parent.base_url = "https://endpoint-a.example.com/v1"
      +        parent._credential_pool = [redacted:secret-assignment]"parent_custom_a_pool")
      +
      +        with patch(
      +            "agent.credential_pool.get_custom_provider_pool_key",
      +            return_value=None,
      +        ):
      +            result = _resolve_child_credential_pool(
      +                "custom", parent, "https://raw-unregistered.example.com/v1"
      +            )
      +
      +        self.assertIsNone(result)
      +
           def test_build_child_agent_assigns_parent_pool_when_shared(self):
               parent = _make_mock_parent()
               mock_pool = MagicMock()
    • tools/delegate_tool.py
      @@ -1184,7 +1184,9 @@ def _child_thinking(text: str) -> None:
       
           # Share a credential pool with the child when possible so subagents can
           # rotate credentials on rate limits instead of getting pinned to one key.
      -    child_pool = _resolve_child_credential_pool(effective_provider, parent_agent)
      +    child_pool = _resolve_child_credential_pool(
      +        effective_provider, parent_agent, effective_base_url
      +    )
           if child_pool is not None:
               child._credential_pool = [redacted:secret-assignment]
       
      @@ -2368,7 +2370,11 @@ def delegate_task(
           )
       
       
      -def _resolve_child_credential_pool(effective_provider: Optional[str], parent_agent):
      +def _resolve_child_credential_pool(
      +    effective_provider: Optional[str],
      +    parent_agent,
      +    effective_base_url: Optional[str] = None,
      +):
           """Resolve a credential pool for the child agent.
       
           Rules:
      @@ -2377,12 +2383,60 @@ def _resolve_child_credential_pool(effective_provider: Optional[str], parent_age
           2. Different provider -> try to load that provider's own pool.
           3. No pool available -> return None and let the child keep the inherited
              fixed credential behavior.
      +
      +    Custom endpoints are a special case: every direct ``delegation.base_url``
      +    runtime collapses to ``provider="custom"``, so bare provider equality would
      +    treat two *different* custom endpoints as interchangeable and let the child
      +    inherit the parent's pool. Leasing from that pool then overwrites the
      +    child's delegated ``base_url`` with the parent's endpoint (issue #7833).
      +    We therefore resolve custom runtimes by endpoint identity (the
      +    ``custom:<name>`` pool key derived from the base_url) and only share the
      +    parent's pool when both resolve to the *same* custom endpoint.
           """
           if not effective_provider:
               return getattr(parent_agent, "_credential_pool", None)
       
           parent_provider = getattr(parent_agent, "provider", None) or ""
           parent_pool = getattr(parent_agent, "_credential_pool", None)
      +
      +    # Custom endpoints: distinguish by endpoint identity, not the bare "custom"
      +    # provider string. Two custom runtimes are only interchangeable when they
      +    # resolve to the same custom:<name> pool key.
      +    if effective_provider == "custom":
      +        try:
      +            from agent.credential_pool import get_custom_provider_pool_key, load_pool
      +
      +            child_key = get_custom_provider_pool_key(effective_base_url)
      +            if child_key is None:
      +                # Unregistered endpoint (raw delegation.base_url with no
      +                # matching custom_providers entry) -> no shared pool exists.
      +                # Keep the child's fixed delegated credential rather than
      +                # risk inheriting the parent's custom endpoint.
      +                return None
      +
      +            # Reuse the parent's pool only when it is the same custom endpoint.
      +            parent_key = get_custom_provider_pool_key(
      +                getattr(parent_agent, "base_url", None)
      +            )
      +            if (
      +                parent_pool is not None
      +                and parent_provider == "custom"
      +                and parent_key is not None
      +                and parent_key == child_key
      +            ):
      +                return parent_pool
      +
      +            pool = load_pool(child_key)
      +            if pool is not None and pool.has_credentials():
      +                return pool
      +        except Exception as exc:
      +            logger.debug(
      +                "Could not resolve custom credential pool for child endpoint '%s': %s",
      +                effective_base_url,
      +                exc,
      +            )
      +        return None
      +
           if parent_pool is not None and effective_provider == parent_provider:
               return parent_pool
       
  • #60577 fix(delegation): make active config authoritative for delegation limits

    merged to main

    files: tests/tools/test_delegate.py, tools/delegate_tool.py

    Show the diff
    • tests/tools/test_delegate.py
      @@ -13,6 +13,7 @@
       import os
       import threading
       import time
      +import types
       import unittest
       from unittest.mock import MagicMock, patch
       
      @@ -21,6 +22,7 @@
           DELEGATE_TASK_SCHEMA,
           DelegateEvent,
           _get_max_concurrent_children,
      +    _load_config,
           _LEGACY_EVENT_MAP,
           MAX_DEPTH,
           check_delegate_requirements,
      @@ -2390,6 +2392,71 @@ def test_progress_callback_task_progress_not_misrendered(self):
       class TestConcurrencyDefaults(unittest.TestCase):
           """Tests for the concurrency default and no hard ceiling."""
       
      +    def test_load_config_prefers_active_persistent_config_over_cli_defaults(self):
      +        stale_cli = types.ModuleType("cli")
      +        stale_cli.CLI_CONFIG = {
      +            "delegation": {
      +                "max_iterations": 45,
      +                "model": "",
      +                "provider": "",
      +                "base_url": "",
      +                "api_key": "",
      +            }
      +        }
      +        active_config = {
      +            "delegation": {
      +                "max_iterations": 50,
      +                "max_concurrent_children": 50,
      +                "max_spawn_depth": 10,
      +            }
      +        }
      +
      +        with patch.dict("sys.modules", {"cli": stale_cli}):
      +            with patch(
      +                "hermes_cli.config.load_config_readonly", return_value=active_config
      +            ):
      +                self.assertEqual(_load_config()["max_concurrent_children"], 50)
      +                self.assertEqual(_get_max_concurrent_children(), 50)
      +
      +    def test_load_config_falls_back_to_cli_config_when_persistent_load_fails(self):
      +        fallback_cli = types.ModuleType("cli")
      +        fallback_cli.CLI_CONFIG = {
      +            "delegation": {
      +                "max_iterations": 45,
      +                "max_concurrent_children": 8,
      +            }
      +        }
      +
      +        with patch.dict("sys.modules", {"cli": fallback_cli}):
      +            with patch(
      +                "hermes_cli.config.load_config_readonly",
      +                side_effect=RuntimeError("boom"),
      +            ):
      +                self.assertEqual(_load_config()["max_concurrent_children"], 8)
      +
      +    def test_load_config_prefers_cli_config_when_user_config_ignored(self):
      +        # `hermes chat --ignore-user-config` sets HERMES_IGNORE_USER_CONFIG=1,
      +        # which only load_cli_config() honors. The delegation loader must keep
      +        # CLI_CONFIG authoritative under the flag so user config.yaml
      +        # delegation keys stay suppressed.
      +        ignoring_cli = types.ModuleType("cli")
      +        ignoring_cli.CLI_CONFIG = {
      +            "delegation": {
      +                "max_iterations": 45,
      +                "max_concurrent_children": 4,
      +            }
      +        }
      +        user_config = {"delegation": {"max_concurrent_children": 50}}
      +
      +        with patch.dict("sys.modules", {"cli": ignoring_cli}):
      +            with patch.dict(os.environ, {"HERMES_IGNORE_USER_CONFIG": "1"}):
      +                with patch(
      +                    "hermes_cli.config.load_config_readonly",
      +                    return_value=user_config,
      +                ) as mock_loader:
      +                    self.assertEqual(_load_config()["max_concurrent_children"], 4)
      +                    mock_loader.assert_not_called()
      +
           @patch("tools.delegate_tool._load_config", return_value={})
           def test_default_is_three(self, mock_cfg):
               # Clear env var if set
    • tools/delegate_tool.py
      @@ -3098,26 +3098,40 @@ def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict:
       
       
       def _load_config() -> dict:
      -    """Load delegation config from CLI_CONFIG or persistent config.
      -
      -    Checks the runtime config (cli.py CLI_CONFIG) first, then falls back
      -    to the persistent config (hermes_cli/config.py load_config()) so that
      -    ``delegation.model`` / ``delegation.provider`` are picked up regardless
      -    of the entry point (CLI, gateway, cron).
      +    """Load delegation config from the active Hermes config.
      +
      +    Prefer the shared persistent loader because it follows the active
      +    HERMES_HOME/profile. ``cli.CLI_CONFIG`` is a legacy fallback for entry
      +    points that cannot import the shared loader; importing it first can return
      +    an old default ``delegation`` block and hide user-set keys such as
      +    ``max_concurrent_children``.
      +
      +    Uses ``load_config_readonly()``: every consumer of this dict is read-only
      +    (``.get()`` lookups), and this runs on each ``get_definitions()`` schema
      +    rebuild via ``_get_max_concurrent_children``, so skipping the defensive
      +    deepcopy matters. Do NOT mutate the returned dict.
      +
      +    ``HERMES_IGNORE_USER_CONFIG=1`` (``hermes chat --ignore-user-config``) is
      +    only honored by the legacy ``cli`` loader, not the shared one, so when the
      +    flag is set we keep ``cli.CLI_CONFIG`` authoritative to preserve the
      +    flag's contract of suppressing user config.yaml settings.
           """
      +    prefer_legacy = os.environ.get("HERMES_IGNORE_USER_CONFIG") == "1"
      +    if not prefer_legacy:
      +        try:
      +            from hermes_cli.config import load_config_readonly
      +
      +            full = load_config_readonly()
      +            cfg = full.get("delegation") or {}
      +            if isinstance(cfg, dict):
      +                return cfg
      +        except Exception:
      +            pass
           try:
               from cli import CLI_CONFIG
       
               cfg = CLI_CONFIG.get("delegation") or {}
      -        if cfg:
      -            return cfg
      -    except Exception:
      -        pass
      -    try:
      -        from hermes_cli.config import load_config
      -
      -        full = load_config()
      -        return full.get("delegation") or {}
      +        return cfg if isinstance(cfg, dict) else {}
           except Exception:
               return {}
       

39 PRs closed without merging

From the close comments: done elsewhere 10 · duplicate 7 · merged via another change 3 · stale or abandoned 3 · superseded by another PR 3 · closed without comment 2 · won't fix / by design 1 · other 10

  • #791 feat: allow configurable subagent model in config.yaml (#609) · done elsewhere
  • #3734 feat: per-call model/provider override on delegate_task · closed without comment
  • #4929 feat(delegation): add named subagent capability profiles · other → ba0bc01, #5583, #44412, #64213, #4928
  • #6933 fix(delegate): sync self.base_url with client_kwargs after credential resolution · merged via another change → #7360
  • #9255 feat(delegate): add task-tier profiles with per-task reasoning_effort and pool validation · stale or abandoned
Show 34 more
  • #9737 feat(delegate): automatic tier routing + task-tier profiles with per-task reasoning_effort · stale or abandoned
  • #10996 feat(tools): add model parameter to delegate_task for per-task model selection · other → #9737
  • #12053 fix(delegate): read fresh config.yaml so delegation.model edits take effect (#11999) · stale or abandoned
  • #12105 fix(delegation): _load_config falls through to hermes_cli config when CLI_CONFIG has no delegation overrides (#11999) · done elsewhere → #11999
  • #16329 fix(delegation): honor delegated provider routing for subagents · merged via another change → #19744
  • #16503 fix(delegate): detect /anthropic URL suffix for proxy endpoints (#7833) · superseded by another PR → #13567
  • #16839 fix(delegate): clear acp_command when override_provider is set · merged via another change → #16894
  • #17581 Fix delegate_task model/provider precedence and expose per-task overrides · other → a6f08ff, #10995
  • #17718 fix: honor per-task model override in delegate_task · other
  • #23769 fix(delegation): accept per-call model override on delegate_task · duplicate → #23649
  • #25026 feat(delegate): per-task model and provider override for delegate_task subagents · duplicate → #3172, #16163, #17756, #15789, #14974
  • #26486 fix(delegation): honor provider overrides for subagents · closed without comment
  • #34369 fix(delegate): detect credential/endpoint mismatch before sending request (#34318, #34334) · done elsewhere → #34318, #34334
  • #34773 feat(delegate): per-task model/provider override in delegate_task tasks array · duplicate → #14974, #17756, #20000, #23266, #32555, #34752, #34764, #15789
  • #34776 feat(phase34754): Centralized Model Complexity Configuration · duplicate → #34752, #34727, #10995, #13663
  • #35033 feat(delegate): per-task model/provider overrides (+ fix two latent delegation bugs) · duplicate → #14974, #25530, #23649, #17756
  • #36790 feat(delegate): add per-task model/provider routing · won't fix / by design
  • #37578 feat: add model/provider override param to delegate_task tool · other
  • #39282 feat(delegate_task): add per-task model/provider override · done elsewhere
  • #41826 feat(delegation): add per-task model override for delegate_task · duplicate → #6771, #14974, #15789, #12794, #16163
  • #41865 fix(delegate): honor model parameter end-to-end (fixes #41821, closes #41814) · other → #41814, #53846
  • #43134 feat(delegate_tool): per-task model/provider override · superseded by another PR → #43185
  • #43185 fix(delegate_tool): address PR #43134 multi-provider review feedback · other
  • #50015 feat(delegate_task): per-call model/provider overrides · duplicate → #6771, #15789, #47014, #47295, #46880, #32711, #6306, #23769, #12715, #12794, #12503, #7586
  • #51368 fix(delegate): preserve named custom provider overrides · other
  • #51650 fix(delegation): fix opencode-go subagents ignoring delegation.model config · done elsewhere → 9ae1fa9, #51540
  • #53240 fix(delegation): resolve custom:* provider base_url from config instead of falling through to parent (Fixes #53064) · other → #53064
  • #55175 fix(delegation): resolve api_key from provider env when base_url + provider set · done elsewhere → efc1c2d
  • #55478 fix(delegate): merge persistent + runtime delegation config sources · done elsewhere → #60577, #59982
  • #59670 fix(tools): respect config model in delegate_task subagent spawn (#58298) · done elsewhere → 0263f1d, #58298
  • #61258 fix(delegation): prevent credential pool from overriding explicit delegation.base_url · done elsewhere → f2c11ff, #61195
  • #61275 fix(delegate): keep delegation.base_url authoritative against credential-pool rotation · done elsewhere → f2c11ff
  • #64299 feat(delegate): per-call and per-task model/provider overrides for delegate_task · superseded by another PR → #63461
  • #72834 feat: add per-call model/provider override to delegate_task · other
Closed issues · 56
  • Closed#609Allow configurable subagent model in config.yaml
  • Closed#3719Feature: Per-call model/provider override on delegate_task
  • Closed#5012[Feature]: Allow delegate_task to accept provider/model parameters
  • Closed#6306Feature: Allow per-task model selection in delegate_task
  • Closed#6825Bug: delegation.base_url correctly resolved but overwritten before first API call
  • Closed#7833delegate_task can overwrite delegated custom endpoint with parent custom credential pool
  • Closed#9712delegate_task(acp_command=...) silently ignored under Anthropic parent
  • Closed#10653[Bug]: delegation config doesn`t work
  • Closed#10995feat: delegate_task should support per-task model selection
  • Closed#11999delegate_task ignores subagent model config — always inherits parent model
  • Closed#14974[Feature]: delegation-per-task-endpoint-overrides
  • Closed#15789feat: per-task model/provider overrides in delegate_task
  • Closed#16816[Bug]: Add delegation.acp_command: none config option
  • Closed#17685delegate_task: per-task model override is silently ignored — children always use parent's model
  • Closed#17732Feature: per-call model/provider override in delegate_task
  • Closed#18591Feature: Per-task model override for delegate_task subagents
  • Closed#19567TUI delegation subagent incorrectly routed to copilot-acp instead of configured deepseek provider
  • Closed#23467delegate_task model parameter silently discarded — subagents always inherit parent model
  • Closed#24263Feature: Per-sub-agent provider/model selection in delegate_task
  • Closed#26482delegation model override ignored — subagents always inherit parent provider/model
  • Closed#27294[Bug] delegate_task ignores delegation.base_url — subagent always inherits parent model
  • Closed#27295[Bug] delegate_task ignores delegation.base_url — subagent always inherits parent model
  • Closed#27296[Bug] delegate_task ignores delegation.base_url — subagent always inherits parent model
  • Closed#31155delegation.model override ignored — subagents always inherit parent model
  • Closed#32711delegate_task() lacks model and provider parameters — prevents per-call subagent routing
  • Closed#34318delegate_task sends API key to wrong provider endpoint (OpenRouter key → OpenAI)
  • Closed#34334Optimization: Correct API key routing for delegate_task
  • Closed#34462[TASK] Implement Per-Call Provider and Model Overrides for delegate_task
  • Closed#34489Per-Task Model Override in delegate_task
  • Closed#34727[FEATURE] Task Delegation + Intelligent Model Selection (Phases 7 & 3)
  • Closed#34764feat(delegate): per-task model/provider override in delegate_task tasks array
  • Closed#35409Add profile/model override parameter to delegate_task
  • Closed#35437feat: add model/provider/base_url/api_format parameters to delegate_task (consolidating #5012, #10995, #17685, #23467, #32711)
  • Closed#37574feat: add model/provider override param to delegate_task tool
  • Closed#41814Feature: Per-task model override for delegate_task
  • Closed#44900feat(delegation): add model override to delegate_task
  • Closed#46295Feature Request: Add subagent configuration to Model page with provider selection
  • Closed#47014Feature Request: Per-call model override for delegate_task
  • Closed#47295feat: per-call model routing in delegate_task (multi-model delegation)
  • Closed#49332delegate_task model override ignored — subagents use wrong model, consume unauthorized credits
  • Closed#50202[Feature]: per-call model/provider override for delegate_task (multi-model subagent orchestration)
  • Closed#51303Custom providers not recognized by delegate_task delegation system
  • Closed#51401Feature Request: Per-Task Model Override in delegate_task
  • Closed#52331[Feature]: Per-call model routing for delegate_task subagents
  • Closed#53064delegation.provider=custom:* resolves wrong base_url (inherits parent provider base_url)
  • Closed#53846delegate_task model parameter not honored — child agents always inherit parent session model
  • Closed#55380Bug: delegate_task ignores delegation config — hardcoded to xiaomi
  • Closed#56891Feature: Expose model parameter on delegate_task for per-call model selection
  • Closed#58298Subagent delegation ignores config, always uses credential-pool model (glm-4-flash)
  • Closed#58731Feature Request: Per-subagent model override in delegate_task
  • Closed#61195[Bug]: delegation.base_url correctly resolved through init_agent() but subagent's actual API call still routes to OpenRouter → 401
  • Closed#61622feat: support per-subagent model selection in delegate_task
  • Closed#62443delegate_task subagent always resolves to Groq/llama-3.3-70b-versatile (401) regardless of delegation config
  • Closed#62731Feature Request: Allow delegate_task to use different models per subtask
  • Closed#66536[Feature]: Per-call model/provider override for delegate_task
  • Closed#66819Feature request: Role-based subagents — inherit profile identity (SOUL.md + skills + tools)
How this cluster was grouped
  • Link evidence (partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
  • Members outside that structural core may belong to a different underlying problem.
  • Pairwise link density 0.03: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#7360, #16894, #19744, #41730, #60577
Closed issues
56
Attempts
39 PRs closed without merging
Fix link checked
8 Jul 2026

For your agent

The same facts, typed.