Switching models¶
The canonical conversation history is provider-neutral, but not every model can
accept every block exactly as stored. TransformMessages projects the stored
history into a request-safe form for the target model before an adapter converts
it to wire format.
The important detail: transformation happens per request. It does not mutate the stored history, so switching to a text-only model does not permanently discard images, and switching away from a reasoning model does not erase its signatures.
Transformation order¶
TransformMessages applies three passes:
downgradeUnsupportedImagesreplaces image blocks with placeholder text when the target model does not listImageinModel.Input.reconcileAssistantHistoryrewrites prior assistant turns for the target model, including reasoning blocks and tool-call IDs.synthesizeOrphanedToolResultsrepairs transcripts where an assistant tool call has no matching tool result.
Reasoning and signatures¶
Reasoning is model-specific. A reasoning signature or redacted payload is only safe to replay when provider, protocol, and model ID all match the target model. For the same model, signed reasoning is preserved. Across models, readable thinking is downgraded to plain text, empty thinking is dropped, and redacted thinking is removed because only the original model can understand it.
Text and tool-call signatures follow the same principle: opaque provider metadata is kept only for the model that produced it.
Tool-call identifiers¶
Different protocols accept different tool-call ID shapes. When an assistant turn
crosses models, the adapter supplies a normalizeToolCallID function. If the ID
changes, the matching ToolResultMessage.ToolCallID is remapped later in the
same pass, so the transcript stays consistent.
The final pass enforces the tool protocol invariant: every assistant tool-call
batch must receive one result per call before another user or assistant turn.
Missing results are synthesized as error tool results with "No result provided".
Overflow detection¶
IsContextOverflow is separate from transformation. It inspects a completed or
failed AssistantMessage and detects provider-specific context overflow signals:
known error-message patterns, successful responses whose usage exceeds the
context window, and length stops where input filled almost the whole window and
no output was produced.
Source: llm/transform.go,
llm/overflow.go.