On GPT-5.6 (Chat Completions API), adding a strict `response_format={"type":"json_schema"}` appears to prevent prompt cache writes entirely

Summary

On GPT-5.6 (Chat Completions API), adding a strict response_format={"type":"json_schema"} appears to prevent prompt
cache writes entirely.

The request succeeds normally (HTTP 200), the schema is clearly processed, and
prompt_tokens_details.cache_write_tokens is still reported — but its value remains 0 on every request, so no
prompt cache is ever created.

The exact same request works correctly with:

  • response_format={"type":"json_object"}
  • no response_format
  • gpt-5-mini using the same strict schema

According to the Prompt Caching and Structured Outputs documentation, structured output schemas are expected to
participate in prompt caching (or at least schema processing is cached for reuse). The observed GPT-5.6 behavior
therefore appears inconsistent with the documented behavior.

I also observed what may be a separate issue: GPT-5.6 implicit prompt caching appears to write (and bill) the cache
repeatedly without ever reading it.

Environment

  • API: OpenAI Chat Completions (/v1/chat/completions, not Azure)
  • Models: gpt-5.6-terra (affected), gpt-5-mini (not affected)
  • SDK: openai-python 2.41.0
  • Tested: 2026-07-13 (JST)

Repro

Two sequential calls, ~3 seconds apart. The system message is ~1.1k tokens of meaningless filler text (identical across
calls, just above the 1,024-token caching minimum); only the short user message differs (test 1 / test 2). Each
pair reuses the same prompt_cache_key. Explicit variants place a breakpoint on the system text block and set
prompt_cache_options to explicit:

client.chat.completions.create(
    model="gpt-5.6-terra",
    max_completion_tokens=512,
    messages=[
        {"role": "system", "content": [
            {"type": "text", "text": FILLER_1100_TOKENS,
             "prompt_cache_breakpoint": {"mode": "explicit"}},
        ]},
        {"role": "user", "content": "test 1"},
    ],
    prompt_cache_key="probe-a",
    extra_body={"prompt_cache_options": {"mode": "explicit"}},
    # vvv with this present, cache_write_tokens stays 0 vvv
    response_format={"type": "json_schema", "json_schema": {
        "name": "probe", "strict": True,
        "schema": {"type": "object",
                   "properties": {"ok": {"type": "boolean"}, "note": {"type": "string"}},
                   "required": ["ok", "note"], "additionalProperties": False}}},
)

Results

Each row = two sequential calls as above. “–” means the cache_write_tokens field does not exist in the usage response
(pre-5.6 models have no write billing).

# Model / cache mode response_format write (call1 / call2) cached (call2) request_id (call1 / call2)
A gpt-5.6-terra / explicit json_schema (strict) 0 / 0 :cross_mark: 0 :cross_mark:
req_c5dcc811de75404697b700b4d22aa8df / req_613ba628cccc4b5289f301079d13332f
B gpt-5.6-terra / explicit json_object 1125 / 0 :white_check_mark: 1125 :white_check_mark: req_08cf4645d1ef4cef9253586f54329047 /
req_743e4abe926c4d1d9caad54c2d1b08ec
C gpt-5.6-terra / explicit (none) 1125 / 0 :white_check_mark: 1125 :white_check_mark: req_e837a17a98054ad1abe0724f7617be96 /
req_b4e63a71391b43c491e9c7868d7d8679
D gpt-5-mini / implicit json_schema (strict) – / – 1024 :white_check_mark: req_338b2ecec8fa46e88f8461ef22d92d06 /
req_441484809a17431da1dce18738f64f66
E gpt-5.6-terra / implicit (none) 1132 / 1132 :warning: 0 :warning: req_ad8e1d9569064c51a4c16fbccf73292c /
req_d2179dd5ab7d4889a633df4c552d3e2d

Notes:

  • A vs B/C: the only difference is response_format. With strict json_schema, prompt cache writes never occur,
    even though the schema is clearly processed (prompt_tokens increase by ~32: 1135 → 1167) and the request succeeds
    normally.
  • D: on gpt-5-mini, the same schema coexists with prompt caching as expected. This matches the documented behavior
    that structured output schemas are processed once and reused subsequently.
  • E: this may be unrelated, but GPT-5.6 implicit mode appears to charge cache writes repeatedly
    (cache_write_tokens=1132 on both sequential calls) without ever reporting cached reads.

Expected behavior

A strict response_format={"type":"json_schema"} should not disable prompt caching on GPT-5.6.

Given an identical cacheable prefix and the same prompt_cache_key, the first request should write the prompt cache and the second request should
If this combination is intentionally unsupported, the API should return a clear error or the limitation should be documented, rather than succeeding
normally while reporting cache_write_tokens=0 for every request.

Note: in order to turn off a cache write at the end of a final user message (total length of input), include:

    "prompt_cache_options": {  # New for gpt-5.6 family [sol, terra, luna]
        "mode": "explicit",  # default "implicit", for only one total cache write
        "ttl": "30m",  # only one default parameter "30m" for 30 minutes
    },

Larger issue: no cache writes at developer messages

Testing json_schema - chat completions - implicit cache

All calls against “gpt-5.6-terra”, default (null) reasoning/verbosity

Sending developer-only message: the AI has to infer an empty schema:


req_20570db7f5e24ff2939357f799bd5ae4

In implicit default, the issue: there is no cache write on only a developer message that is significantly in excess of the threshold.

  "usage": {
    "prompt_tokens": 1374,
    "completion_tokens": 320,
    "total_tokens": 1694,
    "prompt_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 0,
      "audio_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 98,
      "audio_tokens": 0,
      "accepted_prediction_tokens": 0,
      "rejected_prediction_tokens": 0
    }
  }

Making no implicit cache writes, when there is a structured response schema, might be reasonable default if one assumes that a JSON output will never be a growing response like a “chat”. You’ll see they didn’t do that, the API is messed up.

Testing json_object - chat completions - implicit cache

Turning off json_schema, for instead json_object (and the developer message already had high enough quality to operate alone):


req_cdac18a83fc84b97bfc78b81f21d9a42

  "usage": {
    "prompt_tokens": 1297,
    "completion_tokens": 318,
    "total_tokens": 1615,
    "prompt_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 0,
      "audio_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 114,
      "audio_tokens": 0,
      "accepted_prediction_tokens": 0,
      "rejected_prediction_tokens": 0
    }
  }

Then we still have “cache_write_tokens”: 0 in json object mode


Testing no response_format - chat completions - implicit cache

Final implicit test: using developer language only


req_7dbda6406a3b4a29a1dcf8cc27fed223

  "usage": {
    "prompt_tokens": 1297,
    "completion_tokens": 329,
    "total_tokens": 1626,
    "prompt_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 0,
      "audio_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 42,
      "audio_tokens": 0,
      "accepted_prediction_tokens": 0,
      "rejected_prediction_tokens": 0
    }
  }

No cache write was made on 1297 tokens sent - “cache_write_tokens”: 0,

I doubled up the developer message language: still no cache write:
req_81309862dfe7416394c227ebb87b70a7

  "usage": {
    "prompt_tokens": 2600,
    "completion_tokens": 96,
    "total_tokens": 2696,
    "prompt_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 0,
      "audio_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 0,
      "audio_tokens": 0,
      "accepted_prediction_tokens": 0,
      "rejected_prediction_tokens": 0
    }
  }
  • The API is not fulfilling its promise of the amount for cache - PERIOD.*

Test with a “user” message included to actually get an instructed schema - THEN we get a cache write:

  "usage": {
    "prompt_tokens": 1334,
    "completion_tokens": 224,
    "total_tokens": 1558,
    "prompt_tokens_details": {
      "cached_tokens": 0,
      "cache_write_tokens": 1331,
      "audio_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 0,
      "audio_tokens": 0,
      "accepted_prediction_tokens": 0,
      "rejected_prediction_tokens": 0
    }
  }

Switch that to a developer message as the second message, again NO implicit cache write at the end.


req_49447dea43f64c7b822525d7c7cf97de
“cache_write_tokens”: 0


Conclusion: OpenAI is not storing at developer message at end of input, as an automatic “prompt_cache_breakpoint”, or an explicit specification.

They expect “chat” patterns and can’t imagine anything else?

I think both of us have done plenty of free work for OpenAI, that this must be explained or fixed.

Symptom: A naive pattern of “preload” or “warm up” call will not generate a cache write where desired, and the first post shows failure even on explicit use mid-messages. An explicit use is also shown not to (didn’t test that myself).

Workaround: add a 1-part user message as an explicit write, and then use a 2-part user message in production of the next 30 minutes of calls. There, you can just send a linefeed as the first part. Alternately, a standalone “preprompt” user message 1 of no impact.

Thanks for reporting this and for sharing such a detailed reproduction. We retested the same setup on gpt-5.6-terra, including a strict JSON schema and an explicit cache breakpoint, and confirmed that the first request now writes the prompt cache and the second request successfully reuses it. Could you try your original example again? If you still see zero cache writes, please share a recent request ID so we can investigate further.

TL;DR: Seems working, possible latency issue between write and that write being readable.


My version of “Playground”, bring-your-own-key and with sharing of calls/settings/prompt, surfaces enabling “explicit” prompt cache for the API call (turning off an automatic final message write breakpoint). It also allows per-message part additions of the parameter prompt_cache_breakpoint to force a paid write to context window cache (maximum, the most recent four “marks”).

Baseline: JSON schema, gpt-5.4-mini

Here is a share of the settings seen captured in screenshot below, and the assistant response is included. Running, deleting the assistant response, and running again for this screenshot delivers a cache hit when these otherwise untolerated parameters are dropped silently on older models by the software:

MyPlayground share - gpt-5.4-mini + json_schema

As you can see, a JSON schema response is conformed to, and there is 1419 tokens of prompt (plus billed internal system message which is increased by placed schema text). The developer message, a JSON schema helper AI, (not depicted) is a 1306 token message, and then there are more tokens of the JSON schema as response format actually being injected to the AI, where apparently 1280 tokens is the granularity within the start of context that is cached.

Now, switch the model to gpt-5.6-terra, as is the initial problem report. Run the single user input again, where a user message was needed previously, because of the issue of a breakpoint and write NOT created at developer message. All input message parts have breakpoint.

Run 1, a write:

Run 2, ANOTHER WRITE, 30s or so, not a cache hit

Conclusion: the error reported by OP continues where I expect a hit. A prompt cache key was sent (and the MyPlayground still sends a default prompt_cache_key if the UI field is blank.)

Run 3, after 5 minutes of writing this up:

Finally, a cache hit against one of those two previous writes of identical calls

Run 4, changing the user input, expecting the developer message breakpoint to have also been a write point.

Conclusion 2: Caching not ultimately broken, it can succeed with a JSON schema.

Verify this pattern with a changed prompt cache key and different user message, developer message being marked breakpoint

Run 1: write 1398
Run 2, 60s later: cached 1386

It seems the pattern of:

  • mark all message parts with breakpoint, understanding a limit of 4,
  • make a “store” call that writes cache (and also is an initial useful output),
  • a significant delay after write might be required, beyond automation, more like the interval between manual “chat”,
  • repeated within 30 minutes

Can result in success.


My prior report - no write or hit with a developer message as the final message in a sequence

  • turn off the API call’s explicit write only option
  • remove all explicit breakpoints
  • run only a developer message
  • expect a write, expect a match if repeating or growing from that point

Run 1:

write: 1387

Run 2, repeat identical in:

in: 1390 cached: 1387

Run 3, add a user message on that developer message

cached: 1387

So it seems a no-parameter or “naive” setup of just a developer message can create a usable cache write now, addressing my own addition of another concern. So that issue also seems addressed in the GPT-5.6 family (Terra used for all tests).

Note: It is understood that “implicit” on gpt-5.6 and changing and not growing would not have any hits, as there is no longer any automatic partial matching (also a backported “symptom” of using 24h retention default on prior models now).

You will notice a symptom that I reported elsewhere is continuing - Chat Completions NOT preserving or enforcing the order of the JSON schema with GPT-5.6.

Above, the schema and its requirements is in this order:

  "required": [
    "topic of message",
    "instructions",
    "body of message"
  ]

Find the last screenshot in my replications above. gpt-5.6 did not obey.