← Blog
13 de octubre, 2026 · 17 min

El precipicio de la ventana de contexto: overflow, tramos y el 402

El contexto de un agente crece un tool result a la vez. En cierto número de tokens, el precio de todo el request sube de escalón. En un número mayor, el request deja de funcionar, y cada capa del stack lo reporta de forma distinta.

El largo del contexto es la única variable del request que cambia a la vez si una llamada puede tener éxito y cuánto cuesta. Los dos cambios son escalones, no pendientes. Un precio calculado antes de la llamada, como debe serlo una cotización x402, tiene que saber dónde están los escalones.

Revisamos dónde están hoy. Leímos la documentación actual de precios y errores de Anthropic, OpenAI, Google y OpenRouter, y el manejo de overflow en el código de LiteLLM. Corrimos un modelo self-hosted más allá de su ventana para ver qué devuelve. Después sondeamos nuestro propio 402 en ambos bordes. Todo lo que sigue se leyó o midió el 2026-10-13, con las versiones indicadas.

La versión corta: nuestra cotización es lineal a través de todos los tramos de precio que probamos, y pone precio a requests que ningún modelo del request puede atender. El resto del post es la evidencia, y el arreglo.

Dos precipicios, no uno

El primer precipicio es el tramo de precio. Varios proveedores ya cobran una tarifa por token más alta cuando el prompt cruza un umbral. Aplican esa tarifa a todo el request, no solo a los tokens por encima de la línea.

Las páginas de modelos de OpenAI para la familia GPT-6 (gpt-6-astra, gpt-6.1-sol, gpt-6-luna) listan una context window de 1,050,000 tokens y la misma regla: "Prompts with more than 272K input tokens are priced at 2x input and cache rates and 1.5x output for the full request." La página de GPT-5.5 aplica 2x y 1.5x "for the full session". La página de precios define short context como 272K input tokens o menos.

El pricing de Gemini de Google traza la línea en 200k. Gemini 3.1 Pro Preview cuesta $2.00 de input y $12.00 de output por millón de tokens para prompts de hasta 200k, y $4.00 y $18.00 por encima. Gemini 2.5 Pro sube de $1.25/$10.00 a $2.50/$15.00 en la misma línea. Gemini 3.8 Flash tiene precio plano, $0.75/$3.75 hasta el 31 de diciembre de 2026, y un límite de input de 1,048,576 tokens.

Anthropic fue en la dirección contraria para casi toda su línea. Su página de precios dice que Claude 4.6 y los modelos posteriores, salvo Claude Haiku 5.5, cobran toda la ventana de 1M a tarifa estándar: "A 900k-token request is billed at the same per-token rate as a 9k-token request."

Haiku 5.5 es la excepción, y el escalón más empinado que encontramos. Los prompts de más de 100,000 tokens pagan $0.50 de input y $2.50 de output por millón, en lugar de $0.10 y $0.50. Es cinco veces ambos. El umbral cuenta todos los input tokens, incluidos cache reads y cache writes, y "a request over the threshold pays the higher prices even when part of its prompt is a cache hit."

La aritmética es lo que lo convierte en precipicio. En GPT-5.5 con 4,000 output tokens, 272,000 input tokens cuestan $1.48 a precio de lista. Con 273,000 cuestan $2.91. Mil tokens extra cuestan $1.43. En Haiku 5.5, el token 100,001 del prompt multiplica por cinco toda la factura.

El segundo precipicio es la ventana misma, y tampoco es un único número por modelo. GPT-5 tiene una context window de 400,000 tokens pero un input máximo de 272,000. GPT-4o tiene 128,000. Gemini publica límites separados de input y de output. La página de context windows de Anthropic da 1M a Claude Opus 5.5, Sonnet 5.5, Haiku 5.5 y otros, y 200k a modelos más viejos como Sonnet 4.5, ya deprecado.

Ambos umbrales se cuentan en tokens del proveedor. Nadie fuera del proveedor puede contarlos con exactitud para todos los modelos, que es el problema que medimos en nuestra auditoría de tokenizer drift. La propia página de precios de Anthropic aclara que Claude 4.7 y los modelos posteriores producen aproximadamente 30% más tokens para el mismo texto que los anteriores. Un umbral de 100,000 tokens es una cantidad distinta de caracteres a cada lado de ese cambio.

El precipicio de la ventana habla cuatro dialectos

Cuando un request no cabe, el proveedor tiene que decirlo. Cada proveedor lo dice con una forma distinta, y algunos ni siquiera lo dicen como error.

