Skip to content

[Bug]: ACP instruction block (incl. collaborative browser) is lost after context compaction and never re-injected #21036

Closed

Description

@antonsxh

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

  1. Run t3 serve and start a thread with an ACP agent (e.g. OpenCode) with the t3-code MCP server attached.
  2. Let the thread run long enough that the agent compacts/summarizes its own context (OpenCode's native compaction, or T3's own "Compact idle threads" from feat(server): compact idle threads before the prompt cache expires #19662).
  3. Check the agent's active context for the T3 instructions (e.g. ask the agent to quote the section titled "T3 Code collaborative browser", or simply ask it to use the browser).

Expected behavior

The <t3_code_instructions> block — in particular T3_CODE_BROWSER_TOOL_INSTRUCTIONS — stays effective for the life of the thread: after a compaction the agent still knows that the product-native browser is the preview_* server-browser tools, not the host agent's built-in browser tools. (The Codex path effectively does this: restoreAdditionalContext re-injects the saved instruction entries after a compaction.)

Actual behavior

The instruction block is sent exactly once — with the first user prompt, or only when interactionMode or hasT3Mcp changes (t3AcpPromptWithInstructions, packages/provider-core/src/server/orchestrationInstructions.ts:72-94). After a compaction the one-shot message is summarized away and nothing re-sends the block:

  • resolvePromptParts (packages/provider-acp/src/server/adapter.ts:6304-6328) computes the instruction state per turn from interactionMode + hasT3Mcp and compares it against the per-session promptInstructionStates ref. Compaction is not part of that state and no compaction event resets it.
  • The compaction_update / compaction_summary_chunk handling in the ACP adapter only projects a "Context compacted" timeline item; there is no re-injection.

Observed on T3 0.1.0 with an OpenCode ACP thread: after the thread's context was compacted, the active context contained no "T3 Code collaborative browser" section (the installed 0.1.0 binary ships it), although the t3-code MCP server stayed attached throughout and no mode/MCP state change occurred. When the user then asked about the browser, the agent reached for OpenCode's built-in browser.* tools and got [browser.disconnected] — a dead end by design, because T3 never attaches a browser host to OpenCode and the preview_* server browser is the product-native path, which the agent only knew from the lost instruction block. The only recovery was a new thread.

Related (checked, not duplicates)

Impact

Major degradation or frequent failure

Version or commit

0.1.0 (observed) / main @ 07cb902 (source analysis, 2026-10-17)

Environment

LXC container (Linux, Debian-based), t3 serve --host 0.0.0.0 running as root, agent: OpenCode over ACP, T3 0.1.0

Logs or stack traces

No stack trace — silent instruction loss. Observable symptom:

agent → browser.tabs.open (OpenCode built-in)
result → [browser.disconnected] ...

while on the same thread preview_status / preview_open (the t3-code MCP server) work normally.

Workaround

No reliable one. An agent can still discover the preview_* tools by searching the tool catalog, and re-triggering an instruction state change (toggling the interaction mode, or detaching/attaching the MCP server) forces a re-injection — but neither is something a user can reasonably do per thread. A new thread always starts with the full block.


Suggested direction (maintainer's call)

Treat compaction completion as an instruction state change: when a compaction_update for the session reports the summary, invalidate that session's promptInstructionStates entry so the next user prompt re-prepends the full <t3_code_instructions> block. This mirrors what the Codex path already does with restoreAdditionalContext and is a small change in packages/provider-acp/src/server/adapter.ts plus a state field in T3AcpInstructionState.

Activity

  1. juliusmarminge commented on Oct 17, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Confirmed on main. The ACP adapter sends the <t3_code_instructions> block only when interactionMode or hasT3Mcp changes. Nothing resets promptInstructionStates after compaction, whether native compaction_* updates or /compact, so after compaction the block is never sent again. The Codex adapter does restore its instructions after compaction through restoreAdditionalContext. The ACP path puts the block only in the user prompt, so this is on our side, not OpenCode's. It's not a duplicate of #18411, #18415, #20222 or #20236. Keeping this open as a bug.

  2. added
    acceptedfeature request accepted
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 17, 2026
  3. added a commit that references this issue on Oct 18, 2026
    0d87972
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

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions