Skip to content

Task tool silently downgrades subagent model to session model via multiplier guard (frontmatter and explicit model override both ignored) #3565

Description

@ReefProctor

Describe the bug

The Task tool silently downgrades a subagent's requested model to the parent session's model whenever the requested model has a higher cost multiplier than the session model. The downgrade happens both when:

  1. The custom agent file declares model: in its YAML frontmatter, and
  2. The caller passes an explicit "model": "<id>" field in the task tool payload.

Neither path produces a user-visible warning. The only signal is a [INFO] Downgrading subagent model from "<target>" to session model "<session>". line buried in ~/.copilot/logs/process-<pid>.log. Worse, the surfaced metadata for the resulting background agent (via list_agents / read_agent) reports the downgraded model as if it were the one selected, so the orchestrating agent has no reliable way to detect that its model choice was overridden.

Practical impact: a multi-agent setup where a routing/interface agent is pinned to a cheaper model (e.g. gpt-5.4) cannot escalate any individual specialist to a more expensive model (e.g. gpt-5.5, claude-opus-4.7) — every specialist gets clamped back to the routing agent's model. The frontmatter model: field becomes effectively a no-op for any subagent dispatched from a lower-tier parent.

Root cause (from decompiled ~/.cache/copilot/pkg/linux-x64/1.0.55/app.js)

// Task tool, on every subagent spawn:
enforceMultiplierGuard(targetModel) {
  const sessionModel = hp(service.agent.model).model;
  const result = Gbr(targetModel, sessionModel, availableModels);
  if (result !== targetModel)
    log.info(`Downgrading subagent model from "${targetModel}" to session model "${sessionModel}".`);
  return result;
}

function Gbr(t, e, r) {
  const sessionMult = r.find(m => m.id === e)?.multiplier;
  const targetMult  = r.find(m => m.id === t)?.multiplier;
  return (sessionMult !== undefined && targetMult !== undefined && OIe(sessionMult, targetMult))
    ? e   // downgrade to session model
    : t;  // honor requested model
}

function OIe(sessionMult, targetMult) {
  return (sessionMult === 0 && targetMult > 0) || targetMult > sessionMult * fga;
}

So OIe returns true (→ clamp) whenever the requested subagent model costs more than the session model by more than the fga factor. The behavior itself may be intentional cost protection, but its silent, log-only surfacing is the bug.

Affected version

GitHub Copilot CLI 1.0.55.

Also observed under the same code path in 1.0.54.

Steps to reproduce the behavior

Setup:

  1. Create ~/.copilot/agents/parent.agent.md with frontmatter:
    ---
    tools: ["agent", "task"]
    model: gpt-5.4
    description: "Parent agent pinned to a cheaper model."
    ---
  2. Create ~/.copilot/agents/expensive.agent.md with frontmatter:
    ---
    tools: ["read", "execute"]
    model: gpt-5.5
    description: "Specialist that wants gpt-5.5."
    ---

Repro:

  1. Start the CLI: copilot --agent=parent.
  2. From the parent agent, dispatch the specialist with an explicit model override:
    task(
      agent_type="expensive",
      mode="background",
      model="gpt-5.5",
      name="repro",
      prompt="Report which model you are running on."
    )
    
  3. Inspect the agent: list_agents / read_agent(agent_id="repro").

Observed:

  • list_agents and read_agent both report model: gpt-5.4 for the spawned agent, despite:
    • the agent file declaring model: gpt-5.5, and
    • the call site passing "model": "gpt-5.5".
  • ~/.copilot/logs/process-<pid>.log contains a line like:
    [INFO] Downgrading subagent model from "gpt-5.5" to session model "gpt-5.4".
    
  • No warning is surfaced to the orchestrating agent or to the user via the CLI UI / tool result.

If the parent's model: is bumped to gpt-5.5 (or the CLI is launched with --model gpt-5.5), the downgrade stops and the specialist runs on gpt-5.5 as requested. This confirms the clamp is a function of the session model, not of the spawn payload.

Expected behavior

When a subagent declares a model in its agent file frontmatter, or when a caller passes an explicit model in the task tool payload, one of the following should happen:

  1. Preferred: honor the explicitly requested model. Frontmatter and explicit overrides are intentional configuration, not a default to be silently overridden.
  2. If the downgrade is intentional cost protection, surface it visibly:
    • return it in the task tool result so the calling agent can react (e.g. retry, abort, inform the user), and
    • reflect the actually-selected model — not the requested one — in list_agents / read_agent output, with a field indicating the requested vs. effective model and the reason for the difference (e.g. "model_override_reason": "multiplier_guard").
  3. Provide a documented opt-out (env var, CLI flag, or per-agent frontmatter field like allow_higher_cost_subagents: true) for users who knowingly want to escalate a specialist above the parent's tier.

At minimum, the silent log-only behavior is a footgun: agent authors cannot tell that their model: declarations are being ignored.

Additional context

  • OS: Linux (Fedora 41, 6.x kernel), x86_64.
  • Shell: zsh.
  • Reproduces with both background and sync task dispatches.
  • Not the same as Background sub-agent silently hangs at total_turns=0 when model="gpt-5.5" #3547 (which reports a runtime hang on the gpt-5.5 background dispatch path after the guard has let gpt-5.5 through, i.e. when the session model is already high-multiplier). In this issue the guard fires and the agent runs to completion normally — just on the wrong model.

Relevant log line to grep for when reproducing:

grep -F "Downgrading subagent model" ~/.copilot/logs/process-*.log

Activity

  1. added
    area:agentsSub-agents, fleet, autopilot, plan mode, background agents, and custom agents
    area:modelsModel selection, availability, switching, rate limits, and model-specific behavior
    on May 28, 2026
  2. added theissue type on May 28, 2026
  3. ReefProctor commented on Aug 13, 2026

    @ReefProctor
    Author

    unknown when this was resolved but is no longer a issue as of GitHub Copilot CLI 1.0.79.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:agentsSub-agents, fleet, autopilot, plan mode, background agents, and custom agentsarea:modelsModel selection, availability, switching, rate limits, and model-specific behavior

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions