Tag: Agents

  • Construcción de memoria efectiva en agentes de LLMs

    Construcción de memoria efectiva en agentes de LLMs

    ¿Quieres que tu agente recuerde cosas útiles… o que haga como si recordara y te deje colgado en la siguiente conversación?

    Tiempo estimado de lectura: 7 min

    • Separar memoria corta y larga: la conversación viva debe manejarse aparte de hechos estructurados.
    • Extraer hechos estructurados: usar un extractor que emita JSON y aplicar UPSERT/DELETE, no append infinito.
    • Decisiones arquitectónicas: síncrono vs asíncrono, versionado y locks para evitar race conditions.
    • Optimizar costes: usar modelos baratos para extracción, modelos premium solo para generación crítica.
    • Observabilidad y Gobernanza: logs, métricas, cifrado y políticas de retención son imprescindibles.

    Poca gente habla de esto: la memoria en agentes no es un problema de “mandar el historial” al modelo. Es un problema de arquitectura, coste y criterio. Hacerlo mal es pagar tokens, cargar latencia y, lo peor, construir una ilusión de memoria que falla cuando más importa.

    Te voy a contar, sin florituras, cómo se construyó el sistema de memoria de Agent Builder y qué decisiones concretas puedes tomar hoy para replicarlo sin pelearte con un monster framework.

    Resumen rápido (lectores con prisa)

    Separar memoria corta (últimos N mensajes) de memoria larga (hechos estructurados). Usar un extractor barato que devuelva JSON forzado con operaciones UPSERT/DELETE. Preferir extracción asíncrona por defecto y checkpoints síncronos para acciones críticas. Versionado y locks para evitar race conditions; observabilidad y gobernanza desde el día 1.

    Primera verdad incómoda

    Primera verdad incómoda: los LLMs no recuerdan.

    Cada petición es una hoja en blanco. Si quieres que el agente actúe con coherencia, tienes que diseñar la memoria fuera del modelo.

    Resumen rápido del approach que funciona

    • Separar memoria a corto plazo (conversación viva) de memoria a largo plazo (hechos estructurados).
    • Extraer hechos con un LLM dedicado (extractor) y guardarlos como pares clave-valor o documentos estructurados.
    • Forzar salidas en JSON (Tool Calling) para que la memoria sea determinista.
    • Resolver conflictos con UPSERT/DELETE, no con append infinito.
    • Decidir entre extracción síncrona o asíncrona según prioridades (latencia vs coherencia).

    1) Memoria a corto plazo: lo que vive ahora

    ¿Qué es? Los últimos N mensajes del hilo (thread_id).

    Para qué sirve: referencias inmediatas (“bórralo”, “ese archivo”, “la última tarea”).

    Implementación simple: Redis o una tabla en Postgres con TTL y lista acotada.

    Por qué importa: reduce tokens enviados al LLM principal y mantiene claridad a corto plazo.

    2) Memoria a largo plazo: hechos, no chats

    No guardes el chat crudo. Guarda hechos estructurados: preferencias, roles, reglas de negocio, acciones ya realizadas.

    ¿Cómo se obtienen? Un LLM extractor lee el hilo (o el resumen) y emite objetos JSON con campos tipo {key, value, source, timestamp, confidence}.

    Dónde guardarlos: una tabla Key-Value en Postgres o en Redis para lecturas rápidas; opcionalmente, una base vectorial si necesitas búsquedas semánticas sobre fragmentos largos.

    3) El extractor: el héroe silencioso

    Debe ser un LLM barato y rápido (GPT-4o-mini, Claude 3 Haiku o un modelo local si tienes infra).

    Se le da: el hilo reciente + la memoria actual (opcional, si quieres que compare).

    Debe devolver: operaciones del tipo {op: “UPSERT”, key: “pref_theme”, value: “dark”, reason: “…”} o {op: “DELETE”, key: “pref_theme”, reason: “…”}.

    Forzar JSON es obligatorio. Si el modelo alucina, valida la salida con un schema validator (Zod, JSON Schema).

    4) Resolver conflictos: no más “y también”

    Problema típico: ayer dije “React”, hoy “Angular” y el sistema almacena ambos.

    Solución: lógica de reconciliación dentro del extractor — recibe la memoria existente y decide overwrites o borrados.

    Políticas útiles: última declaración gana para preferencias personales; para estados transaccionales usar confirmación explícita (“Confirmo que he migrado a Angular”).

    5) Síncrono vs Asíncrono — la decisión que rompe equipos

    Síncrono: esperas a que el extractor actualice la memoria antes de responder. Plus: coherencia. Contra: latencia.

    Asíncrono: respondes al usuario y actualizas memoria en background. Plus: experiencia rápida. Contra: race conditions si el usuario dispara múltiples mensajes seguidos.

    Recomendación práctica: asíncrono por defecto, con checkpoints síncronos en operaciones críticas (ej. ejecutar acciones que dependen de la memoria: “programa el pago” → usa extracción síncrona o confirmación humana).

    6) Mitigar race conditions: patrones que funcionan

    • Versionado por evento: cada update incluye un version_id. Si un job en background llega con versión vieja, lo descarta.
    • Locks optimistas: comparar-timestamps antes de aplicar UPSERT.
    • Event sourcing ligero: mandar events al bus (Kafka, Redis Streams) y procesarlos ordenadamente.
    • Si necesitas garantía fuerte, usa transacciones y bloqueo por llave (Postgres advisory locks).

    7) Costes y optimización de tokens

    No envíes texto innecesario al LLM principal. Inyecta solo facts relevantes (top-K) y un resumen de contexto.

    Batch extraction: agrupa varias interacciones y extrae cada X minutos si no hay acciones críticas.

    Usar modelos cheap para extractor y modelos premium para generación cuando haga falta.

    8) Observabilidad y LLMOps: no es opcional

    • Logea: inputs al extractor, salidas JSON, ops aplicadas (UPSERT/DELETE), latencias, errores de parsing.
    • Métricas clave: TTFT, tiempo de extracción, tasa de conflictos, porcentaje de respuestas incoherentes relacionadas con memoria.
    • Guarda trazabilidad para auditoría (what was injected, when, by which extractor) — imprescindible si manejas PII.

    9) Privacidad y gobernanza

    • Nunca almacenes datos sensibles sin cifrado y consentimiento.
    • Tokeniza o anonimiza cuando sea posible.
    • Control de accesos: solo servicios autorizados pueden leer/escribir la memoria.
    • Políticas de retención: define cuánto tiempo quedan los hechos y cómo se borran permanentemente.

    10) Tests y validación

    • Tests unitarios de extractor: inputs -> JSON schema válido.
    • Integración: simula secuencias de diálogos para validar conflict resolution.
    • E2E: pruebas que cubran casos de race conditions y rollback.
    • Prueba manual de A/B: compara comportamiento con y sin memoria en producción limitada.

    11) Stack recomendado mínimo (para lanzar rápido)

    • Storage corto: Redis (listas con TTL)
    • Storage largo: Postgres (tabla kv con versioning) + opcional vector DB (Pinecone/Qdrant)
    • Orquestador: n8n / Lambda / Sidecar service
    • Extractor model: GPT-4o-mini / Claude 3 Haiku (económicos)
    • Generación model: GPT-4o / Claude 3 Sonnet (cuando necesites calidad)
    • Validación: JSON Schema + Zod en backend
    • Observabilidad: logs estructurados + Sentry / Datadog

    12) Checklist práctico para ponerlo en producción (si te gusta lo concreto)

    • [ ] Definir qué “hechos” guardas (user_prefs, last_actions, contracts_signed, etc.).
    • [ ] Implementar almacenamiento corto (Redis) y largo (Postgres).
    • [ ] Crear extractor con JSON forced output y validar schema.
    • [ ] Implementar operaciones UPSERT/DELETE con versionado.
    • [ ] Diseñar flujo asíncrono por defecto y rutas síncronas para operaciones críticas.
    • [ ] Añadir metrics y logs para cada extracción y operación.
    • [ ] Revisar PII/retención y cifrado en reposo y en tránsito.
    • [ ] Tests automáticos para race conditions y reconciliación.
    • [ ] Plan de rollback si una actualización de prompt rompe el extractor.

    Metáfora que guarda la idea

    La memoria del agente no es una mochila donde tiras todo el chat. Es una libreta indexada. Solo apuntas lo que te sirve, lo fechas, lo restructuras y borras lo viejo. Si apilas notas sin orden, la libreta es ruido. Si la estructuras, te salva.

    Historias reales (1 párrafo cada una)

    El equipo A metió todo el historial en cada prompt: coste x10, latencias enormes y usuarios desconectados. Migraron a extractor asíncrono y bajaron costes un 70%.

    El equipo B aseguró cada operación con versión y locks: sacrificaron un poco de velocidad, pero nunca perdieron coherencia en flujos transaccionales.

    El equipo C dejó la extracción en background y puso un checkpoint síncrono antes de ejecutar pagos — ganador en UX y seguridad.

    Cierre con decisión: ¿lo haces tú o lo dejas para después?

    Construir memoria útil no es sexy. Es ingeniería, decisiones difíciles y pruebas. Pero sin ella, tu “agente” será otro bot que habla bonito y olvida todo. Si quieres lanzar algo que realmente parezca inteligente, hazlo con lógica, no con parcheos.

    Si quieres la checklist descargable, un prompt extractor listo para copiar/pegar y un mini-plan de 30 días para implementar esto en tu stack, respóndeme “QUIERO MEMORIA” y te lo mando. Esto no acaba aquí — y si no empiezas hoy, otro equipo lo hará.

    Como continuación lógica para quienes trabajan en automatización, agentes y workflows, puedes encontrar recursos y experimentos en Dominicode Labs.

    FAQ

    Respuesta: ¿Qué diferencia hay entre memoria a corto y a largo plazo?

    La memoria a corto plazo contiene los últimos N mensajes del hilo y sirve para referencias inmediatas. La memoria a largo plazo almacena hechos estructurados (preferencias, roles, acciones realizadas) que deben persistir y consultarse por el agente cuando sea relevante.

    Respuesta: ¿Por qué no guardar el chat completo?

    Guardar el chat crudo aumenta costes (tokens), latencia y ruido. Es mejor extraer hechos útiles y estructurarlos para lecturas rápidas y deterministas.

    Respuesta: ¿Qué es un extractor y qué formato debe devolver?

    Un extractor es un LLM barato y rápido que lee el hilo o su resumen y devuelve operaciones en JSON forzado, por ejemplo {op: “UPSERT”, key: “…”, value: “…”, reason: “…”}. La salida debe validarse con un schema validator.

    Respuesta: ¿Cuándo usar extracción síncrona en lugar de asíncrona?

    Usa extracción síncrona para operaciones críticas que dependen inmediatamente de la memoria (ej. ejecutar pagos). Por defecto, asíncrono para mejor UX y menor latencia, con checkpoints síncronos donde haga falta.

    Respuesta: ¿Cómo mitigo race conditions en actualizaciones de memoria?

    Patrones efectivos: versionado por evento (version_id), locks optimistas (comparar timestamps), event sourcing ligero y, si necesitas garantías fuertes, transacciones y bloqueo por llave en Postgres.

    Respuesta: ¿Qué métricas debo monitorizar?

    Métricas clave sugeridas: TTFT, tiempo de extracción, tasa de conflictos y porcentaje de respuestas incoherentes relacionadas con memoria. Además, loggear inputs, salidas JSON y ops aplicadas para trazabilidad.

    Respuesta: ¿Qué precauciones de privacidad aplicar?

    Nunca almacenar datos sensibles sin cifrado y consentimiento. Tokenizar o anonimizar cuando sea posible, controlar accesos y definir políticas de retención claras.

  • Cómo los Cloud Agents transforman la automatización del software

    Cómo los Cloud Agents transforman la automatización del software

    “When we started building Cursor a few years ago, most code was written one keystroke at a time”: La evolución a Cloud Agents

    Tiempo estimado de lectura: 5 min

    • La producción de software está pasando de autocompletados locales a flotas de agentes en la nube, lo que exige repensar pipelines, CI/CD y gobernanza.
    • Reemplaza diffs extensos por artefactos verificables (logs estructurados, grabaciones de pruebas, previews desplegados) para revisar resultados de agentes.
    • Patrón de trabajo para Tech Leads: problema claro, herramientas, VMs aisladas, métricas y revisión de artefactos.
    • Riesgos críticos: flaky tests, privilegios, coste y observabilidad; requieren inversión en determinismo, least-privilege y trazabilidad.
    • Empieza con tareas confinadas que tengan tests automatizados para obtener ROI medible.

    Introducción

    “When we started building Cursor a few years ago, most code was written one keystroke at a time”. Esa frase aparece en las primeras líneas porque resume el punto de inflexión: del autocompletado puntual a la orquestación de agentes en la nube. Para equipos técnicos, la pregunta ya no es si los agentes serán relevantes, sino cómo rediseñar pipelines, CI/CD y gobernanza para que las flotas de agentes produzcan software fiable y mantenible.

    Resumen rápido (lectores con prisa)

    Cloud Agents son agentes que ejecutan trabajos largos y autónomos en VMs en la nube. Úsalos cuando tienes CI/CD estable y tests fiables; importan porque permiten paralelizar y automatizar tareas a escala. Funcionan produciendo artefactos verificables (logs JSON, grabaciones de pruebas, previews desplegados) que los humanos revisan en lugar de inspeccionar cada línea.

    “When we started building Cursor a few years ago, most code was written one keystroke at a time” — tres eras y sus implicaciones técnicas

    1) Era Tab — autocompletado local

    Tab y autocompletados similares automatizaron trabajo repetitivo: imports, snippets, patrones boilerplate. Ventaja: latencia nula y control humano total. Limitación: incapacidad para juicio y contexto extendido.

    2) Era de agentes síncronos — prompt-and-response

    Modelos más capaces permitieron agentes que mantienen contexto y usan herramientas en secuencia. El desarrollador sigue en el bucle, supervisando cada paso. Beneficio: mayores tareas automatizables (refactorings, debugging multiarchivo). Problema: consumo de recursos locales y atención humana constante, lo que limita la paralelización.

    3) Era Cloud Agents — ejecución asíncrona y autónoma

    Ahora entramos en la era donde los agentes corren en VMs dedicadas en la nube, trabajan durante horas, iteran, ejecutan pruebas y entregan artefactos revisables (logs, videos de pruebas, previews). El desarrollador deja de “teclear” para diseñar y gobernar la fábrica que produce software.

    Arquitectura práctica: de diffs a artefactos (qué cambiar en tu stack)

    Revisar diffs pierde sentido cuando un agente genera miles de líneas. En su lugar, los artefactos éstandarizados son la unidad de revisión:

    • Logs estructurados (JSON con traces, métricas, cobertura).
    • Grabaciones o snapshots de pruebas E2E.
    • Previews desplegados en entornos efímeros con URLs accesibles.

    Diseña tu pipeline para producir esos artefactos automáticamente: el agente debe terminar con un paquete que contenga build, test-report, y endpoint de preview. Orquestadores como n8n facilitan la integración entre triggers, ejecución de agentes y recolección de artefactos.

    Patrón de trabajo recomendado para Tech Leads

    • 1. Define el problema y criterios de aceptación (no prompts vagos).
    • 2. Provee herramientas: repositorio, tokens con scopes limitados, staging determinista, y datos de prueba.
    • 3. Despliega agentes en VMs aisladas con acceso controlado.
    • 4. Recolecta artefactos y métricas automáticas de calidad (test coverage, lint score, performance baselines).
    • 5. Revisa artefactos y da feedback estructurado; reitera a nuevos runs si aplica.

    Este patrón transforma al humano en arquitecto del proceso y evaluador del comportamiento, no inspector de cada línea de código.

    Riesgos críticos al escalar flotas de agentes

    • Flaky tests y no-determinismo: lo que un desarrollador soluciona en minutos puede paralizar cientos de ejecuciones. Solución: invertir en tests deterministas, sandboxing y pre-indexado de dependencias.
    • Seguridad y privilegios: agentes necesitan acceso (repos, staging, servicios). Aplica principios de least privilege, rotación de tokens y entornos staging aislados.
    • Coste y latencia: vectoriza qué procesar en la nube. Preprocesado off-line y compresión de artefactos mitigan gasto y reducen tiempos de respuesta.
    • Observabilidad: sin trazabilidad fina, fallos de agente se vuelven cajas negras. Instrumenta cada run con métricas, logs y checkpoints claros.

    Casos de uso iniciales con ROI claro

    • Refactorizaciones repetitivas en código legacy donde reglas de transformación son estables.
    • Migraciones de dependencias donde tests y builds están automatizados.
    • Generación de PRs para scaffolding y plantillas con pruebas mínimas ya verificadas.

    Empieza con tareas confinadas; mide tiempo total (setup + run + review) versus esfuerzo humano reemplazado.

    Criterio para decidir adopción

    Adopta Cloud Agents si:

    • Tienes pipelines CI/CD estables y tests confiables.
    • Puedes automatizar la evaluación mediante artefactos objetivos.
    • El coste de setup y gobernanza se amortiza con paralelismo y tiempo liberado.

    Evítalos cuando:

    • El entorno de staging es frágil o las pruebas son intermitentes.
    • El conocimiento crítico reside en «contexto tribal» no documentado.
    • Las políticas de seguridad impiden conceder accesos controlados a VMs externas.

    Conclusión

    La frase inicial —”When we started building Cursor a few years ago, most code was written one keystroke at a time”— no es nostalgia: es punto de partida. El valor real hoy está en construir la fábrica que permite que agentes trabajen como compañeros: bien orquestados, auditables y seguros. La transición exige inversión en pruebas deterministas, gobernanza de accesos y artefactos que permitan revisar comportamiento en lugar de código línea por línea. Si lo haces bien, pasarás de acelerar tareas repetitivas a escalar la producción de software con flotas autónomas.

    Dominicode Labs

    Para quien explora integración de agentes, workflows y automatización en equipos técnicos, puede ser útil revisar recursos adicionales en Dominicode Labs. Es una continuación lógica para experimentar con orquestación, artefactos y gobernanza en entornos controlados.

    FAQ

    ¿Qué es un Cloud Agent?

    Un Cloud Agent es un agente de software que ejecuta tareas de forma asíncrona y autónoma en VMs o entornos en la nube, con capacidad para iterar durante largos periodos y producir artefactos verificables (logs, pruebas, previews).

    ¿Cuándo debería usarlos?

    Úsalos cuando tus pipelines CI/CD son estables, cuentas con tests fiables y puedes automatizar la evaluación por artefactos objetivos. Evítalos si el staging es frágil o el contexto crítico no está documentado.

    ¿Qué artefactos deben producir los agentes?

    Artefactos estandarizados como logs estructurados en JSON (traces, métricas, cobertura), grabaciones o snapshots de pruebas E2E y previews desplegados con URLs accesibles.

    ¿Cómo mitigo flaky tests?

    Invierte en tests deterministas, sandboxing, pre-indexado de dependencias y aislar variables externas en entornos staging para reducir no-determinismo.

    ¿Qué requisitos de seguridad son críticos?

    Aplica principios de least privilege, usa tokens con scopes limitados, rota credenciales y ejecuta agentes en VMs aisladas con accesos controlados a repos y servicios.

    ¿Cuál es el primer caso de uso recomendado?

    Comienza con tareas confinadas y repetitivas que tengan reglas estables y tests automatizados, como refactorizaciones en código legacy o migraciones de dependencias con cobertura de pruebas.

  • Cómo implementar un Event Bus para arquitecturas con agentes descentralizados

    Cómo implementar un Event Bus para arquitecturas con agentes descentralizados

    ¿Y si tu app dejara de ser un monstruo monolítico con un único “asistente” y se convirtiera en un enjambre de agentes que se pasan la pelota sin romper nada?

    Tiempo estimado de lectura: 6 min

    • Reducir contexto inútil en prompts, aislar fallos y permitir equipos autónomos sin perder UX coherente.
    • Descentraliza la responsabilidad cognitiva; centraliza seguridad, auditoría y orden.
    • Usa un Event Bus global con contratos claros y BFFs que versionen prompts y auditen inferencias.
    • Mide confidence, delegaciones y latencia; trata prompts como código.

    Poca gente lo dice así: dividir la inteligencia en agentes especializados no es exotismo. Es economía de tokens, menos alucinaciones y menos puntos únicos de falla. Y sí: también es más trabajo. Pero si tu producto escala, vale cada minuto invertido.

    Resumen rápido (lectores con prisa)

    Qué es: Un patrón para dividir inteligencia en agentes por dominio y comunicarlos vía un Event Bus global.

    Cuándo usarlo: Cuando la complejidad de dominios y volumen hacen ineficiente un único asistente monolítico.

    Por qué importa: Reduce tokens, mitiga alucinaciones y falla de forma aislada; facilita equipos autónomos.

    Cómo funciona (resumen): Host publica USER_INPUT al bus; agentes calculan confidence; el agente ganador responde y puede delegar sub-problemas a otros agentes vía eventos.

    Introducción

    Te doy el patrón completo. Arquitectura, contratos de evento, anti-patrones, seguridad y el pacto UX que nadie firma hasta que explota.

    Qué estamos resolviendo (en claro)

    Puntos

    • Reducir contexto inútil en prompts.
    • Aislar fallos por dominio.
    • Permitir equipos autónomos (cada uno con su BFF y su agente).
    • Mantener una UX coherente pese a la descentralización.

    Principio arquitectónico imprescindible

    Descentraliza la responsabilidad cognitiva. Centraliza la infraestructura técnica que garantiza seguridad, auditoría y orden. Traducción: agentes por dominio + un Event Bus global para hablarse.

    Componentes esenciales (resumen)

    Host / Shell

    Monta el Event Bus y el UI unificado. No ejecuta prompts.

    Micro-frontends (Remotes)

    UI + agnostic agent client.

    BFF por dominio

    Ejecuta inferencia, almacena prompts versionados, audita.

    Event Bus Global

    Canal estándar para intentos y delegaciones.

    Orquestación concreta

    Coreografía por defecto; orquestador solo si necesitas transacciones distribuidas.

    El contrato del evento (no lo negocies)

    Si no tienes un schema, tendrás ruido. Exige este JSON mínimo:

    {
      "id": "uuid",
      "source": "inventory-agent",
      "intent": "REQUIRE_BILLING_CHECK",
      "context": { "userId": "123", "orderId": "405" },
      "confidence": 0.87,
      "metadata": { "traceId": "abc", "locale":"es-ES" },
      "timestamp": 1700000000
    }
    

    Reglas rápidas

    • confidence < 0.6 => requiere confirmación humana o UI consent.
    • context debe llevar solo IDs y flags. No historial de chat completo.
    • metadata incluye traceId para rastrear en las trazas distribuidas.

    Cómo se mueven los eventos (flujo)

    1. Usuario pregunta algo en el host.
    2. Host publica evento USER_INPUT al bus.
    3. Agentes suscritos calculan su confidence local.
    4. El agente ganador responde y/o emite delegaciones (events) sobre sub-problemas.
    5. Si hay delegación, otros agentes reaccionan y devuelven resoluciones.
    6. Host compone respuestas y muestra coherencia al usuario.

    Ejemplo práctico (en vivo)

    Usuario: “¿Por qué no ha salido el pedido #405? ¿Falló mi tarjeta?”

    • Inventory-agent: detecta pedido retenido → responde estado del envío → emite REQUIRE_BILLING_CHECK.
    • Billing-agent: suscribe y consulta pasarela en su BFF → descubre tarjeta vencida → emite BILLING_ISSUE_FOUND.
    • Host: recibe ambas respuestas y muestra un flujo: “Pedido retenido. Tarjeta expirada. ¿Actualizar ahora?”

    Cómo implementar el Event Bus (dos opciones)

    Opción A — RXJS (más control dentro de Angular)

    // event-bus.service.ts
    import { Subject } from 'rxjs';
    export const globalEventBus = new Subject();
    // publish: globalEventBus.next(event)
    // subscribe: globalEventBus.subscribe(e => ...)
    

    Opción B — CustomEvent (mejor para micro-frontends aislados)

    // emit
    window.dispatchEvent(new CustomEvent('app:event', { detail: event }));
    // listen
    window.addEventListener('app:event', e => handle(e.detail));
    

    Anti-patterns del bus (evítalos)

    • Enviar cada pensamiento del LLM. Solo conclusiones.
    • Compartir historial completo en context.
    • Permitir que cualquier módulo escuche todo sin roles.
    • Esperar sincronía absoluta entre agentes.

    Mecanismo de arbitraje: quién responde primero

    Necesitas un árbitro débil. No un maestro, sino una regla simple:

    1. Cada agente publica su confidence ante USER_INPUT.
    2. Host espera X ms (ej. 200–400ms) o hasta el primer confidence >= threshold.
    3. El agente ganador toma la palabra; los demás quedan “en espera” para delegaciones.

    Seguridad y datos: no es opcional, es ley

    • No inferes en cliente. Nunca. Las keys quedan en los BFF.
    • Filtrado por roles en el Event Bus: cada agente tiene claims y scopes.
    • Sanitización en BFF: elimina PII innecesaria antes de enviar a LLM.
    • Audit log centralizado: guarda hash de mensajes, no el texto completo salvo consentimiento.
    • Rate limiting por agente y por usuario.

    Prompts y versionado: trátalos como código

    Versiona prompts. Haz CI sobre prompts. Un cambio de prompt puede cambiar comportamiento entero. Guarda el promptId en metadata del evento para reproducibilidad.

    Observabilidad: métricas mínimas que necesitas YA

    • Latencia total por intent (ms).
    • Confidence distribution por agente.
    • Delegation rate (cuántas veces un agente pide otro agente).
    • Fallas y errores por BFF.
    • Casos humanos de override (undo/confirm).

    Costes y escalado

    Agentes especializados consumen menos tokens por prompt. Pero multiplicas llamadas si no cacheas. Cachea respuestas frecuentes en BFF. Si el dominio es alto volumen, considera modelos on-prem o inferencia en región cercana.

    UX: cómo evitar que la UX parezca multi-agente

    • Unifica la voz: host normaliza tono y formato.
    • Muestra trazabilidad solo si el usuario la pide (ej. “ver detalle técnico”).
    • Siempre provee undo para acciones críticas.
    • Si confidence baja, pide confirmación editable: muestra la transcripción + intención sugerida.

    Sincronización del historial

    Historial maestro en Host. Los BFFs pueden guardar copias locales por dominio. Para reproducir una conversación: traceId + promptId + promptVersion + snapshot del context.

    Tests y despliegue

    • Contract tests para el Event Schema.
    • E2E con agentes stubs (simula respuestas con confidence).
    • Canary deploy de prompts: prueba nuevos prompts con 1% de tráfico antes de publicar.

    Cuando usar orquestador en vez de coreografía

    Coreografía = menos acoplamiento. Pero si necesitas transacciones distribuidas (ej. reserva + pago atómico), añade un orquestador o un workflow engine (Temporal, Durable Functions). No lo hagas por conveniencia.

    Checklist práctico para arrancar en 2 semanas

    • [ ] Definir dominios y agentes.
    • [ ] Diseñar Event Schema y contract tests.
    • [ ] Implementar Bus (CustomEvent + roles).
    • [ ] BFFs mínimos con secreto seguro y prompt versionado.
    • [ ] UI host de chat, arbiter de confidence y UX confirmaciones.
    • [ ] Observability (traces + metrics).
    • [ ] Políticas de privacidad y retención.

    Cierre directo: lo que debes hacer hoy

    No diseñes agentes porque “está de moda”. Distribuye inteligencia solo donde tenga sentido. Empieza por 2 agentes: uno crítico (ej. facturación) y otro de baja prioridad (ej. FAQ). Lanza el Event Bus y valida la coreografía. Mide confidence y delegations la primera semana. Ajusta prompts con datos reales.

    ¿Quieres el kit para arrancar? Te puedo pasar:

    • Event Bus + arbiter en TypeScript.
    • BFF skeleton que llama a LLM y valida JSON.
    • Prompts versionados y tests de contrato.

    Responde “QUIERO EL KIT” y te lo envío listo para pegar en tu repo.

    Esto no acaba aquí. Si lo haces bien, tu app dejará de ser un oráculo confuso y empezará a funcionar como un equipo de especialistas que no se pisan el uno al otro. ¿Empezamos por el Event Bus o por el BFF? Responde “BUS” o “BFF”.

    Dominicode Labs

    Si quieres recursos prácticos y plantillas para implementar este patrón, revisa Dominicode Labs. Encontrarás ejemplos de Event Bus, skeletons de BFF y tests de contrato que aceleran la puesta en marcha.

    FAQ

    ¿Por qué dividir en agentes en vez de un asistente monolítico?

    Dividir reduce contexto inútil en prompts, aisla fallos por dominio y permite equipos autónomos con BFFs propios. Es coste de ingeniería que compensa cuando el producto escala.

    ¿Qué contiene el contrato mínimo de un evento?

    El JSON mínimo incluye id, source, intent, context (solo IDs/flags), confidence, metadata (traceId, locale) y timestamp. Sin schema tendrás ruido.

    ¿Cómo evito que la UX se perciba como multi-agente?

    Unifica la voz desde el Host, muestra trazabilidad solo si el usuario la solicita y siempre ofrece undo para acciones críticas. Normaliza tono y formato antes de mostrar respuestas.

    ¿Cuándo necesito un orquestador en lugar de coreografía?

    Cuando necesitas transacciones distribuidas atómicas (ej. reserva + pago). Para casos simples, coreografía reduce acoplamiento; usa orquestador solo para transacciones complejas.

    ¿Dónde deben residir las claves y la inferencia?

    Nunca en el cliente. Las keys y la inferencia deben vivir en los BFFs o infraestructura backend segura. El cliente solo publica eventos y muestra resultados.

    ¿Qué métricas son imprescindibles al arrancar?

    Latencia por intent, distribución de confidence por agente, delegation rate, fallas por BFF y casos humanos de override.