These docs track the main branch and may describe unreleased features. The stable documentation lives at docs.docker.com.

Message-merging compatibility probes

The provider catalog records whether consecutive system or user messages must be merged before a Chat Completions request. A catalog flag is a policy assumption, not evidence about a real endpoint. This page describes the opt-in probe that compares preserved message boundaries with the existing merge.

The probe is an experiment harness. It does not change production defaults, and its output is not a compatibility guarantee.

Scope

The first probe wave is deliberately narrow:

The OpenAI API classification redesign tracked in #4756 is intentionally separate. A provider's protocol flavour does not prove a template requirement.

Safety guards

The probe requires both an explicit opt-in and an explicit target list:

DOCKER_AGENT_RUN_MESSAGE_MERGE_LIVE_TESTS=1
DOCKER_AGENT_MESSAGE_MERGE_TARGETS=provider/model[,provider/model...]

Running the probe

Use an explicit target list. A model id may contain slashes; the provider is everything before the first slash.

DOCKER_AGENT_RUN_MESSAGE_MERGE_LIVE_TESTS=1 \
DOCKER_AGENT_MESSAGE_MERGE_TARGETS='deepseek/deepseek-v4-pro,openrouter/qwen/qwen3.6-35b' \
DOCKER_AGENT_MESSAGE_MERGE_REPORT=/tmp/message-merge.jsonl \
go test -count=1 -buildvcs=true -v -run '^TestMessageMergeLive$' ./pkg/model/provider

PowerShell:

$env:DOCKER_AGENT_RUN_MESSAGE_MERGE_LIVE_TESTS = "1"
$env:DOCKER_AGENT_MESSAGE_MERGE_TARGETS = "deepseek/deepseek-v4-pro,openrouter/qwen/qwen3.6-35b"
$env:DOCKER_AGENT_MESSAGE_MERGE_REPORT = "$env:TEMP\message-merge.jsonl"
go test -count=1 -buildvcs=true -v -run '^TestMessageMergeLive$' ./pkg/model/provider

The test skips when the opt-in is absent. It fails when the test binary has no vcs.revision; -buildvcs=true is required so the JSONL report records the commit. A target that cannot be constructed fails the run and records setup_error; a missing credential should be treated as a setup failure, not as a compatibility result.

Scenarios and variants

Each scenario is sent twice against the same provider/model:

Variant Wire shape
preserve Converted messages keep their original boundaries.
merge_system_user The existing MergeConsecutiveMessages helper is applied.

The variants differ only in the messages field. Model, tools, temperatures and all other request fields stay unchanged.

Scenario Preserved shape Merge effect Markers
control system, user none PROBE-CONTROL-OK
multi_system system, system, user two systems become one PROBE-SYSTEM-A-OK, PROBE-SYSTEM-B-OK
consecutive_user system, user, user two users become one PROBE-USER-A-OK, PROBE-USER-B-OK
late_system system, user, system, user none; adjacent merging cannot fix it PROBE-LEADING-OK, PROBE-LATE-OK

late_system is diagnostic. If a target rejects it, that is not evidence that adjacent merging is sufficient: the template or server may reject non-leading system messages entirely.

Reading the result

Outcome Meaning
accepted The endpoint returned a stream and the request was not rejected.
role_rejected The endpoint rejected the message shape with a role/template error.
auth_rejected Credentials or permissions failed; the comparison is invalid.
rate_limited The provider throttled the request; retry later.
empty A stream completed without visible content or a finish reason. Investigate usage and wire data; do not label it a merge requirement by itself.
timeout The request exceeded the per-request deadline.
endpoint_error Another HTTP or transport failure; the comparison is invalid.
not_applicable The target did not route to /chat/completions; no request was sent.
setup_error Provider construction failed before the probe could run.

A preserve rejection followed by a merge_system_user acceptance is strong evidence for that endpoint/model/scenario. Two acceptances only show that both shapes were accepted; they do not prove semantic equivalence. A merge rejection is evidence against a global merge.

Recording evidence

Use one row per provider, model, endpoint and run. Keep the date and commit so a later template change does not silently inherit an old conclusion.

Date Commit Provider/model Endpoint Scenario Preserve Merge Notes
not established No live run recorded in this change.

Only after enough scoped evidence exists should the catalog policy be simplified. Until then, the existing defaults stay in place.

Hermetic tests

The production request path and the merge helper are covered without network access:

go test ./pkg/model/provider/oaistream ./pkg/model/provider

These tests pin: