Repository navigation
[Bug]: Copilot Autopilot final answers stay hidden in tool details #26697
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Searched open and closed issues and PRs for copilot, task_complete, end_turn, copilot autopilot, copilot final and copilot summary. Nothing covers this. #17714 and #24086 deal with Copilot subagent output. #26651 (session recovery) is unrelated.
Area
apps/server
Steps to reproduce
- Enable the ACP Registry agent GitHub Copilot CLI (
github-copilot-cli, Copilot CLI 1.0.105) and sign in. - Start a thread with Copilot and set Mode to Autopilot. Copilot advertises it as
https://agentclientprotocol.com/protocol/session-modes#autopilot. - Ask for a small multi-step task, for example "Read the build scripts in this repo and tell me what
builddoes." - Wait for the turn to finish.
Expected behavior
The turn ends with Copilot's final answer shown as an assistant message, the same as in Agent mode.
Actual behavior
The turn completes, but the final answer often never becomes an assistant message. In Autopilot, Copilot 1.0.104/1.0.105 ends its work by calling its native task_complete tool. The summary argument of that call is the answer, and Copilot writes no assistant text after the call. Upstream doesn't promote that summary into a reply, so when the turn's earlier assistant text is only progress notes, those notes are all the thread shows.
On web, the last progress note is treated as the turn's reply. The task_complete call folds into the "Worked for …" row with the rest of the turn's work. Its row is titled Tool: the completing tool_call_update carries no title, so the row's label falls back from "Task complete" to "Tool". To read the answer, the user has to expand "Worked for …", then expand that Tool row. The answer then shows as a plain-text summary argument line, and again in the output as raw {"content": …, "detailedContent": …} JSON (packages/client-runtime/src/work-log/itemDetail.ts, apps/web/src/components/chat/V2ItemInspector.tsx). Nothing in the web, mobile or client-runtime code handles task_complete specially.
Upstream has no step that turns that summary into a reply (main @ 9826dbb):
packages/provider-acp-registry/src/server/copilotAcp.ts:15-25: the Copilot client capabilities subscribe only tosubagent.*andassistant.*_deltasession events. Nothing observestool.execution_startfortask_completeorsession.task_complete.packages/provider-acp/src/server/adapter.ts:7613-7656: whensession/promptresolves, the turn is finalized straight fromresult.stopReason. The flavor has no hook to append a final answer reported outsideagent_message_chunk.packages/provider-acp/src/server/adapter.ts:3620-3621: thetask_completeACPtool_callis projected like any other tool, with the summary kept only in itsrawInput/rawOutput.
Copilot's own session logs show the pattern. Seven Copilot sessions ran in Autopilot from T3 over ACP on this machine (1.0.104 ×3, 1.0.105 ×4), and every one ended a turn through task_complete:
- 6 of 7: the turn's own assistant text was only short progress notes (18–296 chars each). The
task_completesummary held the actual answer (384–2,548 chars), and nothing came after it. - The 7th: Copilot had already written an 883-char answer, and an autopilot continuation then called
task_completewith a restated summary.
No session outside Autopilot called task_complete.
session/prompt itself behaves correctly. In T3's provider log it resolves about 20 ms after task_complete completes and the native turn ends, so the turn is not cut short. The answer is simply delivered somewhere T3 doesn't read it.
Impact
Major degradation or frequent failure
In six of the seven Autopilot tasks I inspected, the thread looked finished but showed no answer; all seven ended through task_complete, whose summary upstream doesn't promote into a reply. In my case the threads were delegated child tasks, where that summary is the whole result.
Version or commit
main @ 9826dbb (replay test and code reading); behaviour observed with GitHub Copilot CLI 1.0.104 and 1.0.105
Environment
macOS (Darwin 27), GitHub Copilot CLI 1.0.104 and 1.0.105 via the ACP Registry agent github-copilot-cli, Autopilot mode
Logs or stack traces
# Copilot CLI 1.0.105, Autopilot. Copilot's native ~/.copilot/session-state/<session>/events.jsonl
# for the last turn of one interaction. Text replaced by lengths; ids shortened.
21:07:29.393Z assistant.turn_start turnId=157
21:07:34.832Z assistant.message content="" toolRequests=[task_complete]
21:07:34.832Z tool.execution_start toolName=task_complete arguments.summary=<1,565 chars: the final answer>
21:07:34.834Z tool.execution_complete success=true
21:07:34.835Z session.task_complete summary=<1,565 chars> success=true
21:07:34.837Z assistant.turn_end turnId=157
# T3 provider log, same thread:
21:07:34.857Z session/prompt succeeded
# The earlier assistant messages in this interaction were short progress notes (27-84 chars).A synthetic reconstruction of Copilot's session updates, exercised through upstream's real adapter on main @ 9826dbb. It is not a captured Autopilot wire trace or a browser reproduction. The fields follow Copilot's ACP frames for its other tools and the task_complete entries in its session logs. It is a throwaway copy of the existing routes interleaved Copilot subagent output into subagent threads case in apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts, with the same Copilot flavor wiring (makeCopilotSubagentRouting, extractCopilotSubagentUpdate):
agent_message_chunk"Checking the build scripts.", preceded by itsassistant.message_deltasession event.tool_call{toolCallId, title: "Task complete", kind: "other", status: "pending", rawInput: {summary: "FINAL-ANSWER-I1: …"}}.tool_call_update{status: "completed", content: [text summary], rawOutput: {content, detailedContent}}.session/prompt→{stopReason: "end_turn"}.
# vp test run apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts -t SCRATCH-I1
turn.terminal: status=completed
assistant_message items: ["Checking the build scripts."]
summary in any assistant_message: false
items containing the summary: ["dynamic_tool"]
dynamic_tool title over time: "pending:Task complete" -> "completed:Tool"
dynamic_tool.input = {"summary": "FINAL-ANSWER-I1: `build` runs `turbo run build`, ..."}
dynamic_tool.output = {"content": "FINAL-ANSWER-I1: ...", "detailedContent": "FINAL-ANSWER-I1: ..."}Screenshots, recordings, or supporting files
None. The replay under Logs shows what upstream produces for this turn shape.
Workaround
Use Copilot's Agent mode instead of Autopilot. Copilot then writes its answer as normal assistant text.
Additional context
I'm happy to open a focused PR once the expected behavior is agreed.
Investigated by Opus 5.5 with Claude Code. Reviewed by GPT 6.1 Sol.
Activity
ianrowe12 commentedon Nov 2, 2026
Closing this: my original replay omitted a final assistant chunk that Copilot emits over ACP, so it did not establish the reported upstream bug.
I captured two Autopilot turns over ACP from Copilot CLI 1.0.105 (
claude-haiku-4.5, small read-only task). One used upstream's current Copilot event subscription; the other also subscribed tosession.task_complete. In both, right after thetask_completetool call completes, Copilot sends the summary as an ordinaryagent_message_chunk, just beforesession/promptresolves withend_turn.Second capture, using upstream's subscription; times are seconds since process launch:
That chunk text matches the
session.task_completesummary in Copilot's own session log. I replayed this sequence through the registry adapter onmain@ fa31b66. For this captured sequence, upstream produces the summary as the turn's last assistant message.What the issue got wrong: its evidence came from Copilot's local
events.jsonl, which records no assistant message aftertask_complete, and from a synthetic replay built on that assumption. The ACP layer adds the chunk itself, and the synthetic frames also had arawInput.summaryand a "Task complete" title that the real frames don't have. The sessions behind the issue ran on a fork of T3, and I didn't separate its behaviour from upstream's.— Opus 5.5 with Claude Code, reviewed by GPT 6.1 Sol