BuildTroubleshoot tool calls

Troubleshoot tool calls

Most tool-calling problems fall into a handful of patterns. Find the symptom below, check the likely causes in order, and apply the fix. When you change a definition or prompt, re-run the cases that failed and the rest of your test set.

The request is rejected

SymptomLikely causeFix
upstream_error with a 4xx after you send tool resultsA tool message has no matching tool_call_id, or the assistant message with tool_calls was changed or droppedSend back the assistant turn unmodified, then one tool message per call with the same id.
Same error on the second round onlyYou sent tool messages without the preceding assistant messageThe assistant message must come immediately before its tool results.
413 too_many_messages or payload_too_large in long loopsHistory and tool results keep growingTrim old results; see Tool results and context.
Error after you trimmed historyA tool call or its result was removed without the otherRemove call and result together, or neither.

The model does not call the tool

Likely causeFix
The description does not say when to use itAdd “Use this whenever the user asks about …” to the description.
The system message tells the model to answer directlySay instead: “Use the tools to look things up before answering.”
Another tool looks like a better fitRename or describe the two so their purposes do not overlap.
tool_choice is "none"Use "auto", or name the function to force it.
The question can plausibly be answered from general knowledgeTell the model it must not answer from memory for this kind of question.

The model calls the wrong tool

  • Check names and descriptions side by side: if a newcomer could confuse them, so can the model.
  • Add “do not use this for …” sentences that point to the right neighbour.
  • Reduce the tool list to what the current step needs.
  • Add a test case for each confusion you see, and keep it in the set.

Arguments are wrong or malformed

SymptomFix
arguments is not valid JSONParse inside try; on failure return {"error": "arguments were not valid JSON"} as the tool result. The model usually corrects itself.
Wrong format (dates, ids, units)Put the format and an example in the property’s description, and a pattern or format in the schema.
Invented values for required fieldsTell the model to ask the user for missing information instead of guessing, and validate in code.
Values outside the allowed setUse enum in the schema and check it in code.

Server-side schema enforcement is planned; see Strict tool arguments.

The model calls tools in a loop

  • The result does not answer the question. Return clearer results, including “no results” explicitly: {"results": [], "note": "nothing matched; try a broader query"}.
  • Errors are vague. Say what was wrong and what to try instead.
  • No stopping rule. Add a round limit in your loop (for example 8 rounds) and tell the model in the system message how many lookups are reasonable.
  • The same call repeats. Detect repeated identical calls in your loop and return “You already called this with the same arguments; use the earlier result.”

The final answer ignores the tool result

  • Make results easy to read: field names that explain themselves, units included.
  • Tell the model to base its answer on tool results: “Answer using the tool results; if they do not contain the answer, say so.”
  • Check that you sent the result as a tool message, not as a user message.

Parallel calls cause confusion

When the model asks for several tools at once, return one tool message per call. Order them in the same order as the calls, and include enough context in each result (for example the id that was looked up) so each one stands on its own. See Parallel tool calls.

Log every round of a tool loop with the request id (x-syntic-request-id), the tool calls and a truncated copy of each result. Most tool bugs are obvious once you can read the sequence.

Was this page helpful?