Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Open an Antigravity ACP thread in T3 Code (e.g.,
gemini-4-argon/gemini-4-argon-high). - Ask the agent to run a command that exceeds
WaitMsBeforeAsync(e.g.,WaitMsBeforeAsync: 5000on a command that takes ~30–45 seconds, such as a deployment or test suite) so Antigravity moves the command to a background task (Tool is running as a background task with task id: <conversation-id>/task-<N>) and the agent ends its turn to wait for the background task to complete. - Observe the T3 Code thread UI while the background task is still running, and after the background task completes and wakes the agent in the harness.
Expected behavior
- While the background task is running and the agent is waiting for it:
- The open background command (
run_command/shell/schedule/run_workflow) should remain in a running/pending background state rather than being forcibly markedcompleted(Ran command) when the initial turn settles. thread.pendingBackgroundTasksshould include the running background task so the UI displays the background task indicator/banner (and keeps the thread in a waiting/working state rather than looking completely finished).
- The open background command (
- When the background task finishes and wakes the agent:
- T3 Code should start a continuation run (or stream the wakeup turn items and assistant messages live into the thread) so the user sees the agent wake up, execute follow-up tool calls, and output its final response without needing to manually send a follow-up prompt.
Actual behavior
- Thread immediately shows as Done and hides the running background task:
- As soon as the agent outputs its "waiting for
task-<N>to complete" message and ends its turn,finalizeTurnmarks the runcompletedandterminalizeOpenForegroundToolsforcibly overwrites the still-runningcommand_executionturn item fromin_progress(running) tocompleted(Ran command). - Because all turn items are now
completedandproviderThread.pendingBackgroundTasksis[],derivePendingBackgroundWorkreturns[]. The UI shows no running background tasks at all, making it impossible to tell whether the agent finished, died, or is waiting on a background task.
- As soon as the agent outputs its "waiting for
- Agent wakes up in the background when the task finishes, but the UI never shows the wakeup or response:
- When the background task finishes (e.g., 26 seconds later), the Antigravity harness delivers the
<SYSTEM_MESSAGE>task completion wakeup to the model. The agent wakes up in the background, runs follow-up tools, and generates its final completion response (verified in.system_generated/logs/transcript.jsonl), but nothing appears in the T3 Code UI until the user manually sends another prompt.
- When the background task finishes (e.g., 26 seconds later), the Antigravity harness delivers the
Root Cause Analysis (on main @ 5e9d56416f6b395095c772c597e79cd5f94e3052)
There are three interacting causes across AntigravityAdapterV2.ts, packages/provider-acp/src/server/adapter.ts, and antigravity-acp:
1. makeAntigravityAcpAdapterFlavor omits enablePostSettleContinuation: true despite AntigravityDriver wiring continuationRequests
- In
apps/server/src/provider/Drivers/AntigravityDriver.ts#L413-L428andapps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts#L228-L236,continuationRequests(ProviderContinuationRequests) is explicitly passed intomakeAntigravityAdapterV2and forwarded tomakeAcpAdapterV2. - However, in
packages/provider-acp/src/server/adapter.ts#L1356-L1357:const postSettleContinuationEnabled = flavor.enablePostSettleContinuation === true && continuationRequests !== undefined;
- Because
makeAntigravityAcpAdapterFlavor(apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts#L154-L216) never setsenablePostSettleContinuation: true,postSettleContinuationEnabledis alwaysfalsefor Antigravity! - Consequently, when any post-settle session notification arrives while
context === null,bufferPostSettleWake(packages/provider-acp/src/server/adapter.ts#L4270-L4277) immediately returns{ buffered: false, offerContinuation: false, stopProcessing: false },offerContinuationRunis never called, and post-settleagent_message_chunk/agent_thought_chunkupdates fall through toappendLoadedHistory(adapter.ts#L4722-L4755) where they are silently written into the internalsnapshotmap without emittingmessage.updatedorturn_item.updatedevents to the UI.
2. makeAntigravityAcpAdapterFlavor omits extractBackgroundTaskId, causing terminalizeOpenForegroundTools to mark still-running background commands as completed at turn end
- When an Antigravity
run_commandtool call goes to the background,antigravity-acp(server.py:5490-5495and6090-6093) intentionally keeps thetool_callinin_progressstate (moving it tosession_info.persisted_open_tool_callswithout emitting a terminaltool_call_updateuntil the background process actually exits). - However, when the turn settles in T3 Code,
finalizeTurncallsterminalizeOpenForegroundTools(packages/provider-acp/src/server/adapter.ts#L6938-L6947), which checksacpCompletedTurnShouldTerminalizeTool(adapter.ts#L1223-L1231):export function acpCompletedTurnShouldTerminalizeTool( tool: AcpToolCallState, flavor: Pick<AcpAdapterV2Flavor, "extractBackgroundTaskId" | "extractSubagentUpdate">, ): boolean { const status = toolStatus(tool.status); if (status !== "pending" && status !== "running") return false; if (flavor.extractBackgroundTaskId?.(tool) !== undefined) return false; return flavor.extractSubagentUpdate?.(tool) === undefined; }
- Because
makeAntigravityAcpAdapterFlavordoes not provideextractBackgroundTaskId(e.g., for openexecutetools that remaininProgressat turn end, seeisAntigravityOpenCommandinapps/server/src/provider/acp/AntigravityProtocol.ts#L317-L319),acpCompletedTurnShouldTerminalizeToolreturnstrueandterminalizeOpenForegroundToolsforcibly emitsstatus: "completed"(Ran command) for the still-running background command! - Because the
command_executionturn item is now markedcompleted,pendingBackgroundTurnItemsandderivePendingBackgroundWork(packages/shared/src/orchestrationV2PendingBackgroundWork.ts#L174-L243) return[], so the UI hides the running background command and marks the thread completely idle/done.
3. antigravity-acp (server.py / event_processor.py) stops draining agent.conversation.receive_steps() once session/prompt returns
- In
antigravity-acp(google3/cloud/developer_experience/antigravity_extensions/acp_server/server.py:5483), steps fromlocalharness_externalare only forwarded toself._stream_live_step(...)inside theasync for step in agent.conversation.receive_steps():loop during an activesession/promptRPC. - Meanwhile, in
localharness_external, when arun_commandexceedsWaitMsBeforeAsync, theRUN_COMMANDstep remains inSTATE_RUNNING(status = 2) while the planner receives the background task ID (<conv>/task-<N>) and finishes its turn, causinglocalharness_externalto emitTrajectoryStateUpdate(state=STATE_WAITING_FOR_TASKS)(4). - If
session/promptexits onSTATE_WAITING_FOR_TASKS, nothing drainsagent.conversation.receive_steps()when the background task later finishes and wakes the planner inlocalharness_external—so the wakeup turn (e.g., steps 253–256 below) runs insidelocalharness_externalwithout emitting ACPsession/updatenotifications until the nextsession/promptcall. Conversely, ifsession/promptstays open acrossSTATE_WAITING_FOR_TASKS(or spawns a background step drainer that triggers post-settle continuation), T3 Code needs bothextractBackgroundTaskId/ open background command tracking andenablePostSettleContinuation: trueso the UI shows the pending background task while waiting and streams the wakeup turn when it fires.
Impact
Major degradation or frequent failure
Version or commit
0.1.7-nightly.20261031.3991 (and main @ 5e9d56416f6b395095c772c597e79cd5f94e3052)
Environment
Linux x86_64 (CachyOS), T3 Code 0.1.7-nightly.20261031.3991, Provider: Antigravity ACP (gemini-4-argon / gemini-4-argon-high)
Logs or stack traces
Concrete timeline from thread 6af2808e-6d27-43fa-91d1-eda0daffacc3 (Antigravity session c7b20c6f-f402-4c58-ad7b-6f56e7fa6f9c, run ordinal 19):
-
In
.t3/userdata/statev2.sqlite(orchestration_v2_projection_runsandorchestration_v2_projection_turn_items):- At
2026-10-31T23:15:23Z, the agent launches background commandtask-251(tool item...tool:c7b20c6f-f402-4c58-ad7b-6f56e7fa6f9c:236). - At
2026-10-31T23:15:33Z, the agent outputs: "I have launchedtask-251in the background to confirmdpl_2a6G1s8uQYFF7a4QnqnxaRrvvKJEreachesREADY(PROMOTED) and will report back as soon as it finishes." - At
2026-10-31T23:15:48.720Z,terminalizeOpenForegroundToolsmarkstool:...:236asstatus = 'completed'(title = 'Ran command') even thoughtask-251is still running, and at23:15:48.749Zrunordinal: 19is markedstatus = 'completed'withpendingBackgroundTasks = [].
- At
-
In
antigravity-acp/brain/c7b20c6f-f402-4c58-ad7b-6f56e7fa6f9c/.system_generated/logs/transcript.jsonl(steps 251–256):23:15:23Z(step 251,RUN_COMMAND,status: "RUNNING"):Tool is running as a background task with task id: c7b20c6f-f402-4c58-ad7b-6f56e7fa6f9c/task-25123:15:33Z(step 252,PLANNER_RESPONSE,status: "DONE"): Agent stops and waits fortask-251.23:16:14Z(step 253,SYSTEM_MESSAGE,status: "DONE"):Task id "c7b20c6f-f402-4c58-ad7b-6f56e7fa6f9c/task-251" finished with result: The command exited with code 0...23:16:14Z(step 254,PLANNER_RESPONSE,status: "DONE"): Agent wakes up automatically in the background and callsrun_command(curl -sS https://text2voice-pi.vercel.app/api/health).23:16:25Z(step 255,RUN_COMMAND,status: "DONE"): Health check returns{"status":"ok","ok":true,"database":"ok"}.23:16:28Z(step 256,PLANNER_RESPONSE,status: "DONE"): Agent writes its complete 1,048-token final summary (Everything is now 100% resolved, migrated, merged, and promoted to live production...).- In T3 Code (
statev2.sqlite): Zero messages or turn items were recorded after23:15:48.749Z! Steps253–256never appeared in the UI.
Workaround
Manually sending a follow-up prompt (e.g., "where are we at?") forces a new session/prompt turn so the agent can report what happened in the background.
Activity
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
eliophan commentedon Nov 3, 2026
Evidence: on runtime 1.4.5,
session/promptstays open until background tasks finish, so a non-exiting server keeps the turn "Working" foreverEnvironment: Antigravity ACP runtime 1.4.5 (darwin-arm64, release sha256
886fff77…), T3 Code Nightly0.1.7-nightly.20261103.4119.I drove the runtime directly with a minimal ACP stdio client (
fs.readTextFile: false, as T3 sends for 1.4.5) and asked the agent to start a background command and end its turn. Prompt: runsleep 50 && echo BGDONEwithWaitMsBeforeAsync: 1000, reply with one sentence that it is launched, and do nothing else.tool_call/tool_call_update→in_progressfor the commandagent_message_chunk: "The background task has been launched." (the model considers its turn over)tool_call_update→completedfor the commandagent_message_chunk: "The background task has finished successfully…"session/promptreturnsstopReason: end_turnSo the prompt was held open for ~50 s after the agent's final message, until the background task ended, and the wake-up happened inside the same prompt.
This seems to differ from the assumption in #28450 that Antigravity returns
end_turnwhile the command is still running. I only tried this one scenario (a short background command), so it may not cover the cases that PR was written for.Effect in a real thread with a server that never exits (
pnpm start):assistant_messageitem stayedrunning, with nosession/promptresult logged.pnpm startas a new background task, and the turn stayed open again.Stop ends the turn but not the background task (#16442), so the server keeps running.
LOG:
C-1.4.5-bg-task.sanitized.json
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
fix(server): keep Antigravity commands active and show wakeups
fix(server): release Antigravity commands when a prompt request fails
fix(server): forget running commands when the ACP runtime restarts
fix(server): keep Antigravity ACP turns attached across backgrounded …
Q3yp commentedon Nov 11, 2026
Live
agy acp1.5.5 wire findings (Windows ARM64) + working reference fixSharing empirical wire behavior from real authenticated Antigravity CLI
1.5.5(agy acp,gemini-4-carbon) on T3 Code Nightly (0.1.9-nightly.20261110.4491/main@b883156e2), since #28450 noted that liveagydelivery after earlyend_turnwas still unverified.What happens on real
agy acp1.5.5Driving
agy acp1.5.5 directly over stdio JSON-RPC with a minimal harness reproduces two behaviors that prevent passive post-settle listeners alone from receiving the wakeup:session/updatenotifications are emitted aftersession/promptreturnsend_turn: When a foregroundrun_command(IsDaemon: false, such as chainednpm run typecheck; npm run lint; npx vitest run ...) exceedsWaitMsBeforeAsync(capped at 10s),agyemitstool_callwithkind: "execute", status: "in_progress"(notool_call_update) and instructs the planner to end its turn immediately (<messaging>reactive wakeup). As soon as the planner ends its step,agy acpresponds tosession/promptwith{"stopReason": "end_turn"}whileconversation_summaries.dbremainsnot_fully_idle = 1. When the backgrounded shell process exits seconds later with no activesession/promptRPC attached,agywakes the planner internally in its transcript (SYSTEM_MESSAGE->PLANNER_RESPONSE), but sends0session/updateframes over ACP stdout. A client waiting passively for post-settlesession/updateframes never receives the command completion or the wakeup reply.session/request_permissionhangsagyindefinitely on follow-up commands indefaultmode:agy acpalso binds itssession/request_permissionbroker strictly to an activesession/promptcall. Indefaultmode, when the internal wakeup triggers a follow-up tool call (such as a secondrun_command) while nosession/promptis open,agysends0session/request_permissionframes over ACP and blocks forever internally waiting for permission (not_fully_idle = 1permanently).agy1.4.5 (Antigravity: a command still running after the reply is marked completed, and Stop cannot end it #16442): Unlike 1.4.5 (which heldsession/promptopen across all background tasks, causingIsDaemon: truedev servers to hang the turn forever), 1.5.5 returnsend_turnimmediately for bothIsDaemon: falseandIsDaemon: true.Verified behavior when
session/promptstays attached or re-attachesTesting both cases against live
agy acp1.5.5:session/promptopen via an MCP tool (t3_background_wait): Whilesession/promptremains active,agystreamstool_call_update(status: "completed", rawOutput)live the instant the backgrounded command exits, delivers<SYSTEM_MESSAGE>in the next step of the same turn, and routes follow-upsession/request_permissionprompts normally.session/promptimmediately after earlyend_turn: Sending a continuationsession/promptwhile theIsDaemon: falsecommand is stillin_progressre-attaches bothsession/updateandsession/request_permission(and replays gap completions if the command finished between the two RPCs).Working reference implementation (live-tested on Windows 11 ARM64)
Reference branch against
main(b883156e2):Summary of the reference approach (for maintainer design reference; not opened as a PR per
CONTRIBUTING.md):IsDaemoninAntigravityProtocol.tssoIsDaemon: trueservers/watchers never hold turns (Antigravity: a command still running after the reply is marked completed, and Stop cannot end it #16442).awaitBackgroundTasks(t3_background_wait) onAcpAdapterV2flavors opting intoforegroundCommandWait(plus MCP guidance whenhasT3Mcpis active) so foregroundrun_commandtasks hold the activesession/promptstream open untiltool_call_update(completed)arrives (orwaiting: falsereleases them).<t3_background_continuation>prompt loop inAcpAdapterV2as a fallback if the model still ends its turn early while an unreleased foreground command (IsDaemon: false) isinProgress, and drain the Antigravity update semaphore before resolvingruntime.prompt.Environment tested: Windows 11 ARM64, Node
v24.22.1, Antigravity CLI1.5.5(gemini-4-carbon), T3 Code desktop0.1.9-nightlybuild.(Investigated and drafted with
gemini-4-carbonvia Antigravity in T3 Code.)juliusmarminge commentedon Nov 12, 2026
This is the same problem as #16442, so I'm closing it in favour of that one. If it is different, say how and it will be reopened.