Skip to content

[Bug]: GPT models copy compact @N@ reference tags into their replies on OpenCode v2 #632

Open

Description

@kernel-oops

Description

On OpenCode v2, DCP marks messages in the model's context with compact reference tags (@158@, @b3@, @blocked@), introduced for the v2 path in f875b5f. GPT models frequently copy one of these onto the end of their own reply. Unlike #608 (where DCP itself wrote the tag into the stored assistant text), here the tag is model output, so it is stored and rendered as part of the reply.

DCP's system prompt already says these tags "are environment-injected metadata. Do not output them", and COMPACT_TAG_REGEX removes copied tags from the context DCP sends back, but nothing removes them from what the user sees.

Numbers (DCP 3.2.0, OpenCode v2.0.16, experimental.allowSubAgents: true)

Model Replies with text Ending with a tag
openai/gpt-6-sol (before any extra instruction) 49 25
openai/gpt-6-sol (after adding an explicit "never write these tags" rule to AGENTS.md) 12 4
openai/gpt-6-luna 2 0
Claude Opus 5.5 (Claude Code provider) 6 0

So a prompt instruction reduces it but does not stop it.

Suggested fix

v2 exposes no hook to rewrite stored output, but it does let a plugin rewrite provider frames before the driver parses them. For the OpenAI Responses WebSocket transport, response.output_item.done carries the authoritative full message text, which replaces the streamed deltas. Registering experimental.ws.receive (scoped to providerID: "openai") and stripping tags that match COMPACT_TAG_REGEX at the end of the last output_text part (plus response.output_text.done / response.completed for consistency) removes them from the stored reply, leaving mid-text mentions alone. We are running exactly this as a local plugin and are happy to turn it into a PR if you would like it in DCP.

Longer term, placing the ID somewhere models are less inclined to echo (for example, not as the final token of assistant messages) may reduce copying at source.

Related: #608.

Activity

  1. kernel-oops commented on Sep 25, 2026

    @kernel-oops
    Author

    Follow-up after running the frame-rewrite workaround for about nine hours:

    • Trailing tags: 0 of 291 gpt-6-sol replies stored with a trailing @N@ tag (previously about half). The experimental.ws.receive approach works.
    • New finding: GPT also copies the whole nudge block into its replies. 46 of those 291 replies ended with a verbatim <dcp-system-reminder>Evaluate the conversation for compressible ranges. …</dcp-system-reminder> (including the Active compressed blocks … (@b1@) list), which the user then sees in the chat. We now strip <dcp-system-reminder>…</dcp-system-reminder> (or an unclosed one through to the end) from completed message items as well.

    Both look like the same cause: the metadata sits at the end of the model's own previous output, so the model continues the pattern. If DCP adopted the receive-hook scrub, it would be worth covering the reminder block too.

  2. tetipong2542 commented on Sep 28, 2026

    @tetipong2542

    +++

  3. capyBearista commented on Sep 29, 2026

    @capyBearista

    Observed the same behavior with muse-spark-1.3-contributor (via OpenCode Go, atleast).

  4. mathomp4 commented on Oct 13, 2026

    @mathomp4

    I just updated to OpenCode v2 and with Claude Haiku 5.5 I keep seeing things like:

    <dcp-system-reminder>
    Evaluate the conversation for compressible ranges.
    If any messages are cleanly closed and unlikely to be needed again, use the compress tool on them.
    If direction has shifted, compress earlier ranges that are now less relevant.
    The goal is to filter noise and distill key information so context accumulation stays under control.
    Keep active context uncompressed.
    Compressed block context:
    Active compressed blocks in this session: 1 (@b1@)
    If your selected compression range includes any listed block, include each required placeholder exactly once in the summary using @b1@.
    </dcp-system-reminder>
    @143@
    

    is that this issue? I mean, I'm using an Anthropic and not OpenAI model.

  5. skwid138 commented on Oct 29, 2026

    @skwid138

    Adding another occurrence on macOS:

    • OpenCode CLI and server: 2.1.4
    • DCP: 3.2.0, confirmed active
    • Model: github-copilot/gpt-6.1-sol

    An authenticated single-message API response contained a completed assistant reply whose text part ended with a numeric DCP reference. The text part was 451 characters, with the five-character reference occupying its final five characters. It was in the assistant text, not a reasoning or tool-result part.

    I’ve noticed these suffixes frequently in one long session, sometimes on consecutive replies, but haven’t measured the frequency. I haven’t noticed the same pattern in shorter sessions.

    This confirms the reference is present in stored assistant text, but does not establish whether model generation or another output stage introduced it. I don’t yet have a minimal fresh-session reproduction.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions