Spark

10 min de lectura

Día 18 / 60

Spark

Spark

Antes, para que Nelson pudiera interactuar con DIgSILENT, yo mantenía un repositorio con un backend en Python. Yo (y Claude Code, seamos honestos) escribimos miles de líneas de código para que Nelson pudiera hacer cada operación: activar una línea, cambiar el tap de un transformador, correr un flujo de potencia.

En algún momento consideré hacer ese repositorio público. Hasta que me di cuenta de que había una forma mucho mejor de resolver el problema.

El problema no estaba en Nelson — estaba en la conexión con DIgSILENT. Las herramientas eran fijas: ~50 operaciones que yo había programado a mano. Si Nelson necesitaba hacer algo fuera de esas 50 —por ejemplo, ajustar una protección de distancia— no había forma de ejecutarlo. El agente razonaba bien, pero la capa de herramientas simplemente no podía hacer nada.

Mi solución anterior era frágil por diseño: era tan capaz como el código que yo había escrito.

Los recientes avances en ARC-AGI 3 me hicieron pensar en esto de nuevo. Escribí sobre ARC-AGI 3 en un post anterior — básicamente es la competencia donde se mide si los modelos pueden razonar en tareas genuinamente nuevas. El equipo de DukeNLP publicó la mejor solución hasta el momento (*): su agente completa los tres juegos del benchmark usando solo tres herramientas — leer logs, hacer grep (búsqueda de patrones en archivos), y ejecutar Python.

(*) Escribi esto un día antes de publicarlo (26 de Marzo), hoy 27 de Marzo ya hay una solución mejor, pero que mantiene la misma estructura.

La conclusión que más me golpeó: los LLMs son malos razonando sobre estructuras espaciales complejas en contexto, pero cuando les das Python para hacerlo programáticamente, el problema desaparece.

Lo que está pasando en esa dirección me abrió la mente: si el modelo puede razonar, puede programar. Y si puede programar, puede crear sus propias herramientas.

Y ahí está el truco que tardé 2 meses en ver: interactuar con DIgSILENT siempre fueron scripts en Python. No hay magia detrás de las 50 herramientas del harness v1.0 — cada una es, en el fondo, un script Python que abre el archivo de PowerFactory, hace algo, y devuelve un resultado. Yo simplemente los había escrito todos a mano de antemano.

¿Y si el agente los escribiera él mismo cuando los necesita?


¿Qué es Spark?

Spark es un agente especializado en escribir código Python. Nada más. No hace estudios eléctricos, no genera reportes, no habla con el usuario. Su única tarea es tomar un problema y resolverlo con un script.

Es deliberadamente simple: ~500 líneas de código, con un ciclo ReAct básico.

Ciclo ReAct de Spark

Ciclo ReAct de Spark

El ciclo funciona así:

  • Razona — entiende qué operación necesita hacer en DIgSILENT
  • Escribe — genera el script Python correspondiente
  • Ejecuta — corre el script contra PowerFactory
  • Evalúa — ¿funcionó? ¿el resultado tiene sentido?
  • Itera — si falló, entiende por qué y corrige

Lo que lo hace especial no es el ciclo en sí. Es lo que pasa cuando logra algo y cuando falla.


La memoria que se acumula

Cada vez que Spark resuelve un problema exitosamente, guarda dos cosas: el script que funcionó y el razonamiento que lo llevó a ese script.

Pero lo más interesante no es que guarda los éxitos — también guarda los fracasos.

La mayoría de los agentes de IA aprenden solo de sus éxitos. Guardan lo que funcionó y lo reutilizan. Pero los humanos aprendemos más de nuestros fracasos — probablemente porque fallamos más de lo que acertamos. Implementé esa misma lógica en Spark.

Cuando no puede resolver algo, guarda un documento [FALLIDO] con qué intentó, por qué no funcionó, y qué recomienda probar diferente. Antes de escribir cualquier script nuevo, Spark lee ambos: los éxitos y los fracasos. Los fracasos le dicen qué no hacer.

El formato es simple:

# [FALLIDO] Cortocircuito en línea al 50%

## Qué se intentó
- Crear evento de falla (EvtShc) + método IEC 60909 → error code 1

## Por qué falló
- IEC 60909 no procesa eventos de falla en líneas vía script

## Recomendación
- Usar método "Complete" (iopt_mde=1) en lugar de IEC 60909

Un ejemplo concreto: el cortocircuito en una línea eléctrica era una tarea que fallaba consistentemente. Sin memoria, Spark reintentaba el mismo enfoque 30 veces gastando $0.29 USD sin llegar a nada. La segunda vez, tenía guardado el [FALLIDO] — entendió que el método IEC 60909 no funciona para fallas en líneas vía script, cambió al método "Complete", y lo resolvió al primer intento por $0.10.

IntentoResultadoCosto
Sin memoria30 reintentos, sin resultado$0.29
Con [FALLIDO] guardadoFalla, pero documenta por qué$0.27
Siguiente ejecuciónÉxito al primer intento$0.10
Ciclo de auto-retroalimentación de Spark

Ciclo de auto-retroalimentación de Spark

La implementación técnica son ~30 líneas de código extra en el loop del agente y un párrafo adicional en el system prompt. Nada sofisticado. El insight está en el diseño, no en el código.

Esto está inspirado en el paper ExpeL: LLM Agents Are Experiential Learners, que propone que los agentes aprendan tanto de trayectorias exitosas como fallidas. La mitad que casi nadie implementa es la de los fracasos.

La segunda vez que Nelson le pide algo similar, Spark no parte de cero. Con el tiempo acumula una biblioteca construida desde experiencia real — no desde lo que yo anticipé que iba a necesitar.

Esto es lo que me tiene más orgulloso del diseño. No es solo que pueda escribir código. Es que aprende de sus propios logros y fracasos.

Mind blown

Mind blown


Por qué esto cambia el harness

En el harness v1.0, Nelson tenía ~50 herramientas hardcodeadas. Si necesitaba algo fuera de esas 50, se rompía.

Con Spark como parte del harness v2.0, Nelson puede pedirle a Spark que escriba el script que necesita en tiempo real. El conjunto de capacidades de Nelson deja de estar acotado por lo que yo programé de antemano.

Harness v1.0Harness v2.0 con Spark
Líneas de código~16.000~500
Capacidades~50 herramientas fijasIlimitadas (en teoría)
Si falla algo nuevoSe trabaSpark lo escribe
MantenimientoAltoMuy bajo

Ventajas y desventajas

Las ventajas reales:

  • Nelson ya no se traba si le piden algo nuevo
  • El código que mantengo es 30x más pequeño
  • Spark mejora con el tiempo sin que yo intervenga
  • Cualquiera con DIgSILENT puede usarlo — no solo yo

El problema :

Spark gasta tokens para pensar y escribir código. Por ahora uso Gemini (me encanta Gemini 3.1 =D) y el costo por llamada es manejable. Pero si Nelson delega a Spark frecuentemente, los costos se van a ir acumulando.

Es un trade-off que acepto: prefiero pagar tokens que mantener miles de líneas frágiles. Pero voy a estar midiendo el gasto para ver si realmente vale la pena.


Cómo probarlo

Spark es open source. Es la segunda herramienta de Don Nelson que hago pública — la primera fue la skill de Infotécnica.

¿Por qué lo hago público? Dos razones.

Una: necesito validación real. Si otros lo usan y funciona, confirma que el approach técnico va por buen camino. No hay mejor prueba que alguien que no soy yo corriendo el código y llegando al mismo resultado.

Dos: Spark no es lo que hace único a Don Nelson. Spark es infraestructura — un agente que escribe scripts para DigSILENT. Eso no es un secreto que valga la pena guardar.

Pueden clonarlo, forkearlo, contribuir, o simplemente usarlo:

👉 github.com/valdivia-tech/spark

Para instalarlo: clonen el repo en un computador con DIgSILENT, agreguen su API Key de Gemini, y listo.


Lo que viene: integrar Spark al harness v2.0 completo y probarlo con el estudio real del CEN.

Suscríbete al blog