← Volver a casos técnicos

Caso Técnico 05

Qué pasó cuando empecé a tratar los reportes de Power BI como código

Cómo PBIP, Git y un pequeño toolkit de validación me dejaron usar agentes de IA para modificar reportes rápido, sin perder el diff, la validación ni la vuelta atrás.

2026 · 8 min de lectura
  • Power BI
  • PBIP
  • Agentes de IA
  • Git
  • CI/CD
  • Python

Resumen

Empecé a desarrollar reportes de Power BI con agentes de IA trabajando directamente sobre los archivos del proyecto. Me hizo muchísimo más rápido. También me obligó a responder una pregunta que antes no tenía:

¿Cuánta autonomía le puedo dar a un agente antes de necesitar controles de ingeniería más fuertes?

Este caso cuenta cómo fue cambiando mi forma de trabajar: qué ganó el desarrollo al pasar por el agente, qué tipo de riesgo nuevo apareció y qué controles tuve que ir agregando a medida que el agente hacía cambios más grandes.

El cambio: de una interfaz a un proyecto

Durante años, un reporte de Power BI fue un archivo .pbix: un binario que se edita con clics en Power BI Desktop. Con el formato de proyecto (PBIP), el modelo pasa a ser TMDL y el reporte pasa a ser PBIR: carpetas de archivos de texto que se pueden leer, comparar y versionar.

Eso cambió algo más profundo que el formato. Un agente de IA que trabaja con archivos ahora puede agregar un visual, cambiar un filtro, reorganizar una página o refactorizar medidas. La unidad de trabajo dejó de ser una interfaz y pasó a ser un proyecto.

Antes
  1. Idea
  2. Power BI Desktop
  3. Edición manual
  4. Archivo .pbix
  5. Publicar
El reporte es un archivo que se edita con clics.
Ahora
  1. Idea
  2. Agente de IA
  3. Archivos PBIP (texto)
  4. Diff en Git
  5. Validación
  6. Revisión
  7. Publicar
El reporte es un proyecto de archivos versionables que un agente modifica como código.

Hay herramientas que le dan al agente formas de interactuar con Power BI, y son útiles. Para mi forma de trabajar, lo que más pesó fue otra cosa: tener un artefacto versionable que el agente modifica como si fuera código. Las dos ideas se complementan.

El problema: más rápido para todo, también para romper

Si un agente puede cambiar un reporte entero en segundos, también puede romperlo en segundos. Y los errores más peligrosos no son los que impiden abrir el proyecto: son los que dejan un número que se ve bien y está mal.

Un ejemplo concreto. El agente cambia el filtro de una tarjeta para que incluya dos etapas del embudo:

  "filter": { "In": {
    "Expressions": [ Stages[Order] ],
-   "Values": [ [ 3 ] ]
+   "Values": [ [ 2 ], [ 3 ] ]
  } }

Y la medida que muestra esa tarjeta, en otra carpeta del proyecto, resuelve la fila con MAX:

Deals at stage =
    VAR _order = MAX ( Stages[Order] )
    RETURN
        CALCULATE ( COUNTROWS ( Deals ), Stages[Order] = _order )
Sales.Report / visual.json
PBIR · el visual
Stages[Order] IN (2, 3)
válido por sí solo
Sales.SemanticModel / Deals.tmdl
TMDL · la medida
MAX ( Stages[Order] )
válido por sí solo
  1. El filtro del visual admite las etapas 2 y 3
  2. La medida usa MAX(Stages[Order])
  3. Termina resolviendo solo la etapa 3
  4. El valor mostrado puede no representar el contexto que el visual aparenta tener
Cada archivo es válido por separado. El defecto aparece al combinarlos: es un problema de coherencia entre archivos.

Las dos piezas, por separado, son válidas. Juntas, el filtro admite las etapas 2 y 3, pero la medida usa MAX y termina resolviendo solo la 3: el valor mostrado puede no representar el contexto que el visual aparenta tener. Nada está mal formado, así que ningún validador estructural tiene por qué marcarlo.

No es un caso de laboratorio. En un reporte real, un visual llegó a mostrar una tasa de conversión imposible, por encima del 100%. La medida era válida; el problema era el contexto de filtro que le pasaba el visual. El ejemplo de arriba es su equivalente sintético, y cualquiera puede reproducirlo desde el repo.

El filtro vive en el reporte y la medida en el modelo. Nadie estaba evaluando la relación entre las dos.

Válido no es lo mismo que correcto

Lo que me ordenó la cabeza fue separar tres preguntas distintas, que necesitan tres tipos de control distintos. Para la primera ya había herramientas. Para la segunda no encontré ninguna, y de ahí terminó saliendo pbip-guardrails.

  1. Nivel 1 · Válido
    ¿Power BI lo puede leer?
    Validadores de Microsoft (TMDL y PBIR)
    El parser oficial de TMDL y el CLI de PBIR. Detectan un modelo que ni siquiera abriría en Desktop, con archivo y línea.
  2. Nivel 2 · Coherente
    ¿Las piezas del reporte son coherentes entre sí?
    pbip-guardrails
    Lee el DAX de cada medida junto con los filtros del visual que la usa: medidas inexistentes, filtros incompatibles, poblaciones mezcladas, visuales tapados.
  3. Nivel 3 · Correcto
    ¿El número representa lo que el negocio cree?
    Personas + conciliación con los datos de origen
    Ninguna herramienta lo responde. Requiere criterio de negocio y comparar contra la fuente.
No compiten: cada nivel responde una pregunta que el anterior no puede responder.

Los controles alrededor del agente

