Make sense of tool-call responses
When an LLM decides to call a tool, the response buries the useful part — which function, what arguments — inside a verbose JSON envelope, often with the arguments double-encoded as a string. Paste the raw response here and the parser extracts every call cleanly: function name, call ID, and pretty-printed arguments, for both OpenAI and Anthropic formats.
Why the two formats are different
OpenAI and Anthropic each chose a different JSON shape for tool calls:
OpenAI wraps everything inside choices[].message:
{
"choices": [{
"message": {
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\": \"London\", \"unit\": \"celsius\"}"
}
}]
}
}]
}
The arguments are a JSON-encoded string — a string inside the JSON, not a nested object. You have to parse it a second time to read the actual values.
Anthropic uses a flat content[] array with blocks typed as tool_use:
{
"content": [{
"type": "tool_use",
"id": "toolu_01A",
"name": "get_weather",
"input": {
"location": "London",
"unit": "celsius"
}
}]
}
Here the arguments are already a proper object under input — no double-decoding needed.
This tool detects which format you pasted and normalises both into the same human-readable output.
How it works
The parser first tries to read OpenAI’s shape
(choices[].message.tool_calls[].function), where arguments is a JSON string
it decodes and re-indents. If that is absent it looks for Anthropic’s shape
(content[] blocks of type tool_use with an input object). Either way you
get a normalised list of calls. Invalid JSON produces a clear error instead of a
blank screen.
Common debugging scenarios
My handler is not firing. The most frequent cause is malformed arguments — a missing required field, a wrong type, or a key name that does not match what the handler expects. Paste the response here, read the pretty-printed arguments, and compare them against your function schema.
The arguments look correct but the value is wrong. OpenAI sometimes injects default values for optional parameters not present in the model output. Check whether the value you see in the parsed arguments is what the model actually produced or a downstream default.
I am getting a parse error. This usually means the model produced a partial or malformed JSON string inside arguments. This can happen in streaming mode if you assembled the chunks incorrectly. Make sure you are passing the fully-assembled final response, not a raw stream chunk.
Multiple tool calls in one response. Both formats support returning several tool calls in a single response turn. The parser extracts all of them and presents each separately so you can verify every call, not just the first.
Tips
- The pretty-printed arguments are valid JSON you can paste straight into a unit test for your function implementation.
- For streaming responses, paste the fully-assembled final JSON, not individual delta chunks — the parser expects a complete response object.
- Copy the call ID alongside the arguments if you are building a tool-result message to send back to the model; the ID is required for the model to match your result to the original call.