Skip to content
Salyro
Tool

Conversation linter

Finds what makes a provider refuse a conversation — unanswered tool calls, orphan results, misplaced system prompts — and repairs it safely.

What it does

Paste a request body — or just its list of messages — in OpenAI Chat Completions, OpenAI Responses, Anthropic Messages or Gemini format. The linter finds what the provider will refuse, or read differently from what you meant:

  • a tool call with no result, or a result that answers no call;
  • tool results in the wrong place in a message;
  • a system message inside messages where the API refuses one;
  • thinking blocks that were not sent back as they were returned.

Each finding points at its line and at the rule it breaks, below. Where there is a safe fix, you can pick it, see the change as a diff, and copy the repaired JSON. Everything runs in your browser: nothing you paste is sent anywhere.

How it checks

The format is detected from what the document holds, or you choose it. A list of plain text turns reads the same in Chat Completions and in Messages, so the linter asks rather than guesses — unless the request names a Claude model, which makes it a Messages request.

Every rule says where it comes from. Where the provider's own documentation states the requirement, the rule quotes it and can report an error. Where no provider page could be read, the rule is a heuristic: it reports a warning at most, and says so. Today the Anthropic rules are documented. The OpenAI and Gemini rules are heuristics, because their documentation could not be read when the rules were compiled.

Repairs

Only safe, explicit repairs are offered, and each is applied only if you pick it:

  • Move a system prompt that opens messages to the top-level system field, after what is already there. A system message later in the conversation is never moved: that would change when it applies.
  • Merge consecutive turns from the same role into one — what Messages does with them anyway — including tool results split across user messages.
  • Put tool results first in a user turn, each group keeping its order.
  • Add a placeholder result for a call that has none. The placeholder says it is one and, in Messages, is marked is_error. The linter never invents what a tool returned: replace the placeholder with the real result before you send the request.

A repair edits your JSON and nothing else: keys keep their order, and fields it does not touch stay as they were. Applying the same fixes to a repaired conversation changes nothing. A placeholder result does not bring back thinking blocks: with thinking enabled, the linter may then point out the thinking the turn still needs.

Sharing

A share link holds what you pasted, after the # of the address. Your browser never sends that part to a server, but anyone you give the link to can read it. To share a problem without the conversation, choose Structure only. Every text is replaced; a tool's input, arguments and response keep only their shape; numbers that are not the request's own settings become 0; ids and names are renamed consistently; and a Claude model id in its published form is kept, because which rules apply depends on it (any other model id is replaced). The linter finds the same problems in the shared copy.

The rules

Rule: missing tool result

A tool call that no result answers.

  • Messages (documented, error): Anthropic's documentation states: "Tool result blocks must immediately follow their corresponding tool use blocks in the message history. You cannot include any messages between the assistant's tool use message and the user's tool result message." A request that breaks it is refused with an error such as tool_use ids were found without tool_result blocks immediately after.
  • Chat Completions, Responses and Gemini (heuristic, warning): a call with no tool message, function_call_output or functionResponse answering it where the format expects one.

If the result is there but in the wrong place, the finding says where it is. If there is no result at all, the repair adds a marked placeholder.

Rule: orphan tool result

A tool result that answers no call — its id matches no call, or the call is not in the message just before it.

  • Messages (documented, error): the same requirement as above: results immediately follow their calls.
  • Chat Completions, Responses and Gemini (heuristic, warning).

There is no automatic repair: removing a result, or guessing which call it meant, is a decision about your data.

Rule: tool result not first

In a Messages user turn that returns tool results, something comes before a result. Anthropic's documentation states: "In the user message containing tool results, the tool_result blocks must come FIRST in the content array. Any text must come AFTER all tool results." The repair moves the results ahead of the other blocks.

Rule: system in messages

A role: "system" message inside a Messages messages list, where the API refuses it. Some Claude models accept system messages mid-conversation — Anthropic lists Claude Fable 5.1, Mythos 5.1, Fable 5, Mythos 5, Opus 5.5, Opus 4.8 and Opus 5, and says the feature "is not available on Claude Sonnet 5" — so the rule reports only what is refused:

  • At the start. "A system message that carries content cannot be the first entry in messages", on any model. The repair moves it to the top-level system field, which is where instructions that apply from the start belong.
  • On a model that does not accept it. No repair: moving it to the top would make it apply from the start instead of from where it is.
  • In the wrong place. It must immediately follow a user turn (one that returns tool results counts) or an assistant turn ending in a server tool result, and precede an assistant turn or end the list — never between a tool call and its result.

