Sub-agents stream `assistant.reasoning_delta` but never emit the `assistant.reasoning` close event documented as always-sent
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- javascript, python
Direzione di ricerca
Inizia in sdk/index.js intorno a createAgentCallbackBridge (~L4554) e confrontalo con il percorso del main-agent vicino a ~L4541. Esamina session-events.schema.json alle righe 520-522 e il contratto del README, quindi determina se i sub-agents debbano emettere un evento assistant.reasoning corrispondente o documentare la forma di assistant.message. Il lavoro è completato quando il comportamento scelto è implementato in modo coerente e verificato rispetto alla sequenza di eventi reasoningId descritta.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
Per the Python SDK README:
Note:
assistant.messageandassistant.reasoning(final events) are always sent regardless of streaming setting.
And per the schema docstring on AssistantReasoningDeltaData.reasoningId (session-events.schema.json line 520-522):
Reasoning block ID this delta belongs to, matching the corresponding
assistant.reasoningevent.
In practice, sub-agents stream assistant.reasoning_delta events (with agentId set on the event), but the matching assistant.reasoning close is never emitted. Instead the reasoning content lands in the sub-agent's assistant.message.reasoningText / reasoningOpaque fields. Consumers that rely on the documented per-reasoningId close event end up with permanently-orphaned streaming reasoning blocks for every sub-agent turn.
Environment
@github/copilot(CLI bundle):1.0.49github-copilot-sdk(Python):1.0.0b4- Default provider (not BYOK)
- Reasoning model in use (Claude Opus / Sonnet via the default backend)
What I'd expect (per docs)
For every sub-agent reasoning block: one or more assistant.reasoning_delta events with a given reasoningId, followed by exactly one assistant.reasoning event carrying that same reasoningId and the complete content — symmetric with master-agent reasoning.
What actually happens
Code path (built bundle, sdk/index.js ~ L4554, inside createAgentCallbackBridge):
case "reasoning":
u.reasoningId && u.deltaContent &&
this.emitEphemeral("assistant.reasoning_delta",
{ reasoningId: u.reasoningId, deltaContent: u.deltaContent }, r);
// ...later, when the sub-agent's response completes:
this.emit("assistant.message",
{ parentToolCallId: r, messageId: kr(), ..., reasoningOpaque, reasoningText }, r);
// No paired emit("assistant.reasoning", ...) here.
Compare to the main-agent path (sdk/index.js ~ L4541) which does:
this.emit("assistant.message", { ... });
Ho && this.emitEphemeral("assistant.reasoning", { reasoningId: Ho, content: Yi ?? "" });
So the close emit is conditional on the main-agent code path and absent from the sub-agent bridge.
Empirical evidence
Across six debug-mode session JSONL transcripts (~17K reasoning_delta events total) captured from a production run with multiple custom sub-agents (planner, implementer, profiler_agent):
- Every
assistant.reasoning_deltacarrying a sub-agent'sagentIdis never followed by a matchingassistant.reasoning. - Sub-agent
assistant.messageevents for those same turns do carry non-emptyreasoningText(often several KB) andreasoningOpaque, so the data is being retained — it just travels via the message payload instead of the documented close event. - The two log files in the same run that contain no sub-agent activity (master-only) have zero orphan reasoning streams. The four files with sub-agent activity have 25 orphan streams collectively. The pattern is deterministic and 1:1 with sub-agent boundaries.
Suggested fixes (either or both)
- Behavior fix: also emit
assistant.reasoningfrom the sub-agent bridge afterendCurrentStreamingMessage, mirroring the main-agent path. This keeps the documented contract (1:1reasoning_delta→assistant.reasoning) and matches downstream consumer expectations. - Documentation fix: if the embed-in-
assistant.messageshape is intentional for sub-agents, document it explicitly onAssistantReasoningDeltaData(e.g. "for sub-agent reasoning, the closingassistant.messageevent for the sameagentIdcarries the complete content inreasoningText/reasoningOpaque; no separateassistant.reasoningevent is emitted") and in the streaming-events guide referenced by #922.
Related: #922 (CLOSED — "Extended thinking/reasoning events not firing for OpenAI and Anthropic models via Copilot SDK"), #1064 (CLOSED — "BYOK Anthropic provider missing multiple session events ... reasoning ..."). Same family of bug but neither covers this specific main-vs-sub-agent asymmetry on the default provider.
Happy to provide the full JSONL fixtures if helpful.
- Lingua principale
- Java
- Stelle
- 10.5k
- Fork
- 1.5k
- Merge medio
- 1g 9h
- PR unite (30g)
- 131
Guida per i contributori
Apri 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
-
agentic-workflows
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
github/copilot-sdk#2709 · 1 commento ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 78/100
github/copilot-sdk#2673 ·
-
bug testing
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
github/copilot-sdk#2628 ·
-
agentic-workflows
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
github/copilot-sdk#2627 · 1 commento ·
-
agentic-workflows
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
github/copilot-sdk#2493 ·
Tutte le issue di github/copilot-sdk
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
elastic/gradle-plugins#157 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
cryptomator/hub#497 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
johanhaleby/occurrent#1120 ·