Un sistema de reclamaciones funciona bien durante semanas. De pronto las denegaciones se disparan, y solo en una línea de producto. No se desplegó nada. Ningún humano editó un prompt. Ninguna config cambió en ningún archivo que alguien pueda encontrar. El equipo que lo construyó está mirando una regresión que no tiene un commit detrás, y esa es una sensación genuinamente nueva y desagradable en software.
Lo que pasó es que uno de los agentes aprendió. Se dio cuenta de que las autorizaciones exitosas solían incluir ciertos códigos clínicos, empezó a recuperar con ese patrón y mejoró, para los casos de los que aprendió. Después aplicó el mismo patrón a otro tipo de caso donde no se sostiene, los códigos que ahora busca no devuelven coincidencias, y el agente siguiente lee «sin coincidencias» como «denegar». Un agente mejoró localmente y rompió una suposición de coordinación de la que dependía el resto del sistema. Esto es la divergencia evolutiva, y es el modo de fallo que aparece en cuanto tus agentes dejan de ser programas fijos y empiezan a adaptarse.
Por qué esto es otra clase de problema
El software clásico es estático entre despliegues. El sistema que depuras tras un incidente es el sistema que entregaste, y una regresión tiene un commit detrás. Los agentes que se autoadaptan rompen las dos suposiciones. El sistema evoluciona mientras se ejecuta. Cada instancia acumula su propio comportamiento aprendido y se vuelve un poco única, así que el sistema de ayer genuinamente no es el de hoy, y no hay diff que leer porque el cambio nunca llegó a escribirse.
El peligro está justo en las costuras. Un agente que se adapta en aislamiento puede ser localmente correcto y globalmente incorrecto, porque el resto de la malla sigue operando sobre el contrato que ese agente acaba de renegociar en silencio consigo mismo. El analizador de comportamiento mueve un umbral; el scorer de riesgo al que alimenta se escribió contra el umbral viejo y nadie le avisó. Un agente evolucionó, su vecino se quedó quieto y la coordinación entre ambos —que nadie tocó— quedó rota.
La salida son los traces con marca de versión
Si la adaptación es el objetivo, no puedes impedir que los agentes se adapten. Lo que sí puedes hacer es volver cada adaptación visible y atribuible, y eso es un problema de tracing antes que cualquier otra cosa.
Cada span que emita un agente debería llevar la versión del prompt, la config de tool y la política aprendida que estaban vivas cuando corrió. Añadirlo es barato y cambia la depuración por completo. Cuando llega el pico de denegaciones, un span con marca de versión responde lo que un log plano no puede: ¿cuál es la estrategia de recuperación actual?, ¿cuándo cambió por última vez?, ¿qué feedback disparó el cambio?, ¿ese cambio alteró la forma en que este agente coordina con los demás? La regresión sin commit consigue su commit; solo que vive en el trace y no en git.
Por eso mismo tratamos las modificaciones autónomas como eventos de trace de primera clase, no como estado silencioso. Cuando un agente reescribe su propio prompt o mueve un umbral, eso es algo que pasó, con una causa y un timestamp, y le corresponde estar en el trace a máxima fidelidad. Muestrea los éxitos rutinarios si hace falta; jamás descartes por muestreo una automodificación. Es el evento más importante que produce el sistema.
El eval se muda al trace
Atrapar la divergencia después del pico de denegaciones es mejor que no atraparla. Pero el objetivo real es atraparla antes de que la sientan los usuarios, y ahí es donde el eval deja de ser un artefacto de CI y se muda al propio trace de producción.
El patrón consiste en ejecutar de forma continua puntuación con LLM como juez contra traces en vivo, vigilando el drift de validación: la degradación lenta de un límite de seguridad o de un listón de calidad a medida que un agente se optimiza. El juez no pregunta «¿esto reventó?»; pregunta «¿esto sigue siendo bueno, sigue teniendo grounding, sigue dentro del límite que debía respetar?». Cuando un agente baja su umbral de escalación porque los casos escalados resultaron puntuar mejor —optimizando hacia una correlación en lugar de hacia la causa—, el juez sobre el trace atrapa el drift mientras es una métrica en movimiento y no después, cuando ya es un incidente. Es el mismo instinto que el verificador en el runtime, apuntado a un objetivo más lento: la corrupción gradual que el sistema se inflige a sí mismo.
Qué implica esto a la hora de construir
Si entregas agentes que se adaptan, tres cosas dejan de ser opcionales. Marca cada span con las versiones que lo produjeron. Trata cada automodificación como un evento de trace de alta fidelidad, nunca descartado por muestreo. Y ejecuta el eval sobre el trace en vivo, no solo en CI, para que el drift asome como una tendencia sobre la que puedes actuar en lugar de como un pico por el que pides disculpas. Nada de esto impide que los agentes aprendan. Todo esto impide que aprendan a meterse en una caída que después nadie sabe explicar.
La promesa de los agentes adaptativos es que mejoran solos. La factura que viene con ella es que también pueden empeorar solos, en los huecos de coordinación entre ellos, sin ningún commit al que culpar.
La divergencia evolutiva es la cara de esa factura: un agente aprende, se rompe una suposición de coordinación y aparece una regresión en un sistema que nadie cambió. Los traces con marca de versión, y los evals que corren sobre esos traces, son la forma de quedarte con la promesa sin pagar la factura: dejar que los agentes evolucionen y saber, en cualquier momento, qué cambió exactamente y si rompió al agente de al lado.