system-prompts-and-models-o.../salesflow-saas/backend/app/services/agents/router.py
Sami Assiri ebfab72fbd feat: complete Sovereign Growth & M&A capability — add 7 Advanced Strategic Agents
- Added 7 new apex-level agents (Sovereign Intelligence, Alliance Structuring, Due Diligence, Valuation, Exec Negotiator, Strategic PMO, Post-Merger Integration)
- Updated RAW Event Taxonomy in router to fully support HitL escalations, C-Suite reporting, and sovereign dashboards
- Re-architected Executor to support all 37 agents (mappings, tokens up to 8000 for apex, action triggers)
- Health check endpoints updated to validate the 37-agent ecosystem
- All tests passing

System is now fully aligned with the Dealix Autonomous Revenue & Strategic Growth OS execution plan.
2026-04-16 06:57:38 +03:00

704 lines
29 KiB
Python

"""
Agent Router v2.0 — Determines which AI agent handles which event.
The central nervous system of Dealix's AI engine.
Features:
- Priority-based agent ordering
- Parallel vs sequential execution modes
- Retry policies per agent
- Agent metadata (model preference, temperature, timeout)
"""
import logging
from typing import Optional
from dataclasses import dataclass, field
from enum import Enum
logger = logging.getLogger("dealix.agents")
class ExecutionMode(str, Enum):
SEQUENTIAL = "sequential" # Agents run one after another
PARALLEL = "parallel" # Agents run simultaneously
PIPELINE = "pipeline" # Output of one feeds into the next
@dataclass
class RetryPolicy:
max_retries: int = 2
backoff_seconds: float = 1.0
backoff_multiplier: float = 2.0 # Exponential backoff
@dataclass
class AgentConfig:
"""Configuration for a single agent in an event mapping."""
agent_id: str
priority: int = 1 # Lower = higher priority (1 runs first)
required: bool = True # If True, failure stops the chain
timeout_seconds: int = 30 # Max execution time
model_preference: str = "" # Override LLM model (e.g., "groq_fast")
retry_policy: RetryPolicy = field(default_factory=RetryPolicy)
@dataclass
class EventConfig:
"""Configuration for an event type."""
agents: list[AgentConfig]
execution_mode: ExecutionMode = ExecutionMode.SEQUENTIAL
description: str = ""
# ── Event → Agent Mapping (v2.0 with priority & config) ──────
AGENT_REGISTRY: dict[str, EventConfig] = {
# ── Lead Lifecycle ───────────────────────────────
"lead_created": EventConfig(
agents=[
AgentConfig("lead_qualification", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="New lead enters the system — qualify immediately",
),
"lead_score_updated": EventConfig(
agents=[
AgentConfig("lead_qualification", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Lead score changed — re-evaluate qualification",
),
"lead_qualified": EventConfig(
agents=[
AgentConfig("outreach_writer", priority=1, required=True),
AgentConfig("meeting_booking", priority=2, required=False),
AgentConfig("closer_agent", priority=3, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Lead qualified — start outreach sequence",
),
# ── Communication ────────────────────────────────
"whatsapp_inbound": EventConfig(
agents=[
AgentConfig("arabic_whatsapp", priority=1, required=True, timeout_seconds=15),
AgentConfig("closer_agent", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Incoming WhatsApp message — respond in Arabic",
),
"whatsapp_outbound": EventConfig(
agents=[
AgentConfig("outreach_writer", priority=1, required=True),
AgentConfig("compliance_reviewer", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Outgoing WhatsApp — write + compliance check",
),
"email_inbound": EventConfig(
agents=[
AgentConfig("english_conversation", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Incoming email — handle in English",
),
"email_outbound": EventConfig(
agents=[
AgentConfig("outreach_writer", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Outgoing email — craft professional message",
),
"voice_call_completed": EventConfig(
agents=[
AgentConfig("voice_call", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Voice call ended — analyze and log",
),
# ── Meeting Lifecycle ────────────────────────────
"meeting_requested": EventConfig(
agents=[
AgentConfig("meeting_booking", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Meeting requested — find best slot",
),
"meeting_confirmed": EventConfig(
agents=[
AgentConfig("ai_rehearsal", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Meeting confirmed — prepare briefing",
),
"meeting_upcoming": EventConfig(
agents=[
AgentConfig("ai_rehearsal", priority=1, required=True),
AgentConfig("knowledge_retrieval", priority=2, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="Meeting in 24h — final preparation",
),
# ── Deal Lifecycle ───────────────────────────────
"deal_created": EventConfig(
agents=[
AgentConfig("sector_strategist", priority=1, required=True),
AgentConfig("knowledge_retrieval", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="New deal — sector analysis + knowledge lookup",
),
"deal_stage_changed": EventConfig(
agents=[
AgentConfig("proposal_drafter", priority=1, required=False),
AgentConfig("management_summary", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Deal progression — update proposal if needed",
),
"deal_proposal_requested": EventConfig(
agents=[
AgentConfig("proposal_drafter", priority=1, required=True, timeout_seconds=60),
AgentConfig("compliance_reviewer", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Proposal requested — draft + compliance review",
),
# ── Quality & Compliance ─────────────────────────
"content_review": EventConfig(
agents=[
AgentConfig("qa_reviewer", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Content needs QA review",
),
"compliance_check": EventConfig(
agents=[
AgentConfig("compliance_reviewer", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Compliance verification required",
),
"objection_detected": EventConfig(
agents=[
AgentConfig("objection_handler", priority=1, required=True),
AgentConfig("closer_agent", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Client objection detected — handle + attempt close",
),
# ── Affiliate Lifecycle ──────────────────────────
"affiliate_applied": EventConfig(
agents=[
AgentConfig("affiliate_evaluator", priority=1, required=True),
AgentConfig("fraud_reviewer", priority=1, required=True),
],
execution_mode=ExecutionMode.PARALLEL,
description="New affiliate application — evaluate + fraud check simultaneously",
),
"affiliate_approved": EventConfig(
agents=[
AgentConfig("onboarding_coach", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Affiliate approved — start onboarding",
),
# ── Analytics ────────────────────────────────────
"revenue_attribution": EventConfig(
agents=[
AgentConfig("revenue_attribution", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Revenue needs attribution analysis",
),
"fraud_check": EventConfig(
agents=[
AgentConfig("fraud_reviewer", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Fraud check triggered",
),
"guarantee_claim": EventConfig(
agents=[
AgentConfig("guarantee_reviewer", priority=1, required=True),
AgentConfig("fraud_reviewer", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Guarantee claim — review then fraud check",
),
"management_report": EventConfig(
agents=[
AgentConfig("management_summary", priority=1, required=True, timeout_seconds=60),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Generate management report",
),
# ── Knowledge ────────────────────────────────────
"knowledge_query": EventConfig(
agents=[
AgentConfig("knowledge_retrieval", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Knowledge base query",
),
"sector_strategy": EventConfig(
agents=[
AgentConfig("sector_strategist", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Sector strategy analysis",
),
# ── Autonomous Pipeline Events ───────────────────
"pipeline_lead_new": EventConfig(
agents=[
AgentConfig("lead_qualification", priority=1, required=True),
AgentConfig("knowledge_retrieval", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="Autonomous: new lead → qualify + gather knowledge",
),
"pipeline_lead_qualified": EventConfig(
agents=[
AgentConfig("outreach_writer", priority=1, required=True),
AgentConfig("sector_strategist", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="Autonomous: qualified → outreach + strategy",
),
"pipeline_meeting_prep": EventConfig(
agents=[
AgentConfig("ai_rehearsal", priority=1, required=True),
AgentConfig("proposal_drafter", priority=1, required=False),
AgentConfig("knowledge_retrieval", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="Autonomous: pre-meeting full preparation",
),
"pipeline_closing": EventConfig(
agents=[
AgentConfig("closer_agent", priority=1, required=True),
AgentConfig("compliance_reviewer", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Autonomous: closing stage → close + compliance",
),
# ══════════════════════════════════════════════════
# ── Strategic Growth & Enterprise Agents ─────────
# ══════════════════════════════════════════════════
# ── Partnerships ─────────────────────────────────
"partnership_opportunity": EventConfig(
agents=[
AgentConfig("partnership_scout", priority=1, required=True, timeout_seconds=60),
AgentConfig("competitive_intel", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="New partnership opportunity detected — scout + competitive analysis",
),
"partnership_proposal_requested": EventConfig(
agents=[
AgentConfig("partnership_scout", priority=1, required=True, timeout_seconds=60),
AgentConfig("contract_lifecycle", priority=2, required=True),
AgentConfig("compliance_reviewer", priority=3, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Partnership proposal needed — scout → contract → compliance",
),
# ── M&A & Strategic Growth ───────────────────────
"acquisition_target_identified": EventConfig(
agents=[
AgentConfig("ma_growth", priority=1, required=True, timeout_seconds=120),
AgentConfig("competitive_intel", priority=1, required=False),
AgentConfig("finance_automation", priority=2, required=True),
],
execution_mode=ExecutionMode.PARALLEL,
description="M&A target found — valuation + competitive + financial analysis",
),
"growth_strategy_requested": EventConfig(
agents=[
AgentConfig("business_development", priority=1, required=True, timeout_seconds=90),
AgentConfig("ma_growth", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Strategic growth analysis — BizDev → M&A options",
),
# ── Contracts ────────────────────────────────────
"contract_creation_requested": EventConfig(
agents=[
AgentConfig("contract_lifecycle", priority=1, required=True, timeout_seconds=60),
AgentConfig("compliance_reviewer", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Contract needed — draft + compliance review",
),
"contract_review_requested": EventConfig(
agents=[
AgentConfig("contract_lifecycle", priority=1, required=True),
AgentConfig("fraud_reviewer", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Incoming contract — review risks + fraud check",
),
"contract_expiring_soon": EventConfig(
agents=[
AgentConfig("contract_lifecycle", priority=1, required=True),
AgentConfig("customer_success", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Contract expiring — renewal + customer health check",
),
# ── Business Development ─────────────────────────
"market_expansion_requested": EventConfig(
agents=[
AgentConfig("business_development", priority=1, required=True, timeout_seconds=90),
AgentConfig("sector_strategist", priority=1, required=False),
AgentConfig("competitive_intel", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="Market expansion — BizDev + sector + competitive intel",
),
"new_revenue_stream_analysis": EventConfig(
agents=[
AgentConfig("business_development", priority=1, required=True),
AgentConfig("dynamic_pricing", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="New revenue stream — BizDev analysis + pricing strategy",
),
# ── Supply Chain & Procurement ───────────────────
"procurement_rfq": EventConfig(
agents=[
AgentConfig("supply_chain", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="RFQ received — evaluate suppliers and pricing",
),
"supplier_evaluation": EventConfig(
agents=[
AgentConfig("supply_chain", priority=1, required=True),
AgentConfig("fraud_reviewer", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Evaluate supplier — quality + fraud check",
),
"inventory_alert": EventConfig(
agents=[
AgentConfig("supply_chain", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Inventory low — reorder analysis",
),
# ── Customer Success & Retention ─────────────────
"customer_health_check": EventConfig(
agents=[
AgentConfig("customer_success", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Customer health check — churn risk + upsell opportunities",
),
"customer_complaint": EventConfig(
agents=[
AgentConfig("customer_success", priority=1, required=True),
AgentConfig("compliance_reviewer", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Customer complaint — resolve + compliance check",
),
"upsell_opportunity_detected": EventConfig(
agents=[
AgentConfig("customer_success", priority=1, required=True),
AgentConfig("dynamic_pricing", priority=2, required=False),
AgentConfig("outreach_writer", priority=3, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Upsell opportunity — CS assessment + pricing + outreach",
),
"quarterly_business_review": EventConfig(
agents=[
AgentConfig("customer_success", priority=1, required=True, timeout_seconds=60),
AgentConfig("revenue_attribution", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="QBR preparation — customer success + revenue analysis",
),
# ── Dynamic Pricing ──────────────────────────────
"pricing_review_requested": EventConfig(
agents=[
AgentConfig("dynamic_pricing", priority=1, required=True),
AgentConfig("competitive_intel", priority=1, required=False),
],
execution_mode=ExecutionMode.PARALLEL,
description="Pricing review — dynamic pricing + competitive analysis",
),
"discount_approval_requested": EventConfig(
agents=[
AgentConfig("dynamic_pricing", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Discount requested — profitability check",
),
# ── Marketing Automation ─────────────────────────
"campaign_creation_requested": EventConfig(
agents=[
AgentConfig("marketing_automation", priority=1, required=True, timeout_seconds=60),
AgentConfig("compliance_reviewer", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Marketing campaign — create + compliance review",
),
"lead_nurture_triggered": EventConfig(
agents=[
AgentConfig("marketing_automation", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Lead nurture — drip campaign automation",
),
"retargeting_triggered": EventConfig(
agents=[
AgentConfig("marketing_automation", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Retargeting — re-engage inactive leads",
),
# ── Finance Automation ───────────────────────────
"invoice_generation": EventConfig(
agents=[
AgentConfig("finance_automation", priority=1, required=True),
AgentConfig("compliance_reviewer", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Invoice creation — ZATCA compliant + compliance",
),
"collection_overdue": EventConfig(
agents=[
AgentConfig("finance_automation", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Overdue payment — automated collection workflow",
),
"financial_report_requested": EventConfig(
agents=[
AgentConfig("finance_automation", priority=1, required=True, timeout_seconds=60),
AgentConfig("management_summary", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Financial report — finance + management summary",
),
"cashflow_forecast_requested": EventConfig(
agents=[
AgentConfig("finance_automation", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Cash flow forecast — predict inflows/outflows",
),
# ── Competitive Intelligence ─────────────────────
"competitor_alert": EventConfig(
agents=[
AgentConfig("competitive_intel", priority=1, required=True),
AgentConfig("dynamic_pricing", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Competitor movement — intel + pricing response",
),
"battlecard_requested": EventConfig(
agents=[
AgentConfig("competitive_intel", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Battle card needed for sales team",
),
"win_loss_analysis": EventConfig(
agents=[
AgentConfig("competitive_intel", priority=1, required=True),
AgentConfig("management_summary", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Win/loss analysis — competitive intel + management reporting",
),
# ══════════════════════════════════════════════════
# ── Advanced Strategic & M&A Core (The 7 New Agents)
# ══════════════════════════════════════════════════
# ── Alliance Structuring ────────────────────────
"partnership.model_recommended": EventConfig(
agents=[
AgentConfig("alliance_structuring", priority=1, required=True, timeout_seconds=90),
AgentConfig("finance_automation", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Structure alliance mode (Rev-share/JV) and calculate financial impact",
),
"partnership.term_sheet_ready": EventConfig(
agents=[
AgentConfig("alliance_structuring", priority=1, required=True),
AgentConfig("contract_lifecycle", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Generate Term Sheet from Alliance model",
),
# ── M&A Target Screening & DD ───────────────────
"ma.screening_completed": EventConfig(
agents=[
AgentConfig("due_diligence_analyst", priority=1, required=True, timeout_seconds=120),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Run initial comprehensive DD (Financial, Ops, Legal)",
),
"ma.valuation_ready": EventConfig(
agents=[
AgentConfig("valuation_synergy", priority=1, required=True, timeout_seconds=90),
AgentConfig("finance_automation", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Valuation execution + revenue/cost synergy analysis",
),
# ── Strategic Negotiation ────────────────────────
"ma.offer_strategy_ready": EventConfig(
agents=[
AgentConfig("executive_negotiator", priority=1, required=True, timeout_seconds=90),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Prepare executive negotiation playbook (BATNA, ZOPA, Scenarios)",
),
# ── Post-Merger Integration (PMI) ────────────────
"ma.integration_kickoff": EventConfig(
agents=[
AgentConfig("post_merger_integration", priority=1, required=True, timeout_seconds=120),
AgentConfig("strategic_pmo", priority=2, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Kickoff 30/60/90 days integration PMO & tracking",
),
# ── Execution PMO ──────────────────────────────
"growth.milestone_achieved": EventConfig(
agents=[
AgentConfig("strategic_pmo", priority=1, required=True),
AgentConfig("sovereign_intelligence", priority=2, required=False),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Track growth milestone and pass to sovereign intelligence",
),
"growth.execution_blocker_detected": EventConfig(
agents=[
AgentConfig("strategic_pmo", priority=1, required=True),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Handle strategic blocker, assign SLAs and owners",
),
# ── Sovereign Level ─────────────────────────────
"governance.executive_escalation": EventConfig(
agents=[
AgentConfig("sovereign_intelligence", priority=1, required=True, timeout_seconds=120),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="C-suite/Board level escalation and dashboarding",
),
"board_briefing_requested": EventConfig(
agents=[
AgentConfig("sovereign_intelligence", priority=1, required=True, timeout_seconds=120),
],
execution_mode=ExecutionMode.SEQUENTIAL,
description="Generate 360° Sovereign Board Briefing",
),
}
class AgentRouter:
"""Routes events to the appropriate AI agent(s) with priority and config."""
def get_event_config(self, event_type: str) -> Optional[EventConfig]:
"""Return the full event configuration."""
config = AGENT_REGISTRY.get(event_type)
if not config:
logger.warning(f"No agent registered for event: {event_type}")
return config
def get_agents_for_event(self, event_type: str) -> list[str]:
"""Return list of agent IDs sorted by priority."""
config = self.get_event_config(event_type)
if not config:
return []
sorted_agents = sorted(config.agents, key=lambda a: a.priority)
return [a.agent_id for a in sorted_agents]
def get_agents_config_for_event(self, event_type: str) -> list[AgentConfig]:
"""Return agent configs sorted by priority."""
config = self.get_event_config(event_type)
if not config:
return []
return sorted(config.agents, key=lambda a: a.priority)
def get_execution_mode(self, event_type: str) -> ExecutionMode:
"""Return execution mode for an event."""
config = self.get_event_config(event_type)
return config.execution_mode if config else ExecutionMode.SEQUENTIAL
def get_primary_agent(self, event_type: str) -> Optional[str]:
"""Return the primary (highest priority) agent for an event."""
agents = self.get_agents_for_event(event_type)
return agents[0] if agents else None
def list_all_agents(self) -> list[dict]:
"""List all registered agents with their event triggers."""
agent_events: dict[str, list[str]] = {}
for event, config in AGENT_REGISTRY.items():
for agent_cfg in config.agents:
if agent_cfg.agent_id not in agent_events:
agent_events[agent_cfg.agent_id] = []
agent_events[agent_cfg.agent_id].append(event)
return [
{"agent_id": agent_id, "events": events, "event_count": len(events)}
for agent_id, events in sorted(agent_events.items())
]
def list_all_events(self) -> list[dict]:
"""List all registered events with their agent configs."""
return [
{
"event_type": event_type,
"description": config.description,
"execution_mode": config.execution_mode.value,
"agents": [
{
"agent_id": a.agent_id,
"priority": a.priority,
"required": a.required,
"timeout_seconds": a.timeout_seconds,
}
for a in sorted(config.agents, key=lambda x: x.priority)
],
}
for event_type, config in sorted(AGENT_REGISTRY.items())
]
def get_agent_count(self) -> int:
"""Return total number of unique agents."""
agents = set()
for config in AGENT_REGISTRY.values():
for a in config.agents:
agents.add(a.agent_id)
return len(agents)