Consecutive system messages count as one section. A system message with no content — one that only changes the effort level — is accepted anywhere, but only where that is available: it is in beta on Claude Fable 5.1, Mythos 5.1, Opus 5.5 and Opus 5. On another model that accepts system messages it is a warning; on one that does not, an error. When the request names no model the linter recognises, a correctly placed system message with content is a warning to check the model.

Rule: consecutive same role

Two Messages turns in a row from the same role. This is a note, not an error: the API reference states that "Consecutive user or assistant turns in your request will be combined into a single turn." The note is there because two turns you meant to be separate are read as one. Every other rule reads them the same way the API does — as one turn — and the repair merges them explicitly. When the messages split one turn's tool results, the rule is a warning instead: see split tool results.

Rule: thinking not returned

With extended thinking on, the thinking an assistant turn produced must be sent back with its tool results. Anthropic's documentation states: "when you return tool results, you must pass the thinking blocks from the assistant message back to the API, complete and unmodified." A tool loop is one assistant turn, and "Consecutive tool calls do not require interleaved thinking": in manual mode (thinking.type: "enabled") the API enforces that the assistant turn which started the loop begins with a thinking block, and that is what the linter checks — not every step of the loop. Adaptive mode relaxes the rule, and a model that did not think produces no block, so adaptive mode is not checked. There is no repair: thinking cannot be recreated.

Rule: thinking without signature

A thinking block with no signature. The API reference states: "Thinking blocks must be passed back unmodified and in their original order; a modified block results in a 400 invalid_request_error". A block without the signature it was returned with is not that block. There is no repair.

Rule: duplicate tool call id

Two calls with the same id, in any format. It is a heuristic: none of the documentation read states it as a rule. But a result names its call by id, so it cannot say which of the two it answers, and the linter offers no placeholder for either.

Rule: split tool results

A Messages assistant turn made several tool calls, and their results come back in separate user messages. The API combines consecutive user messages into one turn, so the request is accepted — but Anthropic's parallel tool use guide lists this as "Wrong: separate user messages reduce parallel tool use": results returned this way teach the model to stop calling tools in parallel. A warning, with a repair that merges the messages into one.

What it does not know

  • It checks the structure of the conversation, not whether the provider accepts every field, model or parameter in the request.
  • The OpenAI and Gemini rules are heuristics until their documentation can be read. A warning there is a strong hint, not the provider's word.
  • It does not run the conversation, so it cannot tell whether a result is correct — only whether it is where the provider expects it.
  • It pairs function calls with their outputs, not every kind of call: in Responses, custom_tool_call, computer_call and mcp_approval_request items are not checked, and in Gemini thought signatures are not checked.
  • A Responses request that continues an earlier one (previous_response_id, a conversation, or an item_reference) answers calls it does not contain, so outputs there are not reported as orphans.

FAQ

What does "tool_use ids were found without tool_result blocks immediately after" mean?

A Messages assistant turn called a tool, and the user message right after it does not return a tool_result with that call's id. Paste the request here: the finding points at the call, and the repair adds a marked placeholder you can replace with the real result.

Why is a warning not an error for OpenAI or Gemini?

Every error needs the provider's own documentation behind it. Those pages could not be read when these rules were compiled, so their rules are heuristics.

Can I share a conversation without sharing its content?

Yes. In Share, choose Structure only. The link then holds the conversation's shape with every text replaced, and the same problems show up in it.

Sources

Every rule's source — the provider page, the date it was read and the sentence quoted — is recorded as Reference Data and listed in the public tools' data freshness report. The Anthropic rules quote five pages on platform.claude.com: the tool-use guide (handle tool calls), the parallel tool use guide, the Messages API reference, the mid-conversation system messages guide and the extended thinking guide.

Where the numbers come from

  • Facts about models and providers that are not in that catalogue carry their own source and the date they were checked, and are shown as unknown where no reliable source exists.