Um dos nossos engenheiros atingiu seu limite mensal de gasto em dois dias. Nosso Gateway de Governança fez o que devia e interrompeu o gasto, mas o motivo de o limite ter sido atingido em dois dias não era óbvio.
A versão curta
- Nas cargas afetadas, o Codex regrava um prefixo grande e estável no cache de prompts porque não consegue emitir o breakpoint explícito que marca o fim desse prefixo e gera uma nova chave de cache a cada sessão.
- Gravações no cache de prompts são cobradas a 1,25× a entrada sem cache e leituras do cache a 0,10×, então uma gravação custa 12,5× uma leitura. Na nossa fatura, as gravações foram 90% de todo o gasto com GPT-5.6.
- No mesmo período, o uso do mesmo cliente e gateway com o GPT-5.5 registrou 9,17 milhões de tokens de entrada e nenhuma cobrança separada por gravações no cache. O formato de requisição enviado pelo Codex era o mesmo; o que mudou foi a cobrança aplicável.
- Em um replay controlado, injetar o campo ausente no gateway junto com uma chave de cache estável entre sessões produziu 0% de acerto na requisição fria e 96–97% nas requisições quentes, reduziu os tokens de gravação em 65% e reduziu o custo da carga reproduzida em 59% pelos preços publicados do Bedrock. Para a mesma carga capturada, o caminho sem mitigação custou cerca de 2,5 vezes o caminho mitigado.
- Para o tráfego do Codex que não passa por um gateway, não existe hoje uma solução apenas por configuração. A correção geral exige uma mudança dentro do Codex, registrada em openai/codex#35300.
Por que as gravações no cache viraram a maior linha do GPT-5.6
Nas tarifas do Bedrock aplicáveis ao GPT-5.5, as gravações no cache de prompts não geravam cobrança. Um cliente que regravava todo o seu prefixo a cada requisição não pagava por isso, então o comportamento não criava uma linha na fatura nem motivo para investigá-lo. No GPT-5.6, uma gravação é cobrada a 1,25× a entrada sem cache, enquanto uma leitura do cache é cobrada a 0,10×. Regravar um prefixo que poderia ter sido lido custa agora 12,5 vezes o valor de sua leitura.
O limite de gasto é o que tornou isso visível em dois dias, e não no fechamento do mês. O gasto é verificado contra o limite e reservado antes de a inferência ser executada, então uma taxa de consumo fora do padrão aparece como requisição bloqueada, e não como uma linha de fatura que ninguém lê até o mês seguinte.
Nosso próprio registro no gateway já mostrava o volume de gravações no cache, e seus números correspondiam exatamente aos do AWS Cost Explorer. O gasto que investigamos aparece abaixo, com dados do AWS Cost Explorer para OpenAI GPT-5.6 Sol (Amazon Bedrock Edition), dias completos de 2026-07-01 a 2026-07-23, filtrados por RECORD_TYPE = Usage.
| tipo de uso | tokens | custo | participação |
|---|---|---|---|
| gravação no cache | 258,8M | US$ 1.780,33 | 90,0% |
| saída | 3,9M | US$ 127,56 | 6,5% |
| entrada | 9,8M | US$ 53,98 | 2,7% |
| leitura de cache | 28,6M | US$ 15,71 | 0,8% |
| total | US$ 1.977,58 |
Os tokens de gravação superaram os de leitura em 9,1 para 1; incluindo também os tokens de entrada sem cache no denominador, a taxa agregada de acerto foi de 9,6%. As leituras de cache, o resultado que de fato queríamos, custaram US$ 15,71 em todo o período.
A geração anterior do modelo serve como controle. No mesmo período, o uso do mesmo cliente e gateway com OpenAI GPT-5.5 (Amazon Bedrock Edition) registrou 9,17M tokens de entrada e nenhuma cobrança separada por gravações no cache. O formato de requisição enviado pelo Codex era o mesmo; a diferença estava na cobrança aplicável às gravações.
A fatura mostra o tamanho do problema, não o motivo dele. Parte desses 258,8M tokens de gravação é inevitável: inicializações a frio legítimas, prefixos de fato distintos, compactações de contexto. Nunca distribuímos o total entre essas causas, e é o replay controlado, mais abaixo, que identifica o mecanismo.
O campo que o Codex não consegue emitir
O GPT-5.6 permite que o cliente marque exatamente onde termina um prefixo reaproveitável, acrescentando um campo a um bloco de conteúdo suportado:
"prompt_cache_breakpoint": {"mode": "explicit"}
O Codex não omite esse campo por escolha. Ele não tem como expressá-lo. Em codex-rs/protocol/src/models.rs, a variante InputText do enum ContentItem, à qual o campo se anexaria, tem um único campo:
pub enum ContentItem {
InputText { text: String },
...
}
Não há #[serde(flatten)] nem mapa de campos extras, então o breakpoint não tem onde existir nem internamente. ResponsesApiRequest e ResponseCreateWsRequest carregam prompt_cache_key, e nenhum dos dois carrega prompt_cache_options. Configuração também não alcança: ModelProviderInfo customiza comportamento de conexão, não corpo de requisição, e o schema dele é additionalProperties: false.
A evidência mais útil já estava dentro do repositório do Codex. O Codex inclui o guia de migração para GPT-5.6 da própria OpenAI, que descreve esse modo de falha diretamente:
O cache implícito do GPT-5.6 coloca um breakpoint gerenciado perto da última mensagem de usuário ou de ferramenta e não depende mais do arredondamento de 128 tokens. Um prompt com um prefixo estável grande seguido de um sufixo que muda pode, portanto, perder acertos de cache mesmo quando o prefixo estável em si não mudou.
Esse parágrafo descreve o formato de requisição do próprio Codex, é distribuído dentro do Codex e fica cerca de trinta linhas acima de um remédio que o Codex não pode aplicar e de um aviso de custo explicando por que o remédio passou a importar. Um git grep pelo nome do campo em 5.744 arquivos versionados retorna exatamente um resultado, que é esse arquivo de documentação.
O replay que isolou a causa
O gateway processa cada requisição em vez de apenas tunelá-la, então já tínhamos os corpos exatos que o Codex havia enviado em produção. Dois replays controlados contra o openai.gpt-5.6-sol ao vivo — culminando em um experimento fatorial 2×2 que variou o breakpoint e a chave de cache de forma independente — identificaram o mecanismo.
O primeiro replay acrescentou o breakpoint a um corpo sem outras alterações e fixou uma única chave de cache em seis requisições. As taxas de acerto passaram de 0% para 98,6%, e as gravações nas requisições quentes caíram de cerca de 9.060 tokens para algo entre 123 e 128. Esse resultado mostrou que o breakpoint funcionava quando combinado com uma chave fixa, mas não descreve uma carga real, porque o Codex gera um UUID de sessão novo como chave de cache a cada início e nunca envia a chave fixa da qual o resultado dependia.
O segundo replay usou três corpos codex exec capturados e variou as duas mudanças de forma independente.
| configuração | acerto por requisição | total de tokens de gravação no cache |
|---|---|---|
| Codex sem modificação | 0%, 0%, 0% | 16.873 |
| Só breakpoint explícito | 0%, 0%, 0% | 16.873 |
Só prompt_cache_key estável | 0%, 0%, 0% | 16.873 |
| Breakpoint e chave estável | 0%, 96%, 97% | 5.973 (-65%) |
Nenhuma das duas mudanças basta sozinha. O breakpoint define qual prefixo é reaproveitável, e a chave determina se requisições posteriores conseguem reutilizá-lo. Calculado com as tarifas da fatura, o mesmo replay custa US$ 0,1161 sem modificação e US$ 0,0471 com as duas mudanças aplicadas, ou seja, 59% menos para a mesma carga capturada. Os tokens de gravação caem mais que o gasto, porque os tokens recuperados continuam sendo cobrados como leitura, e não se tornam gratuitos.
Duas ressalvas acompanham essa tabela. Os três valores idênticos de 16.873 são aritmética, não erro de cópia: com 0% de acerto, cada requisição grava toda a sua entrada, e reproduzir corpos fixos faz o total repetir exatamente. E a OpenAI documenta prompt_cache_key como uma dica de roteamento combinada com o hash do prefixo, e não como uma partição rígida, então a exigência de chave estável é nossa observação medida no Bedrock Mantle, e não um invariante universal do servidor.
O que a causa não era
Quatro outras explicações foram testadas contra o modelo ao vivo e descartadas. Um prefixo de 101.448 tokens atingiu 99% de acerto com o breakpoint presente, o que descartou um teto abaixo desse tamanho na configuração testada. Seis requisições concorrentes com a mesma carga contra uma chave quente atingiram 99%; não reproduzimos, nesse teste, a corrida de gravação relatada em #33821. O streaming não fez diferença, com stream: true e false se comportando de forma idêntica. O esforço de raciocínio também não fez diferença, com todos os níveis de low a xhigh mostrando a mesma linha de base de 0%.
O que deu para fazer sem esperar o Codex
O defeito está em um tipo Rust, portanto a correção definitiva precisa ser feita no Codex. Não podemos fazer esse reparo upstream, e a configuração não alcança o campo, então buscamos uma mitigação enquanto a mudança no Codex não chega. A única camada que controlamos é o salto entre o agente e o modelo.
O Codex fala com o Bedrock através de um gateway que construímos, que autentica quem desenvolve, aplica o limite de gasto e assina a chamada upstream. Fazer isso exige interpretar o corpo JSON e serializá-lo novamente, e uma camada que já reescreve o corpo pode acrescentar um campo a ele, inclusive um campo que o cliente não tem como expressar. Nosso texto sobre governar Claude Code, Claude Desktop e Codex atrás de um único gateway Bedrock cobre o resto desse desenho.
A mitigação é inject_prompt_cache_breakpoint(), que percorre a requisição de saída, encontra o último bloco de conteúdo suportado no prefixo estável medido e o marca. Ela é restrita a IDs de modelo GPT-5.6 e a requisições que não são de chat, respeita qualquer breakpoint fornecido pelo cliente e ignora tipos de bloco que não aceitam o campo. Sozinha, não teria mudado nada, então o gateway também envia uma chave de cache que permanece estável entre sessões independentes. As duas mudanças estão em produção. No replay controlado, juntas, produziram acertos de 96% a 97% nas requisições quentes e reduziram em 65% os tokens de gravação no cache. Os totais diários da conta também caíram após a implantação, embora os dados agregados de todos os modelos não isolem o efeito da mitigação.

