hachiflow.com

Esta entrada trata de Buzz, nuestro producto anterior. Hoy construimos Waggle.

Dogfooding

El agente es la capa de renderizado

Le dimos una bandeja de correo a nuestro agente de marketing. Un cliente nos escribe, Gary V lee el correo en un canal de nuestro propio workspace alojado en hachiflow, redacta la respuesta y la envía cuando un fundador da el visto bueno. Del correo a AgentMail, al webhook de un workflow, a un agente compañero de equipo: todo con software ya publicado, cero infraestructura propia. Hasta donde sabemos, nadie había publicado exactamente este cableado.

Una URL, una cabecera, un paso de YAML

Las piezas ya estaban en la estantería. AgentMail es una bandeja de correo API-first pensada para agentes: creas una bandeja por API, ella recibe el correo y dispara un webhook a la URL que elijas en cuanto llega un mensaje. Buzz, el workspace de código abierto publicado por Block (hachiflow es independiente y no está afiliada a Block), incluye un motor de workflows en el propio relay. Todos los workspaces de hachiflow.chat lo traen integrado, así que los workflows disparados por webhook funcionan desde el día 1, sin ningún servidor propio que mantener.

Un workflow con disparador webhook obtiene un endpoint como POST https://yourteam.hachiflow.chat/hooks/9f4c21e7-6b3d-4a8e-b02f-c75d10a94e63, autenticado con una cabecera X-Webhook-Secret. Apunta el webhook de AgentMail a esa URL, pon el secreto en la cabecera y el correo entrante cae en tu canal.

Esa es toda la integración: una URL, una cabecera, un paso de YAML. La captura de abajo es todo el lado de Buzz, y la terminal que viene después es todo el contrato, con valores de ejemplo deliberadamente falsos.

El editor de workflows de Buzz: un workflow llamado customer-marketing-emails en el canal marketing, con disparador webhook, un único paso Send Message cuyo texto es el timbre de una línea que menciona a Gary V, y el conmutador formulario/YAML en la esquina.
Toda la integración del lado de Buzz: un disparador webhook y 1 paso Send Message. La única línea de texto que envía es el timbre.
todo el contrato
# simula la entrega de AgentMail: misma URL, misma cabecera $ curl -X POST \ -H 'X-Webhook-Secret: 7d81f3a2-4c96-4b0e-a2d5-e6f4903b17c8' \ -H 'Content-Type: application/json' \ --data '{"event":"message.received"}' \ https://yourteam.hachiflow.chat/hooks/9f4c21e7-6b3d-4a8e-b02f-c75d10a94e63 # el timbre cae en el canal y el agente va a por el correo de verdad

Los dos valores son ejemplos deliberadamente falsos: el UUID del hook y el secreto reales se generan al crear el workflow, y el secreto vive solo en la configuración del webhook de AgentMail.

Intento 1: el muro de JSON

Nuestro primer workflow hizo lo obvio: volcó el payload directamente en el canal con {{trigger.message}}. Lo que salió fue un muro de JSON crudo. Cabeceras, resultados de SPF, metadatos de adjuntos, todo el sobre en un solo párrafo. Se conserva en la captura de más abajo, justo encima de lo que lo sustituyó.

La limitación es concreta, y leímos el código Rust para confirmarla. Hoy las plantillas de workflow de Buzz solo extraen las claves de primer nivel del cuerpo del webhook. Un objeto anidado se renderiza como un único bloque convertido en texto: no existe {{trigger.message.from}}, y los únicos filtros de plantilla son truncate y npub. Hoy por hoy no es posible renderizar bien un payload de webhook anidado dentro de un mensaje de workflow.

No es una queja. Es un motor joven y la superficie de plantillas va a crecer. Pero hoy el consejo honesto es este: no pienses en formatear el payload del webhook en el workflow, diseña pensando en que no puedes.

No renderices en el workflow. No renderices en absoluto.

La salida nos estaba mirando desde todos los demás mensajes del canal. Los mensajes de los agentes en Buzz se ven muy bien, porque el cliente renderiza el contenido como markdown al estilo de GitHub. El workflow no podía dar formato al correo, pero el compañero de equipo al que se lo entregaba da formato a todo lo que dice. Así que le dimos la vuelta a la arquitectura y dejamos de renderizar en el workflow por completo.

El mensaje del workflow ahora es un timbre de una línea que @menciona al agente. Gary V tiene él mismo las herramientas de AgentMail, su servidor MCP alojado, limitado a esta única bandeja. Cuando suena el timbre, trae el correo no leído, publica en el canal una tarjeta markdown legible más su borrador de respuesta, envía la respuesta en el hilo del mensaje original a través de la API de AgentMail y etiqueta el mensaje como atendido para que nada se trabaje dos veces.

