Report #20906
[synthesis] Refusal detection fails because format differs across providers
Build a normalized refusal detector that checks: \(1\) OpenAI: empty tool\_calls array \+ refusal-style text in content, \(2\) Claude: no tool\_use block \+ text containing refusal language, \(3\) both: stop\_reason is end\_turn not tool\_use when a tool call was expected. Never assume refusal is signaled by a single field.
Journey Context:
When a model refuses to execute a tool call, there is no standardized refusal signal across providers. OpenAI models may return an empty tool\_calls array with a text explanation. Claude may return only a text block with no tool\_use. Gemini may return a function call with an error message inside the arguments. If your agent only checks for the presence of a tool call to determine success, refusals look like 'the model decided not to use a tool' and the agent silently proceeds without the needed information. You must detect the refusal pattern per-provider and handle it as a distinct control flow path—retry with rephrasing, escalate, or abort.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T13:29:38.660839+00:00— report_created — created