Summary
Codewhale cannot run a sub-agent on a different model per task. The model-facing agent tool advertises only the 8 built-in roles and, absent a profile, the child inherits the parent's model. There is no supported way for the main agent to say "run this sub-task on the free model" or "run the critic on the strong model", and user-authored role profiles are invisible to the model.
In 0.9.9 (#5324) the agent tool schema was intentionally slimmed from 33 to 12 advertised fields; the routing overrides model, model_strength, and thinking were removed from the advertised surface. They are still parsed and honored when a caller sends them (parse_spawn_request reads model/model_strength/thinking; parse_optional_subagent_model feeds resolve_spawn_model_selection), but because they are absent from the schema and description, the model never learns they exist — so per-task model selection is effectively unusable.
Current behavior
agent(action=roster) returns only the 8 built-in roles and states: "There are no saved members: every spawn resolves a role only."
- User agent profiles (
~/.codewhale/agents/*.toml, workspace .codewhale/agents/, saved Fleet members) are not listed to the model. Passing profile=<user id> fails with "Unknown Fleet role/profile … Fleet profiles are roles" (resolve_spawn_role requires a built-in FleetRole).
- A sub-agent inherits the parent's model, or uses a global
[subagents] <role>_model default. A per-call model is validated against the parent's provider (normalize_requested_subagent_model(…, runtime.client.api_provider())), so requesting a model from a different provider is rejected.
- The only "cheaper sibling" today is
model_strength: "faster" (same provider family), not an arbitrary cheaper model.
- Modes (Plan / Work / Operate) are permission postures, not model selectors, so they offer no per-mode model either.
Desired behavior
- Per-task role/model choice visible to the model. Either re-advertise
model/model_strength/thinking on the agent surface, or expose user profiles as selectable rows, so the main agent can pick the appropriate model/role per spawn instead of being limited to one global default.
- Cost-aware selection. When profiles are listed, include enough for a deliberate choice:
provider, model, and a cost class (free / paid / unknown), derived from route pricing metadata or an optional profile field. Example roster row: bug-hunter · openrouter · minimax/minimax-m3:free · class=free. The model could then use the free profile for wide bug-scanning and a paid/strong profile when a hard critic is needed.
- Unchanged safety: a child never widens the parent's authority; containment clamps stay as-is.
Proposed (maintainer's choice)
- Minimal: re-add
model/model_strength/thinking to the advertised agent schema and description (the fields already parse and are honored), so the parent model can request a per-spawn model on its own provider.
- Fuller:
action=roster also lists user profiles (id, base role, provider, model, cost class); profile=<name> resolves user profiles as well as built-in roles; cost class comes from pricing metadata or an explicit (new) profile field.
- Cross-provider support is a separate question; if not added, requests for a foreign-provider model should keep failing with a clear message rather than silently inheriting.
Acceptance criteria
- A user with two profiles (e.g.
bug-hunter on a free model, critic on a paid model) can tell the main agent "spawn bug-hunter for this scan, critic for the review", and the agent selects the intended profile/model per spawn.
action=roster (or equivalent) shows the model which roles/profiles exist and which are free vs paid.
- Per-spawn model/thinking overrides on the parent's provider work when the model sends them; a different-provider model is rejected with a clear error.
- Authority/containment behavior is unchanged.
Environment
- codewhale
0.9.12 (dev), Linux, tmux.
Summary
Codewhale cannot run a sub-agent on a different model per task. The model-facing
agenttool advertises only the 8 built-in roles and, absent a profile, the child inherits the parent's model. There is no supported way for the main agent to say "run this sub-task on the free model" or "run the critic on the strong model", and user-authored role profiles are invisible to the model.In 0.9.9 (#5324) the
agenttool schema was intentionally slimmed from 33 to 12 advertised fields; the routing overridesmodel,model_strength, andthinkingwere removed from the advertised surface. They are still parsed and honored when a caller sends them (parse_spawn_requestreadsmodel/model_strength/thinking;parse_optional_subagent_modelfeedsresolve_spawn_model_selection), but because they are absent from the schema and description, the model never learns they exist — so per-task model selection is effectively unusable.Current behavior
agent(action=roster)returns only the 8 built-in roles and states: "There are no saved members: every spawn resolves a role only."~/.codewhale/agents/*.toml, workspace.codewhale/agents/, saved Fleet members) are not listed to the model. Passingprofile=<user id>fails with "Unknown Fleet role/profile … Fleet profiles are roles" (resolve_spawn_rolerequires a built-inFleetRole).[subagents] <role>_modeldefault. A per-callmodelis validated against the parent's provider (normalize_requested_subagent_model(…, runtime.client.api_provider())), so requesting a model from a different provider is rejected.model_strength: "faster"(same provider family), not an arbitrary cheaper model.Desired behavior
model/model_strength/thinkingon theagentsurface, or expose user profiles as selectable rows, so the main agent can pick the appropriate model/role per spawn instead of being limited to one global default.provider,model, and a cost class (free/paid/unknown), derived from route pricing metadata or an optional profile field. Example roster row:bug-hunter · openrouter · minimax/minimax-m3:free · class=free. The model could then use the free profile for wide bug-scanning and a paid/strong profile when a hard critic is needed.Proposed (maintainer's choice)
model/model_strength/thinkingto the advertisedagentschema and description (the fields already parse and are honored), so the parent model can request a per-spawn model on its own provider.action=rosteralso lists user profiles (id, base role, provider, model, cost class);profile=<name>resolves user profiles as well as built-in roles; cost class comes from pricing metadata or an explicit (new) profile field.Acceptance criteria
bug-hunteron a free model,criticon a paid model) can tell the main agent "spawn bug-hunter for this scan, critic for the review", and the agent selects the intended profile/model per spawn.action=roster(or equivalent) shows the model which roles/profiles exist and which are free vs paid.Environment
0.9.12 (dev), Linux, tmux.