El agente es la capa de renderizado. El workflow es una llamada para despertar. Y la aprobación no se movió de sitio: Gary redacta en el canal, y un fundador da el visto bueno antes de que nada salga por la puerta.

correo del cliente desde cualquier parte bandeja AgentMail API-first · webhooks workflow en tu relay disparador webhook POST /hooks/… · X-Webhook-Secret timbre de una línea #marketing Gary V agente · tiene las herramientas de la bandeja la @mención despierta tarjeta markdown + borrador MCP: traer · responder · etiquetar fundador: adelante
La forma que funciona: el workflow solo toca el timbre; el agente lee, renderiza y responde. La aprobación se queda en el canal.
El canal marketing en Buzz. Arriba, un mensaje antiguo que renderiza el payload del webhook como un muro de JSON crudo; debajo, el timbre de una línea que lo sustituyó; y en el panel de hilo de la derecha, el resumen legible del agente y su respuesta enviada.
Antes y después en un solo cuadro: arriba el bloque de JSON crudo del intento 1, debajo el timbre de una línea que lo sustituyó, y a la derecha el resumen legible de Gary y su respuesta en hilo.

La mención que no despierta a nadie

El tropiezo 1 nos costó 3 rondas de pruebas. Las menciones en los mensajes de workflow se resuelven en el servidor: el relay compara el @Name del texto de tu paso con los miembros del canal por su nombre visible. Si 2 miembros comparten nombre visible, el relay no despierta a nadie, a propósito. Ni error, ni coincidencia parcial, ni un log que puedas ver. Silencio.

Teníamos un duplicado olvidado: un «Gary V» anterior, ya muerto, seguía siendo miembro del canal junto al que funcionaba, así que cada timbre sonaba para nadie. Como regla contra envíos equivocados es razonable, no quieres que un workflow adivine a cuál de 2 miembros con el mismo nombre despertar. Como experiencia de depuración es brutal, porque nada en ningún sitio te dice que ha pasado. Expulsamos al miembro sobrante y el timbre sonó.

La firma visible es cosmética

El tropiezo 2 es más sutil. Un mensaje de workflow parece que viene de ti. No es así. El cliente renderiza la atribución; criptográficamente, el mensaje está firmado con la clave del propio relay.

La compuerta de a quién responde Gary estaba configurada solo para su dueño, y la compuerta comprueba la firma, no el nombre que se muestra. Así que vio llegar el timbre, vio que no lo firmaba su dueño y lo ignoró, con toda la razón. La compuerta tiene razón, la firma visible es cosmética, y el arreglo es añadir la clave del relay a la lista de permitidos del agente, para que los mensajes de workflow firmados por el relay cuenten como despertar.

Lo descubrimos leyendo el código de buzz-acp, y upstream ha lidiado con el mismo problema: llegó un arreglo y se revirtió. Así que si etiquetas a tu agente y nunca despierta, y hay exactamente 1 como él en el canal, este es el motivo.

Una más para el camino

Una pequeña, del editor YAML de workflows. Un valor de texto que empieza por @ tiene que ir entre comillas, porque un @ sin comillas no puede iniciar un escalar YAML. Y pega con cuidado: una vez conseguimos añadir un segundo documento YAML entero dentro del campo de texto del mensaje, y el editor lo aceptó sin pestañear. Las vistas de formulario y de YAML son 2 puertas al mismo paso; la de formulario muerde menos.

Arreglar las herramientas que tienes en la mano

Cada ronda de pruebas fue un correo real desde nuestro propio dominio, enviado con higgs, nuestra CLI para Proton Mail que maneja Proton Mail Bridge por IMAP y SMTP. Sin mocks: cada prueba cruzó internet de verdad, llegó a la bandeja de verdad e hizo sonar el timbre de verdad, que es exactamente como pillamos tropiezos que un fixture nunca habría sacado a la luz.

El dogfooding cortó en las dos direcciones. En plena depuración descubrimos que higgs send no podía hablar con Bridge tal cual venía, así que lo arreglamos y publicamos higgs v1.3.0 esa misma noche. Así es el trabajo real de conectar agentes entre sí: la mitad del tiempo estás arreglando las herramientas que tienes en la mano.

En fase alfa, y funciona en producción

Todo lo anterior funciona hoy en cualquier workspace de hachiflow: $50 al mes, precio plano, personas ilimitadas y agentes ilimitados, tus propias claves de LLM, un servidor dedicado. Nada de esto necesitó infraestructura a medida. AgentMail es un producto en el que te puedes registrar, el motor de workflows viene en todos los workspaces, y el agente es un miembro de tu equipo como cualquier otro.

Buzz es joven y esto es un cableado en fase alfa con asperezas, que es exactamente por lo que publicamos los tropiezos en lugar de un vídeo de mejores momentos. Si quieres una bandeja de correo con un compañero de equipo detrás, empieza en hachiflow.com.

← Todas las notas