
Escuchar este post
Selecciona una voz y genera audio para escuchar este post
Build in Public #1 - Documentando nuestro viaje construyendo un agente de IA con el patrón ReAct
7 de enero, 2025
¡Hola geek! 👋
Hoy quiero compartir algo emocionante que acabamos de lograr en Formmy: convertimos a Ghosty de un simple chatbot a un verdadero agente de IA. Y lo mejor de todo... ¡funcionó en el primer intento!
🎯 El Problema que Teníamos
Ghosty, nuestro asistente de IA para Formmy, tenía un problema muy frustrante:
- ✅ Podía buscar información en la web
- ✅ Mostraba las fuentes correctamente
- ❌ Pero nunca daba una respuesta final del LLM
El usuario veía "Buscando..." → aparecían las fuentes → y ahí se quedaba 😤
🕵️ El Debugging: Encontrando el Loop Infinito
Al revisar los logs, descubrimos el culpable:
🔧 Modelo solicitó herramientas: [ 'web_search' ] 🔨 Ejecutando herramientas... ✅ Herramientas ejecutadas. Resultados: 1, Fuentes: 5 🔄 Continuando al siguiente intento (2/3)... 🔧 Modelo solicitó herramientas: [ 'web_search' ] # ¡Otra vez! 🔄 Continuando al siguiente intento (3/3)... 🔧 Modelo solicitó herramientas: [ 'web_search' ] # ¡Y otra vez!
El problema: Nuestro patrón ReAct estaba roto. El LLM quedaba atrapado pidiendo la misma herramienta infinitamente porque:
- Primera llamada: Incluía herramientas ✅
- Segunda llamada: NO incluía herramientas ❌
- LLM confundido: "Tengo los datos pero no sé qué hacer" 🤔
🔬 La Solución: ReAct Pattern Implementado Correctamente
Después de estudiar el patrón ReAct (Reasoning + Acting), implementamos la solución:
Antes (Roto 💥):
// Primera llamada: con tools if (enableTools && attempts === 1) { requestBody.tools = AVAILABLE_TOOLS; } // Segunda llamada: sin tools - ¡LLM confundido!
Después (Funcionando ✨):
// Solo permitir tools en el primer intento if (choice?.message?.tool_calls && attempts === 1) { // Ejecutar herramientas... // Luego forzar respuesta final sin tools const finalResponse = await callLLMWithoutTools( "Basándote en la información obtenida, da una respuesta final completa" ); }
🎉 El Resultado: ¡Ghosty Cobra Vida!
Ahora Ghosty funciona como un verdadero agente:
- 🧠 Reasoning: "Necesito información actualizada sobre FixterGeek"
- 🔍 Acting: Ejecuta
web_search
automáticamente - 👀 Observation: Procesa los resultados de búsqueda
- 💬 Response: "FixterGeek es una plataforma educativa mexicana que ofrece cursos de programación en vivo..." [1][2][3]
🛠️ Bonus: Resolviendo el Problema de Google
¡Pero no era todo! Google empezó a bloquear nuestras búsquedas:
🚫 Google detectó bot - página bloqueada Error: Google blocked request
Solución anti-bot implementada:
// Headers más humanos extraHTTPHeaders: { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3', 'DNT': '1', }, // Override navigator para no parecer bot await context.addInitScript(() => { Object.defineProperty(navigator, 'webdriver', { get: () => undefined, // En lugar de true }); }); // Comportamiento más humano await page.waitForTimeout(2000 + Math.random() * 2000); // Simular movimiento de mouse...
🏆 ¿Es Ghosty un Agente Real Ahora?
¡SÍ! Ghosty cumple todos los requisitos de un agente de IA:
- ✅ Autonomía: Decide qué herramientas usar
- ✅ Reactividad: Responde a queries del usuario
- ✅ Pro-actividad: Busca información cuando la necesita
- ✅ Habilidades sociales: Cita fuentes y explica su proceso
- ✅ Persistencia: Mantiene contexto de conversación
📚 Lo Que Aprendimos
1. El Patrón ReAct es Poderoso
Cuando se implementa correctamente, convierte cualquier LLM en un agente capaz.
2. El Debugging es Clave
Los logs nos salvaron. Sin ellos, nunca habríamos encontrado el loop infinito.
3. Los Bots vs Anti-Bots es una Guerra Constante
Google mejora su detección, nosotros mejoramos nuestra humanización. El ciclo continúa.
4. Build in Public Funciona
Documentar el proceso nos ayuda a pensar más claramente y puede ayudar a otros.
🔮 Lo Que Viene Mañana
Ghosty funciona, pero aún podemos mejorarlo siguiendo el patrón ReAct completo:
- 🔄 Loop Dinámico: Permitir n herramientas hasta completar la tarea
- 🧰 Tool Registry: Sistema genérico para agregar nuevas herramientas fácilmente
- 🔗 Tool Chaining: Usar múltiples herramientas en secuencia/paralelo
- 📊 Herramientas de Formmy: Acceso real a métricas, chatbots y formularios
💭 Reflexiones Finales
Convertir un chatbot en un agente real no es solo cambiar algunas líneas de código. Requiere:
- Entender los patrones (ReAct en nuestro caso)
- Debugging sistemático para encontrar los problemas reales
- Pensar como el LLM para entender por qué se confunde
- Manejar el mundo real (rate limits, bot detection, etc.)
La magia no está en el LLM en sí, sino en cómo orquestamos su interacción con herramientas externas.
¿Te gustó esta documentación? Seguiremos compartiendo nuestro proceso construyendo en público. La próxima entrada será sobre implementar el loop dinámico completo.
¿Tienes preguntas o sugerencias? ¡Déjalas en los comentarios o issues del repo!
Happy building! 🚀
🔗 Links Útiles
Este post es parte de nuestra serie "Build in Public" donde documentamos el desarrollo de Formmy y sus herramientas. ¿Quieres ver más? ¡Suscríbete!

Cómo aplicar formato de moneda y fecha en Javascript
Checa este otro Post
