Enjambre de Agentes · LeadFlow Onboarding

Orquestación jerárquica — 5 agentes especializados · Pipeline automatizado de bienvenida a clientes
Topología: Jerárquica Estado: Ejecutando Stack: Python + Claude Opus-4 Retries max: 3 Quality gate: ≥ 0.75
4/5
Agentes OK
3m 42s
Tiempo total
0.91
Confianza avg
1
Retries
Topología del enjambre
⚙️
Orchestrator
Coordinador central · session_id: lf-2026-0892
🌐
WebScraper
Extracción web
✓ Done
🎯
ICPProfiler
Perfil ICP
✓ Done
📣
CampaignDesigner
Diseño campañas
▶ Running
🔍
QualityReviewer
Revisión calidad
· Waiting
📄
ReportGenerator
Informe final
· Waiting
Pipeline de ejecución
1
WebScraperAgent 0:00 → 0:48 · 48s
Extraídas 34 páginas de techsolve.io · sector SaaS B2B identificado · confianza 0.94
2
ICPProfilerAgent 0:48 → 1:31 · 43s
ICP construido: PME de Servicios Financieros, 50-200 emp. · 1 retry por baja confianza inicial (0.62 → 0.87)
3
CampaignDesignerAgent 1:31 → ahora · 2m 11s ⟳
Generando 3 configuraciones de campaña inicial basadas en ICP y sector detectado…
4
QualityReviewerAgent pendiente
Revisará coherencia de outputs · umbral de aprobación ≥ 0.75
5
ReportGeneratorAgent pendiente
Sintetizará todo en informe PDF-ready personalizado para TechSolve SL
Memoria compartida · Redis session lf-2026-0892
WebScraper sector=SaaS B2B · audiencia=Directores Financieros PyME · propuesta="automatización de cobros recurrentes" 0.94
WebScraper tech_stack=[Stripe, Salesforce, HubSpot] · competidores_mencionados=[Billin, Sage] · presencia_blog=true 0.91
ICPProfiler ICP.empresa_size=50-200 · ICP.sector=Servicios Financieros · ICP.dolor_clave="ciclos de cobro lentos, churn involuntario" 0.87
ICPProfiler ICP.cargo_decisor=CFO / Finance Manager · ICP.ciclo_venta=30-60d · ICP.ticket_medio=12.000€/año 0.89
ICPProfiler DECISIÓN: evitar segmento Retail (baja LTV histórica) · priorizar Servicios Financieros + Legal 0.76
Quality Gates · estado por etapa
Datos web completos
Stage: scraping → ICP
Passed
Sin secretos en output
Stage: scraping → ICP
Passed
Confianza ICP ≥ 0.75
Stage: ICP → Campaign
0.87 ✓
Campos ICP obligatorios
Stage: ICP → Campaign
Passed
Campañas ≥ 3 opciones
Stage: Campaign → Review
Pending
Review depth suficiente
Stage: Review → Report
Pending
Informe sin placeholders
Stage: Report → Output
Pending
Score global ≥ 0.80
Stage: final
Pending
Código generado · orchestrator.py — LeadFlow Onboarding Swarm
# orchestrator.py — Enjambre jerárquico para onboarding LeadFlow
# Generado por skill: orquestacion-enjambre-agentes | session: lf-2026-0892

from dataclasses import dataclass, field
from enum import Enum
import asyncio, redis.asyncio as redis, json, logging

logger = logging.getLogger("leadflow.swarm")

class AgentRole(Enum):
    SCRAPER   = "web_scraper"
    PROFILER  = "icp_profiler"
    DESIGNER  = "campaign_designer"
    REVIEWER  = "quality_reviewer"
    REPORTER  = "report_generator"

@dataclass
class AgentTask:
    id: str
    role: AgentRole
    input_data: dict
    output_data: dict = field(default_factory=dict)
    status: str = "pending"
    retries: int = 0
    confidence: float = 0.0

class SharedMemory:
    def __init__(self, session_id: str):
        self.r = redis.from_url("redis://localhost:6379")
        self.key = f"swarm:{session_id}"

    async def set(self, field: str, value: dict):
        await self.r.hset(self.key, field, json.dumps(value))

    async def get(self, field: str) -> dict:
        raw = await self.r.hget(self.key, field)
        return json.loads(raw) if raw else {}

class QualityGate:
    def check(self, stage: str, output: dict) -> bool:
        if stage == "icp":
            return output.get("confidence", 0) >= 0.75 and "sector" in output
        if stage == "campaigns":
            return len(output.get("campaigns", [])) >= 3
        return True

