DEV Community

Cover image for Desbordamiento de Ventana de Contexto de IA: Solución con Puntero de Memoria
Elizabeth Fuentes L for AWS Español

Posted on

Desbordamiento de Ventana de Contexto de IA: Solución con Puntero de Memoria

El desbordamiento de ventana de contexto** ocurre cuando las salidas de herramientas de un agente de IA exceden el límite de tokens que el modelo de lenguaje grande (LLM) puede procesar de una vez. El agente no falla: silenciosamente trunca datos, pierde contexto anterior o produce resultados incompletos. Este post muestra cómo el Patrón de Puntero de Memoria lo soluciona: desde agente único hasta coordinación multi-agente donde 145KB de datos nunca entran en ningún contexto de LLM.

Esta demo usa Strands Agents. El Patrón de Puntero de Memoria es independiente del framework y se puede aplicar con LangGraph, AutoGen u otros frameworks de agentes que soporten contexto de herramientas.

Código funcional: github.com/aws-samples/sample-why-agents-fail

Serie: Por Qué Fallan los Agentes de IA

  1. Desbordamiento de Ventana de Contexto (este post) — Patrón de Puntero de Memoria para datos grandes
  2. Herramientas MCP Que Nunca Responden — Patrón asíncrono para APIs externas lentas
  3. Loops de Razonamiento en Agentes de IA — Detectar y bloquear llamadas repetidas a herramientas

El Problema: Los Agentes No Pueden Manejar Salidas Grandes de Herramientas

Cuando un agente de IA llama a una herramienta que devuelve datos grandes (logs del servidor, resultados de bases de datos, contenidos de archivos), la respuesta puede desbordar la ventana de contexto del LLM. El agente no falla con un error claro. Se degrada silenciosamente: trunca datos, pierde contexto o no completa la tarea.

Una investigación de IBM (Solving Context Window Overflow in AI Agents, 2025) cuantifica esto:

  • En flujos de trabajo de Ciencia de Materiales, las salidas de herramientas pueden alcanzar más de 2 millones de elementos
  • El enfoque tradicional consumió 20,822,181 tokens y falló
  • El mismo flujo con punteros de memoria usó 1,234 tokens y tuvo éxito
  • Eso es una reducción de más de 16,000x en este flujo de trabajo

Una observación comunitaria (Context Window Limits Explained, Airbyte 2025) confirma que los equipos descubren estos límites "de la manera difícil" a través de errores silenciosos. El agente parece funcionar pero produce resultados incompletos o incorrectos.

El concepto de pasar referencias en lugar de datos sin procesar también ha sido validado en configuraciones multi-agente. Una investigación de Amazon (Towards Effective GenAI Multi-Agent Collaboration, 2024) introduce "referenciación de carga útil", donde los agentes intercambian punteros a datos compartidos en lugar de incrustar cargas grandes en mensajes. Esto mejoró el rendimiento en tareas intensivas en código en un 23% y logró tasas de éxito de objetivos de extremo a extremo del 90% en benchmarks empresariales. Esto es exactamente lo que implementamos a continuación con Strands Swarm.

Por Qué Sucede Esto

El bucle del agente: User Query fluye a LLM, luego Tool Call, luego Tool Output (214KB), luego de regreso a LLM. La salida grande de herramienta causa desbordamiento de contexto

Cuando la salida de la herramienta es pequeña (unos pocos KB), esto funciona bien. Pero cuando una herramienta devuelve 200KB de logs del servidor:

  1. La salida completa se inyecta en la conversación
  2. La ventana de contexto del LLM se llena
  3. El contexto más antiguo (incluida la pregunta original) se expulsa
  4. El LLM no puede razonar sobre los datos porque no puede verlos todos
  5. El agente falla o produce respuestas incompletas

Solución 1: Agente Único con Strands ToolContext

El primer enfoque usa agent.state, un almacén clave-valor nativo con alcance para cada instancia de agente. Las herramientas escriben datos grandes allí vía ToolContext y devuelven una cadena de puntero corta al contexto:

from strands import Agent, tool, ToolContext

# context=True inyecta ToolContext como el último parámetro — requerido para acceder a agent.state
@tool(context=True)
def fetch_application_logs(app_name: str, tool_context: ToolContext, hours: int = 24) -> str:
    """Obtiene logs de aplicación. Devuelve un puntero de memoria para datasets grandes."""
    logs = generate_logs(app_name, hours)  # Podría ser 200KB+

    if len(str(logs)) > 20_000:  # Umbral: almacenar externamente por encima de 20KB
        pointer = f"logs-{app_name}"
        # Almacena la carga útil completa en agent.state — nunca entra al contexto del LLM
        tool_context.agent.state.set(pointer, logs)
        # Devuelve solo la clave del puntero (52 bytes) — esto es todo lo que ve el LLM
        return f"Datos almacenados como puntero '{pointer}'. Usa herramientas de análisis para consultarlo."
    return str(logs)  # Suficientemente pequeño para devolver directamente

@tool(context=True)
def analyze_error_patterns(data_pointer: str, tool_context: ToolContext) -> str:
    """Analiza errores — resuelve puntero desde agent.state."""
    # Recupera el dataset completo desde agent.state usando la clave del puntero
    data = tool_context.agent.state.get(data_pointer)
    errors = [e for e in data if e["level"] == "ERROR"]
    # Devuelve un resumen (no datos sin procesar) — mantiene la respuesta pequeña
    return f"Se encontraron {len(errors)} errores en {len(set(e['service'] for e in errors))} servicios"
Enter fullscreen mode Exit fullscreen mode

El LLM nunca ve los 200KB. Solo ve "Datos almacenados como puntero 'logs-payment-service'" (52 bytes). La siguiente herramienta lee los datos completos desde agent.state y devuelve un resumen. Strands proporciona esta capacidad nativamente, sin diccionarios globales, sin hashlib, sin infraestructura externa.

Resultados de Agente Único

Métrica Sin Punteros Con Punteros de Memoria
Datos en contexto 214KB (logs completos) 52 bytes (puntero)
Comportamiento del agente Trunca/falla Procesa todos los datos
Errores detectados Parcial Completo (todos los servicios)

Gráfico de barras comparando uso de tokens con y sin Patrón de Puntero de Memoria en cuatro estrategias de gestión de contexto

Solución 2: Multi-Agente con Strands Swarm

Flujo de datos de Strands Swarm: agentes Collector, Analyzer y Reporter compartiendo 145KB de datos a través de invocation_state sin entrar a ninguna ventana de contexto de LLM

Un solo agente funciona para pipelines lineales. Pero la respuesta a incidentes del mundo real involucra roles especializados: alguien obtiene datos, alguien los analiza, alguien escribe el reporte. Strands Swarm coordina múltiples agentes autónomamente: define agentes con diferentes herramientas, y el Swarm maneja los traspasos.

Este es el mismo patrón de "referenciación de carga útil" del paper de colaboración multi-agente de Amazon. Los agentes intercambian punteros a datos compartidos en lugar de pasar cargas sin procesar. La diferencia es que Strands Swarm maneja la coordinación automáticamente, y proporciona invocation_state como la API oficial para compartir datos entre agentes.

from strands import Agent, tool, ToolContext
from strands.multiagent import Swarm

# invocation_state es un dict compartido entre todos los agentes en el Swarm — el almacén entre agentes
@tool(context=True)
def fetch_application_logs(app_name: str, tool_context: ToolContext, hours: int = 6) -> str:
    logs = generate_logs(hours)  # 145KB+
    pointer = f"logs-{app_name}"
    # Almacena en invocation_state para que todos los agentes descendentes puedan acceder sin re-obtener
    tool_context.invocation_state[pointer] = logs
    # Solo la cadena de puntero viaja a través del contexto del LLM al siguiente agente
    return f"Almacenado como '{pointer}'. Traspasar a analyzer."

@tool(context=True)
def analyze_error_patterns(logs_pointer: str, tool_context: ToolContext) -> str:
    # Resuelve el puntero al dataset completo — sin contexto de LLM consumido
    logs = tool_context.invocation_state.get(logs_pointer)
    errors = [l for l in logs if l["level"] == "ERROR"]
    result = {"total_errors": len(errors)}  # campos adicionales omitidos por brevedad
    # Almacena resultados de análisis como otro puntero para el agente reporter
    tool_context.invocation_state["error_analysis"] = result
    return json.dumps(result)

# Cada agente tiene un rol enfocado; el Swarm decide el orden de traspaso autónomamente
collector = Agent(name="collector", tools=[fetch_application_logs], model=MODEL)
analyzer = Agent(name="analyzer", tools=[analyze_error_patterns, detect_latency_anomalies], model=MODEL)
reporter = Agent(name="reporter", tools=[generate_incident_report], model=MODEL)

swarm = Swarm([collector, analyzer, reporter], entry_point=collector)
result = swarm("Obtén logs, analiza y genera reporte de incidente.")
Enter fullscreen mode Exit fullscreen mode

El Swarm automáticamente:

  • Comienza con el collector, que obtiene 145KB de logs y los almacena en invocation_state
  • El collector traspasa al analyzer con el puntero "logs-payment-service"
  • El analyzer ejecuta análisis de errores y latencia, almacena resultados en invocation_state, traspasa al reporter
  • El reporter genera el reporte de incidente final

No se necesita código de orquestación ni lógica de traspaso manual. Cada agente tiene sus propias herramientas y el Swarm determina el flujo a partir de las descripciones de agentes y la tarea. Todo el intercambio de datos ocurre vía tool_context.invocation_state, la misma API de ToolContext usada en agente único, con un almacén diferente.

Resultados de Swarm

Status: COMPLETED
Agents: collector → analyzer → reporter
Time: ~14s
Shared store:
  logs-payment-service: 145,310 bytes
  error_analysis: 135 bytes
  latency_analysis: 70 bytes
Enter fullscreen mode Exit fullscreen mode

145KB de logs procesados por tres agentes. Nada de eso entró nunca a ninguna ventana de contexto de LLM.

Investigación de Seguimiento

Después de que el swarm se completa, los datos permanecen en el almacén compartido. Un agente investigador separado puede profundizar en servicios específicos sin re-obtener:

# El investigator reutiliza invocation_state poblado por el swarm — sin re-obtención de datos
investigator = Agent(
    name="investigator",
    tools=[get_error_details, analyze_error_patterns],
    model=MODEL,
)

# Cada pregunta resuelve el puntero desde invocation_state y ejecuta análisis en memoria
investigator("¿Qué servicio tuvo más errores?")
investigator("Muéstrame los logs de error de cache-layer")
investigator("¿Qué códigos de estado devuelven esos errores?")
# Todas las consultas leen de los mismos 145KB ya en invocation_state — sin re-obtención, sin desbordamiento de contexto
Enter fullscreen mode Exit fullscreen mode

Cuándo Usar Cada Enfoque

Agente único + agent.state — pipelines lineales donde un agente maneja obtención + análisis + reporte. Usa ToolContext para acceder a tool_context.agent.state desde herramientas.

Swarm + invocation_state — roles especializados, flujos complejos, o cuando quieres coordinación autónoma. Usa ToolContext para acceder a tool_context.invocation_state: la API oficial de Strands para intercambio de datos multi-agente. El Swarm gestiona traspasos, timeouts y detección de traspasos repetitivos.

Ambos — usa SlidingWindowConversationManager como protección adicional. Recorta automáticamente el historial de conversación y maneja ContextWindowOverflowException con reintento.

Estos enfoques son parte de ingeniería de contexto para agentes de IA: la práctica de decidir qué información entra a la ventana de contexto del LLM y cuándo.

Pruébalo Tú Mismo

Necesitas Python 3.9+, uv, y una clave API de OpenAI.

git clone https://github.com/aws-samples/sample-why-agents-fail
cd sample-why-agents-fail/stop-ai-agents-wasting-tokens/01-context-overflow-demo
uv venv && uv pip install -r requirements.txt
export OPENAI_API_KEY="tu-clave-aquí"

uv run python test_context_overflow.py   # Agente único: 4 escenarios
uv run python swarm_demo.py              # Multi-agente: Collector → Analyzer → Reporter
Enter fullscreen mode Exit fullscreen mode

O abre test_context_overflow.ipynb en Kiro, VS Code, o tu entorno de notebook preferido.

Conclusiones Clave

  1. El desbordamiento de contexto es silencioso — los agentes no fallan, producen resultados incorrectos
  2. Los punteros de memoria lo solucionan — almacena datos grandes externamente, pasa referencias
  3. Reducción de >16,000x en tokens — validado por IBM Research en el benchmark de Ciencia de Materiales
  4. Agente único usa agent.state@tool(context=True) + ToolContext para almacenar y recuperar datos fuera del contexto
  5. Multi-agente usa invocation_state — misma API de ToolContext, compartida entre todos los agentes en el Swarm. No se necesita código de orquestación
  6. Los datos persisten para seguimiento — después de que el pipeline se completa, los datos almacenados están disponibles para investigación sin re-obtención

Preguntas Frecuentes

¿Por qué los agentes de IA se quedan sin contexto?

Los agentes de IA se quedan sin contexto cuando las respuestas de herramientas se inyectan directamente en el historial de conversación del LLM. Cada respuesta consume tokens. Cuando las salidas acumuladas de herramientas exceden el límite de ventana de contexto del modelo, el LLM pierde contexto anterior, trunca datos o falla por completo. Esto sucede silenciosamente: el agente parece funcionar pero produce resultados incompletos o incorrectos.

¿Qué es el Patrón de Puntero de Memoria para agentes de IA?

El Patrón de Puntero de Memoria almacena salidas grandes de herramientas (logs, datasets, resultados de consultas) en estado externo en lugar de en la ventana de contexto del LLM. Las herramientas devuelven una clave de referencia corta (el "puntero") que herramientas subsiguientes usan para recuperar los datos completos. IBM Research validó este patrón con una reducción de más de 16,000x en el benchmark de Ciencia de Materiales.

¿En qué se diferencia agent.state de invocation_state en Strands Agents?

agent.state tiene alcance para una sola instancia de agente. Úsalo para pipelines lineales donde un agente maneja todos los pasos. invocation_state se comparte entre todos los agentes en un Strands Swarm. Úsalo cuando múltiples agentes especializados necesitan intercambiar datos sin pasar cargas grandes a través del contexto del LLM.

¿Puedo usar el Patrón de Puntero de Memoria con LangGraph u otros frameworks?

Sí. El patrón requiere dos capacidades: un almacén clave-valor compartido accesible desde herramientas, y la capacidad de pasar cadenas de referencia cortas a través del contexto del LLM. LangGraph proporciona esto a través de su gestión de estado, AutoGen a través de memoria compartida, y CrewAI a través de contexto de tareas. La implementación de Strands usa ToolContext como la API nativa.

Referencias

Investigación

Implementación


¿Has alcanzado límites de ventana de contexto en tus agentes? ¿Qué estrategias funcionaron para ti? Comparte en los comentarios.

Siguiente en esta serie: Herramientas MCP Que Nunca Responden — patrones asíncronos para APIs externas lentas.


Todo el código en esta serie es open source bajo la Licencia MIT-0. Dale estrella al repositorio para seguir las actualizaciones.


Gracias!

🇻🇪Dev.to - Linkedin - GitHub - Twitter - Instagram - Youtube

Top comments (0)