You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
The custom agent file declares model: in its YAML frontmatter, and
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){constsessionModel=hp(service.agent.model).model;constresult=Gbr(targetModel,sessionModel,availableModels);if(result!==targetModel)log.info(`Downgrading subagent model from "${targetModel}" to session model "${sessionModel}".`);returnresult;}functionGbr(t,e,r){constsessionMult=r.find(m=>m.id===e)?.multiplier;consttargetMult=r.find(m=>m.id===t)?.multiplier;return(sessionMult!==undefined&&targetMult!==undefined&&OIe(sessionMult,targetMult))
? e// downgrade to session model
: t;// honor requested model}functionOIe(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:
Create ~/.copilot/agents/parent.agent.md with frontmatter:
---
tools: ["agent", "task"]model: gpt-5.4description: "Parent agent pinned to a cheaper model."
---
Create ~/.copilot/agents/expensive.agent.md with frontmatter:
---
tools: ["read", "execute"]model: gpt-5.5description: "Specialist that wants gpt-5.5."
---
Repro:
Start the CLI: copilot --agent=parent.
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."
)
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:
Preferred: honor the explicitly requested model. Frontmatter and explicit overrides are intentional configuration, not a default to be silently overridden.
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").
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.
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:
model:in its YAML frontmatter, and"model": "<id>"field in thetasktool 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 (vialist_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 frontmattermodel: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)So
OIereturns true (→ clamp) whenever the requested subagent model costs more than the session model by more than thefgafactor. The behavior itself may be intentional cost protection, but its silent, log-only surfacing is the bug.Affected version
Also observed under the same code path in 1.0.54.
Steps to reproduce the behavior
Setup:
~/.copilot/agents/parent.agent.mdwith frontmatter:~/.copilot/agents/expensive.agent.mdwith frontmatter:Repro:
copilot --agent=parent.list_agents/read_agent(agent_id="repro").Observed:
list_agentsandread_agentboth reportmodel: gpt-5.4for the spawned agent, despite:model: gpt-5.5, and"model": "gpt-5.5".~/.copilot/logs/process-<pid>.logcontains a line like:If the parent's
model:is bumped togpt-5.5(or the CLI is launched with--model gpt-5.5), the downgrade stops and the specialist runs ongpt-5.5as 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
modelin thetasktool payload, one of the following should happen:tasktool result so the calling agent can react (e.g. retry, abort, inform the user), andlist_agents/read_agentoutput, with a field indicating the requested vs. effective model and the reason for the difference (e.g."model_override_reason": "multiplier_guard").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
taskdispatches.gpt-5.5background dispatch path after the guard has letgpt-5.5through, 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: