You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Logic behind mapping <think> tags to reasoning_content #9433
I noticed that if a model sends <think> tags, you convert them into reasoning_content.
And if a model supports interleaved reasoning, you theoretically send the content of those <think> tags back as reasoning_content (otherwise they are filtered out).
I'm not sure if there is a model that supports reasoning_content while simultaneously sending <think> tags, but could you please tell me the logic behind this?
This should only happen if the model is configured to both:
A) be interleaved reasoning model
B) expect reasoning to be sent back as reasoning_content | reasoning_details
@rekram1-node
It seems OpenCode always extracts <think>...</think> tags from model output into “reasoning” parts here.
Then, only when model.capabilities.interleaved.field === "reasoning_content", those reasoning parts are mapped into providerOptions.openaiCompatible.reasoning_content and removed from content.
This means a model that expects <think> tags to remain in history won’t receive them back. For example, MiniMax 2.1 docs state tags should stay in history.
Questions:
Do you know of any model/provider that both outputs <think>...</think> and expects preserved/interleaved reasoning via reasoning_content / reasoning_details?
If not, what’s the rationale for always stripping <think> tags by default — is it purely to save context/cost, or something else?
Should this behavior be driven by models.dev capabilities or be configurable?
And could you tell me if removing the <think>...</think> from history was intentional or a mistake? I've heard conflicting opinions on whether the coding agent should restore it.
{# System Prompt Logic #}
{%- set system_message = "You are a helpful assistant. IMPORTANT: You MUST always begin your response with a <think> tag to start your reasoning process." -%}
{%- if messages[0]['role'] == 'system' -%}
{%- set system_message = messages[0]['content'] -%}
{%- endif -%}
<|im_start|>system
{{ system_message }}<|im_end|>
{# Loop through remaining Messages #}
{%- for message in messages -%}
{# Skip System Prompt if it was handled above #}
{%- if not (loop.first and message['role'] == 'system') -%}
<|im_start|>{{ message['role'] }}
{# Allow Deep Reasoning #}
{%- set reasoning = message['reasoning_content'] or message['thinking'] -%}
{%- if reasoning -%}
<think>
{{ reasoning }}
</think>
{%- endif -%}
{# Completion vs Response #}
{%- if message['content'] is string -%}
{{ message['content'] }}
{%- elif message['content'] is iterable -%}
{%- for item in message['content'] -%}
{%- if item['type'] in ['text', 'input_text'] -%}
{{ item['text'] }}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
<|im_end|>
{%- endif -%}
{%- endfor -%}
{# Provide <think> Tag for models used to Native Thinking flow #}
{%- if add_generation_prompt -%}
<|im_start|>assistant
{%- endif -%}
{# System Prompt Logic #}
{%- set system_message = "You are a helpful assistant." -%}
{%- if messages[0]['role'] == 'system' -%}
{%- set system_message = messages[0]['content'] -%}
{%- endif -%}
<|im_start|>system
{{ system_message }}<|im_end|>
{# Loop through remaining Messages #}
{%- for message in messages -%}
{# Skip System Prompt if it was handled above #}
{%- if not (loop.first and message['role'] == 'system') -%}
<|im_start|>{{ message['role'] }}
{# Allow Deep Reasoning #}
{%- set reasoning = message['reasoning_content'] or message['thinking'] -%}
{%- if reasoning -%}
<think>
{{ reasoning }}
</think>
{%- endif -%}
{# Completion vs Response #}
{%- if message['content'] is string -%}
{{ message['content'] }}
{%- elif message['content'] is iterable -%}
{%- for item in message['content'] -%}
{%- if item['type'] in ['text', 'input_text'] -%}
{{ item['text'] }}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
<|im_end|>
{%- endif -%}
{%- endfor -%}
{# Provide <think> Tag for models used to Native Thinking flow #}
{%- if add_generation_prompt -%}
<|im_start|>assistant
<think>
{%- endif -%}
I can't get it to work anymore, specifically v1/responses. Any hints or confirmation at least it's just transition pains?
Activity
github-actions commentedon Jan 19, 2026
This issue might be a duplicate of existing issues. Please check:
<think>tags indelta.contentinstead ofdelta.reasoning_content<think>tag formatting issuesreasoning_contentnot being sent in subsequent requestsFeel free to ignore if none of these address your specific case.
rekram1-node commentedon Jan 19, 2026
This should only happen if the model is configured to both:
A) be interleaved reasoning model
B) expect reasoning to be sent back as reasoning_content | reasoning_details
zikajk commentedon Jan 20, 2026
@rekram1-node
It seems OpenCode always extracts
<think>...</think>tags from model output into “reasoning” parts here.Then, only when
model.capabilities.interleaved.field === "reasoning_content", those reasoning parts are mapped intoproviderOptions.openaiCompatible.reasoning_contentand removed from content.This means a model that expects
<think>tags to remain in history won’t receive them back. For example, MiniMax 2.1 docs state tags should stay in history.Questions:
<think>...</think>and expects preserved/interleaved reasoning viareasoning_content / reasoning_details?<think>tags by default — is it purely to save context/cost, or something else?Thank you
rekram1-node commentedon Jan 20, 2026
I see what u mean hmm
rekram1-node commentedon Jan 20, 2026
Yeah ig we should remove that wrapping or something hm
zikajk commentedon Jan 20, 2026
And could you tell me if removing the
<think>...</think>from history was intentional or a mistake? I've heard conflicting opinions on whether the coding agent should restore it.rekram1-node commentedon Jan 20, 2026
There is some nuance but tldr:
I feel like this is best of both worlds the only reason we have that parser is for that
daryltucker commentedon Jan 26, 2026
response.reasoning_text.deltais this why Thinking isn't shown inopencodenow?#4947
I can't get it to work anymore, specifically
v1/responses. Any hints or confirmation at least it's just transition pains?rekram1-node commentedon Jan 31, 2026
I removed the thing, need to make it prettier later
@daryltucker im not sure im following urs? Im closing cause I addressed issue OP raised