Skip to content

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.

Display a trace, store it, and replay it if the model and API allow.

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: enabled and clear_thinking: false to the request. OpenRouter maps the chat's effort to its reasoning parameters.
  • 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 thinking blocks and tool calls into tool_use blocks. 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.