--json-schema: no way to tell whether strict schema enforcement was applied (silent fallback to non-strict)
What I'm asking for
A way for a caller using --json-schema to determine whether strict schema enforcement was actually applied to their request.
Today there is no such signal on any channel a caller can read, so a caller who needs the guarantee cannot verify they got it.
Background
--json-schema compiles the supplied schema into a synthesized StructuredOutput tool. That much is visible at runtime:
[INFO] [Stall] tool_dispatch_start tool=StructuredOutput toolUseId=toolu_… permissionDecisionMs=1
[INFO] [Stall] tool_dispatch_end tool=StructuredOutput toolUseId=toolu_… outcome=ok durationMs=0
Before that, the CLI attempts to derive a strict tool schema, and on failure continues without it. The 2.1.263 binary carries the branch and its message:
Strict structured-output schema derivation failed, falling back to non-strict: <err>
with these named derivation-rejection reasons:
unsupported_keyword, unsupported_const, unsupported_enum, mismatched_keywords, no_properties, additional_properties, invalid_required, unsupported_items, missing_type, schema too large, $async schemas are not supported
Strict tool use guarantees tool_use.input validates exactly; non-strict does not. So the two outcomes differ in exactly the property a caller passes a schema to obtain — but they are indistinguishable from outside.
What I tried, and why none of it works as a workaround
CLI 2.1.263, seven schemas: a minimal strict-shaped one, plus pattern+minLength, format: date-time, anyOf, patternProperties, not, and a recursive $ref.
| Channel | Result |
|---|---|
| --output-format json result object | No field reports strict vs non-strict (26 top-level keys; structured_output is present but says nothing about how it was enforced) |
| process stderr | 0 bytes, all seven |
| --debug | 0 bytes on stderr |
| --debug-file | 37 KB captured, zero occurrences of the fallback message |
The --debug-file result is not evidence the fallback didn't fire. tengu_structured_output_enabled is emitted on the success path, so it should have appeared for all seven accepted schemas — it appears zero times as well. That is a positive control showing the debug log does not carry these tengu_* events at all, so the channel cannot be used to observe either outcome.
So please don't close this with "use --debug" or "check stderr" — both were tested and neither carries it. The only channel that appears to carry the signal is internal analytics, which the caller cannot see.
What I could not establish
Whether the fallback ever actually fires. All seven schemas above were accepted and produced correct structured output, including the ones using keywords I would have expected strict mode to reject. I could not force the degradation path, so I can't speak to how often this matters — which is itself the reason I'm filing: there is no way to find out.
I've deliberately framed this as a feature request rather than a bug for that reason. Nothing documents --json-schema as promising strict enforcement, so this is a missing capability, not broken behaviour.
Suggested shape
A boolean on the result object, alongside the existing plugins_applied / hooks_applied bits which set the precedent — e.g.:
{ "subtype": "success", "structured_output": { … }, "strict_schema_applied": true }
Anything equivalent would do: a field, a system init line, or a documented rule for when derivation is guaranteed to succeed. The last would arguably be best — if the accepted-keyword set were documented, callers could author schemas that provably derive strict and would not need a runtime bit at all.
Why it matters
A caller who needs guaranteed-valid arguments has to keep a full client-side validation-and-repair loop regardless, because they cannot tell whether the CLI's guarantee is in force for their particular schema. That loop is redundant work whenever strict derivation did succeed, and there is currently no way to know when that is.
Related, and the reason this came up: error_max_structured_output_retries and structured_output_retry_exhausted already give a clean signal for "the model called the tool but no attempt survived validation". That failure is well surfaced; the enforcement mode is the gap.
CLI version: 2.1.263