Skip to content

Antigravity ACP: Assistant text stream stays stuck in streaming/running state when agent ends planner step to wait on a background run_command #28898

Closed

Description

@mahmoodnizamani94-png

Summary

When an Antigravity ACP agent (gemini-4-argon / localharness_external) invokes run_command and the command exceeds WaitMsBeforeAsync (converting into a background task task-<N>), the agent's system instructions require it to emit a short status update to the user and stop calling tools to wait for the background task to complete:

"After launching a background task such as 'run_command', YOU MUST TAKE ONE OF THE FOLLOWING TWO ACTIONS: A) either proceed to other relevant work (if any) or, B) simply update the user with a short message (e.g. 'task-20 has been launched in the background. I will wait for it to complete before proceeding.') and end the turn. DO NOTHING ELSE."

When the agent follows Path B—emitting an assistant text message (agent_message_chunk) and ending its planner step without calling any further tools while the background run_command is still running—the assistant message item in T3 Code remains permanently stuck in streaming: true (status: "running") for the entire duration of the background command (or indefinitely if the background command hangs).

In Paragraph streaming mode (assistantDeliveryMode: "paragraph"), this also withholds the final paragraph buffer of the assistant's message from rendering until the background task finishes or the user manually interrupts/messages the thread.


Reproduction Steps

  1. Start an Antigravity ACP session in T3 Code (gemini-4-argon).
  2. Ask the agent to run a CLI command that takes longer than WaitMsBeforeAsync (i.e. > 10s, such as a preview build/deployment CLI or long-running test suite) and wait for it.
  3. Observe the event sequence:
    • tool_call (kind: "execute", title: "run_command", status: "in_progress") is emitted.
    • After WaitMsBeforeAsync (10s), Antigravity moves the command to a background task (task-<N>) and completes the synchronous tool step so the planner can continue.
    • The agent emits an agent_message_chunk explaining that task-<N> is running in the background and ends its planner step (StepStatus.DONE) to wait for the reactive wakeup.
  4. Observe the T3 Code conversation UI while task-<N> continues running in the background.

Expected Behavior

  • Once the planner step finishes emitting the assistant message and transitions into waiting on the background task (STATE_WAITING_FOR_TASKS), the assistant message stream is closed (streaming: false, status: "completed") and all buffered text is flushed to the UI, while the turn/background task indicator reflects that background work is still running.

Actual Behavior

  • The assistant message item in orchestration_v2_projection_turn_items stays stuck at:
    {
      "kind": "assistant_message",
      "status": "running",
      "data": {
        "text": "...",
        "streaming": true
      }
    }
  • The UI displays the assistant text as perpetually streaming/hanging for minutes (until the background task exits or the user sends a follow-up message / interrupts).

Root Cause Analysis

This happens due to the interaction between Antigravity ACP's LocalHarnessEventProcessor and T3 Code's makeAcpAdapterV2 (packages/provider-acp/src/server/adapter.ts):

  1. Antigravity ACP keeps session/prompt open during STATE_WAITING_FOR_TASKS:

    • In antigravity-acp (localharness_external/acp/session.py), LocalHarnessEventProcessor.process_event inspects event.trajectory_status.status.
    • When a background run_command (task-<N>) is still running (hasActiveTasks() == true), the trajectory transitions to STATE_WAITING_FOR_TASKS (4) rather than STATE_FULLY_IDLE (2).
    • Because self.is_idle.set() is only triggered on STATE_FULLY_IDLE or STATE_CANCELLED, the session/prompt JSON-RPC request remains open for the entire lifetime of the background command.
  2. makeAcpAdapterV2 only closes context.assistant.current on a new stream, new tool call, or session/prompt resolution:

    • In packages/provider-acp/src/server/adapter.ts, appendText(context, "assistant", update.content.text) creates/updates context.assistant.current with streaming: true (status: "running").
    • closeTextStream(context, "assistant") is currently only called when:
      1. A reasoning or user stream starts (appendText for another stream kind),
      2. A new tool call is emitted (emitTool), or
      3. turn.settled / finalizeTurn runs after session/prompt resolves (closeAllTextStreams(context)).
    • Because the agent has already emitted its "waiting for background task" message after the run_command tool call and then stops calling tools to wait on STATE_WAITING_FOR_TASKS, no subsequent emitTool or reasoning chunk arrives, and session/prompt does not resolve until the background task finishes. Consequently, closeTextStream(context, "assistant") is never invoked during the wait.

Relationship to Existing Issues & PRs

Activity

  1. juliusmarminge commented on Nov 1, 2026

    @juliusmarminge
    Member

    Duplicate of #28172 (git.cafe). Both report the same thing: the Antigravity ACP assistant_message stays streaming: true / running because Antigravity holds session/prompt open in STATE_WAITING_FOR_TASKS, and makeAcpAdapterV2 closes the assistant stream only on a new text stream, a tool call, or prompt settlement. https://git.cafe/pingdotgg/t3code/issues/28172 already gives this as its root cause 4, and its suggested fix 1 is the same fix.

    Checked on main at 01a93e7b51: packages/provider-acp/src/server/adapter.ts still closes context.assistant.current only on those three paths. The paragraph-mode half (the held final paragraph) is tracked in #28175, with an open PR, #28221. Closing this one so the work stays in https://git.cafe/pingdotgg/t3code/issues/28172.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions