Tool-Call JSONL Validator
Function calling is where the upload fails. The conversation validators check roles and content; none of them checks that arguments is a string rather than an object, that every tool_call_id is answered, or that the tool being called was ever declared. Those are the three that get a file rejected — after the upload, in a message that names neither the line nor the field.
Validate
Full report
Why this is separate from the other validators
The OpenAI and Anthropic validators check the conversation: roles, alternation, empty content, an assistant turn that exists. Tool calling adds a second structure on top of that — a declaration list, an id that has to round-trip, and an argument payload with its own encoding rules — and it is checked here rather than bloating both.
What it checks — OpenAI
argumentsis a JSON string. Not an object."{\"city\":\"Paris\"}", not{"city":"Paris"}. It also has to parse, and to parse to an object.- Every
tool_calls[].idis answered by exactly one later message withrole: "tool"and a matchingtool_call_id. A call with no result teaches the model to call and stop. - Every tool message answers a real call. An orphan
role: "tool"message — usually left behind when a conversation was trimmed — is rejected. - Names are declared and legal. A call to a function missing from
tools[]is an error; so is a name outside[A-Za-z0-9_-]{1,64}, and a name declared twice. - Parameter schemas are objects.
"type": "object"at the top,propertiespresent, and every entry inrequiredactually inproperties— the mismatch that makes a model omit an argument it was told to send. - Arguments satisfy the declared schema's required list, and respect
additionalProperties: falsewhen it is set. - The deprecated shapes are flagged: top-level
functionsand message-levelfunction_callstill work in some places and are not what to write in 2026.
What it checks — Anthropic
inputis an object, not a JSON string. This is the mirror image of the OpenAI rule and the reason a file converted from one to the other fails.input_schema, notparameters. Using OpenAI's field name is the most common single mistake in an Anthropic tools array.- Every
tool_useblock is answered by atool_resultwith a matchingtool_use_id, in a user message, as its first content block. - Blocks are in the right role —
tool_useonly from the assistant,tool_resultonly from the user. - Ids are unique and never answered twice.
Mixed formats
Auto-detect works per record, which means it will happily read a file with some OpenAI records and some Anthropic ones — and then say so in the summary, in red. A fine-tune file has one format; a mixture is usually two exports concatenated, and the fix is to convert one side with the chat format converter before merging.
What it does not check
Types inside the arguments, string formats, enum membership, and anything else a full JSON Schema validator does. It checks the structure a provider rejects on, not the semantics of your tool. It also cannot tell you that the result you recorded is the result the tool would really return — a training file full of plausible but invented tool outputs validates perfectly and teaches the model to hallucinate confidently.