diff --git a/agents/base/agent.py b/agents/base/agent.py index a417118..72603ec 100644 --- a/agents/base/agent.py +++ b/agents/base/agent.py @@ -3,6 +3,10 @@ Base Agent Class The foundation for all BlackRoad agents. Provides common functionality, error handling, logging, and execution framework. + +Integrations: +- LEITL Protocol: Multi-agent collaboration with live session management +- Cognition Framework: Access to Cece's reasoning and architecture capabilities """ import asyncio @@ -109,6 +113,11 @@ class BaseAgent(ABC): 'on_success': [] } + # LEITL Protocol integration (optional) + self._leitl_enabled: bool = False + self._leitl_session_id: Optional[str] = None + self._leitl_protocol = None # Will be set if LEITL is enabled + @abstractmethod async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]: """ @@ -171,6 +180,16 @@ class BaseAgent(ABC): f"(ID: {execution_id})" ) + # Broadcast task started via LEITL (if enabled) + await self._leitl_broadcast( + "task.started", + { + "task_id": execution_id, + "agent": self.metadata.name, + "description": str(params.get("input", ""))[:200] + } + ) + try: # Validate params if not self.validate_params(params): @@ -184,6 +203,10 @@ class BaseAgent(ABC): # Execute with retries self.status = AgentStatus.RUNNING + + # Send heartbeat + await self._leitl_heartbeat(f"Executing {self.metadata.name}") + result_data = await self._execute_with_retry(params) # Run success hooks @@ -204,6 +227,17 @@ class BaseAgent(ABC): f"(Duration: {duration:.2f}s)" ) + # Broadcast task completed via LEITL (if enabled) + await self._leitl_broadcast( + "task.completed", + { + "task_id": execution_id, + "agent": self.metadata.name, + "duration": duration, + "status": "success" + } + ) + return AgentResult( agent_name=self.metadata.name, execution_id=execution_id, @@ -225,6 +259,17 @@ class BaseAgent(ABC): # Run error hooks await self._run_hooks('on_error', {'error': str(e)}) + # Broadcast task failed via LEITL (if enabled) + await self._leitl_broadcast( + "task.failed", + { + "task_id": execution_id, + "agent": self.metadata.name, + "error": str(e), + "duration": duration + } + ) + return AgentResult( agent_name=self.metadata.name, execution_id=execution_id, @@ -311,5 +356,101 @@ class BaseAgent(ABC): 'author': self.metadata.author, 'tags': self.metadata.tags, 'status': self.status.value, - 'dependencies': self.metadata.dependencies + 'dependencies': self.metadata.dependencies, + 'leitl_enabled': self._leitl_enabled, + 'leitl_session_id': self._leitl_session_id } + + async def enable_leitl( + self, + leitl_protocol=None, + tags: Optional[List[str]] = None + ) -> str: + """ + Enable LEITL protocol for this agent + + Args: + leitl_protocol: LEITL protocol instance (optional, will be imported if not provided) + tags: Optional tags for session categorization + + Returns: + LEITL session ID + """ + if self._leitl_enabled: + return self._leitl_session_id + + # Import LEITL protocol if not provided + if leitl_protocol is None: + try: + from app.services.leitl_protocol import leitl_protocol as protocol + self._leitl_protocol = protocol + except ImportError: + self.logger.warning("LEITL protocol not available - running in standalone mode") + return None + else: + self._leitl_protocol = leitl_protocol + + # Register session + try: + session = await self._leitl_protocol.register_session( + agent_name=self.metadata.name, + agent_type=self.metadata.category, + tags=tags or self.metadata.tags + ) + + self._leitl_enabled = True + self._leitl_session_id = session.session_id + + self.logger.info(f"✅ LEITL enabled - Session ID: {session.session_id}") + return session.session_id + + except Exception as e: + self.logger.error(f"Failed to enable LEITL: {str(e)}") + return None + + async def disable_leitl(self): + """Disable LEITL protocol and end session""" + if not self._leitl_enabled: + return + + try: + if self._leitl_protocol and self._leitl_session_id: + await self._leitl_protocol.end_session(self._leitl_session_id) + + self._leitl_enabled = False + self._leitl_session_id = None + self.logger.info("LEITL session ended") + + except Exception as e: + self.logger.error(f"Error disabling LEITL: {str(e)}") + + async def _leitl_broadcast( + self, + event_type: str, + data: Optional[Dict[str, Any]] = None + ): + """Broadcast event via LEITL protocol""" + if not self._leitl_enabled or not self._leitl_protocol: + return + + try: + await self._leitl_protocol.broadcast_event( + event_type=event_type, + session_id=self._leitl_session_id, + data=data + ) + except Exception as e: + self.logger.warning(f"LEITL broadcast failed: {str(e)}") + + async def _leitl_heartbeat(self, current_task: Optional[str] = None): + """Send heartbeat to LEITL protocol""" + if not self._leitl_enabled or not self._leitl_protocol: + return + + try: + await self._leitl_protocol.heartbeat( + session_id=self._leitl_session_id, + current_task=current_task + ) + except Exception as e: + self.logger.warning(f"LEITL heartbeat failed: {str(e)}") diff --git a/agents/base/registry.py b/agents/base/registry.py index 8e47ae0..b2cb09b 100644 --- a/agents/base/registry.py +++ b/agents/base/registry.py @@ -321,3 +321,80 @@ class AgentRegistry: 'categories': self.list_categories(), 'stats': self.get_stats() } + + async def enable_leitl_for_all( + self, + leitl_protocol=None, + tags: Optional[List[str]] = None + ) -> Dict[str, str]: + """ + Enable LEITL protocol for all registered agents + + This allows all agents to participate in the Live Everyone In The Loop + multi-agent collaboration protocol. + + Args: + leitl_protocol: LEITL protocol instance (optional, will be imported if not provided) + tags: Optional tags for sessions + + Returns: + Dict mapping agent names to LEITL session IDs + """ + self.logger.info("🔗 Enabling LEITL for all agents...") + + sessions = {} + + for agent_name, agent in self._agents.items(): + try: + session_id = await agent.enable_leitl( + leitl_protocol=leitl_protocol, + tags=tags + ) + + if session_id: + sessions[agent_name] = session_id + self.logger.info(f" ✓ {agent_name}: {session_id}") + + except Exception as e: + self.logger.warning(f" ✗ {agent_name}: {str(e)}") + + self.logger.info(f"✅ LEITL enabled for {len(sessions)}/{len(self._agents)} agents") + + return sessions + + async def disable_leitl_for_all(self): + """Disable LEITL protocol for all agents""" + self.logger.info("🔌 Disabling LEITL for all agents...") + + for agent_name, agent in self._agents.items(): + try: + await agent.disable_leitl() + self.logger.debug(f" ✓ {agent_name}") + except Exception as e: + self.logger.warning(f" ✗ {agent_name}: {str(e)}") + + self.logger.info("✅ LEITL disabled for all agents") + + def get_leitl_status(self) -> Dict[str, Any]: + """ + Get LEITL status for all agents + + Returns: + Dict with LEITL enabled counts and session IDs + """ + enabled_agents = {} + disabled_agents = [] + + for agent_name, agent in self._agents.items(): + if agent._leitl_enabled: + enabled_agents[agent_name] = agent._leitl_session_id + else: + disabled_agents.append(agent_name) + + return { + "leitl_enabled_count": len(enabled_agents), + "leitl_disabled_count": len(disabled_agents), + "enabled_agents": enabled_agents, + "disabled_agents": disabled_agents, + "total_agents": len(self._agents) + } diff --git a/backend/app/main.py b/backend/app/main.py index fc1456a..beb729d 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -15,7 +15,7 @@ from app.routers import ( digitalocean, github, huggingface, vscode, games, browser, dashboard, railway, vercel, stripe, twilio, slack, discord, sentry, api_health, agents, capture, identity_center, notifications_center, creator, compliance_ops, - search, cloudflare, system, webhooks, prism_static, ip_vault, leitl + search, cloudflare, system, webhooks, prism_static, ip_vault, leitl, cognition ) from app.services.crypto import rotate_plaintext_wallet_keys @@ -34,6 +34,7 @@ openapi_tags = [ {"name": "cloudflare", "description": "Cloudflare zone, DNS, and Worker scaffolding"}, {"name": "IP Vault", "description": "Cryptographic proof-of-origin for ideas and intellectual property"}, {"name": "LEITL", "description": "Live Everyone In The Loop - Multi-agent collaboration with WebDAV context"}, + {"name": "Cognition", "description": "Cece Cognition Framework - 15-step reasoning + 6-step architecture + multi-agent orchestration"}, ] @@ -165,6 +166,9 @@ app.include_router(ip_vault.router) # LEITL Protocol - Live Everyone In The Loop app.include_router(leitl.router) +# Cognition Framework - Cece + Multi-Agent Orchestration +app.include_router(cognition.router) + # GitHub Webhooks (Phase Q automation) app.include_router(webhooks.router) diff --git a/backend/app/routers/cognition.py b/backend/app/routers/cognition.py index 3f722d7..ebe67f0 100644 --- a/backend/app/routers/cognition.py +++ b/backend/app/routers/cognition.py @@ -30,7 +30,7 @@ from agents.categories.ai_ml.cece_agent import CeceAgent from agents.categories.ai_ml.wasp_agent import WaspAgent from agents.categories.ai_ml.clause_agent import ClauseAgent from agents.categories.ai_ml.codex_agent import CodexAgent -from backend.app.services.orchestration import ( +from app.services.orchestration import ( OrchestrationEngine, Workflow, WorkflowStep,