Empezar aquí
Índice de la sección
Lección 7.1 · práctica

El contexto como presupuesto

Por qué el contexto de un modelo es un recurso finito que cuesta dinero, latencia y atención, y cómo medir cuánto ocupa cada componente de tu agente.

Publicado 40 min
Al terminar podrás
  • Explicar los tres costes del contexto (dinero, latencia y atención) y el efecto de la posición descrito en Lost in the Middle
  • Medir con count_tokens y usage cuántos tokens ocupa cada componente de una petición
  • Identificar qué componente crece más en un bucle agéntico y fijar un presupuesto por componente

Requiere: La ventana de contexto y qué cabe en ella · El bucle agéntico

Al terminar esta lección sabrás por qué llenar la ventana de contexto «por si acaso» empeora a tu agente, y tendrás un script que desglosa cuántos tokens ocupa cada parte de una petición. Es el primer paso de todo lo demás: no puedes gestionar lo que no mides.

La idea

La ventana de contexto es todo lo que el modelo ve en una llamada: prompt de sistema, definiciones de herramientas, historial de mensajes, resultados de herramientas y la propia respuesta que genera. Tiene un tamaño máximo, pero el límite real llega antes de ese máximo.

Piensa en el contexto como un presupuesto con tres monedas:

  • Dinero. Pagas cada token de entrada en cada llamada. En un bucle agéntico, el historial se reenvía entero en cada paso, así que un resultado de herramienta de 5.000 tokens en el paso 3 lo pagas también en los pasos 4, 5, 6 y siguientes. El prompt caching abarata el prefijo repetido, pero no lo elimina (Prompt caching).
  • Latencia. Más tokens de entrada significa más tiempo hasta el primer token de salida (latencia).
  • Atención. Es la moneda menos visible. Cuanto más contexto, más le cuesta al modelo usar bien cada parte.

La atención también se gasta

Effective context engineering for AI agents (Anthropic, 2025) describe el contexto como un recurso finito con rendimientos decrecientes. El artículo explica que, a medida que crece el número de tokens, la capacidad del modelo para recordar con precisión la información de ese contexto disminuye, un fenómeno que se ha llamado context rot. La causa está en la arquitectura transformer: cada token se relaciona con todos los demás, y con muchos tokens la atención se reparte entre muchas más relaciones. Por eso el artículo habla de un «presupuesto de atención» que cada token nuevo consume.

A esto se suma el efecto de la posición. Liu et al. (2023), en Lost in the Middle: How Language Models Use Long Contexts, midieron cómo cambiaba el rendimiento al mover la información relevante dentro de un contexto largo. El resultado: los modelos aprovechaban mejor la información situada al principio o al final, y el rendimiento bajaba de forma notable cuando estaba en medio. Los modelos han mejorado desde entonces, pero la lección práctica sigue vigente: no basta con que la información esté en el contexto; importa cuánta hay alrededor y dónde está.

Qué ocupa el contexto de un agente

ComponenteCuándo se fijaCómo crecePalanca principal
Prompt de sistemaAl diseñarFijoRedacción concisa; caché
HerramientasAl diseñarFijo, uno por herramientaMenos herramientas, descripciones precisas
Archivos de memoria o documentos precargadosAl empezarFijoPrecargar solo lo que casi siempre hace falta
Mensajes del usuario y del asistenteCada turnoLinealCompactación
Resultados de herramientasCada pasoRápido y a saltosRecortar, paginar, limpiar los antiguos
Respuesta del modeloCada pasoLimitada por max_tokensPedir formatos breves

En casi todos los agentes que midas, los resultados de herramientas acaban siendo la mayor parte del contexto. Una lectura de archivo, una búsqueda web o una consulta SQL sin límite pueden ocupar más que todo lo demás junto.

Medir

Hay dos fuentes de datos. client.messages.count_tokens cuenta la entrada antes de enviarla, con el mismo formato que messages.create. resp.usage te dice lo que se consumió de verdad, incluida la caché. El script siguiente desglosa una petición midiendo de forma incremental: cada componente es la diferencia entre contar con él y sin él.

import anthropic

MODEL = "claude-sonnet-5-5"
client = anthropic.Anthropic()
MINIMO = [{"role": "user", "content": "."}]

def contar(**kwargs) -> int:
    return client.messages.count_tokens(model=MODEL, **kwargs).input_tokens

def desglose(system: str, tools: list[dict], messages: list[dict]) -> dict[str, int]:
    base = contar(messages=MINIMO)
    con_system = contar(system=system, messages=MINIMO)
    con_tools = contar(system=system, tools=tools, messages=MINIMO)
    total = contar(system=system, tools=tools, messages=messages)
    sin_resultados = contar(system=system, tools=tools, messages=quitar_resultados(messages))
    return {
        "system": con_system - base,
        "tools": con_tools - con_system,
        "historial (sin resultados)": sin_resultados - con_tools,
        "resultados de herramientas": total - sin_resultados,
        "total": total,
    }

def quitar_resultados(messages: list[dict]) -> list[dict]:
    """Sustituye el contenido de cada tool_result por un marcador mínimo."""
    limpio = []
    for m in messages:
        if m["role"] == "user" and isinstance(m["content"], list):
            m = {**m, "content": [{**b, "content": "-"} if b.get("type") == "tool_result" else b
                                  for b in m["content"]]}
        limpio.append(m)
    return limpio

if __name__ == "__main__":
    import json, sys
    datos = json.load(open(sys.argv[1]))  # {"system": ..., "tools": [...], "messages": [...]}
    for k, v in desglose(datos["system"], datos["tools"], datos["messages"]).items():
        print(f"{k:<30}{v:>8}")
import Anthropic from "@anthropic-ai/sdk";

const MODEL = "claude-sonnet-5-5";
const client = new Anthropic();
const MINIMO: Anthropic.MessageParam[] = [{ role: "user", content: "." }];

async function contar(p: Omit<Anthropic.MessageCountTokensParams, "model">): Promise<number> {
  return (await client.messages.countTokens({ model: MODEL, ...p })).input_tokens;
}

export async function desglose(system: string, tools: Anthropic.Tool[], messages: Anthropic.MessageParam[]) {
  const base = await contar({ messages: MINIMO });
  const conSystem = await contar({ system, messages: MINIMO });
  const conTools = await contar({ system, tools, messages: MINIMO });
  const total = await contar({ system, tools, messages });
  return { system: conSystem - base, tools: conTools - conSystem, mensajes: total - conTools, total };
}
# salida de ejemplo
system                             412
tools                             1830
historial (sin resultados)        2210
resultados de herramientas       38950
total                            43402

Guarda el historial de una ejecución real de tu agente en JSON y pásalo por el script. La salida de ejemplo es típica: los resultados de herramientas dominan. Las restas son aproximadas (la plantilla interna añade algunos tokens), pero bastan para saber dónde está el gasto.

En producción, registra resp.usage en cada paso. La serie input_tokens por paso de una ejecución te dice cómo crece el contexto; si sube en escalones grandes, busca qué herramienta los produce.

Fijar un presupuesto

Con el desglose delante, pon límites explícitos por componente. Un punto de partida razonable para un agente es:

  • prompt de sistema y herramientas: fijos, revisados en cada cambio, y cacheados;
  • cada resultado de herramienta: un máximo de tokens o caracteres, con paginación si hace falta más;
  • el historial completo: un umbral (por ejemplo, una fracción de la ventana de tu modelo) a partir del cual compactas.

Los números concretos dependen del modelo, de la tarea y de tus medidas. Lo importante es que existan y que los compruebes con datos. Las técnicas para cumplirlos son el resto del curso.

Errores frecuentes

  • Medir solo la primera llamada. El problema aparece en el paso 30, no en el 1.
  • Confiar en que la ventana es grande. Que quepa no significa que funcione igual de bien.
  • Mirar solo el coste. Un agente barato que se olvida de la instrucción del paso 1 sale caro.
  • Ignorar las definiciones de herramientas. Veinte herramientas con descripciones largas pueden ocupar más que tu prompt de sistema en cada llamada.

Ejercicio

EjercicioPistas

El historial contiene objetos del SDK en los mensajes del asistente. Conviértelos antes de guardarlos con [b.model_dump() for b in resp.content]. Para encontrar la herramienta más cara, agrupa los tool_result por el nombre del tool_use correspondiente y mide su longitud.

Resumen

  • El contexto cuesta dinero, latencia y atención; la atención es la moneda que más se olvida.
  • Más tokens reducen la precisión al recordar (context rot) y la posición importa (Lost in the Middle).
  • En un agente, los resultados de herramientas suelen ser el componente más grande.
  • Mide con count_tokens antes y con usage después, paso a paso.
  • Fija presupuestos por componente y compruébalos con datos.

Para seguir