Which API surface a rule applies to
The one-line version. An ordering rule is a claim about a model reached through a specific API, not about the model. Enable a recipe only when you are dispatching through the API that recipe was derived from. Through any other surface it will, at best, check nothing; at worst it will block turn state that the surface you are actually using accepts.
Why this page exists
Every other page in this section is organised by model — "dispatching to Nova? enable 'nova'." That framing is incomplete, and the omission is load-bearing.
A vendor's ordering requirements are enforced by an endpoint, not by weights. The same model reached two different ways enforces two different sets of rules:
| The model | Reached via | What enforces ordering |
|---|---|---|
| Amazon Nova | Bedrock Converse | Converse's own content-block grammar — text before toolUse, strict alternation |
| Amazon Nova | an OpenAI-compatible gateway | whatever that gateway normalises to before it calls Converse |
| Claude | Anthropic Messages | Anthropic's block ordering, conditioned on anthropic-beta headers |
| Claude | Bedrock Converse | Converse's grammar plus Anthropic's |
| Gemini | generateContent | functionCall / functionResponse part ordering, thoughtSignature |
| Gemini | an OpenAI-compatible gateway | the gateway's translation of tool_calls into parts |
The recipes in Recipes were derived from vendor documentation describing the first row of each pair. Applied to the second, they are describing a wire format the request never takes.
A gateway may already be doing the guard's job
This is the failure mode that is hardest to see, because everything appears to work.
An OpenAI-compatible gateway in front of a non-OpenAI vendor cannot forward your messages verbatim — it has to translate them into the vendor's native shape. That translation routinely includes the very normalisations these rules check for. A gateway fronting Bedrock will merge consecutive same-role messages (and insert a filler turn if merging is not possible) because Converse rejects them. A gateway fronting Gemini will inject a thoughtSignature sentinel on historical functionCall parts because Gemini 3 rejects requests without one.
Both of those are correct behaviour for the gateway. Both also mean that if you enable 'strict_alternation' or 'thought-signature-required' while dispatching through such a gateway:
- the guard evaluates turn state the vendor will never see in that shape;
- a violation the guard blocks would have been repaired in transit anyway;
- and a passing dispatch tells you nothing about the vendor, because you measured the gateway.
We hit exactly this while auditing these rules against live models. Cells dispatched through an OpenAI-compatible endpoint returned "the vendor accepts this" for strict_alternation on three separate families — until reading the gateway's source showed it merging consecutive same-role messages before the request left the building. The vendor never received the violation. The result was an artefact of the path, not a fact about the model.
What this means for you
Match the recipe to the API you dispatch through.
| If you dispatch through… | Then… |
|---|---|
the vendor's native API (Anthropic Messages, Gemini generateContent, Bedrock Converse) | The recipes apply as documented. This is the case they were written for. |
| an OpenAI-compatible gateway in front of another vendor | Assume the gateway normalises shape. Prefer 'permissive' or a recipe narrowed to rules the gateway demonstrably does not touch, and verify against the gateway's own behaviour rather than the vendor's docs. |
| a gateway you do not control | Treat every ordering rule as unverified until you have observed the request the vendor actually received. |
Rules that are surface-specific by construction. These name an API in their own description and are meaningless anywhere else:
converse_text_before_tool_use— Bedrock Converse content blocks. There is notoolUseblock on an OpenAI-shaped request, so through any other surface this rule cannot fire on the thing it describes.thought_signature_required/thought_signature_advisory— GeminigenerateContentthoughtSignatureparts. An OpenAI-shapedtool_callsentry has no such field; whether one reaches Gemini is decided by the translator, not by your turn state.harmony_commentary_channel— the Harmonycommentarychannel, a prompt-format concept. Whether it survives depends on how the serving stack renders the conversation.role_remap_split_tool_roles/role_remap_inline_tool_call— a consumer-supplied wire-role tag. These check the consistency of your own renderer against your own tag; see Writing a profile. Nothing in the ADK writes that tag, so without a renderer that reads it, both legs of any test render identically.
How to check, rather than assume. Capture the request as assembled. Every LLM battery exposes an onPromptAssembled hook that hands back the exact body about to be dispatched — observe it, compare it to what the vendor's documentation describes, and only then decide whether a rule is checking something real. If your traffic passes through a gateway, that hook shows what the gateway received, not what the vendor did; for that you need the gateway's own logs.
Measured: the same rule, two surfaces
Amazon Nova, strict_alternation. The violating shape is two consecutive user turns.
| Path | Result |
|---|---|
| OpenAI-compatible gateway → Bedrock | 200 — but the gateway merged the two turns before Converse saw them |
| Bedrock Converse directly (no gateway) | 200 — Nova accepted the consecutive user turns as sent |
Only the second row is evidence about Nova. The first measured the gateway's repair. Both look identical from the client.
Same model, converse_text_before_tool_use — the rule that says text blocks must precede toolUse within one assistant turn. Sent natively, toolUse first and text second:
| Shape | Result |
|---|---|
[toolUse, text] — what the rule forbids | 200 end_turn |
[text, toolUse] — what the rule demands | 200 end_turn |
Converse accepted both. That does not make the rule worthless — a vendor may still degrade quality, and behaviour differs across models on the same API — but it does mean the rule is not enforcing a hard wire constraint on this model, and should not gate dispatch as though it were.
Honest limits of the shipped recipes
The recipes encode vendor documentation. Documentation describes the native API. We have verified a subset against live traffic and found that several rules do not reproduce through an OpenAI-compatible surface — which is a statement about surfaces, not a refutation of the vendor docs.
Treat a recipe as: this is what the vendor says its native API requires. It is not: this is what will happen to your request on the path you are actually using. Only observation settles the second, and this page exists because the difference between the two is easy to miss and expensive to discover in production.