#!/usr/bin/env python3 """ Sub-Agent Flow Integration - Integrates sub-agent context with Luzia 9-phase flow Features: 1. Inject parent context into sub-agent flow execution 2. Execute 9-phase flow with context awareness 3. Coordinate sub-agent execution 4. Aggregate results from sub-agents 5. Propagate learnings back to parent task """ from typing import Dict, List, Optional, Any, Callable from datetime import datetime from sub_agent_context import SubAgentContextManager, SubAgentContext class SubAgentFlowIntegrator: """Integrates sub-agent context management with task execution flow""" def __init__(self, context_manager: Optional[SubAgentContextManager] = None): """Initialize flow integrator Args: context_manager: SubAgentContextManager instance """ self.context_manager = context_manager or SubAgentContextManager() self.phase_handlers: Dict[str, Callable] = {} def register_phase_handler( self, phase_name: str, handler: Callable[[SubAgentContext], Dict[str, Any]] ) -> None: """Register handler for a specific phase Args: phase_name: Name of phase (e.g., 'CONTEXT_PREP', 'ANALYZING') handler: Callable that executes phase logic """ self.phase_handlers[phase_name] = handler def execute_sub_agent_flow( self, parent_task_id: str, parent_project: str, parent_description: str, parent_context: Optional[Dict[str, Any]] = None, parent_tags: Optional[List[str]] = None, parent_metadata: Optional[Dict[str, Any]] = None, ) -> Dict[str, Any]: """Execute full 9-phase flow for a sub-agent Args: parent_task_id: ID of parent task parent_project: Parent project parent_description: Parent task description parent_context: Parent task context parent_tags: Tags from parent parent_metadata: Metadata from parent Returns: Results from all phases """ # Create sub-agent context context = self.context_manager.create_sub_agent_context( parent_task_id=parent_task_id, parent_project=parent_project, parent_description=parent_description, parent_context=parent_context, parent_tags=parent_tags, parent_metadata=parent_metadata, ) results = {"sub_agent_id": context.sub_agent_id, "phases": {}} # Execute each phase phases = [p.phase_name for p in context.phase_progression] for phase_name in phases: phase_result = self.execute_phase(context.sub_agent_id, phase_name) results["phases"][phase_name] = phase_result return results def execute_phase(self, sub_agent_id: str, phase_name: str) -> Dict[str, Any]: """Execute a single phase for a sub-agent Args: sub_agent_id: ID of sub-agent phase_name: Name of phase to execute Returns: Phase execution results """ context = self.context_manager.get_sub_agent_context(sub_agent_id) if not context: return {"error": f"Context not found for {sub_agent_id}"} # Mark phase as in progress self.context_manager.update_phase(sub_agent_id, phase_name, "in_progress") try: # Execute phase handler if registered if phase_name in self.phase_handlers: handler = self.phase_handlers[phase_name] output = handler(context) else: # Default phase execution output = self._execute_default_phase(context, phase_name) # Mark phase as complete self.context_manager.update_phase( sub_agent_id, phase_name, "completed", output=str(output) ) return {"status": "completed", "output": output} except Exception as e: # Mark phase as failed self.context_manager.update_phase( sub_agent_id, phase_name, "failed", error=str(e) ) return {"status": "failed", "error": str(e)} def _execute_default_phase(self, context: SubAgentContext, phase_name: str) -> Dict[str, Any]: """Execute default behavior for a phase Args: context: SubAgentContext phase_name: Name of phase Returns: Phase output """ output = { "phase": phase_name, "parent_task": context.parent_task_id, "parent_project": context.parent_project, "sibling_agents": len(context.sibling_agents), } if phase_name == "CONTEXT_PREP": output["action"] = "Preparing context from parent task" output["parent_description"] = context.parent_description output["context_keys"] = list(context.parent_context.keys()) elif phase_name == "RECEIVED": output["action"] = "Received and registered sub-agent" output["sub_agent_id"] = context.sub_agent_id output["created_at"] = context.created_at elif phase_name == "PREDICTING": output["action"] = "Predicting sub-agent requirements" output["parent_tags"] = context.parent_tags output["metadata_available"] = bool(context.parent_metadata) elif phase_name == "ANALYZING": output["action"] = "Analyzing parent task context" output["parent_tags_count"] = len(context.parent_tags) output["coordination_needed"] = len(context.sibling_agents) > 0 elif phase_name == "CONSENSUS_CHECK": output["action"] = "Checking consensus with siblings" output["sibling_agents"] = list(context.sibling_agents) output["messages_sent"] = len(context.coordination_messages) elif phase_name == "AWAITING_APPROVAL": output["action"] = "Awaiting approval to proceed" output["ready_to_execute"] = True elif phase_name == "STRATEGIZING": output["action"] = "Strategizing execution approach" output["strategy"] = f"Execute sub-task within parent context" elif phase_name == "EXECUTING": output["action"] = "Executing sub-agent task" output["execution_start"] = datetime.utcnow().isoformat() elif phase_name == "LEARNING": output["action"] = "Learning from execution" output["parent_project"] = context.parent_project output["completion_status"] = "ready" return output def get_sub_agent_progress(self, sub_agent_id: str) -> Dict[str, Any]: """Get progress report for a sub-agent Args: sub_agent_id: ID of sub-agent Returns: Progress information """ context = self.context_manager.get_sub_agent_context(sub_agent_id) if not context: return {"error": f"Context not found for {sub_agent_id}"} phases = context.phase_progression completed_phases = [p for p in phases if p.status == "completed"] in_progress_phases = [p for p in phases if p.status == "in_progress"] failed_phases = [p for p in phases if p.status == "failed"] current_phase = self.context_manager.get_current_phase(sub_agent_id) total_duration = sum(p.duration_seconds or 0 for p in completed_phases) return { "sub_agent_id": sub_agent_id, "total_phases": len(phases), "completed_phases": len(completed_phases), "in_progress_phases": len(in_progress_phases), "failed_phases": len(failed_phases), "current_phase": current_phase, "progress_percentage": (len(completed_phases) / len(phases)) * 100 if phases else 0, "total_duration_seconds": total_duration, "phase_details": [ { "name": p.phase_name, "status": p.status, "duration": p.duration_seconds, } for p in phases ], } def coordinate_sub_agents( self, parent_task_id: str, coordination_strategy: str = "sequential", ) -> Dict[str, Any]: """Coordinate execution of multiple sub-agents for a parent task Args: parent_task_id: ID of parent task coordination_strategy: 'sequential', 'parallel', or 'dependency-based' Returns: Coordination results """ sub_agent_ids = self.context_manager.get_sub_agents_for_parent(parent_task_id) if not sub_agent_ids: return {"status": "no_sub_agents", "parent_task_id": parent_task_id} results = { "parent_task_id": parent_task_id, "strategy": coordination_strategy, "sub_agents": sub_agent_ids, "coordination_details": [], } if coordination_strategy == "sequential": # Execute sub-agents sequentially for i, sub_agent_id in enumerate(sub_agent_ids): context = self.context_manager.get_sub_agent_context(sub_agent_id) results["coordination_details"].append( { "order": i + 1, "sub_agent_id": sub_agent_id, "siblings_count": len(context.sibling_agents) if context else 0, "strategy": "Execute after previous sub-agent completes", } ) elif coordination_strategy == "parallel": # Mark all sub-agents for parallel execution for sub_agent_id in sub_agent_ids: results["coordination_details"].append( { "sub_agent_id": sub_agent_id, "strategy": "Execute simultaneously with other sub-agents", } ) elif coordination_strategy == "dependency-based": # Analyze sibling relationships for dependency-based execution for sub_agent_id in sub_agent_ids: siblings = self.context_manager.get_sibling_agents(sub_agent_id) results["coordination_details"].append( { "sub_agent_id": sub_agent_id, "depends_on": list(siblings), "strategy": "Execute considering dependencies on siblings", } ) return results def collect_sub_agent_results( self, parent_task_id: str ) -> Dict[str, Any]: """Collect and aggregate results from all sub-agents Args: parent_task_id: ID of parent task Returns: Aggregated results """ sub_agent_ids = self.context_manager.get_sub_agents_for_parent(parent_task_id) results = { "parent_task_id": parent_task_id, "sub_agents_total": len(sub_agent_ids), "sub_agents": [], } for sub_agent_id in sub_agent_ids: progress = self.get_sub_agent_progress(sub_agent_id) summary = self.context_manager.get_context_summary(sub_agent_id) results["sub_agents"].append( { "sub_agent_id": sub_agent_id, "progress": progress, "summary": summary, } ) # Aggregate status all_completed = all( p.get("completed_phases") == p.get("total_phases") for p in [s["progress"] for s in results["sub_agents"]] ) results["all_sub_agents_complete"] = all_completed return results