El gate que impide que un agente publique una cifra fiscal inventada

· 5 min read

Cuando un agente de IA escribe sobre impuestos, una sola cifra equivocada puede costarle a alguien una sanción real. No es una metáfora. En el contenido fiscal —lo que Google llama YMYL, Your-Money-Your-Life— un número mal puesto no es un error de redacción: es un dato falso con consecuencias económicas. Y los modelos de lenguaje se los inventan con una seguridad pasmosa.

Ese es el problema que me encontré al automatizar la publicación de consultas de la Dirección General de Tributos en Conversor. Tenía ~1.897 consultas vinculantes cruzadas con códigos IAE, y quería que mis agentes generaran resúmenes precisos para cada una. El plan parecía sencillo: pasarle la consulta completa a un LLM, pedirle un resumen con las cifras clave y publicarlo.

Lo que probé primero

La arquitectura inicial era directa. Un agente leía la consulta DGT desde la base de datos, se la pasaba a DeepSeek o Claude con un prompt que pedía extraer el porcentaje de sanción, el recargo aplicable, el tipo de retención y la conclusión vinculante. El modelo devolvía un borrador, otro agente lo formateaba y listo.

Funcionó durante las primeras pruebas. Las cifras parecían correctas, los textos eran legibles, y el sistema entero corría sin intervención humana. Confié en que los modelos, al tener el texto fuente delante, iban a respetar los números. Error de principiante.

Dónde se rompió

Revisando una tanda de borradores encontré algo que me heló la sangre. Una consulta sobre recargos del artículo 27 de la LGT decía una cosa en el texto fuente y otra completamente distinta en el resumen del agente. El modelo había sustituido el porcentaje real por uno que recordaba de su entrenamiento: un 20% que no aparecía por ninguna parte en la consulta original.

No fue un caso aislado. DeepSeek y Claude —los dos— recordaban cifras de sanción, recargo y retención que no estaban en el documento que estábamos procesando. Las traían de su memoria de entrenamiento, de miles de textos fiscales donde probablemente sí aparecían, pero que no tenían nada que ver con la consulta vinculante concreta que estábamos resumiendo.

El segundo problema fue aún más sutil y más peligroso. En las contestaciones de la DGT, la resolución vinculante —lo que realmente importa— está al final del documento. La cabecera describe la consulta del contribuyente y la normativa aplicable, pero la respuesta con fuerza legal vinculante viene al cierre. Si el modelo truncaba el texto de entrada —y los LLM truncan— o si pesaba más las primeras secciones que las últimas, el resumen podía invertir el significado por completo. No es que se inventara un número: es que resumía la pregunta como si fuera la respuesta.

Me llevó varias horas de verificación manual darme cuenta del patrón. No bastaba con pasar el texto completo. Había que asegurarse de que el resumen reflejara el final de la contestación, que es donde la DGT dice lo que hay que hacer.

La solución: hechos anclados y revisor adversario

La pieza central de la solución es un fichero que ahora vive en cada clúster YMYL del proyecto: content/<cluster>/VERIFIED-FACTS.md. Es un documento plano, mantenido a mano, que contiene exactamente las cifras verificadas para ese grupo de contenido. Porcentajes de sanción, tipos de retención, plazos, umbrales. Nada más. Nada de interpretación.

Cada borrador nuevo —lo genere DeepSeek, Claude o el modelo que sea— se ancla contra ese fichero de hechos. El prompt del agente redactor incluye una instrucción explícita: toda cifra que aparezca en el resumen debe estar respaldada por VERIFIED-FACTS.md. Si el modelo propone un número que no está en ese fichero, el sistema lo rechaza.

Pero tener el ancla no basta si no hay quien verifique. Por eso añadí un segundo agente: el revisor adversario. Antes de que cualquier borrador llegue a la fase de publicación, este revisor toma el texto generado, lo compara cifra por cifra contra VERIFIED-FACTS.md y emite un veredicto. Si detecta una sola discrepancia numérica —un porcentaje que no cuadra, un plazo que no aparece en el fichero de hechos, una inversión del significado— el borrador se bloquea. No hay excepción, no hay umbral de tolerancia. Un fallo es bloqueante.

El revisor también aplica la regla de la cola para las consultas DGT: comprueba que las conclusiones del resumen reflejen la sección final de la contestación, no la cabecera. Si el resumen pesa más la pregunta del contribuyente que la respuesta de la Administración, se rechaza.

Este sistema de dos capas —fichero de hechos como fuente de verdad, revisor adversario como guardarraíl— es lo que me permite dormir tranquilo sabiendo que los agentes no están publicando cifras inventadas sobre sanciones, recargos o retenciones. No es perfecto: el fichero de hechos lo mantengo yo a mano, y cada nuevo clúster YMYL requiere su propio VERIFIED-FACTS.md antes de que los agentes puedan tocarlo. Pero prefiero ese trabajo manual a una cifra equivocada publicada.

Qué aprendí

Los modelos de lenguaje no diferencian entre lo que leen ahora y lo que recuerdan de su entrenamiento. Te dan un número con la misma fluidez tanto si lo acaban de leer en el documento fuente como si lo están recuperando de un texto de hace tres años que no tiene nada que ver. En contenido YMYL, esa fluidez es veneno.

La verificación mecánica no es opcional. Un fichero de hechos ancla el sistema a la realidad; un revisor adversario impide que el sesgo del modelo se cuele en producción. Los dos juntos forman un gate que no se salta nadie.

Si estás automatizando contenido donde los números importan —y en fiscal importan todos— no confíes en la memoria del modelo. Ancla cada cifra a una fuente verificada explícita. Y pon a otro agente a vigilar al primero.

https://www.conversoriaecnae.es/consultas-dgt

Brian Mena

Brian Mena

Software engineer building profitable digital products: SaaS, directories and AI agents. All from scratch, all in production.

LinkedIn