Espressif sigue iterando sobre un mismo experimento: cómo trabajar con un agente IA cuando lo que está en juego no es una API web sino firmware embebido. Tras un primer artículo en abril sobre desarrollo en Rust con IA, ahora la compañía publicó la versión Zephyr del mismo recorrido, usando el kit ESP DualKey de M5Stack como banco de pruebas.

El producto no cambió. El product_spec.md que ya regía la versión Rust se mantiene: el dispositivo tiene que dialogar con la app Espressif ESP BLE Provisioning exactamente igual que antes, con los mismos gestos, LEDs, timeouts, política de reinicio y comportamiento MQTT/HID. Lo que se movió fue la implementación a C sobre Zephyr y, sobre todo, las reglas con las que se trabaja con el modelo.

¿Por qué Zephyr y no seguir con Rust?

Zephyr es un RTOS open source administrado por la Linux Foundation. Es bastante más que un kernel: incluye un catálogo in-tree de drivers, stacks de protocolo y servicios, configurado con Kconfig y devicetree, construido con la metaherramienta west. Espressif lo soporta desde 2020 sobre la familia ESP32 y mantiene una página de estado con el avance del port.

La adopción en la base de usuarios de Espressif viene creciendo de forma sostenida, pero la queja recurrente sigue siendo la misma: arrancar un proyecto Zephyr desde cero es difícil. La compañía eligió esa fricción concreta para iterar su método con IA. No es que Zephyr reemplace a Rust ni a ESP-IDF, todos son opciones válidas; lo interesante es probar el mismo contrato evaluador/codificador en un stack distinto.

Fig. 1: el kit ESP DualKey con etiquetas.
Fig. 1: el kit ESP DualKey con etiquetas.

El contrato base: lo que ya traían de la experiencia Rust

Espressif arrancó esta corrida asumiendo que las reglas del artículo anterior seguían vigentes. La lista mínima de hábitos que el equipo ya tenía interiorizados:

  • Una spec escrita vale más que prompts ad-hoc.
  • El código de referencia (ejemplos ESP-IDF, protocomm) supera a la prosa para trabajo de protocolo.
  • Git es el deshacer cuando los experimentos salen mal; cada hito merece commit.
  • Tareas acotadas ganan a los monolitos del estilo "implementá el subsistema".
  • El trazado y la evidencia del banco vencen a discutir desde el código fuente.
  • El humano es dueño de la arquitectura y la evaluación; el agente, del tipeo.
  • Cuando algo se publica roto, la responsabilidad es del humano.
  • Una vez clara la dirección, el agente codea.
  • Cuando los dos están perdidos, debuggean los dos.

Sobre esa base, el artículo en Rust había añadido prácticas concretas: usar Agent Mode solo después de acordar el objetivo, activar Planning cuando hay muchos pasos secuenciales, commitear en cada plan para que bisect y rollback no sean teóricos, y combatir la entropía con la disciplina de "limpiá tu pieza". También dejó un aprendizaje doloroso: borrar el diario de debug durante una limpieza, sin tratarlo como cuaderno de laboratorio.

Lo que Zephyr suma al contrato

Como Zephyr trae su propio paradigma, el equipo formalizó cuatro principios de integración que después funcionan como prompt constraints concretos para el modelo:

  • Usar tanto Zephyr como sea posible: preferir los flujos soportados del RTOS antes que armar capas paralelas tipo "mini-OS" dentro de la app.
  • Usar tanto de los servicios del OS como sea posible: networking, gestión Wi-Fi, host BLE, patrones settings/NVS, logging, workqueues. Cablear vía subsistemas Zephyr en vez de inventar shims propios.
  • Usar tanto de la distro Zephyr como sea posible: aprovechar módulos in-tree y bloques seleccionables por Kconfig antes que copias privadas; contribuir upstream si falta algo, no forkear en silencio.
  • Integrarse de forma seamless a Zephyr: workspace west, módulo out-of-tree, devicetree, prj.conf, samples, naming y docs que se vean como un Zephyr normal.

Esas cuatro líneas le dicen al modelo qué se considera "bueno" antes de que invente una forma de proyecto extranjera. La organización del repo terminó reflejándolas sin que el equipo tuviera que redefinirlas a mitad de camino.

¿Qué cambió en este experimento?

El equipo identificó tres correcciones de método sobre la versión Rust:

Código rápido, magia lenta. El modelo escribe más rápido que el humano, pero eso no achica el trabajo del evaluador, lo aumenta. El valor humano no está en tipear sino en pensamiento crítico, arquitectura, testing, debug y organización. Cuando el provisioning misbehaved, la jugada ganadora siguió siendo "pegá el log, declará la expectativa, preguntá qué rama está mal", no "generá más código hasta que compile".

La organización es trabajo humano. Scripts descartables, docs duplicadas y archivos "útiles" en la carpeta equivocada aparecen si nadie impone estructura. La spec versus el journal, el módulo versus la app, el .gitignore, los pins de submódulos, qué se borra y qué se commitea: todo eso lo decide el humano. Esta vez el journal sobrevivió.

Dejar de darle al agente el árbol completo. En la versión Rust hubo una fase de "la IA hace todo en un mismo árbol". Ahora se separó la implementación en tres piezas: un componente reusable (la librería de provisioning), una proof application y un producto delgado. La respuesta al macaronic code (lógica apilada sin fronteras claras) no fue sintáctica sino arquitectónica: un componente formal con API pública revisada como librería, separado del journal de debug.

¿Qué se llevan los integradores embebidos?

El experimento de Espressif no es una guía Zephyr ni un manifiesto Rust: es un caso documentado de cómo organizar el trabajo con un agente IA cuando lo que está en juego es firmware con restricciones reales (timings, banco, protocolo). El repositorio público dualkey-provisioning queda disponible como referencia para equipos que quieran arrancar un proyecto Zephyr sobre ESP32 sin reinventar la estructura cada vez.

Para Espressif, la apuesta editorial es clara: el flujo Plan-Code-Test-Commit, con spec como contrato y Git como red de seguridad, es lo que escala. La elección de RTOS pasa a segundo plano.