dax-for-agents: DAX para que tu agente deje de inventar

csalcedodatabi DAX Power BI Herramientas
Mosaico de las 479 funciones DAX del catálogo de dax-for-agents agrupadas por categoría, una celda por función: 31 en verde oscuro tienen nota de campo propia, 99 en verde claro tienen ejemplos ejecutables y el resto va en blanco con solo la ficha de Microsoft. Cinco categorías enteras — INFO.*, financieras, fecha y hora, sin categoría y padre-hijo, 168 funciones — están completamente en blanco

En resumen — El ecosistema agéntico de Power BI está bien resuelto en herramientas y vacío en lenguaje. dax-for-agents llena ese hueco: 479 fichas de funciones derivadas de la documentación de DAX de Microsoft, 34 páginas conceptuales, 31 notas de campo escritas a mano — cada una con la consulta que la prueba y el número que devolvió — y 4 modelos de Power BI que te puedes bajar para correrlas tú. Es MIT y se instala como plugin de Claude Code.

El hueco: mucha herramienta, cero lenguaje

Si alguna vez le pediste una medida a un agente y te devolvió una función que no existe, ya conoces el problema. No es que el agente sea malo escribiendo DAX. Es que cuando le falta un dato, lo rellena.

Y hoy le falta justo ese dato. Mira lo que hay disponible:

ProyectoQué cubre
microsoft/skills-for-fabricOperaciones de Fabric. Nada de DAX como lenguaje
data-goblin/power-bi-agentic-developmentModelos semánticos, TMDL, informes — y rendimiento de DAX
MicrosoftDocs/Agent-SkillsSkills de Azure. Ninguna de Power BI ni de DAX
daxlib/daxlibUn registro de paquetes de funciones personalizadas

Todos son buenos en lo suyo. Ninguno responde la pregunta que el agente necesita antes de escribir una línea: qué hace esta función, cuándo te muerde, y qué deberías usar en su lugar.

Por qué esto duele en un agente y no en ti

Cuando tú tienes esa duda, abres dax.guide, daxpatterns.com o daxformatter.com — los tres de SQLBI —, lees dos minutos y sigues. El hueco no existe para un humano: hay recursos excelentes, mejores que cualquier cosa que yo pueda escribir para leerse con los ojos.

El agente no puede hacer eso. O tiene el dato en su contexto, o lo inventa. Y meterle la documentación entera tampoco funciona: son cientos de miles de tokens que competirían con tu modelo, tu pregunta y todo lo demás.

Así que la forma importa tanto como el contenido. La estructura es esta: un catálogo que se lee una vez, y una ficha por función que se abre sola.

El recorrido de una consulta
Pregunta:  "¿por qué mi ratio da vacío en vez de cero?"

1. el agente lee catalog.md          → una vez
2. encuentra DIVIDE                  → un archivo
3. abre esa ficha + su nota de campo → ~2 KB

Las otras 478 fichas nunca entran al contexto.

Las cinco skills que enrutan todo esto ocupan 806 tokens de descripciones siempre activas — el número que reporta Claude Code con el plugin ya instalado, no una estimación a ojo. El resto se lee solo cuando una pregunta lo pide.

Una nota de campo, entera

Aquí está la parte que hace distinto al repo, y prefiero mostrarla completa antes que describirla. Esta es la nota de DIVIDE, tal cual:

Trampa: la barra / no te protege, y el “0” que devuelves cambia el gráfico.

DIVIDE devuelve (vacío) al dividir por cero, no un error. Ese vacío es deliberado: hace que la categoría desaparezca del visual en lugar de dibujar un cero que nadie midió.

La consulta que lo prueba
EVALUATE
ROW(
"DIVIDE_1_0_es_blank", ISBLANK(DIVIDE(1,0)),
"DIVIDE_1_0_alt0",     DIVIDE(1,0,0)
)
expresiónresultado
ISBLANK(DIVIDE(1,0))TRUE
DIVIDE(1,0,0)0

El tercer argumento es una decisión de negocio, no una medida de seguridad: usa 0 solo si “no hubo divisor” y “el resultado fue cero” significan lo mismo para quien lee el informe. Casi nunca significan lo mismo.

Fíjate en lo que la nota no hace: no te pide que le creas. Trae la consulta, trae el número, y dice contra qué modelo se midió y en qué fecha. Una afirmación sobre DAX vale exactamente lo que puedas correr.

Honestidad sobre el alcance

Las notas de campo son 31, no 479. Son las funciones de más tráfico, no una cobertura completa. Los ejemplos ejecutables llegan más lejos — 99 funciones con 3 ejemplos cada una, todos con resultado medido — pero tampoco cubren el catálogo entero. Las fichas restantes llevan los ejemplos propios de Microsoft, marcados como lo que son: escritos contra un modelo que no está aquí.

Y el hueco no está repartido parejo, que es lo que enseña la portada de este artículo. Cinco categorías enteras siguen solo con la ficha de Microsoft: 168 de las 479 funciones — INFO.* (72, la categoría más grande), financieras (51), fecha y hora (24), las que el catálogo no clasifica (16) y padre-hijo (5). En el otro extremo, matemáticas, texto y lógicas están cubiertas casi al completo: los ejemplos se escribieron por categorías enteras, no salteados.

Las 31 notas, además, son todas de modelo clásico. En cálculos visuales el plugin te da la ficha, pero no criterio propio.

El laboratorio: cuatro modelos que puedes abrir

Para que una nota sea verificable tiene que existir el modelo donde se midió. Por eso el repo trae cuatro proyectos de Power BI que abren en tu máquina sin cuenta y sin configurar nada. Cada uno lee sus tablas en Parquet por HTTPS desde un repositorio de datos público, así que lo versionado son unos pocos kilobytes.

EscenarioLo que solo él puede mostrar
contosoEl modelo contra el que se midieron 30 de las 31 notas
blancosUn vacío en una columna numérica: qué funciones lo cuentan y cuáles lo saltan
claves-huerfanasClaves foráneas huérfanas, y la fila en blanco que el motor agrega por su cuenta
rendimiento2.000.000 de filas, para comparar lo que cuesta de verdad un plan de consulta

Y cada nota deja escrito contra qué midió. La de DIVIDE registra FactSales con 126.524 filas, 137 productos y un calendario del 2023-01-01 al 2024-12-31, medido el 2026-08-12. No tienes que creerte esa línea: el escenario está en el repo justamente para que la compruebes. Los datos son sintéticos — generados, no tomados de ningún lado — y no se redistribuye ningún dataset de Microsoft.

Hay un script, check_lab.py, que corre las consultas publicadas contra un modelo que tengas abierto y compara los resultados. Eso convierte cada nota de campo en un test en vez de una afirmación.

Cómo se instala (y la trampa de la versión)

Son dos comandos dentro de Claude Code:

Instalación
/plugin marketplace add CSalcedoDataBI/dax-for-agents
/plugin install dax@dax-for-agents

Necesitas Claude Code 2.1.142 o superior

Y este piso de versión no es una precaución: es una cicatriz.

En la 2.1.141 el plugin se instalaba, reportaba éxito y cargaba cero skills. Sin error, sin advertencia. Claude Code solo empezó a leer una ruta de skill que apunta a una carpeta con SKILL.md dentro a partir de la 2.1.142; antes, cuando ninguna de las rutas listadas resolvía, hacía un fallback silencioso a escanear una carpeta que en ese momento no existía. Lo medí bisectando las versiones publicadas contra el layout anterior.

Ahora hay un guardia — check_plugin_manifest.py — que mantiene el manifiesto y el árbol sincronizados para que ese fallo no pueda volver en silencio. Y la instalación desde el marketplace publicado está comprobada corriéndola: los dos comandos cargan las cinco skills.

Instaladas, las cinco skills quedan como dax:dax-reference, dax:dax-lib, dax:dax-lib-install, dax:dax-udf-authoring y dax:dax-window-functions.

Nada aquí te pide que confíes

Esa es la regla del repo, y se aplica también a su propia prosa. Los números que lees en el README no los mantiene nadie acordándose de actualizarlos: los revisa una compuerta que lee el árbol y falla si no coinciden.

Las seis compuertas, más tres suites de tests
python scripts/validate_skills.py         # frontmatter, INDEX, integridad del catálogo
python scripts/check_no_credentials.py    # que no se escape una credencial al árbol
python scripts/check_workflow_cost.py     # que un workflow no se coma la cuota de CI
python scripts/check_plugin_manifest.py   # el manifiesto contra las skills que existen
python scripts/check_doc_claims.py        # los números de la prosa contra el disco
python scripts/check_examples.py          # 3 ejemplos por función cubierta, con resultado

python -m unittest discover -s scripts -t scripts
python -m unittest discover -s evals   -t evals
python -m unittest discover -s skills/dax-reference/scripts -t skills/dax-reference/scripts

La interesante es check_doc_claims.py: lee cualquier número escrito junto a un sustantivo que este repositorio cuenta — fichas, funciones con ejemplos, conceptos, notas, skills, escenarios, tests — y falla si el árbol no está de acuerdo. Un número tecleado en un párrafo es justo lo que se pudre.

Y funciona incluso contra su propio autor. Escribí este artículo diciendo que las compuertas eran cuatro, porque cuatro son las que el README lista en su sección de verificación. Son seis, más los tres bloques de tests: el README se queda corto sobre sí mismo. Lo pillé leyendo el YAML de CI en vez de la prosa — que es exactamente lo que este repositorio te pide hacer.

Lo que no es

Es la sección más importante y por eso va al final, no escondida.

  • No reemplaza a un experto en DAX. Evita que tu agente invente funciones que no existen. Eso es todo lo que promete.
  • No hace tuning de rendimiento. Para eso está la skill dax de data-goblin, y este repo deliberadamente no la duplica.
  • No compite con SQLBI. dax.guide, daxpatterns.com y daxformatter.com son mejores para leer con tus propios ojos. Esto es para lo otro.
  • No redistribuye código de paquetes. La skill dax-lib es un índice offline de daxlib.org: te dice qué existe y quién lo escribió, antes de que te pongas a escribir una función personalizada desde cero.

El código y el contenido escrito a mano son MIT. Las fichas generadas son CC BY 4.0 de Microsoft, derivadas de MicrosoftDocs/query-docs — su propio repositorio de documentación de DAX —, con su aviso de atribución donde corresponde.

Actualización del 26 de agosto: la fuente desapareció

Mientras terminaba este artículo, MicrosoftDocs/query-docs dejó de existir. Hoy devuelve 404, tanto en la web como en la API de GitHub, sin autenticación de por medio, y no hay sucesor: ni en la organización ni entre los forks. El último commit que llegó a leerse fue 616f1e8, el 2026-08-24.

Queda la copia archivada del 1 de marzo y, viva, la documentación de DAX en Microsoft Learn, que es la forma publicada del mismo material. La atribución sigue siendo a Microsoft y el nombre del repositorio se mantiene escrito, porque eso es lo que exige CC BY 4.0 — pero he quitado el enlace, porque enlazar a un 404 no atribuye nada.

No se me escapa la ironía. Un artículo sobre que una afirmación vale lo que puedas correr, y cuya biblioteca entera deriva de un repositorio, publicado la semana en que ese repositorio se evaporó. Las 479 fichas siguen en su sitio y siguen siendo verificables — es justamente el argumento a favor de tener una copia derivada, versionada y con compuertas, en lugar de un enlace.

Y ahora

El siguiente paso está abierto y es el evidente: llevar los ejemplos ejecutables de 99 funciones al resto del catálogo. Son unos 380 archivos, cada uno con su consulta y su resultado medido, y el suelo de cobertura está puesto de forma que borrar un ejemplo rompe la compilación en vez de encoger la biblioteca sin que nadie lo note.

Si trabajas DAX con un agente y te ha pasado lo de la función inventada, pruébalo y dime qué se rompe. El repositorio está aquí:

github.com/CSalcedoDataBI/dax-for-agents

¿Te resultó útil este artículo?

Tu apoyo me permite seguir creando contenido de calidad.

¡Contáctame!