Ask: Fall back to the parent model when a sub-agent's model fails at call-time
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 52/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- rust, typescript
- Ambito
- ai-infra-agents, backend-api-design
Direzione di ricerca
Inizia da custom_model.rs::resolve_custom_agent_model e agent_tools.rs::validate_and_resolve_subagent_model, quindi traccia il percorso dell'errore al momento della chiamata attraverso sessionExecutor.ts e session.ts. Riproduci il 400 unavailable-model descritto nell'issue ed esamina i dati di ModelCallFailure in session-events.d.ts. Il lavoro è completato quando un sub-agent ritenta una volta con il modello padre dopo un errore unavailable-model e il turno prosegue.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Component: @github/copilot-sdk + copilot-agent-runtime — sub-agent model resolution
Status: Behavior does not match the documented CustomAgentConfig.model contract
Model IDs below are redacted placeholders:
<unavailable-model>= a model in the catalog but not onboarded / no-capacity for the test user;<parent-model>= the (available) parent session model.
1. TL;DR
Ask. When a sub-agent's configured model fails at call-time — i.e. when the runtime issues the actual model request to CAPI (the Copilot model API) — with a model-unavailable 400 (unknown / not onboarded / no capacity), the runtime should fall back to the parent session model and retry that sub-agent's call — instead of letting the sub-agent's model call fail.
Why this is the contract, not a feature request. The SDK already documents this fallback: CustomAgentConfig.model "falling back to the parent session model if unavailable" (types.d.ts:1160-1165). We observe it does not happen at call-time.
One-line evidence. A sub-agent set to <unavailable-model> under a <parent-model> parent → the model is sent to CAPI unchanged → CAPI returns 400 Unknown model "<unavailable-model>" → no retry with the parent model → the sub-agent's call fails.
2. The documented contract
A host application embeds @github/copilot-sdk and dispatches sub-agents via SessionConfig.customAgents: CustomAgentConfig[]. Each sub-agent's model is a string on CustomAgentConfig.model, documented as:
// @github/copilot-sdk/dist/types.d.ts:1160-1165
/**
* Model identifier for this agent (e.g. "claude-haiku-4.5").
* When set, the runtime will attempt to use this model for the agent,
* falling back to the parent session model if unavailable.
*/
model?: string;
Three cases follow; we rely on the third:
model value |
Documented behavior |
|---|---|
| set to a valid model | used for the sub-agent |
omitted / undefined |
sub-agent inherits the parent session model |
| set but unavailable | fall back to the parent session model and continue |
The third row is what fails at call-time.
3. The gap (observed)
For a sub-agent model that is unavailable through the user's CAPI endpoint — e.g. not onboarded or no capacity (<unavailable-model> in our repro) — we observe in the outgoing request and in the event stream:
- The configured model is sent to CAPI unchanged (logged: the sub-agent's first request carries
<unavailable-model>). - CAPI returns
400:Unknown model "<unavailable-model>". Please ensure the model is onboarded. - The runtime emits an ephemeral, telemetry-only
model.call_failure(source=subagent,statusCode=400,model="<unavailable-model>"). - No fallback: no call is re-issued with the parent model. The sub-agent's model call fails.
Confirmed gap: the documented "fall back to the parent session model if unavailable" is not honored for a call-time
400. (Our source-level reading of why is in Appendix §6.3 — hypothesis only.)
4. Evidence
4.1 Setup
- A host embedding
@github/copilot-sdk; a local end-to-end run. - Parent session model:
<parent-model>. - Three sub-agents dispatched via
SessionConfig.customAgents:- A, C →
<unavailable-model>(unavailable → 400) - B →
<parent-model>(available → success)
- A, C →
- All sub-agent event hooks,
model.call_failure, and the model sent on each request are instrumented.
4.2 Event sequence
subagent.started×3 (A, B, C).- First model request per sub-agent: A→
<unavailable-model>, B→<parent-model>, C→<unavailable-model>. model.call_failure×2 (A, C) — ephemeral / telemetry-only:
({ "source": "subagent", "initiator": "sub-agent", "statusCode": 400, "model": "<unavailable-model>", "errorMessage": "...Unknown model \"<unavailable-model>\". Please ensure the model is onboarded.", "agentId": "call_xxx" }agentIdis the Task tool-call ID, not the sub-agent name.)- No parent-model retry follows. The sub-agent's call fails.
4.3 Downstream behavior after the 400 — not confirmed
Our probe covered only background/detached dispatch. We did not verify what happens after the 400 on the normal foreground path, so we make no claim about whether the failure stays isolated to the sub-agent or affects the parent session. Appendix §6.3 records a source-level hypothesis only.
4.4 Why the host cannot recover this itself
model.call_failureisephemeraltelemetry (session-events.d.ts:2821-2887,ephemeral: true); we found no in-turn hook that lets the host intercept the400and retry the sub-agent with another model within the same turn.- Per the SDK types,
customAgentsis applied when a session is created or resumed (types.d.ts—SessionConfigBase.customAgents, inherited byResumeSessionConfig). The host therefore cannot change the model during the failing turn — only after resuming the session, which is too late to recover the first turn. So the fallback must occur inside the runtime.
5. What we're asking
1. Honor the documented fallback at call-time.
When CAPI rejects a sub-agent's CustomAgentConfig.model as unavailable (400), retry that sub-agent's call once with the parent session model, then continue the turn — matching the model? contract.
The runtime can identify this condition from the failure data already present: statusCode plus the provider error / structured badRequestKind (session-events.d.ts:2821-2887). A one-shot fallback scoped to the sub-agent is sufficient.
6. Appendix
6.1 Minimal repro
- Configure a sub-agent with
CustomAgentConfig.model= a model that is in the catalog but not onboarded / no-capacity for the test user (<unavailable-model>; parent<parent-model>). - Dispatch it.
- Observe
model.call_failure (400)with no parent-model retry; the sub-agent's call fails.
6.2 Key references
@github/copilot-sdk/dist/types.d.ts:1160-1165—CustomAgentConfig.modelfallback contract.@github/copilot-sdk/dist/generated/session-events.d.ts:2821-2887—ModelCallFailureEvent/ModelCallFailureData(ephemeral: true,initiator="sub-agent",statusCode,model,errorMessage).- Observed call-time
400:Unknown model "<unavailable-model>". Please ensure the model is onboarded.
6.3 Our runtime-source reading (hypothesis — please verify)
Disclaimer: this is our interpretation of
copilot-agent-runtime, offered only as a starting pointer. We may be reading the wrong path. Please verify. The ask in §5 stands on the observed behavior (§3 / §4) regardless.
On why no fallback fires (§3). Sub-agent model selection appears to run through one of two functions, and both seem to fail open (no fallback) when the host supplies no populated available_models list:
custom_model.rs::resolve_custom_agent_model— emptyavailable_models→ first candidate returned verbatim ("CAPI will validate"), no check, no fallback (:236-260); non-empty + unresolved → falls back to session model (:317-328, the only fallback path we see).agent_tools.rs::validate_and_resolve_subagent_model— empty → model verbatim (:171-173); non-empty + unresolvable →Error, no fallback (:182-190).available_modelsis populated from the CAPI session bootstrap (model/session.rs:19,96;model/capi_client.rs:1587-1628); an embedded host appears not to feed a catalog, which would leave the list empty on our client.- Net (our reading): with an empty list the configured model goes straight to CAPI with no check and no fallback →
400. A populated list may still not fix it — membership is not a capacity check, so an in-list but no-capacity model would still400at call-time. This is why we ask for a call-time fallback (§5).
On the foreground path (§4.3). The source suggests the normal foreground path degrades gracefully: SessionAgentExecutor.run() catches a sub-agent turn error and emits subagent.failed, returning the failure to the parent as a tool result so the turn continues (sessionExecutor.ts:282-286; session.ts:12364-12382). We have not verified this end-to-end.
- Lingua principale
- TypeScript
- Stelle
- 10.5k
- Fork
- 1.5k
- Merge medio
- 1g 7h
- PR unite (30g)
- 98
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di github/copilot-sdk
-
documentation
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 92/100
github/copilot-sdk#2804 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
github/copilot-sdk#2798 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
github/copilot-sdk#2793 ·
I maintainer di solito rispondono entro 1 giorno
-
agentic-workflows
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
github/copilot-sdk#2782 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
github/copilot-sdk#2781 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di github/copilot-sdk
Issue simili
-
enhancement providers-api ui-dashboard
Difficoltà 2/5 1-3 ore Idoneità per principianti 61/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
external-issue to-triage
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
I maintainer di solito rispondono entro 1 giorno
-
needs triage
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
homarr-labs/homarr#6976 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno