Skip to content

deepseek.v3.2 on amazon-bedrock: long --auto sessions intermittently end with a complete DSML tool call left as plain text (finish reason 'stop') #45600

Closed as not planned

Description

@fkucharczyk

Summary

On amazon-bedrock/deepseek.v3.2, a long opencode --auto session intermittently ends mid-task: the assistant's final message contains a complete, well-formed DeepSeek DSML tool-call block as plain text, the step finishes with reason stop, and no tool part is produced. The session then sits idle with the task unfinished.

Reproduced 1 time in 3 at ~40 sequential tool calls. Reporting observed behaviour only — I have not tried to apportion this between the Bedrock serving layer and opencode's adapter, and the data below is consistent with either owning part of it.

Environment

  • opencode 1.18.23 (latest release at time of testing)
  • provider amazon-bedrock, model deepseek.v3.2, region eu-west-2, AWS SSO auth
  • Linux (WSL2)

Repro

Prompt asks for N sequential one-per-step bash calls, each writing a distinct nonce file, then a final count:

Step 1: run  echo step-1 > <dir>/step-1.txt
Step 2: run  echo step-2 > <dir>/step-2.txt
... (40 steps)

Run as opencode --auto --model amazon-bedrock/deepseek.v3.2 --prompt "<the above>" under a pty. Count the nonce files that appear.

entry point sessions outcome
opencode --auto (TUI) 3 × 40 steps 1 stopped at step 32/40; 2 completed
opencode run 3 (22, 40, 61 tool calls) all completed

What the stalled session contains

Final three parts of the failing session, from the session store:

{"reason": "tool-calls", "type": "step-finish", "tokens": {"total": 26118, "input": 25749, "output": 369}}
{"type": "step-start"}
{"type": "text", "text": "\n\n<|DSML|function_calls\n<|DSML|invoke name=\"bash\">\n<|DSML|parameter name=\"command\" string=\"true\">echo step-32 > <dir>/step-32.txt</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>"}
{"reason": "stop", "type": "step-finish", "tokens": {"total": 26224, "input": 26137, "output": 87}}

So the intended call is fully formed and unambiguous — it just arrives as text, and --auto reasonably treats a no-tool-call message as the final answer.

Related, and present in every tool-calling turn on this model: the text block always ends with a bare \n\n<|DSML|function_calls fragment alongside a correct tool call. In the failing session, 35 of 36 text parts carry one.

Counter-evidence: the raw Bedrock API looked clean

To check whether the serving layer alone explains it, I drove bedrock-runtime directly with boto3, same model and region, classifying every turn as native toolUse / DSML-in-text / plain text:

shape calls native toolUse call landed as text
converse, 20 × 1 turn 20 20 0
converse-stream, 20 × 1 turn 20 20 0
converse-stream, 5 × 6 turns 30 30 0
as above + 10 tools and a long system prompt 30 30 0
converse-stream, 1 × 30 turns 30 30 0
converse-stream, 1 × 45 turns, padded tool results (~26k-token context) 45 45 0

175/175 returned a native toolUse block. All 175 also carried the same trailing <|DSML|function_calls fragment in the text, so the leak reproduces at the API level — but the whole-call-as-text failure did not, including at the turn depth and context size where the real session broke.

The OpenAI-compatible endpoint (/openai/v1/chat/completions) shows the identical leak: correct tool_calls array, and "content" ending in ...\n\n<|DSML|function_calls.

Why I am raising it here

I could not reproduce the fatal case outside opencode, and it appeared only on the --auto TUI path, so I cannot rule out something about how that path builds requests or handles the assistant history. My synthetic API loop feeds the leaked text fragment back verbatim and still never fails, but it obviously does not replicate everything opencode sends.

Two things maintainers may find worth considering, offered as options rather than a diagnosis:

  1. A fallback parse for in-band DSML markup when a message finishes with stop and contains a complete tool-call block — the information needed to recover the call is fully present.
  2. Failing that, treating "final message contains unparsed tool-call markup" as a loud error rather than a normal completion, so it does not read as a finished task.

Downstream context, if useful: dare-global/conductor#2024. We have blocked the model for agentic use on our side meanwhile.

I can supply the full session parts or the API soak harness if either helps.

Activity

  1. github-actions commented on Aug 27, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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

Metadata

Metadata

Assignees

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