Skip to content

fix(sandbox): a sandbox agent's own replies reach the chat on every client - #72

Merged
t3-code-sandboxes[bot] merged 1 commit into
feat/sandbox-environmentsfrom
fix/sandbox-wake-reaches-host
Nov 15, 2026
Merged

t3-code-sandboxes[bot] merged 1 commit into
feat/sandbox-environmentsfrom
fix/sandbox-wake-reaches-host

Conversation

@t3-code-sandboxes

Copy link
Copy Markdown

Stacked on #71.

Problem. In a normal T3 chat, when the agent wakes on its own (a background task or subagent finishing, a Monitor line, a scheduled task), the reply appears in the chat on every client. In a sandbox chat seen through the host (the phone, or a desktop not paired with the sandbox), it didn't. The bridge only relayed the sandbox run carrying the host's forwarded message, and after #68 it only reported the background roster. The agent woke on the sandbox, but its reply never reached the host's mirror, not even on the next turn.

Fix (bridge and host ACP adapter; orchestration unchanged).

  • The bridge treats a sandbox run whose message nobody typed (createdBy !== "user", or a scheduledTaskId) as a wake. It only considers runs that started after the newest run a host turn followed, so no history is replayed. For each wake it sends a new ACP notification (SANDBOX_BRIDGE_WAKE_METHOD) with the sandbox's message id, text and notice, without sandbox-only ids.
  • The sandbox flavor turns it into a provider continuation through the existing offerContinuationRun, which keeps one request pending and ignores notices during a running turn. The host message reuses the sandbox's message id, text and notice.
  • The wake run's prompt carries the sandbox's message id, so the existing turnTargetOf attaches and relays it with the same TurnTracker as normal turns, starting at that message. A continuation whose message the sandbox doesn't have does nothing, and its text never reaches the sandbox.
  • fix(sandbox): a sandbox chat stays Working while its sandbox thread works on #68's follow now keeps going until the next prompt or until the bridge process ends, because a task's end and the wake it causes arrive separately. That costs one subscription per live bridge, on perf(sandbox): sandbox chat turns reuse one connection and send less #66's shared compact connection, bounded by idle session release.
  • Left as is:
    • A wake right after a user's Stop isn't shown until the next host turn, because the adapter blocks wakes after a Stop.
    • If a user's message waits on the sandbox behind a wake, the wake's remaining output shows in the user's turn.

Test plan

  • bridge.test.ts: shows a run the sandbox starts itself as a run of the host's, once. It asks the host once with the cleaned notice, streams the reply, and dispatches nothing to the sandbox (fails on the base).
  • AcpRegistryAdapterV2.test.ts: starts a run when the bridge reports one the sandbox began itself. A repeated notice gives one continuation, and the prompt carries the sandbox's message id (fails on the base).
  • bridge.test.ts, AcpRegistryAdapterV2.test.ts and AcpAdapterV2.test.ts (206 tests), and typecheck of contracts, provider-acp, provider-acp-registry, sandbox-bridge and server pass. In check:changed, only the known base failures fail (remote-parent fixture, the tailscale host leak), both fixed in test: fix the tests that fail on the sandbox branch itself #69.

Claude Opus 5.5 via Claude Code.

🤖 Generated with Claude Code

When the sandbox's thread woke itself between host turns (a background task or
subagent finishing, a monitor line, a scheduled task), the reply stayed on the
sandbox: the bridge only sent the host its background roster, so the phone and
any client not paired with the sandbox saw the chat go idle without the answer.

The bridge now keeps following the sandbox's thread between turns and, for each
run the thread starts on a message no user typed, asks the host for a run of its
own (SANDBOX_BRIDGE_WAKE_METHOD). The host's ACP adapter offers that as a
provider continuation carrying the sandbox's message id, text and notification,
so the mirror gets a wake run like any T3 thread. That run's prompt names the
sandbox's message, which the bridge follows with the relay normal turns use;
a provider continuation's text is never sent to the sandbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@t3-code-sandboxes t3-code-sandboxes Bot mentioned this pull request Nov 15, 2026
5 tasks done
Base automatically changed from fix/sandbox-keepalive-background to feat/sandbox-environments November 15, 2026 21:16
@t3-code-sandboxes
t3-code-sandboxes Bot merged commit ddd2094 into feat/sandbox-environments Nov 15, 2026
@t3-code-sandboxes
t3-code-sandboxes Bot deleted the fix/sandbox-wake-reaches-host branch November 15, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant