27 de septiembre de 2026 · 4 min de lectura

Extended thinking: por qué el historial de un agente no tolera ediciones retroactivas

agentes claude-code harness producción
Nicolás Neira
Nicolás Neira
Arquitectura de agentes e IA aplicada

Un harness de agentes suele tratar el historial de una conversación como una lista de mensajes a la que solo se agrega texto. Con extended thinking eso deja de ser cierto. El historial pasa a incluir bloques opacos (razonamiento, redacted_thinking, resultados de búsqueda cifrados) que el modelo generó y que el cliente no puede reconstruir. Y varias acciones que parecen inofensivas (cambiar de modelo a mitad de turno, editar un prompt anterior, reanudar una sesión tras un corte, compactar el contexto) en realidad reescriben la forma de ese historial. Cuando eso pasa, la API no se adapta con gracia: o descarta el razonamiento en silencio, o rechaza la request entera.

Los changelogs de Claude Code de esta semana muestran ese patrón de punta a punta, con suficientes casos como para sacar una regla general.

El historial se rompe de dos formas distintas

La primera es silenciosa. En Claude Code v2.1.282 se corrigió que el extended thinking se perdiera cuando se usaba /model, /rename, /artifacts u otro comando inmediato mientras Claude seguía trabajando, y que una conversación reanudada o continuada perdiera el razonamiento anterior al relanzarse con una lista de --tools que omite una herramienta nativa ofrecida antes. En ningún caso hay un error visible: el agente simplemente sigue, pero sin la cadena de razonamiento previa, respondiendo peor sin que nada lo indique.

La segunda es dura y se repite. La misma versión corrigió sesiones que fallaban en cada turno con un error de API “Invalid data in redacted_thinking block”, y conversaciones que fallaban con 400 cuando el historial contenía resultados de búsqueda web que la API no podía desencriptar (por ejemplo, de un turno respondido a través de un gateway de terceros). Claude Code v2.1.281, por su parte, arregló sesiones con un resultado de un advisor que la API ya no podía leer: fallaban una request en cada turno y perdían el razonamiento anterior repetidamente, hasta que el historial se reparaba una sola vez.

Reanudar y compactar son las rutas que más mutan el historial

v2.1.281 corrigió sesiones reanudadas o continuadas (--continue, --resume) que reenviaban turnos anteriores en una forma distinta (un turno de tool calls en paralelo, el input de una tool call de MCP, o un resultado de tool-search mientras su servidor seguía reconectando), lo que podía hacer que la API descartara el razonamiento previo de Claude. También arregló que una sesión reanudada después de un reinicio durante un permission prompt pendiente enviara un historial distinto al de antes, rompiendo el prompt cache desde ese punto en adelante. Y v2.1.282 corrigió que la compactación fallara por completo cuando la request de resumen era rechazada, en vez de reintentar en un modelo de respaldo.

El mismo tipo de fragilidad aparece un nivel más abajo, en el SDK. El Agent SDK de Python v0.2.160 corrigió turnos de seguimiento que fallaban con “Stream closed” cuando un subagente en background terminaba justo antes de que llegara el resultado del turno: se cerraba stdin demasiado pronto y el modelo terminaba reportando la tool como rechazada. El SDK de TypeScript v0.3.283 corrigió que getSessionMessages() y forkSession() devolvieran una rama del historial que ya había sido descartada por un rewind, cuando la rama más nueva terminaba en una fila de metadata o de un comando local. Son bugs distintos, pero la pregunta de fondo es la misma: ¿cuál es la forma verdadera y actual del historial, y qué pasa si algo la lee o la reenvía de otra forma?

La regla que se repite en cada fix

Ningún fix de esta lista intenta hacer que la API tolere un historial con forma distinta a la esperada. Todos hacen lo mismo: detectan la forma inválida específica y reparan el historial una vez, en lugar de reenviarlo sin cambios con la esperanza de que funcione, o reintentar indefinidamente contra el mismo payload roto. Eso es lo que hace, por ejemplo, la corrección del error de redacted_thinking: Claude Code ahora descarta los bloques de thinking de la conversación y reintenta una sola vez, en vez de fallar en cada turno subsiguiente.

Reglas para tu propio harness

Si tu harness reenvía extended thinking, resultados cifrados o cualquier bloque opaco generado por el proveedor:

Fuentes: https://github.com/anthropics/claude-code/releases/tag/v2.1.281, https://github.com/anthropics/claude-code/releases/tag/v2.1.282, https://github.com/anthropics/claude-agent-sdk-python/releases/tag/v0.2.160, https://github.com/anthropics/claude-agent-sdk-typescript/releases/tag/v0.3.283

Seguir leyendo

Nicolás Neira

Esto se demuestra en video, y se sigue a diario en la comunidad

Las demos completas van al canal. El seguimiento release por release, adentro.