Equipo Easybits
4 min de lectura
agentes
Un cliente reportó que su agente dejó de servir en un grupo de WhatsApp. En los otros cuatro respondía normal. Mismo agente, mismo número, misma configuración.

El síntoma: cada mensaje devolvía "me quedé a medias" a los nueve segundos, sin haber llamado una sola herramienta.
Cuando pasa esto, todo el mundo empieza por el mismo lado —el prompt, el modelo, los conectores, "límpiale el contexto"— y ese lado casi nunca es. Vale la pena descartarlo en dos minutos, con una prueba en vez de una corazonada.
Nuestra API deja mandar un turno con un groupId inventado pero apuntando a la configuración de un grupo real:
Respondió perfecto, con todas sus herramientas cargadas. La configuración no era el problema. Ese configGroupId importa: sin él, el turno arranca sin los conectores del grupo y el resultado se parece mucho a un agente roto — un falso positivo que cuesta una hora.
El mismo turno con el groupId real reprodujo el corte: 9 segundos, cero herramientas.
Config sana + conversación enferma. El problema viaja en la memoria del hilo, no en la configuración ni en la máquina. Eso ya explica por qué apagar y prender los interruptores del grupo no hacía nada: ninguno de ellos toca el historial.
Cada conversación es un archivo .jsonl en la caja del agente. Un grep bastó:
Repetido en cada turno desde las 23:03 del día anterior. Diez minutos antes, el agente había capturado una página web completa en formato móvil: 1170 × 17019 píxeles. La visión de la API no acepta más de 8000 por lado.
Lo importante no es que fallara la captura. Es que la imagen quedó escrita en el historial. Y como cada turno reanuda la conversación, esa imagen se reenviaba siempre. La captura falló una vez; la conversación quedó muerta para siempre.
Es un modo de fallo desagradable porque no se parece a nada roto: la infraestructura está sana, el agente vivo, los otros hilos funcionando. Reciclar la máquina tampoco cura — el veneno viaja con el hilo, no con la caja.
Podamos la imagen del historial dejando una nota de texto en su lugar. El agente volvió, con toda su memoria: precios, tablero de costos, la guía de estilo de los flyers.
Uno evita que el veneno entre; el otro cura la conversación si entra de todos modos. Hacen falta los dos.
Que no entre: la captura se recorta antes de guardarse.
Antes, la herramienta devolvía la página completa aunque midiera 17019 píxeles. Ahora mide el resultado y, si pasa de 8000, guarda sólo los primeros 8000 y avisa: "la página mide 17019px, tienes aquí los primeros 8000; para ver el resto captura por partes".
Recorta en vez de encoger. Encoger la página entera a 0.47× la deja completa pero ilegible, y una captura donde no se lee el texto no sirve para lo único que existe: revisar cómo quedó el diseño. Media página legible vale más que una página entera borrosa.
Que se cure: el worker limpia el historial y reintenta.
Aquí hubo una sorpresa. Ese error 400 no llegaba como excepción —que sí se reintenta— sino disfrazado de turno terminado con éxito, con una banderita is_error que nadie miraba. Por eso el reintento que ya existía nunca se disparaba.
Ahora el worker reconoce ese fin de turno, abre el historial de la conversación, sustituye las imágenes por una nota de texto ("imagen retirada: la API la rechazaba") y vuelve a intentar el mismo mensaje. El usuario ve una respuesta normal, un poco más lenta; el agente perdió una imagen que de todas formas nunca pudo mirar.
Y si al abrir el historial no hay ninguna imagen que quitar, no reintenta: el problema era otro y repetirlo sólo gastaría dinero.
Al historial de un agente no entra un blob de imagen sin límite. Nunca. Todo lo que viene de fuera —lo que sube el usuario y lo que produce una herramienta— se mide y se recorta antes de tocar la memoria de la conversación, o se guarda como archivo y se pasa por referencia.
Un error transitorio que se escribe en la memoria deja de ser transitorio.