Skip to content

feat(delegation): add per-task model override for delegate_task - #41826

Closed
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:feat/delegate-task-model-override
Closed

feat(delegation): add per-task model override for delegate_task#41826
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:feat/delegate-task-model-override

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

Problem

delegate_task currently uses a single global model configured via delegation.model / delegation.provider in config.yaml. All delegated subagents run on the same model regardless of task complexity.

This limits a common pattern: using different model tiers for different subtasks — e.g. a smart/expensive model for hard reasoning tasks, a cheap/fast model for mechanical work, and a medium-tier model as the default.

Solution

Add an optional model parameter to delegate_task that overrides the global delegation.* config for that specific invocation. Supports both top-level (applies to all children) and per-task (individual tasks in batch mode) overrides.

Precedence: per-task model > top-level model > delegation.* config

API

# Top-level: all children use this model
delegate_task(
    goal="Analyze this complex codebase architecture",
    model={"provider": "anthropic", "model": "claude-sonnet-4"}
)

# Per-task: different models for different tasks
delegate_task(
    tasks=[
        {"goal": "Complex reasoning task", "model": {"provider": "anthropic", "model": "claude-sonnet-4"}},
        {"goal": "Format 50 files with black", "model": {"provider": "openrouter", "model": "deepseek/deepseek-chat"}},
    ]
)

# Model-only: inherit parent's provider, just swap the model
delegate_task(goal="Quick task", model={"model": "cheap-model"})

Implementation

  • _resolve_model_override() — resolves a model dict into a credential dict (provider, base_url, api_key, api_mode), following the same pattern as cron job model overrides
  • When only model is specified (no provider), the child inherits the parent's provider credentials — the common "use a cheaper model" pattern
  • When provider is specified, full credentials are resolved via the runtime provider system
  • Bare "custom" provider is treated as no provider (inherits parent) — prevents LLM hallucinated custom providers from breaking resolution

Changes

  • tools/delegate_tool.py: +122 lines (new _resolve_model_override helper, schema additions, handler update)
  • tests/tools/test_delegate.py: +207 lines (12 new tests covering schema validation, credential resolution, precedence ordering)

Tests

tests/tools/test_delegate.py::TestModelOverride::test_schema_has_model_top_level PASSED
tests/tools/test_delegate.py::TestModelOverride::test_schema_has_model_per_task PASSED
tests/tools/test_delegate.py::TestModelOverride::test_resolve_model_override_none_returns_none PASSED
tests/tools/test_delegate.py::TestModelOverride::test_resolve_model_override_model_only_inherits_parent_provider PASSED
tests/tools/test_delegate.py::TestModelOverride::test_resolve_model_override_bare_custom_ignored PASSED
tests/tools/test_delegate.py::TestModelOverride::test_resolve_model_override_with_provider_resolves_credentials PASSED
tests/tools/test_delegate.py::TestModelOverride::test_resolve_model_override_provider_no_key_raises PASSED
tests/tools/test_delegate.py::TestModelOverride::test_resolve_model_override_invalid_provider_raises PASSED
tests/tools/test_delegate.py::TestModelOverride::test_top_level_model_override_used_for_child PASSED
tests/tools/test_delegate.py::TestModelOverride::test_per_task_model_overrides_top_level PASSED
tests/tools/test_delegate.py::TestModelOverride::test_no_model_override_uses_delegation_config PASSED
tests/tools/test_delegate.py::TestModelOverride::test_batch_per_task_model_with_provider PASSED

Fixes #41814

Add an optional `model` parameter to `delegate_task` that allows
routing different subagents to different model tiers.  Supports both
top-level (applies to all children) and per-task (overrides for
individual tasks in batch mode) overrides.

Precedence: per-task model > top-level model > delegation.* config.

The `model` parameter follows the same pattern as cron job model
overrides — a dict with optional `provider` and `model` keys.  When
only `model` is set, the child inherits the parent's provider
credentials (common case: use a cheaper model on the same provider).
When `provider` is also set, full credentials are resolved via the
runtime provider system.

Usage examples:
  delegate_task(goal='...', model={'model': 'deepseek/deepseek-chat'})
  delegate_task(tasks=[{'goal': '...', 'model': {'provider': 'anthropic', 'model': 'claude-sonnet-4'}}])

Fixes NousResearch#41814
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have tool/delegate Subagent delegation labels Jun 8, 2026
@yimisunrise

Copy link
Copy Markdown

+1 for this feature. Per-task model/provider override would be very useful for routing different subtasks to different cost/quality tiers. Looking forward to seeing this merged.

FCelestial pushed a commit to FCelestial/FCelestial-hermes-agent that referenced this pull request Jun 11, 2026
…earch#41826)

- Adds _resolve_model_override() for resolving per-task/top-level model config
- Adds 'model' parameter to delegate_task (both top-level and per-task)
- Supports model-only override (inherits parent provider)
- Supports full provider override (resolves via runtime provider)
- Adds 'model' field to delegate_task schema

fix(tools): use \r on Windows PTY submit_stdin (NousResearch#31697 follow-up)
- submit_stdin now sends \r on Windows (Enter key), \n on POSIX
- write_stdin already handles bytes/str conversion per platform
@jarodtaylor

Copy link
Copy Markdown

For the love of God, PLEASE implement this feature!

@creemer

creemer commented Jun 16, 2026

Copy link
Copy Markdown

+1 Please implement it. It will be great!

@dresraz

dresraz commented Jun 17, 2026

Copy link
Copy Markdown

+1 Please implement! would be really useful!

@rigario

rigario commented Jun 19, 2026

Copy link
Copy Markdown

Strong +1 for this PR. Per-task/per-call model overrides are a useful foundation for routing delegated work across cost/quality tiers.

I opened #46981 as a small dependent/additive follow-up that builds on this shape and adds explicit fallback isolation for cost-capped subagents e.g. allowing a cheap child model to avoid silently inheriting an expensive parent fallback chain.

If #41826 lands first, #46981 can be rebased down to just the fallback-isolation delta.

@alt-glitch alt-glitch added the duplicate This issue or pull request already exists label Jun 26, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.
Duplicate of #6771 (earliest open per-task model-override PR). This is part of a heavily saturated cluster (tracking #14974/#15789) with 6+ competing PRs (#6771, #12794, #16163, and others). Marking as duplicate of the earliest canonical open implementation; a maintainer should pick one to land and close the rest.

@teknium1

teknium1 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

We do not want this

@teknium1 teknium1 closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have tool/delegate Subagent delegation type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Per-task model override for delegate_task

8 participants