Anthropic distingue dos casos. Si el input por sí solo excede la ventana, la API devuelve un 400 invalid_request_error ("prompt is too long") en todos los modelos. Si el input cabe pero input más max_tokens no, los modelos Claude 4.5 y posteriores aceptan el request. Dejan de generar cuando la ventana se llena, con stop_reason: "model_context_window_exceeded".

Ese segundo caso es un HTTP 200 que trae una respuesta truncada. La página de stop reasons les pide a los clientes "treat the response as truncated." Aparte, los requests de más de 32 MB reciben un 413 request_too_large. Según la página de errores, en la API directa ese lo devuelve Cloudflare antes de que el request llegue a los servidores de Anthropic.

La Responses API de OpenAI tenía un interruptor explícito. En la spec OpenAPI publicada (commit 77618e6, 2026-10-13), truncation: "disabled" es el default y hace que un input demasiado grande "fail with a 400 error". Con "auto", el modelo va a "truncate the response to fit the context window by dropping items from the beginning of the conversation."

La misma spec ahora marca truncation como deprecated. También incluye un array context_management cuyo único tipo de entrada es compaction, que se dispara en un compact_threshold de al menos 1,000 tokens. El enum de errores para los turnos de sesiones de agentes tiene un valor dedicado, context_length_exceeded: "The request exceeds the model's context window."

OpenRouter normaliza todo esto en su propio vocabulario. Su referencia de errores define un error_type canónico context_length_exceeded, HTTP 400, para cuando "the combined input and output tokens exceed the model's context window."

Dos detalles importan para quien enruta a través de él. En su skin de Responses API, ese tipo colapsa al código nativo invalid_prompt, junto con refusals e invalid requests genéricos, algo que marcamos en la auditoría de Open Responses. Y la misma sección lista context_length_exceeded entre los errores "transformed into successful completions", con finish reason length.

OpenRouter además trae un arreglo que en realidad es una decisión de política. Su plugin de context compression elimina o trunca mensajes "from the middle of the prompt, until the prompt fits within the model's context window." Es opt-in, salvo que todo endpoint con 8,192 tokens de contexto o menos "will default to using context compression."

Sus docs de model fallback agregan que cualquier error puede disparar el siguiente modelo, incluyendo explícitamente "context length validation errors". El request se cobra "using the model that was ultimately used."

El cuarto dialecto es el silencio. Ese tuvimos que medirlo.

Un modelo self-hosted, más allá de su ventana

Los backends self-hosted son un último eslabón habitual en una cadena de fallback: baratos, privados, siempre arriba. Corrimos el más común más allá de su ventana.

El setup fue Ollama 0.30.6 en nuestra propia máquina, sirviendo qwen2.5:1.5b con num_ctx 2048 y temperatura 0, llamado por su /v1/chat/completions compatible con OpenAI. Cada prompt contenía un dato corto ("the secret code is 7341"), unos 5,100 tokens de texto del RFC 9110 y una pregunta pidiendo el código. Movimos el dato entre tres posiciones y corrimos cada una cinco veces. Un prompt de control de 569 tokens respondió bien.

# Ollama 0.30.6, num_ctx 2048, prompts de 5,146-5,165 tokens, n=5 cada uno
posición             HTTP  finish_reason  usage.prompt_tokens  respondió 7341
dato al inicio       200   stop           2047                 0/5
dato al final        200   stop           2047                 5/5
dato en system msg   200   stop           2047                 0/5

Todas las llamadas devolvieron HTTP 200 con finish_reason: "stop". Nada en la respuesta decía que el input había sido cortado. Solo el log del servidor lo decía:

level=WARN msg="truncating input prompt" limit=2048 prompt=5146 keep=4 new=2047

keep=4 es el detalle que importa. Ollama conservó los primeros cuatro tokens y la cola, y descartó todo lo del medio. El system message estaba en la parte descartada, así que el modelo respondió sin él, cinco de cinco veces. Para un agente, el system prompt es donde viven la tarea, la política de tools y las reglas de gasto.

El bloque de usage también queda mal, en silencio, para facturar. Reporta los 2,047 tokens que vio el modelo, no los 5,146 que se enviaron. Un gateway que cobra sobre el usage reportado cobra el request truncado, y no recibe ninguna señal de que fue truncado.

La documentación de la API de Ollama sí describe un flag truncate que "returns error if false and context length is exceeded". Está documentado solo para el endpoint de embeddings.

Cómo detectan el overflow los routers: leyendo inglés

Un gateway que quiere hacer fallback ante un overflow primero tiene que reconocerlo. Leímos cómo lo hace LiteLLM, en el commit a5d0535 (2026-10-12), porque su exception mapper es en la práctica un censo de cómo los proveedores redactan la falla.