Con eso en claro, el flujo quedó así. No es un pipeline automático de punta a punta: algunos pasos los hace una herramienta y otros los decide una persona, y el diagrama los distingue.

  1. Pedido en lenguaje natural
  2. Agente de IA
  3. Edita los archivos PBIP
  4. Revisar el diff en Git
  5. pbip lint
  6. Nivel 1 · Válido
    TMDL + PBIR
    validadores de Microsoft
    ✓ pasa
  7. Nivel 2 · Coherente
    visual ↔ medida
    pbip-guardrails
    ✓ pasa
    Camino de falla · ejemplo
    Inspeccionar el diff · corregir · revertir
    ↺ vuelve al agente
  8. safe-copy → reporte ZZ-
  9. Publicar la copia en Power BI Service
  10. Refresh y revisión visual
  11. Publicar el reporte real
No es prompt → producción.
  1. Prompt
  2. Artefacto
  3. Evidencia
  4. Liberación controlada por una persona
lo hace una herramienta lo decide una persona
  1. Un estado conocido en Git. No arranqué con este proceso: fue apareciendo a medida que el agente hacía cambios más grandes. Hoy, antes de dejarlo hacer cambios importantes, quiero el proyecto en un estado conocido de Git. Eso me da un diff legible y una vuelta atrás barata.
  2. pbip lint. Corre los validadores de Microsoft y los chequeos de coherencia. Si algo falla, el cambio vuelve al agente con el hallazgo, o se revierte.
  3. safe-copy. El reporte se publica primero como una copia con otro nombre (ZZ-…). Como la publicación busca los items por nombre, la copia se crea como un item nuevo y no pisa el real.
  4. Mirarlo. No existe un renderizador de Power BI para Linux: la única prueba de que un visual se ve bien es abrirlo. Recién después se publica el real.

Qué detecta cada herramienta

Armé un reporte sintético con defectos plantados a propósito y lo pasé por todas las capas. El objetivo no es mostrar que una herramienta "gana": herramientas distintas responden preguntas distintas.

Defecto Validadores estructurales Chequeos de coherencia
Una medida que ya no existe — ✓
Filtro de varios valores + medida con MAX — ✓
Un visual que cruza métricas de dos poblaciones — ✓
Un visual duplicado tapado por otro — ✓
Un visual fuera del canvas ✓ (aviso) ✓
TMDL que no se puede parsear ✓ (cualquier error) un solo patrón conocido

Las dos últimas filas son las que muestran que se complementan. El validador de PBIR marca el visual fuera del canvas; el parser de TMDL detecta cualquier error de sintaxis, mientras que mi chequeo solo reconoce un patrón puntual que ya me había roto un proyecto entero. Así se ve el hallazgo del ejemplo de arriba:

$ pbip lint examples/broken --family 'Segment (\d+)'
  'Pipeline' [filters] cardVisual b0000000000000000001: Order IN ['2L', '3L']
      -> ['Deals at stage'] depend(s) on the row's Order: the value shown may not match the filter

No confié en la IA

Buena parte del código de pbip-guardrails lo escribió un agente, rápido. Eso deja una pregunta que cualquier ingeniero haría: ¿cómo sé que no inventó una solución que solo parece funcionar? Por eso nada se aceptó por su cuenta: cada paso se contrastó con algo independiente.

  1. Código generado por IA
  2. Caso con respuestas conocidas
  3. Tests
  4. Herramientas oficiales
  5. Paridad con la versión anterior
  6. Validación real en solo lectura
  1. Un caso con respuestas conocidas. Un script genera un reporte sano y uno roto, con un defecto plantado por cada tipo de chequeo.
  2. Tests automáticos. El sano tiene que dar cero hallazgos; el roto, exactamente los que se plantaron.
  3. Las herramientas oficiales como referencia. El parser y el CLI de Microsoft corren sobre el mismo caso: el sano pasa, el TMDL roto falla donde tiene que fallar.
  4. Paridad con la versión anterior. Los chequeos nacieron como un script interno. La versión generalizada tuvo que dar exactamente los mismos hallazgos sobre varios proyectos PBIP reales, en modo solo lectura.
  5. Correcciones que salieron de mirar, no de suponer. El primer reporte "sano" que generó el agente tenía un error real de TMDL, y el propio linter lo marcó. Lo dejé como lección: el fixture también se valida.

Límites

  • Pasar el linter no garantiza que el reporte se vea bien. Una consulta puede fallar bajo cierto filtro o faltar un permiso. Por eso existe la copia ZZ-.
  • El nivel 3 sigue siendo humano. Ninguna herramienta sabe qué quiere decir "cliente activo" en tu negocio.
  • Los chequeos son heurísticos y están calibrados para no hacer ruido. Cada regla descuenta los casos legítimos conocidos; si aparecen cientos de hallazgos, el problema es el umbral, no el reporte.

Qué aprendí

El formato habilita todo

Diff, rollback, CI, linting y revisión existen porque PBIP convirtió un artefacto de interfaz en uno que un agente puede editar.

Velocidad pide controles

Si dejo que una IA toque mis reportes, necesito los mismos controles que ya damos por sentado cuando una IA toca código.

Nombrar el nivel

"¿Es válido?", "¿es coherente?" y "¿es correcto?" son preguntas distintas. Mezclarlas es lo que hace que un error pase.

El código

pbip-guardrails es open source (MIT): trae los chequeos de coherencia, la integración con los validadores de Microsoft, la copia segura para publicar, un ejemplo sintético para probarlo y un ejemplo de CI.

Ver pbip-guardrails en GitHub →

Tocá fuera de la imagen para cerrar