Claude Platform Docs
MessagesCompactación

Compactación en segundo plano

Solicita un resumen de compactación bajo demanda mientras la conversación continúa con su historial completo y luego intercambia el bloque cuando llegue.

La "background compaction" (compactación en segundo plano), a menudo llamada "async compaction" (compactación asíncrona), cambia dos cosas en el bucle de compactación: la solicitud de compactación se ejecuta mientras la conversación continúa con su historial completo, y el "swap" (intercambio) espera hasta que llega el bloque. Continuar a partir del resumen y Manejar un resumen faltante o un error se aplican sin cambios.

Cómo funciona el intercambio mientras el trabajo continúa

La solicitud de compactación y el bloque que devuelve son los mismos que en el bucle. Tu historial crece entre el envío de la solicitud y el uso de su resultado, y el intercambio debe dejar ese crecimiento en su lugar.

  1. Envía la solicitud de compactación con tu historial tal como está y registra cuántos mensajes contenía.
  2. Mientras esa solicitud se ejecuta, mantén la conversación en marcha con el historial completo. Agrega cada turno nuevo, no edites nada que ya esté en el historial y no inicies otra solicitud de compactación hasta que esta se haya intercambiado o haya fallado.
  3. Cuando llegue la respuesta con stop_reason "compaction", elimina exactamente los mensajes que enviaste del inicio de tu historial y coloca el mensaje devuelto en su lugar. Cada turno agregado desde el paso 1 permanece después de él.
  4. Envía el historial intercambiado en la primera solicitud después de que llegue el bloque, para que el pensamiento producido mientras se escribía el resumen siga siendo válido.

Por ejemplo, si la solicitud de compactación contenía los mensajes 1 a 5 y la conversación ganó los mensajes 6 a 8 mientras se ejecutaba, después del intercambio tu historial es el bloque seguido de los mensajes 6 a 8.

Request sentmessages 1–512345While it runs6–8 arrive12345678compaction request: 1–5After the swapblock, then 6–8compaction block678

Si la respuesta tiene cualquier otro stop_reason, no se produjo ningún resumen, lo cual cuenta como un fallo en el paso 2. Conserva el historial completo; Manejar un resumen faltante o un error enumera las causas y qué hacer en cada caso.

Solicita el resumen en segundo plano

La solicitud de compactación cuenta para tus "rate limits" (límites de velocidad) como cualquier otra solicitud, y mientras se ejecuta tu aplicación tiene dos solicitudes abiertas a la vez. La conversación sigue creciendo con su historial completo hasta el intercambio, así que inicia la solicitud de compactación mientras la "context window" (ventana de contexto) todavía tenga espacio para los turnos que lleguen mientras tanto.

El siguiente programa es el bucle de Compactar en un bucle con la solicitud de compactación sacada del camino de la conversación. No tiene versión en PHP, porque el ejemplo depende de ejecutar dos solicitudes a la vez. Las líneas resaltadas muestran dónde difiere del bucle, y la lista siguiente las recorre en el orden en que el programa las ejecuta.

from concurrent.futures import Future, ThreadPoolExecutor

import anthropic
from anthropic.types.beta import BetaMessage, BetaMessageParam

client = anthropic.Anthropic()
executor = ThreadPoolExecutor(max_workers=1)

# Ajusta esto cerca de tu presupuesto real de entrada. Aquí es bajo para que una conversación corta se compacte.
COMPACT_AT_TOKENS = 2500
SYSTEM = "You help design a recipe app's data model. Keep answers short."

QUESTIONS = [
    "What are the main entities in the data model?",
    "Which fields should Recipe have?",
    "Which fields should Ingredient have?",
    "Which fields should RecipeIngredient have?",
    "Which fields should Step have?",
    "Which indexes should these tables have?",
    "Which fields should be required?",
    "Which fields should have default values?",
]


def swap_in(history: list[BetaMessageParam], summary: BetaMessage, sent: int) -> None:
    if summary.stop_reason == "compaction":
        # Reemplaza exactamente los mensajes que contenía la solicitud de compactación.
        # Los turnos posteriores quedan después del bloque.
        history[:sent] = [{"role": "assistant", "content": summary.content}]
        print(f"Swapped {sent} messages")


history: list[BetaMessageParam] = []
pending: Future[BetaMessage] | None = None
sent = 0
for turn, question in enumerate(QUESTIONS, start=1):
    if pending is not None and pending.done():
        swap_in(history, pending.result(), sent)
        pending = None

    history.append({"role": "user", "content": question})
    response = client.beta.messages.create(
        model="claude-opus-5-5",
        max_tokens=8192,
        system=SYSTEM,
        betas=["compact-2026-09-04"],
        messages=history,
    )
    history.append({"role": "assistant", "content": response.content})

    # La siguiente solicitud también envía esta respuesta, así que cuéntala.
    conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
    if (
        conversation_tokens > COMPACT_AT_TOKENS
        and turn < len(QUESTIONS)
        and pending is None
    ):
        sent = len(history)
        pending = executor.submit(
            client.beta.messages.create,
            model="claude-opus-5-5",
            max_tokens=4096,
            system=SYSTEM,
            betas=["compact-2026-09-04"],
            messages=history.copy(),
            compaction={"type": "summarize"},
        )

# Sustituye un resumen que aún está en camino antes de guardar
# o de continuar la conversación.
if pending is not None:
    swap_in(history, pending.result(), sent)
executor.shutdown()
  • Decidir cuándo compactar: La verificación de tamaño también requiere que no haya ninguna solicitud de compactación pendiente.
  • Iniciar la solicitud: Donde el bucle espera la respuesta de compactación, esta versión registra cuántos mensajes contiene el historial, inicia la solicitud sobre una copia del historial con la herramienta de concurrencia propia de cada lenguaje y pasa al siguiente turno sin esperar.
  • Comprobar el resultado: Al inicio de cada turno, el programa comprueba si la solicitud pendiente ha terminado. Si es así, el programa realiza el intercambio antes de enviar la solicitud de ese turno.
  • Realizar el intercambio: Donde el bucle reemplaza todo el historial con el mensaje devuelto, la función de intercambio de esta versión reemplaza solo los mensajes que contenía la solicitud, contados desde el inicio, y conserva todo lo agregado desde entonces.
  • Terminar el bucle: Si la solicitud de compactación sigue pendiente cuando termina el bucle, el programa la espera y realiza el intercambio, para que un resumen que todavía está en camino no se pierda antes de que guardes o continúes la conversación.

La verificación de stop_reason no cambia respecto al bucle: una respuesta sin bloque deja el historial como estaba. Como ya no hay nada pendiente, el programa puede entonces iniciar una nueva solicitud de compactación.

Mantén válido el pensamiento mientras se construye el resumen

Los turnos que llegan mientras se escribe el resumen son turnos conservados. Si devuelves bloques de pensamiento en un modelo con pensamiento preservado, el pensamiento de esos turnos sigue siendo válido solo mientras se cumplan las condiciones para el pensamiento conservado.

Compatibility

Supported models
  • Fable 5 and 5.1
  • Mythos 5, 5.1, and Preview
  • Opus 4.6, 4.7, 4.8, 5, and 5.5
  • Sonnet 4.6 and 5
Supported platforms
  • Claude APIBeta
  • Claude Platform on AWSBeta
  • Google CloudBeta
  • Microsoft FoundryBeta

Was this page helpful?