Skip to content

delegate_task: per-task model override is silently ignored — children always use parent's model #17685

@mjwicker

Description

@mjwicker

Bug Description

delegate_task accepts a model field inside each task object (e.g. model: "qwen/qwen-turbo"), but this field is completely ignored — subagents always inherit the parent agent's model. This affects both batch mode (tasks[].model) and there is no top-level model parameter on delegate_task at all.

Severity: Medium (feature gap, not a crash)


Root Cause — Three-layer failure

Layer 1: No model in the tool schema

In tools/delegate_tool.py (lines 2438–2463), the DELEGATE_TASK_SCHEMA task item properties include goal, context, toolsets, acp_command, acp_args, and role. There is no model property anywhere in the schema.

Additionally, the top-level delegate_task() function signature (line 1812) has no model parameter:

def delegate_task(
    goal: Optional[str] = None,
    context: Optional[str] = None,
    toolsets: Optional[List[str]] = None,
    tasks: Optional[List[Dict[str, Any]]] = None,
    max_iterations: Optional[int] = None,
    acp_command: Optional[str] = None,
    acp_args: Optional[List[str]]] = None,
    role: Optional[str] = None,
    parent_agent=None,
) -> str:

Layer 2: Model resolved exclusively from config

In the task loop at line 1950:

child = _build_child_agent(
    ...
    model=creds["model"],   # <-- always from config, never from task
    ...
)

creds comes from _resolve_delegation_credentials(cfg, parent_agent) (line 1890), which reads only from cfg.get("model") — the delegation.model key in config.yaml. There is no code path that reads a per-task model field.

Layer 3: Silent fallback chain

In _build_child_agent at line 982:

effective_model = model or parent_agent.model

Since model is always None (no per-task override is ever extracted), it silently falls back to the parent agent's model. No warning is logged.


Reproduction

Setup: Parent agent using any model (e.g. minimax/m2.7).

Call:

{
  "goal": "Return the model name you are using",
  "tasks": [
    {
      "goal": "Return just the model name you are using",
      "model": "qwen/qwen-turbo"
    }
  ]
}

Expected: Child uses qwen/qwen-turbo
Actual: Child uses minimax/m2.7 (parent's model), silently

The model key in the task dict is accepted without error but completely discarded.


Proposed Fix

1. Add model to task schema properties (tools/delegate_tool.py, around line 2447):

"model": {
    "type": "string",
    "description": "Per-task model override (e.g. 'qwen/qwen-turbo'). "
        "Only used when delegation.provider is set in config.yaml, "
        "or as a shorthand that sets the model without changing provider."
},

2. Extract and pass per-task model (tools/delegate_tool.py, around line 1950):

model=creds["model"] if "model" not in t else t["model"],

3. (Optional ergonomics) Add top-level model param to delegate_task() function signature for single-task mode parity.


Workaround

Set delegation.provider and delegation.model in config.yaml to route all subagents to a specific model. However, this is a global setting — it cannot be changed per-task in the same parent call.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havetool/delegateSubagent delegationtype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions