Cuatro capas de ingeniería de contexto para agentes de inteligencia artificial de producción: Cómo Deep Insight las aplica en código de trabajo
Four layers of context engineering for production AI agents: How Deep Insight applies them in working code
Yoonseo Kim
Cuando los agentes de inteligencia artificial (AI) de producción manejan tareas como el análisis de datos y la generación de informes, la gestión de contexto puede convertirse en un cuello de botella importante. Una ventana de 200K-token suena generosa hasta que una tarea del mundo real consume la mayor parte de ella en minutos. El análisis de datos y la generación de informes hacen que el agente falle en la ejecución, pierda precisión o aumente los costos. Ya existe una guía publicada que aborda esto, pero las técnicas individuales son más fáciles de leer que de aplicar. Aplicadas juntas, hacen una diferencia medible: en la implementación de referencia que se describe en este post, una sola herramienta de escritura y ejecución reduce los tokens que cada script agrega al contexto en aproximadamente un 95 por ciento, y la carga de habilidades bajo demanda reduce la llamada del sistema en aproximadamente un 97 por ciento.
Deep Insight, una solución de análisis de datos de multiagente de código abierto construida sobre el SDK de Strands Agents y Amazon Bedrock AgentCore, que sirve como implementación de referencia en todo el proceso.
Parte 2: Cuatro capas de ingeniería de contexto para agentes de inteligencia artificial de producción: Cómo Deep Insight las aplica en código en funcionamiento.
Parte 3: Ingeniería de harness en la práctica: mover Deep Insight de desarrollo a producción. (Próximamente)
El primer post definió cinco desafíos clave que los sistemas de multiagente de producción deben resolver. Presentó cómo Strands Agents SDK, Amazon Bedrock y Bedrock AgentCore, y AWS Fargate abordan diferentes capas del problema, con ejemplos de código. Este segundo post toma las cuatro capas de práctica de ingeniería de contexto que se encuentran sobre esa arquitectura y muestra cada una implementada. El tercer post te guía a través de la implementación y operación de agentes en una red privada segura en Amazon Virtual Private Cloud (Amazon VPC), cubriendo todo lo necesario para operaciones del mundo real.
¿Qué es la ingeniería de contexto?
La ingeniería de contexto es la disciplina de optimizar la información en la ventana de contexto limitada de un modelo de lenguaje grande (LLM) para que los agentes funcionen de la mejor manera posible. Anthropic Claude Sonnet 4.5, disponible en Amazon Bedrock, ofrece una ventana de contexto de 200K, pero las tareas de producción complejas rápidamente la exceden. Por ejemplo, una solicitud aparentemente sencilla como “Analizar datos de ventas y crear un informe DOCX” pasa por varias etapas: carga y exploración de datos (5 min), análisis de ventas basado en categorías (3 min), generación de cinco gráficos para análisis de series temporales (10 min), validación estadística (3 min) y generación final del informe (5 min). En conjunto, consumen más de 150K tokens en 15 minutos.
Procesar tales tareas en un solo contexto causa problemas: la ventana se desborda a mitad de tarea, el contexto estancado degrada el rendimiento y los errores requieren volver a ejecutar toda la pipeline. A medida que el contexto crece, la atención a la información importante disminuye y la ineficiencia aumenta el costo bajo el precio por token.
“A medida que aumenta el número de tokens en la ventana de contexto, disminuye la capacidad del modelo para recordar información de ese contexto con precisión (pudrición de contexto).”
La ingeniería de contexto resuelve exactamente estos problemas, y no es solo una colección de técnicas. Abarcando el diseño de arquitectura, la escritura de prompts, la implementación de herramientas y la verificación, es una disciplina en capas donde cada capa compensa lo que las anteriores pasan por alto. Esta publicación detalla el enfoque de cuatro capas que puede aplicar para gestionar el contexto de manera eficiente.
Cómo manejar tareas que exceden la ventana de contexto
Anthropic ha publicado varias técnicas para manejar tareas de horizonte largo. Deep Insight agrupa estas técnicas en cuatro capas, con cada capa abordando las limitaciones de las demás. La siguiente tabla establece las cuatro capas.
Capa
Práctica
Principio fundamental
Limitaciones
Capa 1: Arquitectura
Aislamiento de contexto a través de arquitectura multiagente
Cada agente opera en un contexto independiente
Cuando el aislamiento solo no es suficiente
Capa 2: Prompt
Control de salida y reglas de comportamiento
Limitar la ingesta de contexto a través de prompts
Cuando los prompts solos no son suficientes
Capa 3: Herramientas
Externalización de contexto basada en archivos
Mantener contenido pesado en archivos fuera del contexto
Cuando aún surgen problemas
Capa 4: Agentes de verificación y salvaguardas
Verificación y salvaguardas independientes
Capturando errores y evitando desbordamiento de contexto
Última línea de defensa
Las secciones que siguen analizan cada capa en orden, describiendo lo que prescribe la capa, por qué las capas anteriores solas son insuficientes y cómo se implementa la práctica en Deep Insight.
1. Aislamiento de contexto a través de arquitectura de multiagente
Asigne a cada agente especializado su propia ventana de contexto y pase solo resultados comprimidos al coordinador. Deep Insight hace esto con una jerarquía de Coordinador, Planificador, Revisor de planes, Supervisor y Agentes de herramientas (Codificador, Validador, Informador, Seguidor, Auditor).
Con un solo agente, toda la información, desde las solicitudes de usuario hasta la exploración de datos, análisis, generación de gráficos, validación y generación de informes, se acumula en un contexto y fácilmente excede la ventana. Dar a cada agente su propio contexto mantiene incluso al Codificador, que utiliza el más, por debajo de 25K tokens en total. Cada agente recibe solo lo que necesita y señaliza a otros con un aviso de finalización y un resumen breve.
La clave del aislamiento es minimizar la información compartida. Deep Insight utiliza un diccionario de Python, shared_state, que almacena solo cuatro cosas:
messages: El mensaje final del agente anterior (no la historia de conversación completa).
clues: Resúmenes comprimidos recopilados de cada agente.
full_plan: Una lista de verificación generada por Planificador y actualizada por Seguidor.
history: Un registro breve de nombres y mensajes de agentes.
Las pistas utilizan un formato de pista fijo CLUES_FORMAT: en lugar de la conversación completa de cada agente (decenas de miles de tokens), solo se pasan resultados core comprimidos.
# coder_agent_tool.py -- context passing format
CLUES_FORMAT = "Here is clues from {}:\n\n<clues>\n{}\n</clues>\n\n"
RESPONSE_FORMAT = "Response from {}:\n\n<response>\n{}\n</response>\n\n*Please execute the next step.*"
# After Coder completes: add only compressed result to clues
clues += CLUES_FORMAT.format("coder", response["text"])
Este patrón es el recomendado en el post de Anthropic “Cómo construimos nuestro sistema de investigación de multiagente”, que describe un patrón de coordinador-trabajador en el que un agente principal delega a subagentes especializados, con cada agente trabajando solo dentro de su propio contexto. No necesitas construirlo tú mismo: el patrón de agentes como herramientas en el SDK de Strands Agents proporciona este aislamiento a nivel de framework.
2. Control de flujo de contexto a través de solicitudes
El aislamiento de la capa 1 solo no es suficiente: incluso con contextos independientes, un agente que genera respuestas largas infla el contexto del Supervisor. La capa 2 limita la salida de cada agente a través de solicitudes.
Para Deep Insight, utilizamos instrucciones para limitar la cantidad de información que cada agente devuelve al Supervisor. Tres reglas realizan la mayor parte del trabajo, como lo muestran las instrucciones de Deep Insight.
“Comience con el modelo más fuerte y una instrucción simple. Luego agregue instrucciones específicas de forma incremental basadas en casos de fallas observados en realidad.”
— Anthropic, “Ingeniería de contexto efectiva para agentes de IA” (2025.09)
Detalle de implementación 2-1: Presupuestos de tokens de salida explícitos por agente
La instrucción de cada agente especifica un recuento máximo de tokens de respuesta, lo que evita respuestas largas que contaminan el contexto del Supervisor.
Agente
Presupuesto de tokens de salida
Razón
Coder
1,000–1,500 tokens
El código de análisis se guarda en archivos, por lo que el agente devuelve solo un resumen del estado, las tareas completadas y las ideas
Validator
800 tokens
Los resultados de la validación se guardan en citations.json. El agente devuelve solo un resumen
Reporter
1,000 tokens
El agente genera el informe como un archivo DOCX y devuelve solo un resumen del resultado
La publicación de Anthropic ” Herramientas de escritura efectivas para agentes” sugiere dar a las herramientas una opción de respuesta CONCISA o DETALLADA para la eficiencia del contexto. Aplicar la misma idea un nivel más arriba, en la instrucción del sistema de cada agente. En Deep Insight, todos los agentes comparten un formato estandarizado:
## Status
[SUCCESS | PARTIAL_SUCCESS | ERROR]
## Completed Tasks
- [Task 1 from FULL_PLAN -- use exact wording so Tracker can match]
- [Task 2 -- be specific, not generic]
## Key Insights
- [Key finding 1 with numbers and ratios]
- [Key finding 2 with business implications]
## Generated Files
- ./artifacts/chart.png -- brief description
- ./artifacts/calculation_metadata.json -- N calculations
Detalle de implementación 2-2: Filosofía de código autocontenido
La instrucción del agente Coder establece explícitamente “las variables no persisten entre scripts”. Cada script debe incluir todas las importaciones necesarias y cargar los datos directamente. La instrucción proporciona ejemplos correctos e incorrectos:
# WRONG -- Attempting to use a variable from Turn 1 in Turn 2
# Turn 1:
df = pd.read_csv('data.csv')
total = df['Amount'].sum()
# Turn 2:
print(f"Total: {total}") # NameError: name 'total' is not defined
# CORRECT -- Every script is self-contained
import pandas as pd
df = pd.read_csv('./artifacts/cache/df_main.csv') # Load from cache
total = df['Amount'].sum()
print(f"Total: {total}")
La razón por la que esta regla se relaciona con la ingeniería de contexto es que hacer referencia a variables de scripts anteriores requiere que el agente “recuerde” conversaciones anteriores, lo que significa que el código anterior debe permanecer en contexto. El principio autocontenido significa que el código anterior se puede eliminar de forma segura del contexto.
Detalle de implementación 2-3: Regla de finalización de sección del Supervisor
La instrucción del Supervisor incluye la regla “No avanzar al siguiente agente hasta que todos los elementos de la lista de verificación en la sección del agente actual estén marcados [x]”. Expresamos esta regla en la instrucción porque decidir si el trabajo del Coder está completo requiere que el Supervisor interprete el plan utilizando información de las actualizaciones del Tracker. Este juicio es difícil de expresar solo en código.
3. “Solo referencias en contexto, datos reales en archivos”
La Capa 1 aísla el contexto entre agentes, y la Capa 2 limita la salida dentro de los agentes. Pero cuando el agente Coder genera 100 líneas de código Python, ese código en sí mismo entra en el contexto. Incluso con instrucciones de instrucción de “responder brevemente”, algunos códigos no se pueden escribir brevemente. La Capa 3 utiliza el diseño de herramientas para mover el contenido pesado fuera del contexto, hacia el sistema de archivos. Cuatro técnicas llevan la mayor parte del beneficio, como muestran los detalles de implementación siguientes.
Detalle de implementación 3-1: Mover código fuera del contexto con la herramienta Write y Execute
El Coder lee el plan de análisis, escribe Python y lo ejecuta para generar visualizaciones. Pero cuando el código se vuelve largo, el enfoque convencional (herramientas de escritura y ejecución de archivos separados) agrega 100 líneas directamente al contexto por script, acumulando más de 1,000 líneas.
La solución es colapsar los dos pasos en una sola herramienta, para que el código nunca entre en el contexto como un mensaje. El agente Coder de Deep Insight utiliza un write_and_execute_tool para esto.
Aquí está parte de la herramienta write_and_execute_tool. Después de escribir y ejecutar el archivo, devuelve solo un resumen: “Escribió 105 líneas, ejecución exitosa, análisis de cinco categorías completado”. El código permanece en el archivo y alrededor de tres líneas de resumen permanecen en el contexto. Basado en este ejemplo, eso ahorra alrededor del 95 por ciento de los tokens.
# write_and_execute_tool.py
def _handle_write_and_execute_tool(file_path, content, timeout=300):
"""Write a Python script and immediately execute it."""
# Step 1: Write file
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
# Step 2: Execute immediately
result = subprocess.run(
f"python {file_path}",
shell=True,
capture_output=True,
timeout=timeout
)
# Return only summary
return f"Written {len(content.split(chr(10)))} lines to {file_path}\n" \
f"Execution successful\n" \
f"Output: {result.stdout[:500]}" # Only first 500 chars
“Filtrado del lado del servidor: filtrado de datos en la capa de ejecución antes de que lleguen al contexto, reducción del 98,7% de tokens (150K a 2K).”
Detalle de implementación 3-2: Reutilizar lógica común como módulos en el agente Coder
Los módulos comunes se reutilizan en análisis. En lugar de regenerarlos cada vez, definir funciones frecuentemente utilizadas como un módulo una vez e importarlos, lo que evita el desperdicio de tokens y la duplicación de contexto.
Sin esto, definir funciones como to_python_type() o track_calculation() en cada análisis produce 200–300 líneas de código duplicado en 10 análisis. Deep Insight genera un módulo llamado coder_analysis_utils.py antes de la primera tarea. Incluye funciones para convertir tipos numpy, rastrear metadatos de cálculo y guardar en JSON. Los análisis posteriores lo importan, reemplazando 20–30 líneas regeneradas con dos líneas de importación, lo que ahorra tokens y mejora la consistencia y la depuración.
# coder_analysis_utils.py -- common module generated before first task
import numpy as np
import json
from datetime import datetime
_calculations = []
def to_python_type(value):
"""Convert numpy/pandas types to Python native types"""
if isinstance(value, (np.integer, np.int64)): return int(value)
elif isinstance(value, (np.floating, np.float64)): return float(value)
elif isinstance(value, np.ndarray): return value.tolist()
return value
def track_calculation(calc_id, value, description, formula,
source_file, source_columns, importance):
"""Track calculation metadata -- Validator independently verifies later"""
_calculations.append({
"id": calc_id, "value": to_python_type(value),
"description": description, "formula": formula,
"source_file": source_file, "source_columns": source_columns,
"importance": importance
})
def save_calculation_metadata(path="./artifacts/calculation_metadata.json"):
"""Save all tracked calculations to JSON"""
with open(path, 'w', encoding='utf-8') as f:
json.dump({"generated_at": datetime.now().isoformat(),
"calculations": _calculations}, f, ensure_ascii=False, indent=2)
Detalle de implementación 3-3: Guardar y compartir resultados de análisis a través de la toma de notas estructurada
Usamos la toma de notas estructurada para compartir resultados de análisis detallados sin pasarlos por el contexto de cada agente. Deep Insight almacena estos resultados en un archivo llamado all_results.txt, que luego es leído por los agentes según sea necesario.
Por ejemplo, el agente Coder agrega resultados a all_results.txt después de cada tarea de análisis:
with open('./artifacts/all_results.txt', 'a', encoding='utf-8') as f:
f.write(f"""
## Category Sales Analysis (completed at: 14:32)
- Top revenue category: Fruit (417,166,008 KRW, 45% of total)
- Top 3 categories: Fruit, Vegetables, Meat (78% of total)
- Generated file: ./artifacts/category_sales_chart.png
""")
El Coder registra resultados detallados en este archivo después de cada análisis, y el Reporter lo lee al escribir el informe final. Otros agentes colaboran a través de all_results.txt de la misma manera.
Sin la toma de notas, el Coder pasa resultados detallados al Supervisor después de cada tarea, acumulándolos en su contexto. Con la toma de notas, solo se pasa un mensaje de aproximadamente 30 tokens como “Análisis de ventas de categorías completo, 3 ideas clave encontradas, resultados detallados guardados en all_results.txt”, y el Reporter lee el archivo cuando sea necesario.
El patrón se generaliza más allá de un solo archivo. El propio sistema de archivos puede servir como el bus de comunicación entre agentes, como lo hace en Deep Insight:
Nombre del archivo
Productor
Consumidor
Rol
all_results.txt
Coder
Reporter
Registro acumulado de resultados de análisis
calculation_metadata.json
Coder
Validator
Registro de cálculos numéricos: fuentes, fórmulas y valores (para verificación)
citations.json
Validator
Reporter
Datos de cita verificados (insertados como [1], [2] en el informe)
audit_findings.json
Auditor
Reporter
Defectos de cita encontrados en el informe final (impulsa reintentos dirigidos del Reporter)
coder_analysis_utils.py
Coder
Todos los scripts
Funciones de utilidad compartidas (escribir una vez, importar repetidamente)
plan_completa (estado_compartido)
Planificador/Seguimiento
Supervisor
Estado de la lista de verificación (actualizando [x])
“El enfoque”justo a tiempo”, que carga dinámicamente los datos en el contexto en tiempo de ejecución en lugar de procesar todos los datos relevantes de antemano, mantiene el contexto fresco, relevante y adaptable al estado evolutivo de la tarea.”
Detalle de implementación 3-4: Cargar solo el conocimiento necesario con Habilidades
En lugar de poner todo el conocimiento especializado en la llamada del sistema, este enfoque lo carga solo cuando es necesario. Incluir todas las guías de habilidades (comprobación de estructuras de datos, generación de README, creación de habilidades, escritura de llamadas del sistema, creación de herramientas) agregaría más de 20.000 tokens, cargaría información innecesaria en el agente Coder en cada llamada y forzaría una redeploy para agregar una habilidad.
El sistema de Habilidades de Deep Insight carga solo un catálogo de habilidades de unos 500 tokens al inicio, con la lista de habilidades que solo contiene nombres y descripciones breves. Cuando un usuario solicita “Crear un archivo README”, el agente decide “Necesito la habilidad de generador de README” y llama a skill_tool(skill_name="readme-generator"). El SkillLoader lee readme-generator/SKILL.md y devuelve una guía detallada de unos 3K tokens.
# 1. Skill Discovery (at initialization)
from src.utils.skills.skill_utils import initialize_skills
available_skills, skill_prompt = initialize_skills(
skill_dirs=["./skills"],
verbose=True
)
# 2. Add to System Prompt (~500-token catalog)
system_prompt = base_prompt + skill_prompt
# 3. Runtime -- Agent loads skill when needed
# Agent decides: "This is README generation, I need the readme-generator skill"
# -> skill_tool(skill_name="readme-generator")
# -> Returns full SKILL.md content (~3K tokens)
Cada habilidad se define como un archivo SKILL.md compuesto por frontmatter YAML y guía markdown detallada. Incluye metadatos como nombre, descripción, licencia y herramientas permitidas, junto con descripción general, cuándo usar esta habilidad, instrucciones detalladas y mejores prácticas. Para agregar una nueva habilidad, crear un nuevo directorio bajo habilidades/ y escribir un archivo SKILL.md, y se descubre automáticamente.
Al inicio, el agente carga un catálogo de habilidades de unos 500 tokens en lugar de desperdiciar más de 20.000 tokens en guías completas (aproximadamente un 97 por ciento menos). Cuando sea necesario, puede cargar unos pocos miles de tokens adicionales de instrucciones detalladas para habilidades.
4. Verificar la calidad con agentes de verificación y salvaguardas
Incluso con las capas 1-3, queda un riesgo: los agentes aislados no pueden ver el trabajo de los demás, por lo que si el Coder calcula mal, el Reporter lleva ese error al informe. La capa 4 es la última línea de defensa.
“Proporcionar herramientas de prueba para que el agente pueda autoverificar características y corregir errores que no son obvios desde el código solo. Hacer que el modelo comprometa su progreso en git con mensajes de compromiso descriptivos y escriba resúmenes de progreso en un archivo de progreso.”
Detalle de implementación 4-1: Agentes Tracker, Validator y Auditor: seguimiento del progreso y aseguramiento de la calidad
Tracker actualiza la lista de verificación del plan en tiempo real. Cuando el Coder completa la carga de datos, el Supervisor llama a Tracker, que actualiza el elemento del plan de [ ] a [x] en función de información como “Carga de datos completa (1,000 filas, 5 columnas).” Esto ayuda a los usuarios y al sistema a saber exactamente en qué punto se encuentra el progreso.
Validator re-ejecuta de forma independiente los cálculos del Coder para verificar la precisión. Lee calculation_metadata.json, vuelve a realizar cada cálculo a partir de los datos de origen y compara: las coincidencias dentro de 0.01 pasan, las discrepancias se marcan. Los cálculos verificados se envían a citations.json para que el Reporter los cite. Después de que el Reporter termine, el Auditor verifica el DOCX final contra citations.json y calculation_metadata.json sin modificarlos. Registra los defectos de citación en audit_findings.json y puede solicitar hasta dos reintentos dirigidos al Reporter.
Detalle de implementación 4-2: Priorización de cálculos para verificación
Verificar cada cálculo es ineficiente, por lo que se reduce el alcance de la verificación por importancia. El OptimizedValidator de Deep Insight aplica los siguientes umbrales:
Más de 50 cálculos: filtrado agresivo, se verifican todos los de alta prioridad y solo 10 de prioridad media.
Más de 20 cálculos: filtrado moderado, se verifican todos los de alta prioridad y 15 de prioridad media.
20 cálculos o menos: se verifican la mayoría, todos los de alta prioridad, todos los de prioridad media y 5 de baja prioridad.
También aplica comparación segura de tipos: para evitar problemas de tipos entre numpy y Python, todos los valores se convierten a float() y se verifican para una diferencia absoluta inferior a 0.01:
# validator.md -- type-safe numerical comparison
try:
match = abs(float(expected) - float(actual)) < 0.01
except:
match = str(expected) == str(actual)
Detalle de implementación 4-3: SummarizingConversationManager: la última red de seguridad
El contexto aún puede desbordarse en casos excepcionales, por lo que se mantiene una red de seguridad bajo las otras capas. Deep Insight utiliza el SummarizingConversationManager en el SDK de Strands Agents para esto.
# strands_sdk_utils.py -- safety net configuration at agent creation
agent = Agent(
model=llm,
system_prompt=system_prompts,
tools=tools,
conversation_manager=SummarizingConversationManager(
summary_ratio=0.5, # summarize oldest 50% on overflow
preserve_recent_messages=10, # always preserve 10 most recent messages
summarization_system_prompt=apply_prompt_template("summarization", {})
)
)
En caso de desbordamiento, el LLM resume el 50 por ciento más antiguo de los mensajes en uno, mientras siempre conserva los 10 más recientes para mantener el contexto de la tarea actual. La solicitud de resumen (summarization.md) requiere que clues, plans y tracking status se conserven exactamente tal como están.
Detalle de implementación 4-4: Cacheo de solicitudes selectivo para optimización de costos
La ingeniería de contexto abarca la optimización de costos, no solo el ahorro de tokens. Habilita el cacheo de solicitudes por agente, según la frecuencia con la que cada uno se llama con la misma solicitud. Configuraciones por agente de Deep Insight:
Agente
Cache de solicitud
Cache de herramienta
Razón
Supervisor
Sí
Sí
Alta frecuencia de llamadas repetidas, con una gran solicitud de sistema y definiciones de herramientas
Codificador
Sí
Sí
Ejecuta varios scripts de análisis secuencialmente, con la misma solicitud cada vez
Informador
Sí
Sí
Genera un informe de forma incremental sección por sección, con alta frecuencia de reutilización de solicitudes
Auditor
Sí
Sí
Inspecta los archivos DOCX y JSON durante muchas iteraciones con la misma solicitud y herramientas, y vuelve a ejecutar después de cada reintento del Informador
Coordinador
No
No
Una sola llamada única, sin beneficio de cacheo
Planificador
No
No
Llamado una vez por solicitud, y nuevamente solo cuando el usuario solicita una revisión del plan
Validador
No
No
Llamado con datos diferentes cada vez, baja tasa de acierto de cache
Seguidor
No
No
Tarea ligera, sin herramientas, cacheo innecesario
Los agentes con cacheo habilitado insertan puntos de cache en las solicitudes de sistema y definiciones de herramientas, reduciendo los costos de tokens de entrada hasta un 90 por ciento en llamadas repetidas. Esta es una función admitida de forma nativa por el SDK de Strands Agents. El revisor de planes no aparece en la tabla porque es un paso de bucle humano que recopila aprobación o comentarios del usuario en lugar de llamar a un modelo.
Conclusión
Esta publicación ha detallado el enfoque de ingeniería de cuatro capas que puede utilizar para gestionar eficientemente el contexto para tareas complejas que exceden la ventana de contexto.
Capa 1 (aislamiento a nivel de arquitectura): Cada agente trabaja en un contexto independiente a través de una arquitectura multiagente, pasando solo resúmenes comprimidos.
Capa 2 (control basado en instrucciones): Los presupuestos de tokens de salida, los formatos de respuesta estandarizados y la filosofía de código autocontenido limitan activamente el flujo de contexto.
Capa 3 (uso del sistema de archivos): write_and_execute_tool mantiene el código fuera del contexto, el sistema de archivos sirve como un bus de comunicación entre agentes y el conocimiento se carga de forma diferida solo cuando se necesita.
Capa 4 (verificación y salvaguardas): La verificación de cálculo independiente del Validador, la auditoría de citación de solo lectura del Auditor del informe final, el seguimiento de progreso del Tracker, la prevención de desbordamiento del SummarizingConversationManager y la caché de instrucciones selectiva gestionan tanto la calidad como el costo.
Cada capa forma un sistema de defensa que compensa lo que las capas anteriores pasan por alto. Cuando el aislamiento de arquitectura es insuficiente, las instrucciones limitan la salida. Cuando las instrucciones son insuficientes, las herramientas mantienen el contenido externo. Y cuando aún surgen problemas, la verificación los detecta.
Al construir agentes de producción, la ventana de contexto de LLM por sí sola rara vez es suficiente. Aplica estas técnicas de ingeniería de contexto para gestionar el contexto de forma eficiente y escalar tus agentes para cargas de trabajo de producción.
Deep Insight, la implementación de referencia utilizada aquí, es de código abierto. Revisa el código y extiéndelo para tu dominio.
When production AI agents handle tasks such as data analysis and report generation, context management can become a major bottleneck. A 200K-token window sounds generous until a real-world task burns through most of it in minutes. Data analysis and report generation leave the agent failing mid-execution, losing accuracy, or driving up costs. A body of published guidance already addresses this, but the individual techniques are easier to read about than to apply. Applied together, they make a measurable difference: in the reference implementation this post walks through, a single write-and-execute tool cuts the tokens each script adds to context by about 95 percent, and loading skills on demand shrinks the system prompt by about 97 percent.
This series organizes that guidance into practices you can apply directly. Anthropic’s engineering posts, together with features built into the Strands Agents SDK, converge on four layers of context engineering: isolate context at the architecture level, control it through prompts, externalize it to the filesystem, and verify it with independent agents and safeguards. In this post (Part 2), you will learn how each layer works and what it looks like in working code. We applied these techniques in Deep Insight, an open source multi-agent data analysis solution built on the Strands Agents SDK and Amazon Bedrock AgentCore, which serves as the reference implementation throughout.
Part 2: Four layers of context engineering for production AI agents: How Deep Insight applies them in working code.
Part 3: Harness engineering in practice: moving Deep Insight from dev to production. (Coming soon!)
The first post defined five core challenges that production multi-agent systems must solve. It introduced how Strands Agents SDK, Amazon Bedrock and Bedrock AgentCore, and AWS Fargate each address different layers of the problem, with code examples. This second post takes the four layers of context engineering practice that sit on top of that architecture and shows each one implemented. The third post guides you through deploying and operating agents in a secure private network on Amazon Virtual Private Cloud (Amazon VPC), covering everything needed for real-world operations.
What is context engineering?
Context engineering is the discipline of optimizing the information in a large language model (LLM)’s limited context window so agents perform at their best. Anthropic Claude Sonnet 4.5, available on Amazon Bedrock, offers a 200K context window, but complex production tasks quickly exceed it. For example, a seemingly straightforward request like “Analyze sales data and create a DOCX report” runs through several stages: data loading and exploration (5 min), category-based sales analysis (3 min), generating five charts for time-series analysis (10 min), statistical validation (3 min), and final report generation (5 min). Together they consume over 150K tokens across 15 minutes.
Processing such tasks in a single context causes problems: the window overflows mid-task, stale context degrades performance, and errors require re-running the whole pipeline. As context grows, attention to important information drops, and inefficiency raises cost under per-token pricing.
“As the number of tokens in the context window increases, the model’s ability to accurately recall information from that context decreases (Context rot).”
Context engineering solves exactly these problems, and it is not only a collection of techniques. Spanning architecture design, prompt writing, tool implementation, and verification, it’s a layered discipline where each layer compensates for what the previous ones miss. This post details the four-layer approach you can apply to manage context efficiently.
How to handle tasks that exceed the context window
Anthropic has published several techniques for handling long-horizon tasks. Deep Insight groups these techniques into four layers, with each layer addressing the limitations of the others. The following table sets out the four layers.
Layer
Practice
Core Principle
Limitations
Layer 1: Architecture
Isolating Context Through Multi-Agent Architecture
Each agent operates in an independent context
When isolation alone is not enough
Layer 2: Prompt
Output Control and Behavioral Rules
Limiting context intake through prompts
When prompts alone are not enough
Layer 3: Tools
File-based Context Externalization
Keeping heavy content in files outside the context
When issues still arise
Layer 4: Verification Agents and Safeguards
Independent Verification and Safeguards
Catching errors and preventing context overflow
Final line of defense
The sections that follow take each layer in order, stating what the layer prescribes, why the preceding layers alone are insufficient, and how the practice is implemented in Deep Insight.
1. Isolating context through multi-agent architecture
Give each specialized agent its own context window and pass only compressed results to the orchestrator. Deep Insight does this with a hierarchy of Coordinator, Planner, Plan Reviewer, Supervisor, and Tool Agents (Coder, Validator, Reporter, Tracker, Auditor).
With a single agent, all information, from user requests through data exploration, analysis, chart generation, validation, and reporting, accumulates in one context and easily exceeds the window. Giving each agent its own context keeps even the Coder, which uses the most, under 25K tokens total. Each agent receives only what it needs and signals others with a completion notice and brief summary.
The key to isolation is minimizing shared information. Deep Insight uses a Python dictionary, shared_state, that stores only four things:
messages: The previous agent’s final message (not the full conversation history).
clues: Compressed summaries collected from each agent.
full_plan: A checklist generated by Planner and updated by Tracker.
history: A brief log of agent names and messages.
The clues use a fixed CLUES_FORMAT: instead of each agent’s full conversation (tens of thousands of tokens), only compressed core results are passed.
# coder_agent_tool.py -- context passing format
CLUES_FORMAT = "Here is clues from {}:\n\n<clues>\n{}\n</clues>\n\n"
RESPONSE_FORMAT = "Response from {}:\n\n<response>\n{}\n</response>\n\n*Please execute the next step.*"
# After Coder completes: add only compressed result to clues
clues += CLUES_FORMAT.format("coder", response["text"])
This pattern is the one recommended in Anthropic’s “How We Built Our Multi-Agent Research System” post, which describes an orchestrator-worker pattern in which a lead agent delegates to specialized subagents, with each agent working only within its own context. You do not need to build it yourself: the agents-as-tools pattern in the Strands Agents SDK provides this isolation at the framework level.
2. Controlling context inflow through prompts
Layer 1 isolation alone is not sufficient: even with independent contexts, an agent that generates long responses inflates the Supervisor’s context. Layer 2 limits each agent’s output through prompts.
For Deep Insight, we use prompts to limit how much information each agent returns to the Supervisor. Three rules do most of the work, as Deep Insight’s prompts show.
“Start with the strongest model and a simple prompt. Then incrementally add specific instructions based on actually observed failure cases.”
— Anthropic, “Effective Context Engineering for AI Agents” (2025.09)
Each agent’s prompt specifies a maximum response token count, preventing long responses that pollute the Supervisor’s context.
Agent
Output Token Budget
Reason
Coder
1,000–1,500 tokens
Analysis code is saved to files, so the agent returns only a summary of state, completed tasks, and insights
Validator
800 tokens
Validation results are saved to citations.json. The agent returns only a summary
Reporter
1,000 tokens
The agent generates the report as a DOCX file and returns only a summary of the result
Anthropic’s ” Writing Effective Tools for Agents” post suggests giving tools a CONCISE or DETAILED response option for context efficiency. Apply the same idea one level up, in each agent’s system prompt. In Deep Insight, all agents share one standardized format:
## Status
[SUCCESS | PARTIAL_SUCCESS | ERROR]
## Completed Tasks
- [Task 1 from FULL_PLAN -- use exact wording so Tracker can match]
- [Task 2 -- be specific, not generic]
## Key Insights
- [Key finding 1 with numbers and ratios]
- [Key finding 2 with business implications]
## Generated Files
- ./artifacts/chart.png -- brief description
- ./artifacts/calculation_metadata.json -- N calculations
The Coder agent’s prompt explicitly states “variables do not persist between scripts.” Every script must include all necessary imports and load data directly. The prompt provides both incorrect and correct examples:
# WRONG -- Attempting to use a variable from Turn 1 in Turn 2
# Turn 1:
df = pd.read_csv('data.csv')
total = df['Amount'].sum()
# Turn 2:
print(f"Total: {total}") # NameError: name 'total' is not defined
# CORRECT -- Every script is self-contained
import pandas as pd
df = pd.read_csv('./artifacts/cache/df_main.csv') # Load from cache
total = df['Amount'].sum()
print(f"Total: {total}")
The reason this rule relates to context engineering is that referencing variables from previous scripts requires the agent to “remember” prior conversations, which means past code must remain in context. The self-contained principle means past code can be safely removed from context.
The Supervisor’s prompt includes the rule “Do not move to the next agent until all checklist items in the current agent’s section are marked [x].” We express this rule in the prompt because deciding whether the Coder’s work is complete requires the Supervisor to interpret the plan using information from the Tracker’s updates. This judgment is difficult to express in code alone.
3. “Only pointers in context, actual data in files”
Layer 1 isolates context between agents, and Layer 2 limits output within agents. But when the Coder agent generates 100 lines of Python code, that code itself enters the context. Even with “respond briefly” prompt instructions, some code can’t be written briefly. Layer 3 uses tool design to move heavy content outside the context, into the filesystem. Four techniques carry most of the benefit, as the following implementation details show.
Implementation detail 3-1: Moving code outside context with Write and Execute Tool
The Coder reads the analysis plan, writes Python, and executes it to generate visualizations. But when the code gets long, the conventional approach (separate file-write and execute tools) adds 100 lines directly to context per script, accumulating over 1,000 lines.
The fix is to collapse the two steps into a single tool, so the code never enters context as a message. Deep Insight’s Coder agent uses one write_and_execute_tool for this.
Here’s part of the write_and_execute_tool. After writing and executing the file, it returns only a summary: “Wrote 105 lines, execution successful, completed analysis of five categories.” The code stays in the file and about three lines of summary remain in context. Based on this example, that saves about 95 percent of the tokens.
# write_and_execute_tool.py
def _handle_write_and_execute_tool(file_path, content, timeout=300):
"""Write a Python script and immediately execute it."""
# Step 1: Write file
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
# Step 2: Execute immediately
result = subprocess.run(
f"python {file_path}",
shell=True,
capture_output=True,
timeout=timeout
)
# Return only summary
return f"Written {len(content.split(chr(10)))} lines to {file_path}\n" \
f"Execution successful\n" \
f"Output: {result.stdout[:500]}" # Only first 500 chars
“Server-side filtering: filtering data at the execution layer before it reaches context, 98.7% token reduction (150K to 2K).”
Implementation detail 3-2: Reusing common logic as modules in the Coder agent
Common modules get reused across analyses. Rather than regenerating them each time, define frequently-used functions as a module once and import them, which prevents token waste and context duplication.
Without this, defining functions like to_python_type() or track_calculation() in every analysis produces 200–300 lines of duplicate code across 10 analyses. Deep Insight generates a module called coder_analysis_utils.py before the first task. It includes functions for converting numpy types, tracking calculation metadata, and saving to JSON. Subsequent analyses import it, replacing 20–30 regenerated lines with two import lines, which saves tokens and improves consistency and debugging.
# coder_analysis_utils.py -- common module generated before first task
import numpy as np
import json
from datetime import datetime
_calculations = []
def to_python_type(value):
"""Convert numpy/pandas types to Python native types"""
if isinstance(value, (np.integer, np.int64)): return int(value)
elif isinstance(value, (np.floating, np.float64)): return float(value)
elif isinstance(value, np.ndarray): return value.tolist()
return value
def track_calculation(calc_id, value, description, formula,
source_file, source_columns, importance):
"""Track calculation metadata -- Validator independently verifies later"""
_calculations.append({
"id": calc_id, "value": to_python_type(value),
"description": description, "formula": formula,
"source_file": source_file, "source_columns": source_columns,
"importance": importance
})
def save_calculation_metadata(path="./artifacts/calculation_metadata.json"):
"""Save all tracked calculations to JSON"""
with open(path, 'w', encoding='utf-8') as f:
json.dump({"generated_at": datetime.now().isoformat(),
"calculations": _calculations}, f, ensure_ascii=False, indent=2)
Implementation detail 3-3: Saving and sharing analysis results through structured note-taking
We use structured note-taking to share detailed analysis results without passing them through each agent’s context. Deep Insight stores these results in a file called all_results.txt, which is then read by agents as needed.
For example, the Coder agent appends results to all_results.txt after each analysis task:
with open('./artifacts/all_results.txt', 'a', encoding='utf-8') as f:
f.write(f"""
## Category Sales Analysis (completed at: 14:32)
- Top revenue category: Fruit (417,166,008 KRW, 45% of total)
- Top 3 categories: Fruit, Vegetables, Meat (78% of total)
- Generated file: ./artifacts/category_sales_chart.png
""")
The Coder records detailed results in this file after each analysis, and the Reporter reads it when writing the final report. Other agents collaborate through all_results.txt the same way.
Without note-taking, the Coder passes detailed results to the Supervisor after every task, accumulating in its context. With note-taking, only an approximately 30-token message like “Category sales analysis complete, 3 key insights found, detailed results saved to all_results.txt” is passed, and the Reporter reads the file when needed.
The pattern generalizes beyond a single file. The filesystem itself can serve as the inter-agent communication bus, as it does in Deep Insight:
File name
Producer
Consumer
Role
all_results.txt
Coder
Reporter
Cumulative log of analysis results
calculation_metadata.json
Coder
Validator
Record of numeric calculations: sources, formulas, and values (for verification)
citations.json
Validator
Reporter
Verified citation data (inserted as [1], [2] in the report)
audit_findings.json
Auditor
Reporter
Citation defects found in the final report (drives targeted Reporter retries)
“The”just in time” approach, dynamically loading data into context at runtime rather than pre-processing all relevant data up front, keeps context fresh, relevant, and adaptive to the evolving state of the task.”
Implementation detail 3-4: Loading only needed knowledge with Skills
Rather than putting all specialized knowledge into the system prompt, this approach loads it only when needed. Including every skill guide (data structure checking, README generation, skill creation, system prompt writing, tool creation) would add over 20K tokens, load unnecessary information into the Coder agent on every call, and force a redeploy to add a skill.
Deep Insight’s Skills system loads only a skill catalog of about 500 tokens at startup, with the skill list holding only names and brief descriptions. When a user requests “Create a README file,” the agent decides “I need the readme-generator skill” and calls skill_tool(skill_name="readme-generator"). The SkillLoader reads readme-generator/SKILL.md and returns a detailed guide of about 3K tokens.
# 1. Skill Discovery (at initialization)
from src.utils.skills.skill_utils import initialize_skills
available_skills, skill_prompt = initialize_skills(
skill_dirs=["./skills"],
verbose=True
)
# 2. Add to System Prompt (~500-token catalog)
system_prompt = base_prompt + skill_prompt
# 3. Runtime -- Agent loads skill when needed
# Agent decides: "This is README generation, I need the readme-generator skill"
# -> skill_tool(skill_name="readme-generator")
# -> Returns full SKILL.md content (~3K tokens)
Each skill is defined as a SKILL.md file composed of YAML frontmatter and detailed markdown guide. It includes metadata like name, description, license, and allowed-tools, along with Overview, When to Use This Skill, detailed instructions, and Best Practices. To add a new skill, create a new directory under skills/ and write a SKILL.md file, and it is automatically discovered.
At startup, the agent loads a skill catalog of about 500 tokens instead of wasting over 20,000 tokens on full guides (about 97 percent less). When needed, it can load an additional few thousand tokens’ worth of detailed instructions for skills.
4. Verifying quality with verification agents and safeguards
Even with Layers 1–3, one risk remains: isolated agents can’t see each other’s work, so if the Coder miscalculates, the Reporter carries that error into the report. Layer 4 is the final line of defense.
“Provide testing tools so the agent can self-verify features and fix bugs that aren’t obvious from the code alone. Have the model commit its progress to git with descriptive commit messages and write progress summaries in a progress file.”
Implementation detail 4-1: Tracker, Validator, and Auditor agents: progress tracking and quality assurance
Tracker updates the plan’s checklist in real time. When the Coder completes data loading, the Supervisor calls Tracker, which updates the plan item from [ ] to [x] based on information like “Data load complete (1,000 rows, 5 columns).” This helps both users and the system know exactly where progress stands.
Validator independently re-executes the Coder’s calculations to verify accuracy. It reads calculation_metadata.json, re-performs each calculation from source data, and compares: matches within 0.01 pass, mismatches are flagged. Verified calculations go to citations.json for the Reporter to cite. After the Reporter finishes, the Auditor checks the final DOCX against citations.json and calculation_metadata.json without modifying them. It records citation defects in audit_findings.json and can request up to two targeted retries from the Reporter.
Implementation detail 4-2: Prioritizing calculations for verification
Verifying every calculation is inefficient, so scope the verification by importance. Deep Insight’s OptimizedValidator applies the following thresholds:
Over 50 calculations: aggressive filtering, verify all high plus only 10 medium.
Over 20 calculations: moderate filtering, verify all high plus 15 medium.
20 or fewer calculations: verify most, all high plus all medium plus 5 low.
It also applies type-safe comparison: to avoid numpy-versus-Python type issues, all values are converted to float() and checked for an absolute difference under 0.01:
# validator.md -- type-safe numerical comparison
try:
match = abs(float(expected) - float(actual)) < 0.01
except:
match = str(expected) == str(actual)
Implementation detail 4-3: SummarizingConversationManager: the last safety net
Context can still overflow in exceptional cases, so keep a safety net under the other layers. Deep Insight uses the SummarizingConversationManager in the Strands Agents SDK for this.
# strands_sdk_utils.py -- safety net configuration at agent creation
agent = Agent(
model=llm,
system_prompt=system_prompts,
tools=tools,
conversation_manager=SummarizingConversationManager(
summary_ratio=0.5, # summarize oldest 50% on overflow
preserve_recent_messages=10, # always preserve 10 most recent messages
summarization_system_prompt=apply_prompt_template("summarization", {})
)
)
On overflow, the LLM summarizes the oldest 50 percent of messages into one, while always preserving the 10 most recent to keep the current task’s context. The summarization prompt (summarization.md) requires clues, plans, and tracking status to be preserved verbatim.
Implementation detail 4-4: Selective prompt caching for cost optimization
Context engineering covers cost optimization, not only token savings. Enable prompt caching per agent, based on how often each is called with the same prompt. Deep Insight’s per-agent settings:
Agent
Prompt Cache
Tool Cache
Reason
Supervisor
Yes
Yes
High frequency of repeated calls, with a large system prompt and tool definitions
Coder
Yes
Yes
Running multiple analysis scripts sequentially, with the same prompt each time
Reporter
Yes
Yes
Generating a report incrementally section by section, with high prompt-reuse frequency
Auditor
Yes
Yes
Inspects the DOCX and JSON files over many turns with the same prompt and tools, and reruns after each Reporter retry
Coordinator
No
No
A single one-off call, no caching benefit
Planner
No
No
Called once per request, and again only when the user requests a plan revision
Validator
No
No
Called with different data each time, low cache hit rate
Tracker
No
No
Lightweight task, no tools, caching unnecessary
Agents with caching enabled insert cache points into system prompts and tool definitions, reducing input token costs by up to 90 percent on repeated calls. This is a feature natively supported by the Strands Agents SDK. Plan Reviewer does not appear in the table because it’s a human-in-the-loop step that collects user approval or feedback rather than calling a model.
Conclusion
This post has detailed the four-layer engineering approach you can use to efficiently manage context for complex tasks that exceed the context window.
Layer 1 (architecture-level isolation): Each agent works in an independent context through multi-agent architecture, passing only compressed summaries.
Layer 3 (filesystem use): write_and_execute_tool keeps code outside context, the filesystem serves as an inter-agent communication bus, and knowledge is lazy-loaded only when needed.
Layer 4 (verification and safeguards): Validator’s independent calculation re-verification, Auditor’s read-only citation audit of the final report, Tracker’s progress tracking, SummarizingConversationManager’s overflow prevention, and selective prompt caching manage both quality and cost.
Each layer forms a defense system that compensates for what the preceding layers miss. When architecture isolation is insufficient, prompts limit output. When prompts are insufficient, tools keep content external. And when problems still arise, verification catches them.
When building production agents, the LLM’s context window alone is rarely enough. Apply these context engineering techniques to manage context efficiently and scale your agents for production workloads.
Deep Insight, the reference implementation used here, is open source. Review the code and extend it for your domain.