El chequeo genérico, is_error_str_context_window_exceeded en exception_mapping_utils.py, pasa a minúsculas el string de error del proveedor y busca nueve substrings. Entre ellos están "this model's maximum context length is", "exceeds the available context size" (comentado como llama.cpp) y "exceeds the maximum number of tokens allowed" (comentado como Gemini).

Dos patrones más atrapan a Cerebras ("current length is" junto con "while limit is") y "maximum input length is" junto con "tokens". Las ramas por proveedor agregan "prompt is too long", "Input is too long" y "Too many input tokens". En total, el archivo lanza ContextWindowExceededError desde 16 lugares.

Un comentario en ese archivo muestra hasta dónde llega la dependencia de la redacción. Para el endpoint Mantle de Bedrock, LiteLLM reescribe los errores de overflow al string "prompt is too long", porque "Clients such as Claude Code only treat 'prompt is too long' as overflow." El mensaje de error se convirtió en la API.

Una vez detectado el overflow, el router de LiteLLM lo maneja aparte. context_window_fallbacks es su propia lista. Cuando no está configurada, el router registra que está "Defaulting to fallbacks, if available". Los fallbacks por orden se saltan explícitamente para este tipo de error.

El router también puede evitar el overflow por completo. Con enable_pre_call_checks, que por default es False, descarta cualquier deployment cuyo max_input_tokens sea menor que el conteo de tokens del request. Ese conteo se hace una vez por request, llamando a token_counter sin nombre de modelo, lo que resuelve a cl100k_base de tiktoken. Un deployment de Claude y uno de Gemini se filtran con el mismo conteo de la era de GPT-4.

El hallazgo más silencioso está en el camino de éxito. LiteLLM traduce el stop_reason de Anthropic a un finish_reason de OpenAI con un mapa fijo en core_helpers.py. El mapa tiene entradas para end_turn, max_tokens, tool_use, refusal y hasta compaction.

No tiene ninguna para model_context_window_exceeded. Los valores sin mapear registran un warning y caen por default en "stop". Una respuesta de Claude cortada por la ventana le llega a un cliente con forma OpenAI con aspecto de terminada.

Junta los cuatro dialectos y una cadena tiene tres maneras de enterarse de que hubo overflow. Recibe un 400 cuyo inglés tiene que parsear, un 200 cuyo finish reason pudo haberse reescrito a stop o length, o nada en absoluto. Solo el primero dispara un fallback de forma confiable.

Nuestro propio 402, en ambos bordes

Nuestra cotización walk-up es pública por diseño. Un POST /v1/chat/completions sin autenticar devuelve un 402 cuyo header payment-required trae el monto. Lo usamos para leer la cotización en ambos precipicios el 2026-10-13.

La estimación de input detrás de la cotización sigue siendo la que documentamos el 6 de octubre: ceil(JSON.stringify(messages).length / 4), multiplicada por una única tarifa plana por modelo.

Para los modelos de OpenAI podemos contar tokens con exactitud usando un tokenizer público: tiktoken 0.14.0 mapea gpt-5.5 a o200k_base. Armamos payloads con el texto de los RFC 9110, 9111 y 9112, cortados en conteos exactos de o200k, y pedimos 4,000 output tokens. La columna de lista aplica las tarifas short y long publicadas por OpenAI para GPT-5.5.

# openai/gpt-5.5, max_tokens 4000, conteos o200k, 2026-10-13
tokens reales  estimación  cotización  precio lista  cotiz./lista
      250,000     277,688       $1.82         $1.37          1.33
      272,000     300,716       $1.95         $1.48          1.32
      273,000     301,705       $1.96         $2.91          0.67
      300,000     328,896       $2.12         $3.18          0.67
      500,000     547,538       $3.43         $5.18          0.66
      900,000     990,210       $6.09         $9.18          0.66
    1,100,000   1,206,082       $7.39  fuera de ventana         -

Por debajo de 272,000 tokens, la cotización queda por encima de la lista, como debe ser. Nuestra estimación corre cerca de 10% alta en este texto, y la cotización incluye nuestro margen. Mil tokens después, la cotización queda un tercio por debajo de la lista, y se mantiene ahí hasta el final de la ventana. Pasada la ventana, con 1.1 millones de tokens, sigue devolviendo un 402 normal para un request que GPT-5.5 no puede aceptar.

Para modelos cuyo tokenizer no es público, leímos la cotización en pares de tokens estimados a cada lado del umbral publicado, con max_tokens en 1. La columna de lista asume que el proveedor cuenta la misma cantidad de tokens que nuestra estimación. Ilustra el escalón; no es una factura.