class LeadFlowOrchestrator:
    """Coordina el pipeline jerárquico de onboarding para nuevos clientes."""

    def __init__(self, agents: dict, session_id: str):
        self.agents  = agents
        self.memory  = SharedMemory(session_id)
        self.gate    = QualityGate()
        self.tasks: list[AgentTask] = []

    async def run_onboarding(self, client_url: str) -> dict:
        # Stage 1: Scraping
        scrape = await self._run(AgentRole.SCRAPER, {"url": client_url})
        await self.memory.set("scrape", scrape)

        # Stage 2: ICP con quality gate y retry
        icp = await self._run_with_gate(AgentRole.PROFILER, {"scrape": scrape}, "icp")
        await self.memory.set("icp", icp)

        # Stage 3: Campañas en paralelo (3 variantes)
        ctx   = await self.memory.get("icp")
        camps = await self._run_with_gate(AgentRole.DESIGNER, {"icp": ctx}, "campaigns")
        await self.memory.set("campaigns", camps)

        # Stage 4: Revisión de calidad
        review = await self._run(AgentRole.REVIEWER, {
            "icp": icp, "campaigns": camps
        })

        # Stage 5: Informe final
        report = await self._run(AgentRole.REPORTER, {
            "scrape": scrape, "icp": icp,
            "campaigns": camps, "review": review
        })
        return {"status": "ok", "report": report}

    async def _run_with_gate(self, role, inp, stage, max_retries=3) -> dict:
        for attempt in range(max_retries):
            result = await self._run(role, inp)
            if self.gate.check(stage, result):
                return result
            logger.warning(f"Gate failed [{stage}] attempt {attempt+1} conf={result.get('confidence')}")
            inp["feedback"] = "Increase specificity and confidence score"
        raise RuntimeError(f"Quality gate [{stage}] no superado tras {max_retries} intentos")

    async def _run(self, role, inp) -> dict:
        agent = self.agents[role]
        task  = AgentTask(id=f"{role.value}_{len(self.tasks)}", role=role, input_data=inp)
        self.tasks.append(task)
        task.status = "running"
        logger.info(f"[HANDOFF] → {role.value} | task_id={task.id}", extra={"task": task.id})
        try:
            result = await agent.execute(inp)
            task.output_data, task.status = result, "completed"
            return result
        except Exception as e:
            task.status = "failed"
            logger.error(f"Agent {role.value} failed: {e}")
            raise
Output preview · Informe de bienvenida generado (simulado)
Bienvenida a LeadFlow · TechSolve SL
Informe personalizado generado por IA · 16 Jun 2026
Ideal Customer Profile detectado
Sector
Servicios Financieros
Tamaño empresa
50 – 200 empleados
Decisor principal
CFO / Finance Manager
Dolor clave
Ciclos de cobro lentos
Ticket medio
12.000 €/año
Ciclo de venta
30 – 60 días
Campañas recomendadas
1
Cold outreach CFOs · LinkedIn Ads
Segmento: CFO · Empresas 50-200 emp · España · Presupuesto sugerido: 1.500€/mes
92%
2
Secuencia email nurturing · Pain-led
7 emails · ciclo 21 días · trigger: descarga calculadora ROI · open rate est. 38%
88%
3
Retargeting Google Display · BOFU
Audiencia: visitantes /pricing · exclusión <30s · CPC est. 0.85€ · conv. 4.2%
81%
Log de handoffs (JSON estructurado)
TIMESTAMPEVENTOAGENTEESTADO
00:00:00 Pipeline iniciado · url=techsolve.io Orchestrator START
00:00:01 HANDOFF → web_scraper · task_id=scraper_0 WebScraper → RUN
00:00:48 web_scraper completado · páginas=34 · conf=0.94 WebScraper ✓ OK
00:00:49 HANDOFF → icp_profiler · task_id=profiler_1 ICPProfiler → RUN
00:01:02 Gate failed [icp] attempt 1 · conf=0.62 < 0.75 ICPProfiler ⚠ RETRY
00:01:31 icp_profiler retry 2 · conf=0.87 ✓ gate passed ICPProfiler ✓ OK
00:01:32 HANDOFF → campaign_designer · task_id=designer_2 CampaignDesigner → RUN
00:03:42 campaign_designer en curso… esperando respuesta LLM CampaignDesigner ⟳ NOW
CULTIVA IA · Skill: orquestacion-enjambre-agentes · Apache-2.0 · Ejemplo generado para LeadFlow SaaS · session lf-2026-0892 · 16 Jun 2026