Durante las últimas semanas he estado experimentando bastante con agentes de IA ejecutándose completamente en local, especialmente con modelos relativamente pequeños.
Y me encontré con un problema que inicialmente parecía simplemente una limitación del context window.
Pero había algo más.
No todo el contexto lo genera el usuario
Cuando pensamos en context windows solemos pensar en conversaciones demasiado largas.
En un agente existe otra fuente de consumo muy importante: las herramientas.
Imaginemos un agente trabajando durante una tarea relativamente larga:
Agent → Tool → 12k chars → Agent → Tool → 8k chars → Agent → Tool → 20k chars → ...
Logs, respuestas de APIs, búsquedas, contenido de archivos, JSON, resultados de terminal…
Todo ese contenido puede terminar formando parte del contexto activo del modelo.
Con modelos grandes y ventanas de contexto enormes puede pasar relativamente desapercibido.
Con agentes locales pequeños, no tanto.
El contexto crece rápidamente y llega un punto en el que el modelo empieza a tener dificultades para identificar qué información sigue siendo importante.
Y aumentar el context window no siempre es la mejor solución.
Quizá deberíamos controlar mejor qué dejamos entrar en él.
Una capa entre las tools y el modelo
Hermes Agent expone un hook especialmente interesante para este problema: transform_tool_result.
Se ejecuta después de obtener el resultado de una herramienta y antes de introducirlo nuevamente en la conversación.
Eso permite hacer algo así:
Tool → Raw result → tool-output-compactor → Bounded result → Model context
A partir de esa idea construí tool-output-compactor, un plugin open source para Hermes cuyo objetivo es muy concreto:
No es memoria.
No es RAG.
No almacena los resultados originales en una base de datos.
Es simplemente una frontera antes del contexto del modelo.
¿Cómo decide qué compactar?
El pipeline es deterministic-first.
Los resultados pequeños simplemente pasan sin modificaciones.
Cuando un resultado supera el presupuesto configurado, el plugin analiza primero su estructura e intenta preservar información relevante:
- errores, warnings y tracebacks;
- exit codes y stderr;
- comandos y argumentos;
- paths y queries;
- estados y approvals;
- estructura y claves de JSON;
- cabecera y final de outputs largos;
- información crítica relacionada con la acción ejecutada.
A partir de ahí puede utilizar dos estrategias.
1. Deterministic compaction
No necesita ningún LLM adicional.
Aplica reglas dependiendo de la estructura del resultado y genera una representación acotada.
Además, determinados resultados —como errores, outputs estructurados o resultados de herramientas como read_file, grep o glob— permanecen deliberadamente en esta ruta.
La idea es evitar que una “compactación inteligente” termine eliminando precisamente el error que el agente necesita diagnosticar.
2. LLM-assisted compaction
Para outputs grandes y no estructurados se puede habilitar opcionalmente un pequeño LLM mediante un endpoint compatible con OpenAI.
Pero hay una decisión de diseño importante:
el LLM nunca recibe directamente el enorme resultado original.
Primero se realiza la compactación determinista.
Después, el pequeño LLM trabaja sobre ese resultado ya reducido para intentar obtener una representación semántica todavía más compacta.
Raw output → Deterministic reduction → Optional LLM → Bounded context
Si el LLM falla, hay timeout o devuelve una respuesta inválida, el resultado determinista actúa como fallback.
Por tanto, utilizar otro modelo es completamente opcional.
Hay otro problema: repetir información
Durante mis pruebas apareció otro patrón interesante.
Un agente puede consultar varias veces una herramienta y recibir exactamente el mismo resultado.
Desde el punto de vista del context window tenemos algo parecido a esto:
- Tool result A
- Tool result B
- Tool result A
- Tool result A
- Tool result C
Aunque ya hayamos visto A, cada nueva aparición puede volver a consumir contexto.
Por eso el plugin incorpora también deduplicación proactiva de tool outputs.
Mantiene una ventana de resultados dentro de la sesión y, cuando detecta que un resultado suficientemente grande ya apareció anteriormente, puede sustituirlo por una pequeña referencia factual.
Conceptualmente:
read_file → 23.330 chars
↓ el mismo resultado ya existe en contexto
↓ dedup
↓ pequeña referencia factual
En lugar de volver a introducir otros 23.330 caracteres.
La diferencia con una compresión posterior del contexto es importante.
La deduplicación ocurre antes de que ese contenido vuelva a entrar en el contexto.
No estamos limpiando el contexto después de llenarlo. Estamos intentando evitar llenarlo innecesariamente.
Y existe otra decisión de diseño detrás de esto:
el plugin informa, pero no dirige el comportamiento del agente.
Puede indicar que ese resultado exacto ya apareció anteriormente durante la sesión, pero la decisión sobre qué hacer después continúa perteneciendo al agente.
Características actuales
Actualmente tool-output-compactor incluye:
- compactación determinista sin dependencias externas;
- compactación opcional asistida por LLM;
- deduplicación proactiva de resultados repetidos;
- detección específica de errores, warnings, tracebacks y stderr;
- preservación de comandos, paths, queries, estados y exit codes;
- tratamiento específico para JSON y resultados estructurados;
- preservación de head/tail en outputs largos;
- normalización de resultados de procesos ejecutados en background;
- fallback automático a compactación determinista si falla el LLM;
- límites configurables de tamaño;
- audit/debug mode para entender cada decisión;
- métricas de reducción;
- benchmark para medir la efectividad sobre datos sintéticos o sesiones reales de Hermes.
Y algo que considero importante:
el plugin informa de lo que está haciendo.
Podemos medir cuánto contexto estamos evitando introducir y, al mismo tiempo, comprobar si la información crítica continúa disponible para el agente.
¿Qué ocurre en una sesión real?
Quería evitar evaluar el plugin únicamente con ejemplos preparados, así que empecé a observar su comportamiento durante sesiones reales de Hermes.
Uno de los primeros casos fue un agente trabajando con código y logs.
Durante la sesión, el plugin intervino sobre tres resultados:
read_file· código Python — Original: 23.330 chars → Compactado: 5.337 chars (deterministic, -77,1 %)read_file· mismo archivo repetido — Original: 23.330 chars → dedup, sustituido por referencia factual mínima (~100 %)read_file· agent.log — Original: 96.088 chars → Compactado: 11.971 chars (deterministic, -87,5 %)
En conjunto: ~119.418 caracteres → ~17.308 caracteres
Es aproximadamente un 85,5 % menos de contenido introducido en el contexto.
Pero el porcentaje por sí solo no era lo que más me interesaba.
Código: 23k → 5k caracteres
El primer resultado era un archivo Python largo. El plugin detectó líneas consideradas críticas y utilizó compactación determinista:
23.330 → 5.337 caracteres (-77,1 %)
manteniendo estructura y fragmentos relevantes para que el agente pudiera seguir razonando sobre el código.
Logs: 96k → 12k caracteres
El tercer caso era todavía más representativo: un agent.log de más de 96.000 caracteres.
En lugar de introducirlo completo en el contexto: 96.088 → 11.971 caracteres (-87,5 %)
preservando warnings, errores, shutdowns y otras líneas consideradas relevantes.
Aquí es donde este tipo de estrategia empieza a resultar especialmente interesante para agentes pequeños.
El modelo no necesita necesariamente 96 KB de logs.
Necesita la parte de esos 96 KB que le permita entender qué está ocurriendo y decidir qué hacer después.
Las pruebas también hicieron evolucionar el dedup
La misma sesión reveló un caso borde interesante. El agente volvió a leer exactamente el mismo archivo Python.
El plugin detectó que esos 23.330 caracteres eran exactamente el mismo resultado que ya había aparecido anteriormente y activó la deduplicación.
En las primeras pruebas, esta deduplicación era demasiado agresiva: eliminaba el contenido repetido, pero dejaba muy poca información al modelo sobre lo que acababa de ocurrir.
Eso podía generar un efecto contraproducente.
Un modelo pequeño, al no tener suficiente evidencia de que la operación se había realizado correctamente, podía decidir ejecutar nuevamente la herramienta.
Las propias pruebas sirvieron para corregir ese comportamiento.
Ahora la deduplicación no intenta simplemente hacer desaparecer el resultado.
En su lugar, sustituye el contenido repetido por un registro factual y acotado que permite al agente saber qué ocurrió sin volver a introducir todo el contenido.
Este caso resume bastante bien cómo estoy desarrollando el plugin:
medir → observar → encontrar casos borde → ajustar → volver a medir.
Porque un 100 % de reducción no significa necesariamente una buena compactación.
El objetivo no es eliminar tantos caracteres como sea posible.
Es: evitar contexto redundante preservando suficiente información para que el agente pueda seguir tomando buenas decisiones.
¿Y qué pasa con la compactación asistida por LLM?
Esta es precisamente la parte que todavía estoy evaluando.
El modo LLM-assisted ya está implementado, pero quiero hacer más pruebas antes de sacar conclusiones sobre su efectividad real.
La hipótesis es interesante.
La compactación determinista funciona especialmente bien cuando existen señales claras que preservar: errores, warnings, paths, estructura, estados, fragmentos de código, JSON…
Pero hay outputs mucho más difíciles de reducir mediante reglas: documentación extensa, resultados de investigación, respuestas textuales de APIs o contenido no estructurado.
Ahí un pequeño LLM podría aportar una segunda capa de compresión semántica.
El pipeline sería:
Raw output → Deterministic reduction → Small LLM → Semantic compact representation → Agent context
Pero no quiero medir únicamente cuánto consigue reducir. Quiero comprobar algo más importante: ¿la información que preserva sigue siendo suficiente para que el agente complete correctamente su tarea?
Y también hay un coste que considerar.
Introducir otro LLM significa añadir inferencia, latencia y consumo de recursos.
En un entorno local, precisamente donde los recursos son limitados, esa decisión tiene que justificar su coste.
Por eso las siguientes pruebas estarán orientadas a comparar:
- reducción obtenida;
- información crítica preservada;
- calidad de las decisiones posteriores del agente;
- latencia añadida;
- coste de inferencia;
- diferencia real frente a utilizar únicamente compactación determinista.
Puede que LLM-assisted aporte mucho valor para determinados tipos de outputs.
Puede que deterministic sea suficiente en muchos más casos de los que inicialmente esperaba.
Eso es precisamente lo que quiero medir.
Por ahora, los resultados que comparto corresponden principalmente a deterministic compaction y deduplication en sesiones reales de Hermes.
Context management como recurso
Después de trabajar en esto, mi forma de pensar sobre los context windows ha cambiado ligeramente.
Para agentes locales pequeños, el contexto no es simplemente una capacidad del modelo.
Es un recurso limitado que debemos administrar.
Podemos utilizar modelos con ventanas mayores.
Podemos comprimir conversaciones antiguas.
Podemos utilizar memoria externa.
Pero también podemos controlar algo mucho más cercano al origen: qué información permitimos entrar en el contexto en primer lugar.
Y creo que ahí está la idea fundamental detrás de este experimento:
tool-output-compactor intenta explorar precisamente esa parte del problema.
El proyecto es open source y todavía está evolucionando.
Quiero compartir no solo los buenos resultados, sino también los casos borde que aparezcan durante las pruebas y las decisiones de diseño que surjan de ellos.
Me interesa especialmente probarlo con más herramientas, modelos pequeños y workloads agentic reales.
Para estos casos los modelos que he estado utilizando son:
- Ornith-1.5-35B-A3B-MLX-4bit (Modelo razonador)
- Qwen3.6-35B-A3B-Heretic-MLX-4bit (Modelo razonador)
- Qwen3.5-9B-MLX-4bit (Modelo auxiliar de compactación y resumen)
- Qwen2.5-3B-Instruct-4bit (Modelo auxiliar de compactación y resumen)
Si utilizas Hermes Agent, experimentas con local LLMs o estás trabajando en context management para agentes, cualquier feedback, issue, prueba o contribución será bienvenida.
Conversación
Comparte una idea, pregunta o mejora sobre esta publicación.