# cotización vs lista, asumiendo tokens del proveedor = nuestra estimación, max_tokens 1
modelo                      tramo  tokens est.  cotización    lista
anthropic/claude-haiku-5.5  100k        90,008       $0.02  $0.0090
                                       110,008       $0.02  $0.0550
                                       900,008       $0.11  $0.4500
google/gemini-2.5-pro       200k       190,008       $0.29  $0.2375
                                       210,008       $0.32  $0.5250
                                       900,008       $1.36  $2.2500
openai/gpt-6-astra          272k       270,008       $3.25  $2.7001
                                       275,008       $3.31  $5.5002

A través de cada umbral, la cotización se movió entre cero y seis centavos. La lista creció 6.1x entre los dos puntos de Haiku 5.5 (22% más tokens a cinco veces la tarifa), 2.2x en Gemini 2.5 Pro y 2x en GPT-6 Astra.

Después, la ventana. Enviamos requests que el modelo pedido no puede atender, cada uno contado con o200k:

# requests más grandes que el límite del modelo, max_tokens 1000
modelo                     tokens o200k  límite                     cotización
openai/gpt-4o                   150,000  128,000 context window          $0.51
openai/gpt-5                    300,000  272,000 input máximo            $0.51
openai/gpt-5.5                1,100,000  1,050,000 context window        $7.28
anthropic/claude-opus-5.5     2,500,000  1M context window              $13.20

Los cuatro volvieron como 402 normales. El último es un body de 11 MB, por debajo del límite de 32 MB de Anthropic, así que upstream fallaría como "prompt is too long" y no como 413. o200k no es el tokenizer de Claude, pero el margen es de 2.5x. En nuestra auditoría de tokenizers, el texto en inglés varió mucho menos que eso entre seis tokenizers.

Por último, la cadena de fallback. Nuestro array models, descrito en el post de fallback chains, cotiza el modelo más caro de la cadena. Enviamos el payload de 300,000 tokens con models: ["openai/gpt-4o", "openai/gpt-5.5"] y 4,000 output tokens. La cotización fue $2.12, el precio de GPT-5.5 a tarifa plana.

El primer eslabón no puede tomar ese request de ninguna manera. El único modelo que puede atenderlo es el segundo, que lista $3.18 a tarifas de long context. Enviado solo a openai/gpt-4o, el mismo payload cotizó $1.04 por una llamada que no puede tener éxito.

Tres hallazgos, entonces. La cotización es lineal a través de todos los tramos de precio que probamos. No revisa la context window, así que pone precio a requests que ningún modelo del request puede atender. Y la cotización de la cadena toma el modelo más caro a su tarifa plana, no al tramo en el que el request realmente va a caer.

Quién paga cada error

Los dos errores caen sobre partes distintas.

Una cotización fuera de ventana le cuesta al comprador sobre todo tiempo. El middleware oficial de x402 para Hono, en el commit 6c470a8, cancela el settlement cuando el handler protegido devuelve un status de 400 o más, con el motivo handler_failed. Un "prompt is too long" de upstream, por lo tanto, no liquida nada.

El comprador igual pagó una firma, un round trip y la subida de un body de varios megabytes, por un request que nunca iba a correr. La excepción es el caso parcial de Anthropic. Un input que cabe, pero no junto con max_tokens, vuelve como 200, y un 200 se liquida.

Muchas de estas cotizaciones ni siquiera se firmarían. Los SDKs cliente oficiales de x402 traen un tope por default de $1 por pago, que cubrimos en la auditoría de spend controls. El cliente de TypeScript todavía fija DEFAULT_MAX_AMOUNT_PER_PAYMENT en "$1" hoy. La cotización de GPT-5.5 cruza $1 mucho antes de su tramo, así que un comprador con la configuración por default nunca llega a la banda de long context en ese modelo. Un comprador en Haiku 5.5 o Gemini 2.5 Pro sí llega, por unos pocos centavos.

La subcotización por encima de un tramo cae sobre nosotros. En x402, la firma del comprador pone tope a lo que se puede liquidar, así que la cotización es el techo. Nuestra auditoría de tokenizers rastreó a dónde va el resto en cada uno de nuestros caminos de cobro; en ninguno lo paga el comprador.

Eso hace del lado largo de cada tramo la única banda donde nuestro precio walk-up está de forma confiable por debajo del costo. Es también la banda que más probablemente crezca, porque los contextos de los agentes solo se alargan.

Qué significa para LLM4Agents

El 402 es nuestro contrato de precio. El largo del contexto es el único input donde ese contrato se equivoca en las dos direcciones: una sobrecotización por debajo de cada tramo, por margen más inflación del estimador, y un tercio por debajo de la lista por encima. Ninguno de los dos errores es aleatorio. Ambos son funciones de números que cualquiera puede leer en páginas públicas.

El chequeo de ventana es el arreglo más barato, y el más vergonzoso de dejar pendiente. Nuestro contrato público de API ya expone un contextWindow para cada modelo en /api/v1/models. Un 402 que pide pago por un request que el modelo no puede aceptar gasta la firma del comprador, y nuestra llamada upstream, en una falla garantizada.

Las cadenas de fallback empeoran el problema, y podrían mejorarlo. El overflow es el disparador de fallback más predecible que existe: depende solo de un conteo de tokens y de un número del catálogo. Tratarlo como un error upstream a parsear significa pagar un round trip para aprender algo que sabíamos antes de la llamada. Tratarlo como un input de routing significa que la cadena puede saltar los eslabones que no caben, y cotizar el eslabón que de verdad va a atender, en el tramo en el que de verdad va a caer.

Hay un argumento de producto además del de costos. El trabajo de long context es donde los agentes más necesitan un precio antes de comprometerse: revisión de repositorios completos, triage de logs, comparación de contratos. Una API key plana no puede decirle a un agente que su próxima llamada cuesta el doble por token porque su historial cruzó 272,000 tokens. Un 402 sí puede. Bien hecho, el precipicio se vuelve información que vendemos, no margen que perdemos.

El dialecto silencioso es una advertencia para nuestro propio roadmap. Cualquier eslabón self-hosted u open-weight que agreguemos hereda lo que haga su servidor ante un overflow. Si es el default de Ollama, nuestros agentes reciben respuestas a prompts sin sus instrucciones, detrás de un 200 y un finish reason limpio.

Cómo mantenerse en la frontera

En concreto, y en este orden.

Primero, rechazar los requests fuera de ventana antes del 402. Si el input estimado excede la ventana de todos los modelos del request, devolver un 400 con context_length_exceeded, la ventana y la estimación, en lugar de un payment requirement. Usar una banda de seguridad para que el error del estimador no rechace un request que cabe. La banda puede ser estrecha en modelos con tokenizer público.

Segundo, hacer la cotización consciente de los tramos. Guardar los tramos de cada modelo como datos: el umbral, qué clases de tokens cuentan para él (Haiku 5.5 cuenta cache reads y writes), los multiplicadores de input, cache y output, y el alcance, que en todos los tramos que encontramos es el request completo. Cotizar cada request en el tramo donde cae su estimación. La cotización ya es una cota superior que se liquida hacia abajo al costo real, así que una cota consciente de tramos no le cuesta nada al comprador cuando se pasa.

Tercero, contar con exactitud solo donde importa. La mayoría de los requests están lejos de cualquier umbral, y la estimación por caracteres alcanza ahí. Dentro de una banda alrededor de un tramo o de una ventana, llamar a un contador exacto. El endpoint de token counting de Anthropic es gratuito y tiene rate limits separados. El endpoint de input token count de OpenAI devuelve "the exact count the model will receive", y o200k corre localmente para los modelos de OpenAI.

Cuarto, enrutar las cadenas según el contexto antes de la llamada. Descartar los eslabones cuya ventana no puede contener el request, y cotizar el eslabón restante más caro en su tramo. El pre-call check de LiteLLM es el patrón correcto con el contador equivocado: un único conteo cl100k aplicado a todos los deployments. Contar por familia de tokenizer, o al menos por proveedor.

Quinto, nunca reportar una respuesta truncada como terminada. Mapear model_context_window_exceeded a length, no a stop, y pasar el stop reason nativo en un header de respuesta para los agentes que lo necesiten. No habilitar compresión silenciosa por default en ningún eslabón. No agregar a una cadena un backend estilo Ollama sin convertir el overflow en error.

Sexto, decirles a los agentes dónde están los precipicios. Publicar los umbrales de tramo de cada modelo junto a contextWindow, como campos estructurados en el catálogo de modelos. Así un planner puede dividir el trabajo por debajo de 272,000 tokens, en lugar de descubrir el tramo después.

Séptimo, convertir los sondeos de este post en tests. Pares de umbral para cada modelo con tramos, un request fuera de ventana para cada tamaño de ventana que vendemos, y una cadena cuyo primer eslabón no cabe. Pedir un 402 es gratis, así que la suite no cuesta nada correrla, y habría atrapado los tres hallazgos.

Paga por llamada, en stablecoins, sobre una API compatible con OpenAI

Un 402, una firma, más de 345 modelos. Sin suscripción, sin mínimo.

Registra tu agente