O posicionamento é mais difícil do que parece, e a mesma dificuldade restringe qualquer correção upstream. O Codex ativa use_responses_lite para os três slugs de GPT-5.6, o que insere um item inicial additional_tools no início de input sem nenhum array content. O posicionamento automático do breakpoint precisa, portanto, lidar com um bloco inicial que não tem onde receber um, o que torna #31882 parte central deste problema, e não apenas relacionado.
O que ainda precisa mudar no Codex
Um campo documentado da API do GPT-5.6 continua irrepresentável nos tipos de requisição do Codex. Até que openai/codex#35300 seja resolvido, usuários do Codex no GPT-5.6 via Bedrock que executem chamadas isoladas, subagentes derivados ou cargas multiagente podem continuar pagando o prêmio de escrita sobre um prefixo que nunca mudou. Uma mitigação no gateway só alcança tráfego que passa por um gateway.
A solução alternativa que parece mais plausível não alcança o campo. O #34569 propõe o repasse, configurável por provedor, de campos de nível superior do corpo, o que poderia fornecer prompt_cache_options. Um breakpoint fica aninhado dentro de input, e essa proposta diz explicitamente que não deve sobrescrever chaves gerenciadas pelo Codex, como input.
A mudança mínima upstream é pequena: um campo opcional de breakpoint nas variantes de conteúdo suportadas com skip_serializing_if = "Option::is_none", testes de serialização provando que ele é emitido só onde é suportado e omitido por padrão, e uma verificação de capacidade. Essa verificação deveria ler metadados de capacidade, como supports_prompt_cache_breakpoints, em vez de testar o nome do modelo, porque modelos mais antigos rejeitam esses campos, e aliases customizados e backends compatíveis com a OpenAI não se encaixam bem em uma verificação por 5.6.
Como verificar a mesma coisa na sua conta
Consulte o serviço do modelo GPT-5.6 no Cost Explorer, agrupe os dados por tipo de uso e compare tokens de gravação no cache com tokens de leitura. Uma razão muito acima de 1 é um sinal para investigar, não a prova deste mecanismo. Correlacione esses dados com os registros do gateway ou das requisições para verificar se codex exec em CI, subagentes derivados ou outras cargas automatizadas são os principais responsáveis.
Vale conhecer quatro propriedades desses dados antes de tirar conclusões deles.
RECORD_TYPE = Usageé o que isola consumo medido. Créditos, reembolsos e outros registros que não são de uso são compensados pelo uso na visão padrão, e é assim que um serviço com gasto real pode aparecer como US$ 0.- Use somente dias fechados. O Cost Explorer marca períodos em andamento como
Estimated: true, e a mesma janela apresentou 329,5M e depois 375,2M tokens de gravação no cache. As razões se mantiveram entre as leituras enquanto os totais se moviam. - Ao dividir os valores acumulados, obtém-se US$ 5,4997 por milhão de tokens de entrada em vez de US$ 5,5000, o que é arredondamento, não outra tarifa. A partir dos preços publicados, US$ 6,88 / US$ 5,50 dá 1,25× e US$ 0,55 / US$ 5,50 dá 0,10×, o que corresponde aos multiplicadores documentados de cache de prompt e confirma que esses são os medidores de cache, e não faturamento genérico de entrada.
- A string do tipo de uso contém essa informação.
USE1-MP:USE1_cache_write_tokens_30m_standard-Unitscodifica o TTL padrão de 30 minutos do guia de caching, o que identifica o medidor do lado do provedor.
Para tráfego que já passa por um gateway, injete o breakpoint e fixe uma chave de cache que sobreviva entre sessões, porque, no replay, cada alteração isolada produziu 0% de acertos. Para tráfego que não passa, não há hoje uma solução apenas por configuração, e o #35300 é o que acompanhar.
Perguntas frequentes
Por que o gasto com gravação no cache é tão alto para o Codex com GPT-5.6 no Bedrock?
O GPT-5.6 depende de um breakpoint gerenciado implícito colocado perto da última mensagem. O Codex não consegue emitir o prompt_cache_breakpoint explícito que marcaria o fim do prefixo estável de inicialização e gera uma nova prompt_cache_key a cada sessão. Nas cargas afetadas, requisições independentes que compartilham o prefixo mas divergem no primeiro turno do usuário podem regravá-lo inteiro em vez de lê-lo. Gravações no cache são cobradas a 1,25× a entrada sem cache, então cada reescrita custa 12,5 vezes o que a leitura equivalente teria custado.
Isso acontecia no GPT-5.5 também?
O formato de requisição do cliente era o mesmo, mas, nas tarifas aplicáveis ao GPT-5.5, as gravações no cache não geravam cobrança separada. No mesmo período, nosso uso de GPT-5.5 registrou 9,17M tokens de entrada.
Isso é específico do Amazon Bedrock?
O defeito de serialização é independente de backend e verificável direto no código do Codex. Nossas medições absolutas de acerto de cache e de faturamento vêm do Bedrock Mantle e deveriam ser reproduzidas contra outros endpoints antes de serem tratadas como universais, em especial a constatação de que uma chave de cache estável também era necessária.
Consigo corrigir por configuração?
Não. ModelProviderInfo customiza comportamento de conexão, não corpo de requisição, e o schema dele é additionalProperties: false. Mesmo uma passagem de campos de nível superior do corpo não alcançaria um breakpoint aninhado dentro de input.
Um gateway corrige isso por completo?
Não. Para o tráfego que passa por ele, o gateway mitiga o problema ao injetar o breakpoint e manter uma chave de cache estável entre sessões independentes; no replay, isso reduziu em 65% os tokens de gravação no cache. O gateway não elimina partidas frias nem alcança o tráfego que o contorna, portanto a mudança upstream continua necessária.
Conclusão
As gravações no cache foram 90% do nosso gasto com GPT-5.6. O replay controlado isolou um mecanismo por trás das regravações caras, e a pista já estava distribuída dentro do Codex: um guia de migração descrevendo o modo de falha do próprio cliente, ao lado de um remédio que seus tipos não conseguem carregar.
A mitigação é real e está rodando, mas é limitada. Um gateway pode definir um ponto de cache que o Codex não define, e só consegue fazer isso para as requisições que passam por ele. Nas cargas afetadas que não passam por um gateway, o Codex no GPT-5.6 pode continuar mais caro do que o necessário até que o cliente consiga emitir o campo por conta própria.
Leitura relacionada: Codex e OpenAI Agents no Amazon Bedrock, governança de Claude Code, Desktop e Codex atrás de um único gateway Bedrock e Claude Code na AWS.





