Preserved Reasoning System¶
Numi Chat can store reasoning returned by a model and send it back on later turns. Whether it is sent back depends on the model catalog and API adapter. Seeing a thinking block in the browser does not, by itself, mean the next request includes that block.
To change effort in a chat, use Configure Reasoning Effort.
What is Preserved Reasoning¶
Three separate things happen to reasoning:
| Stage | What Numi Chat does |
|---|---|
| Display | Streams returned reasoning text or summaries to the browser. Some structured provider data is not displayable. |
| Storage | Saves returned reasoning alongside the assistant response in the chat database. |
| Replay | Filters and converts stored messages for the next request, according to the selected model and API. |
preserve_reasoning controls replay in the shared message filter; it is not a
switch that prevents reasoning from being stored. The selected model determines
how loaded history is prepared; filtering does not rewrite stored messages.
A displayed trace is the text or summary the provider exposes. It is not a guarantee of access to all of the model's internal computation.
Reasoning Modes¶
The catalog's reasoning_mode describes how reasoning is requested. It does
not describe a ranking of models or determine preservation by itself.
| Mode | Request behavior |
|---|---|
effort |
Requests a named effort level, normalized to the model's supported levels. |
enabled |
Uses an on/off reasoning control. |
native |
Uses provider-specific behavior; the web UI treats effort as fixed. |
none |
Declares that the model does not support reasoning. |
For example, an OpenRouter entry can have both reasoning_mode: "effort" and
preserve_reasoning: true. The packaged catalog uses that combination. Check
an entry's provider, wire_api, and preservation flag together in
Model Catalog.
The Message Preparation Filter¶
prepare_messages() in src/numi_chat/agent/messages.py makes a copy of each
message before removing internal metadata and incompatible reasoning fields.
It is used by the agent before the protocol adapter builds the outgoing request.
For ordinary assistant history, the current filter behaves as follows:
| Route or capability | reasoning_content |
reasoning_details |
|---|---|---|
| Model without reasoning support | Removed | Removed |
Direct openai or inception provider |
Removed | Removed |
anthropic or anthropic_compat provider |
Kept for conversion to thinking blocks | Removed |
openrouter, preservation enabled |
Kept | Kept |
openrouter, preservation disabled |
Removed | Kept on tool-call messages for continuation; otherwise removed |
| Other reasoning-capable routes | Kept only when preservation is enabled | Removed |
The distinction between plain text and structured details matters. Provider
signatures or other opaque data can be part of reasoning_details; replacing
those blocks with visible text is not equivalent to replaying them.
Provider-Specific Handling¶
The filter is only one stage. The selected wire_api adapter performs the
final conversion:
- OpenAI Chat Completions sends the filtered message objects. The Z.AI
provider adds
thinking.type: enabledandclear_thinking: falseto the request. OpenRouter maps the chat's effort to itsreasoningparameters. - OpenAI Responses converts messages and tool calls to Responses input items. The current adapter displays returned reasoning summaries but does not replay stored reasoning fields as Responses reasoning items.
- Anthropic Messages converts retained reasoning text into assistant
thinkingblocks and tool calls intotool_useblocks. This describes the current conversion; it does not guarantee compatibility with every endpoint's signature requirements. - Local Chat Completions endpoints can return reasoning fields or
<think>...</think>text. The adapter separates those text tags for display; replay still depends on the catalog and endpoint.
The source of these conversions is src/numi_chat/llm/adapters/. A catalog
flag declares intended behavior; it does not test that a remote model accepts
that history. Provider names alone are not sufficient evidence of support.
The User Experience¶
During generation, the browser receives reasoning and answer events separately. A model can also request tools, receive their results, and continue reasoning within the same user turn. The exact order and amount of visible reasoning depend on the response.
Reloading a chat can show stored reasoning even when that reasoning is excluded from future requests. A contextual follow-up answer is not proof of replay: the model also receives the ordinary conversation text.
Trade-offs and Implications¶
Replayed reasoning consumes context and can increase input cost. It can retain useful intermediate work, but it can also carry forward mistakes. Stored traces may contain sensitive content regardless of whether replay is enabled.
Preservation is bounded by the history sent with a request. Older turns may be omitted to meet context limits or replaced by a compaction summary. Numi Chat does not promise that every prior reasoning token is included indefinitely.
Configuration¶
Use the chat's effort control to change generation effort. Use the admin Models page to inspect or change model capabilities. These are separate controls: turning reasoning off does not delete traces already stored in the database.
For the storage and request path, see Message Flow and Persistence.