Compact
Gestión de MemoriaThree-Layer Compression
Context will fill up; three-layer compression strategy enables infinite sessions
s01 > s02 > s03 > s04 > s05 > [ s06 ] | s07 > s08 > s09 > s10 > s11 > s12
"El contexto se llenará; necesitas una forma de hacer espacio" -- estrategia de compresión de tres capas para sesiones infinitas.
Problema
La ventana de contexto es finita. Un simple read_file en un archivo de 1000 líneas cuesta ~4000 tokens. Después de leer 30 archivos y ejecutar 20 comandos bash, llegas a 100,000+ tokens. El agente no puede trabajar en grandes bases de código sin compresión.
Solución
Tres capas, aumentando en agresividad:
Cada turno:
+------------------+
| Tool call result |
+------------------+
|
v
[Capa 1: micro_compact] (silencioso, cada turno)
Reemplazar tool_result > 3 turnos viejos
con "[Previous: used {tool_name}]"
|
v
[Check: tokens > 50000?]
| |
no sí
| |
v v
continuar [Capa 2: auto_compact]
Guardar transcript en .transcripts/
LLM resume la conversación.
Reemplazar todos los mensajes con [summary].
|
v
[Capa 3: compact tool]
El modelo llama compact explícitamente.
Mismo resumen que auto_compact.
Cómo Funciona
- Capa 1 -- micro_compact: Antes de cada llamada LLM, reemplazar resultados de herramientas antiguos con placeholders.
def micro_compact(messages: list) -> list:
tool_results = []
for i, msg in enumerate(messages):
if msg["role"] == "user" and isinstance(msg.get("content"), list):
for j, part in enumerate(msg["content"]):
if isinstance(part, dict) and part.get("type") == "tool_result":
tool_results.append((i, j, part))
if len(tool_results) <= KEEP_RECENT:
return messages
for _, _, part in tool_results[:-KEEP_RECENT]:
if len(part.get("content", "")) > 100:
part["content"] = f"[Previous: used {tool_name}]"
return messages
- Capa 2 -- auto_compact: Cuando los tokens exceden el umbral, guardar el transcript completo en disco, luego pedir al LLM que resuma.
def auto_compact(messages: list) -> list:
# Save transcript for recovery
transcript_path = TRANSCRIPT_DIR / f"transcript_{int(time.time())}.jsonl"
with open(transcript_path, "w") as f:
for msg in messages:
f.write(json.dumps(msg, default=str) + "\n")
# LLM summarizes
response = client.messages.create(
model=MODEL,
messages=[{"role": "user", "content":
"Summarize this conversation for continuity..."
+ json.dumps(messages, default=str)[:80000]}],
max_tokens=2000,
)
return [
{"role": "user", "content": f"[Compressed]\n\n{response.content[0].text}"},
{"role": "assistant", "content": "Understood. Continuing."},
]
-
Capa 3 -- manual compact: La herramienta
compactdispara el mismo resumen a demanda. -
La boucle integra las tres:
def agent_loop(messages: list):
while True:
micro_compact(messages) # Capa 1
if estimate_tokens(messages) > THRESHOLD:
messages[:] = auto_compact(messages) # Capa 2
response = client.messages.create(...)
# ... tool execution ...
if manual_compact:
messages[:] = auto_compact(messages) # Capa 3
Los transcripts preservan el historial completo en disco. Nada se pierde realmente -- solo movido fuera del contexto activo.
Qué Cambió Respecto a s05
| Componente | Antes (s05) | Después (s06) |
|---|---|---|
| Herramientas | 5 | 5 (base + compact) |
| Gestión contexto | None | Compresión de tres capas |
| Micro-compact | None | Resultados antiguos -> placeholders |
| Auto-compact | None | Disparador de umbral de tokens |
| Transcripts | None | Guardados en .transcripts/ |
Pruébalo
python agents/s06_context_compact.py
Leer cada archivo Python en el directorio agents/ uno por uno(observar micro-compact reemplazar resultados antiguos)Continuar leyendo archivos hasta que la compresión se dispare automáticamenteUsar la herramienta compact para comprimir manualmente la conversación
