From cf0c19943e0ddb7a91020ba6b13d6d00e4d3aa5f Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sat, 26 Jul 2025 20:19:34 +0300 Subject: [PATCH 01/18] Add files via upload --- .../board_of_directors_decision_making.md | 885 +++++++++++++ .../board_of_directors_example.md | 466 +++++++ .../board_of_directors_roles.md | 1151 +++++++++++++++++ .../board_of_directors_swarm.md | 704 ++++++++++ .../board_of_directors_workflow.md | 908 +++++++++++++ .../structs/board_of_directors/index.md | 291 +++++ 6 files changed, 4405 insertions(+) create mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md create mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_example.md create mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_roles.md create mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_swarm.md create mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_workflow.md create mode 100644 docs/swarms/structs/board_of_directors/index.md diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md b/docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md new file mode 100644 index 00000000..22a3cb35 --- /dev/null +++ b/docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md @@ -0,0 +1,885 @@ +# Board of Directors Decision Making + +The Board of Directors decision-making process is a sophisticated, multi-layered system that ensures comprehensive analysis, balanced consideration, and effective consensus building. This process combines democratic principles with hierarchical authority to achieve optimal outcomes. + +## Decision-Making Framework + +### Overview of the Decision Process + +```mermaid +graph TD + A[Task Analysis] --> B[Expertise Assignment] + B --> C[Individual Analysis] + C --> D[Group Discussion] + D --> E[Proposal Development] + E --> F[Voting Process] + F --> G[Consensus Building] + G --> H{Consensus Achieved?} + H -->|Yes| I[Decision Finalization] + H -->|No| J[Conflict Resolution] + J --> K[Proposal Refinement] + K --> F + I --> L[Execution Planning] + L --> M[Implementation Oversight] + + style A fill:#e3f2fd + style I fill:#c8e6c9 + style H fill:#fff3e0 +``` + +**Diagram Explanation:** +This comprehensive decision-making framework shows the complete process from initial task analysis to final implementation oversight. The process begins with task analysis and expertise assignment, followed by individual analysis where each board member contributes their specialized knowledge. Group discussion facilitates information sharing and debate, leading to proposal development. The voting process and consensus building ensure democratic decision-making, with conflict resolution mechanisms for when consensus cannot be reached. Once consensus is achieved, decisions are finalized and execution planning begins, followed by implementation oversight. + +**Technical Implementation:** +```python +# Example: Decision-making framework implementation +class DecisionMakingFramework: + def __init__(self, board_members, config): + self.board_members = board_members + self.config = config + self.decision_history = [] + self.consensus_threshold = config.get("consensus_threshold", 0.7) + self.max_voting_rounds = config.get("max_voting_rounds", 3) + + async def execute_decision_process(self, task): + """Execute the complete decision-making process""" + decision_result = { + "task": task, + "phases": [], + "final_decision": None, + "consensus_achieved": False, + "execution_plan": None + } + + # Phase 1: Task Analysis and Expertise Assignment + analysis_phase = await self.analyze_task_and_assign_expertise(task) + decision_result["phases"].append(analysis_phase) + + # Phase 2: Individual Analysis + individual_analysis = await self.conduct_individual_analysis(task, analysis_phase["expertise_assignments"]) + decision_result["phases"].append(individual_analysis) + + # Phase 3: Group Discussion + group_discussion = await self.facilitate_group_discussion(individual_analysis) + decision_result["phases"].append(group_discussion) + + # Phase 4: Proposal Development + proposal_development = await self.develop_proposals(group_discussion) + decision_result["phases"].append(proposal_development) + + # Phase 5: Voting and Consensus Building + consensus_result = await self.build_consensus(proposal_development["proposals"]) + decision_result["phases"].append(consensus_result) + + # Phase 6: Decision Finalization + if consensus_result["consensus_achieved"]: + finalization = await self.finalize_decision(consensus_result) + decision_result["phases"].append(finalization) + decision_result["final_decision"] = finalization["decision"] + decision_result["consensus_achieved"] = True + else: + # Handle conflict resolution + conflict_resolution = await self.resolve_conflicts(consensus_result) + decision_result["phases"].append(conflict_resolution) + decision_result["final_decision"] = conflict_resolution["decision"] + decision_result["consensus_achieved"] = False + + # Phase 7: Execution Planning + execution_planning = await self.plan_execution(decision_result["final_decision"]) + decision_result["phases"].append(execution_planning) + decision_result["execution_plan"] = execution_planning["plan"] + + # Store decision in history + self.decision_history.append(decision_result) + + return decision_result + + async def analyze_task_and_assign_expertise(self, task): + """Analyze task and assign expertise areas to board members""" + # Analyze task complexity and requirements + task_analysis = await self.analyze_task_complexity(task) + + # Identify required expertise areas + required_expertise = await self.identify_required_expertise(task_analysis) + + # Assign expertise areas to board members + expertise_assignments = await self.assign_expertise_to_members(required_expertise) + + return { + "phase": "task_analysis_and_expertise_assignment", + "task_analysis": task_analysis, + "required_expertise": required_expertise, + "expertise_assignments": expertise_assignments, + "timestamp": datetime.now().isoformat() + } + + async def conduct_individual_analysis(self, task, expertise_assignments): + """Conduct individual analysis by each board member""" + individual_analyses = {} + + for member_role, expertise_areas in expertise_assignments.items(): + member = self.board_members[member_role] + + # Conduct analysis based on assigned expertise + analysis = await member.analyze_task_areas(task, expertise_areas) + + individual_analyses[member_role] = { + "expertise_areas": expertise_areas, + "analysis": analysis, + "recommendations": analysis.get("recommendations", []), + "concerns": analysis.get("concerns", []), + "proposals": analysis.get("proposals", []) + } + + return { + "phase": "individual_analysis", + "analyses": individual_analyses, + "timestamp": datetime.now().isoformat() + } +``` + +## Voting Mechanisms + +### Weighted Voting System + +```mermaid +graph TD + A[Proposal Submission] --> B[Vote Collection] + B --> C[Weight Application] + C --> D[Score Calculation] + D --> E[Threshold Check] + E -->|Above Threshold| F[Consensus Achieved] + E -->|Below Threshold| G[Additional Rounds] + G --> H[Proposal Refinement] + H --> B + + subgraph "Voting Components" + I[Individual Votes] + J[Role Weights] + K[Consensus Threshold] + L[Conflict Resolution] + end + + B --> I + C --> J + E --> K + G --> L +``` + +**Diagram Explanation:** +This diagram illustrates the weighted voting system used by the Board of Directors. The process begins with proposal submission, followed by vote collection from all board members. Each vote is weighted according to the member's role and authority level. Scores are calculated using the weighted voting formula, and results are checked against the consensus threshold. If the threshold is met, consensus is achieved. If not, additional voting rounds with proposal refinement are conducted until consensus is reached or maximum rounds are exceeded. + +**Technical Implementation:** +```python +# Example: Weighted voting system implementation +class WeightedVotingSystem: + def __init__(self, board_members, config): + self.board_members = board_members + self.config = config + self.voting_weights = { + "CHAIRMAN": 1.5, + "VICE_CHAIRMAN": 1.2, + "EXECUTIVE_DIRECTOR": 1.5, + "SECRETARY": 1.0, + "TREASURER": 1.0, + "MEMBER": 1.0 + } + self.consensus_threshold = config.get("consensus_threshold", 0.7) + self.max_voting_rounds = config.get("max_voting_rounds", 3) + + async def conduct_weighted_voting(self, proposals): + """Conduct weighted voting on proposals""" + voting_result = { + "rounds": [], + "final_decision": None, + "consensus_achieved": False, + "voting_summary": {} + } + + current_proposals = proposals + round_number = 1 + + while round_number <= self.max_voting_rounds: + # Collect votes from all board members + votes = await self.collect_votes(current_proposals) + + # Apply voting weights + weighted_votes = self.apply_voting_weights(votes) + + # Calculate scores + scores = self.calculate_weighted_scores(weighted_votes, current_proposals) + + # Check consensus threshold + consensus_check = self.check_consensus_threshold(scores) + + round_result = { + "round": round_number, + "votes": votes, + "weighted_votes": weighted_votes, + "scores": scores, + "consensus_achieved": consensus_check["achieved"], + "winning_proposal": consensus_check["winning_proposal"] + } + + voting_result["rounds"].append(round_result) + + if consensus_check["achieved"]: + voting_result["final_decision"] = consensus_check["winning_proposal"] + voting_result["consensus_achieved"] = True + break + + # Refine proposals for next round + current_proposals = await self.refine_proposals(current_proposals, round_result) + round_number += 1 + + # Generate voting summary + voting_result["voting_summary"] = self.generate_voting_summary(voting_result["rounds"]) + + return voting_result + + async def collect_votes(self, proposals): + """Collect votes from all board members""" + votes = {} + + for member_role, member in self.board_members.items(): + # Each member votes on all proposals + member_votes = await member.vote_on_proposals(proposals) + + votes[member_role] = { + "proposal_scores": member_votes["scores"], + "rationale": member_votes["rationale"], + "confidence_level": member_votes.get("confidence_level", 1.0), + "timestamp": datetime.now().isoformat() + } + + return votes + + def apply_voting_weights(self, votes): + """Apply voting weights to member votes""" + weighted_votes = {} + + for member_role, vote_data in votes.items(): + weight = self.voting_weights.get(member_role, 1.0) + + weighted_scores = {} + for proposal_id, score in vote_data["proposal_scores"].items(): + weighted_scores[proposal_id] = score * weight + + weighted_votes[member_role] = { + "original_scores": vote_data["proposal_scores"], + "weighted_scores": weighted_scores, + "weight": weight, + "rationale": vote_data["rationale"], + "confidence_level": vote_data["confidence_level"] + } + + return weighted_votes + + def calculate_weighted_scores(self, weighted_votes, proposals): + """Calculate final weighted scores for each proposal""" + proposal_scores = {} + + for proposal in proposals: + proposal_id = proposal["id"] + total_weighted_score = 0 + total_weight = 0 + vote_count = 0 + + for member_role, vote_data in weighted_votes.items(): + if proposal_id in vote_data["weighted_scores"]: + weighted_score = vote_data["weighted_scores"][proposal_id] + weight = vote_data["weight"] + + total_weighted_score += weighted_score + total_weight += weight + vote_count += 1 + + # Calculate average weighted score + if total_weight > 0: + final_score = total_weighted_score / total_weight + else: + final_score = 0 + + proposal_scores[proposal_id] = { + "final_score": final_score, + "total_weight": total_weight, + "vote_count": vote_count, + "consensus_percentage": final_score + } + + return proposal_scores + + def check_consensus_threshold(self, scores): + """Check if any proposal meets the consensus threshold""" + best_proposal = None + best_score = 0 + + for proposal_id, score_data in scores.items(): + if score_data["final_score"] > best_score: + best_score = score_data["final_score"] + best_proposal = proposal_id + + consensus_achieved = best_score >= self.consensus_threshold + + return { + "achieved": consensus_achieved, + "winning_proposal": best_proposal if consensus_achieved else None, + "best_score": best_score, + "threshold": self.consensus_threshold + } +``` + +## Consensus Building Process + +### Multi-Round Consensus Building + +```mermaid +flowchart TD + A[Initial Proposals] --> B[Round 1 Voting] + B --> C[Score Calculation] + C --> D{Consensus?} + D -->|Yes| E[Consensus Achieved] + D -->|No| F[Proposal Refinement] + F --> G[Round 2 Voting] + G --> H[Score Calculation] + H --> I{Consensus?} + I -->|Yes| J[Consensus Achieved] + I -->|No| K[Final Round] + K --> L[Round 3 Voting] + L --> M[Score Calculation] + M --> N{Consensus?} + N -->|Yes| O[Consensus Achieved] + N -->|No| P[Authority Decision] + + subgraph "Consensus Building Elements" + Q[Discussion Facilitation] + R[Conflict Resolution] + S[Proposal Synthesis] + T[Mediation Process] + end + + F --> Q + F --> R + F --> S + K --> T +``` + +**Diagram Explanation:** +This flowchart shows the multi-round consensus building process used by the Board of Directors. The process begins with initial proposals and proceeds through multiple voting rounds. After each round, scores are calculated and consensus is checked. If consensus is not achieved, proposals are refined through discussion facilitation, conflict resolution, proposal synthesis, and mediation processes. The process continues for up to three rounds, after which authority decision-making is used if consensus still cannot be reached. + +**Technical Implementation:** +```python +# Example: Consensus building system +class ConsensusBuildingSystem: + def __init__(self, board_members, config): + self.board_members = board_members + self.config = config + self.max_rounds = config.get("max_consensus_rounds", 3) + self.consensus_threshold = config.get("consensus_threshold", 0.7) + self.discussion_facilitator = board_members.get("CHAIRMAN") + + async def build_consensus(self, initial_proposals): + """Build consensus through multiple rounds""" + consensus_result = { + "rounds": [], + "consensus_achieved": False, + "final_proposal": None, + "authority_decision": None + } + + current_proposals = initial_proposals + round_number = 1 + + while round_number <= self.max_rounds: + # Conduct voting round + voting_result = await self.conduct_voting_round(current_proposals, round_number) + + # Check consensus + if voting_result["consensus_achieved"]: + consensus_result["rounds"].append(voting_result) + consensus_result["consensus_achieved"] = True + consensus_result["final_proposal"] = voting_result["winning_proposal"] + break + + # If no consensus and not final round, refine proposals + if round_number < self.max_rounds: + refinement_result = await self.refine_proposals(current_proposals, voting_result) + consensus_result["rounds"].append(voting_result) + current_proposals = refinement_result["refined_proposals"] + else: + # Final round - use authority decision + authority_decision = await self.make_authority_decision(voting_result) + consensus_result["rounds"].append(voting_result) + consensus_result["authority_decision"] = authority_decision + consensus_result["final_proposal"] = authority_decision["selected_proposal"] + + round_number += 1 + + return consensus_result + + async def conduct_voting_round(self, proposals, round_number): + """Conduct a single voting round""" + round_result = { + "round": round_number, + "proposals": proposals, + "votes": {}, + "scores": {}, + "consensus_achieved": False, + "winning_proposal": None + } + + # Collect votes from all board members + for member_role, member in self.board_members.items(): + vote = await member.vote_on_proposals(proposals, round_number) + round_result["votes"][member_role] = vote + + # Calculate weighted scores + weighted_scores = self.calculate_weighted_scores(round_result["votes"], proposals) + round_result["scores"] = weighted_scores + + # Check consensus + consensus_check = self.check_consensus(weighted_scores) + round_result["consensus_achieved"] = consensus_check["achieved"] + round_result["winning_proposal"] = consensus_check["winning_proposal"] + + return round_result + + async def refine_proposals(self, current_proposals, voting_result): + """Refine proposals based on voting results and discussion""" + refinement_result = { + "refined_proposals": [], + "discussion_summary": "", + "conflicts_resolved": [] + } + + # Analyze voting patterns + voting_analysis = self.analyze_voting_patterns(voting_result) + + # Identify areas of disagreement + disagreements = self.identify_disagreements(voting_result) + + # Facilitate discussion to resolve conflicts + discussion_result = await self.facilitate_discussion(disagreements, current_proposals) + refinement_result["discussion_summary"] = discussion_result["summary"] + refinement_result["conflicts_resolved"] = discussion_result["resolved_conflicts"] + + # Synthesize refined proposals + refined_proposals = await self.synthesize_proposals(current_proposals, discussion_result) + refinement_result["refined_proposals"] = refined_proposals + + return refinement_result + + async def facilitate_discussion(self, disagreements, proposals): + """Facilitate discussion to resolve disagreements""" + discussion_result = { + "summary": "", + "resolved_conflicts": [], + "new_insights": [] + } + + # Chairman facilitates discussion + if self.discussion_facilitator: + facilitation_result = await self.discussion_facilitator.facilitate_discussion( + disagreements, proposals + ) + + discussion_result["summary"] = facilitation_result["summary"] + discussion_result["resolved_conflicts"] = facilitation_result["resolved_conflicts"] + discussion_result["new_insights"] = facilitation_result["new_insights"] + + return discussion_result + + async def make_authority_decision(self, final_voting_result): + """Make authority decision when consensus cannot be reached""" + # Chairman makes final decision based on best available information + authority_decision = { + "decision_maker": "CHAIRMAN", + "decision_method": "authority_decision", + "selected_proposal": None, + "rationale": "", + "board_support_level": 0.0 + } + + # Analyze all proposals and select the best one + best_proposal = self.select_best_proposal(final_voting_result["scores"]) + authority_decision["selected_proposal"] = best_proposal["proposal_id"] + authority_decision["rationale"] = best_proposal["rationale"] + authority_decision["board_support_level"] = best_proposal["support_level"] + + return authority_decision +``` + +## Conflict Resolution Mechanisms + +### Structured Conflict Resolution + +```mermaid +graph TD + A[Conflict Identification] --> B[Conflict Analysis] + B --> C[Stakeholder Mapping] + C --> D[Root Cause Analysis] + D --> E[Resolution Strategy] + E --> F[Mediation Process] + F --> G[Compromise Facilitation] + G --> H[Agreement Building] + H --> I[Resolution Implementation] + + subgraph "Conflict Resolution Tools" + J[Mediation Techniques] + K[Compromise Strategies] + L[Consensus Building] + M[Authority Intervention] + end + + F --> J + G --> K + H --> L + I --> M +``` + +**Diagram Explanation:** +This diagram illustrates the structured conflict resolution process used by the Board of Directors. The process begins with conflict identification and proceeds through systematic analysis including stakeholder mapping and root cause analysis. A resolution strategy is developed, followed by mediation processes and compromise facilitation. The process culminates in agreement building and resolution implementation, using various tools including mediation techniques, compromise strategies, consensus building, and authority intervention when necessary. + +**Technical Implementation:** +```python +# Example: Conflict resolution system +class ConflictResolutionSystem: + def __init__(self, board_members, config): + self.board_members = board_members + self.config = config + self.mediation_techniques = [ + "active_listening", + "interest_based_negotiation", + "brainstorming", + "consensus_building" + ] + self.resolution_strategies = [ + "compromise", + "collaboration", + "accommodation", + "authority_decision" + ] + + async def resolve_conflicts(self, conflicts, context): + """Resolve conflicts using structured approach""" + resolution_result = { + "conflicts": conflicts, + "resolution_process": [], + "final_resolution": None, + "implementation_plan": None + } + + for conflict in conflicts: + # Step 1: Analyze conflict + conflict_analysis = await self.analyze_conflict(conflict, context) + resolution_result["resolution_process"].append({ + "step": "conflict_analysis", + "conflict_id": conflict["id"], + "analysis": conflict_analysis + }) + + # Step 2: Map stakeholders + stakeholder_mapping = await self.map_stakeholders(conflict, context) + resolution_result["resolution_process"].append({ + "step": "stakeholder_mapping", + "conflict_id": conflict["id"], + "mapping": stakeholder_mapping + }) + + # Step 3: Analyze root causes + root_cause_analysis = await self.analyze_root_causes(conflict, context) + resolution_result["resolution_process"].append({ + "step": "root_cause_analysis", + "conflict_id": conflict["id"], + "analysis": root_cause_analysis + }) + + # Step 4: Develop resolution strategy + resolution_strategy = await self.develop_resolution_strategy( + conflict, conflict_analysis, stakeholder_mapping, root_cause_analysis + ) + resolution_result["resolution_process"].append({ + "step": "resolution_strategy", + "conflict_id": conflict["id"], + "strategy": resolution_strategy + }) + + # Step 5: Implement resolution + resolution_implementation = await self.implement_resolution( + conflict, resolution_strategy + ) + resolution_result["resolution_process"].append({ + "step": "resolution_implementation", + "conflict_id": conflict["id"], + "implementation": resolution_implementation + }) + + # Generate final resolution + resolution_result["final_resolution"] = await self.generate_final_resolution( + resolution_result["resolution_process"] + ) + + # Create implementation plan + resolution_result["implementation_plan"] = await self.create_implementation_plan( + resolution_result["final_resolution"] + ) + + return resolution_result + + async def analyze_conflict(self, conflict, context): + """Analyze the nature and scope of a conflict""" + analysis = { + "conflict_type": self.categorize_conflict(conflict), + "severity_level": self.assess_severity(conflict), + "scope": self.define_scope(conflict), + "impact_assessment": await self.assess_impact(conflict, context), + "urgency_level": self.assess_urgency(conflict) + } + + return analysis + + async def map_stakeholders(self, conflict, context): + """Map stakeholders involved in the conflict""" + stakeholders = { + "primary_stakeholders": [], + "secondary_stakeholders": [], + "influencers": [], + "decision_makers": [] + } + + # Identify stakeholders based on conflict type + if conflict["type"] == "resource_allocation": + stakeholders["primary_stakeholders"] = self.identify_resource_stakeholders(conflict) + elif conflict["type"] == "strategic_direction": + stakeholders["primary_stakeholders"] = self.identify_strategic_stakeholders(conflict) + elif conflict["type"] == "implementation_approach": + stakeholders["primary_stakeholders"] = self.identify_implementation_stakeholders(conflict) + + # Map stakeholder interests and positions + for stakeholder in stakeholders["primary_stakeholders"]: + stakeholder["interests"] = await self.identify_stakeholder_interests(stakeholder, conflict) + stakeholder["position"] = await self.identify_stakeholder_position(stakeholder, conflict) + stakeholder["influence_level"] = self.assess_influence_level(stakeholder) + + return stakeholders + + async def analyze_root_causes(self, conflict, context): + """Analyze root causes of the conflict""" + root_causes = { + "structural_causes": [], + "communication_causes": [], + "resource_causes": [], + "process_causes": [] + } + + # Analyze based on conflict type + if conflict["type"] == "resource_allocation": + root_causes["resource_causes"] = await self.analyze_resource_causes(conflict) + elif conflict["type"] == "strategic_direction": + root_causes["structural_causes"] = await self.analyze_structural_causes(conflict) + elif conflict["type"] == "implementation_approach": + root_causes["process_causes"] = await self.analyze_process_causes(conflict) + + # Identify communication issues + root_causes["communication_causes"] = await self.analyze_communication_causes(conflict) + + return root_causes + + async def develop_resolution_strategy(self, conflict, analysis, stakeholders, root_causes): + """Develop appropriate resolution strategy""" + strategy = { + "approach": self.select_resolution_approach(analysis, stakeholders), + "techniques": self.select_mediation_techniques(conflict, stakeholders), + "timeline": self.estimate_resolution_timeline(analysis), + "resources": self.identify_resolution_resources(analysis), + "success_criteria": self.define_success_criteria(conflict) + } + + return strategy + + async def implement_resolution(self, conflict, strategy): + """Implement the resolution strategy""" + implementation = { + "mediation_process": await self.conduct_mediation(conflict, strategy), + "compromise_facilitation": await self.facilitate_compromise(conflict, strategy), + "agreement_building": await self.build_agreement(conflict, strategy), + "implementation_oversight": await self.oversee_implementation(conflict, strategy) + } + + return implementation +``` + +## Decision Quality Assurance + +### Quality Assessment Framework + +```mermaid +graph TD + A[Decision Made] --> B[Quality Assessment] + B --> C[Completeness Check] + C --> D[Accuracy Verification] + D --> E[Feasibility Analysis] + E --> F[Risk Assessment] + F --> G[Stakeholder Impact] + G --> H[Quality Score] + H --> I{Quality Threshold?} + I -->|Yes| J[Decision Approved] + I -->|No| K[Decision Refinement] + K --> L[Additional Analysis] + L --> B + + subgraph "Quality Metrics" + M[Completeness Score] + N[Accuracy Score] + O[Feasibility Score] + P[Risk Score] + Q[Impact Score] + end + + C --> M + D --> N + E --> O + F --> P + G --> Q +``` + +**Diagram Explanation:** +This diagram shows the quality assessment framework used to ensure high-quality decisions. After a decision is made, it undergoes comprehensive quality assessment including completeness checks, accuracy verification, feasibility analysis, risk assessment, and stakeholder impact evaluation. A quality score is calculated based on these metrics, and the decision is either approved if it meets the quality threshold or sent back for refinement and additional analysis. + +**Technical Implementation:** +```python +# Example: Decision quality assurance system +class DecisionQualityAssurance: + def __init__(self, config): + self.config = config + self.quality_threshold = config.get("quality_threshold", 0.8) + self.quality_metrics = { + "completeness": {"weight": 0.2, "threshold": 0.8}, + "accuracy": {"weight": 0.25, "threshold": 0.85}, + "feasibility": {"weight": 0.2, "threshold": 0.8}, + "risk": {"weight": 0.15, "threshold": 0.7}, + "impact": {"weight": 0.2, "threshold": 0.8} + } + + async def assess_decision_quality(self, decision, context): + """Assess the quality of a decision""" + quality_assessment = { + "decision": decision, + "metrics": {}, + "overall_score": 0.0, + "threshold_met": False, + "recommendations": [] + } + + # Assess completeness + completeness_score = await self.assess_completeness(decision, context) + quality_assessment["metrics"]["completeness"] = completeness_score + + # Assess accuracy + accuracy_score = await self.assess_accuracy(decision, context) + quality_assessment["metrics"]["accuracy"] = accuracy_score + + # Assess feasibility + feasibility_score = await self.assess_feasibility(decision, context) + quality_assessment["metrics"]["feasibility"] = feasibility_score + + # Assess risk + risk_score = await self.assess_risk(decision, context) + quality_assessment["metrics"]["risk"] = risk_score + + # Assess stakeholder impact + impact_score = await self.assess_stakeholder_impact(decision, context) + quality_assessment["metrics"]["impact"] = impact_score + + # Calculate overall score + overall_score = self.calculate_overall_score(quality_assessment["metrics"]) + quality_assessment["overall_score"] = overall_score + + # Check if threshold is met + quality_assessment["threshold_met"] = overall_score >= self.quality_threshold + + # Generate recommendations + quality_assessment["recommendations"] = await self.generate_quality_recommendations( + quality_assessment["metrics"], overall_score + ) + + return quality_assessment + + async def assess_completeness(self, decision, context): + """Assess the completeness of the decision""" + completeness_factors = { + "all_aspects_covered": self.check_aspect_coverage(decision, context), + "stakeholder_consideration": self.check_stakeholder_consideration(decision, context), + "implementation_details": self.check_implementation_details(decision), + "resource_allocation": self.check_resource_allocation(decision), + "timeline_definition": self.check_timeline_definition(decision) + } + + # Calculate completeness score + completeness_score = sum(completeness_factors.values()) / len(completeness_factors) + + return { + "score": completeness_score, + "factors": completeness_factors, + "threshold_met": completeness_score >= self.quality_metrics["completeness"]["threshold"] + } + + async def assess_accuracy(self, decision, context): + """Assess the accuracy of the decision""" + accuracy_factors = { + "data_quality": self.assess_data_quality(decision, context), + "analysis_quality": self.assess_analysis_quality(decision, context), + "assumption_validity": self.assess_assumption_validity(decision, context), + "conclusion_soundness": self.assess_conclusion_soundness(decision, context) + } + + # Calculate accuracy score + accuracy_score = sum(accuracy_factors.values()) / len(accuracy_factors) + + return { + "score": accuracy_score, + "factors": accuracy_factors, + "threshold_met": accuracy_score >= self.quality_metrics["accuracy"]["threshold"] + } + + def calculate_overall_score(self, metrics): + """Calculate overall quality score""" + weighted_score = 0.0 + total_weight = 0.0 + + for metric_name, metric_data in metrics.items(): + weight = self.quality_metrics[metric_name]["weight"] + score = metric_data["score"] + + weighted_score += score * weight + total_weight += weight + + return weighted_score / total_weight if total_weight > 0 else 0.0 +``` + +## Best Practices for Decision Making + +### 1. Structured Approach +- Follow the defined decision-making framework +- Ensure all phases are completed thoroughly +- Document decisions and rationale + +### 2. Inclusive Participation +- Encourage all board members to contribute +- Value diverse perspectives and expertise +- Ensure fair representation in voting + +### 3. Quality Assurance +- Implement quality checkpoints throughout the process +- Assess decision quality before implementation +- Continuously monitor and improve decision-making processes + +### 4. Conflict Management +- Address conflicts promptly and constructively +- Use appropriate resolution strategies +- Maintain focus on organizational objectives + +### 5. Continuous Improvement +- Learn from previous decisions +- Refine decision-making processes based on outcomes +- Adapt to changing circumstances and requirements \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_example.md b/docs/swarms/structs/board_of_directors/board_of_directors_example.md new file mode 100644 index 00000000..34c5edc3 --- /dev/null +++ b/docs/swarms/structs/board_of_directors/board_of_directors_example.md @@ -0,0 +1,466 @@ +# Board of Directors Example + +This example demonstrates how to use the Board of Directors swarm feature for democratic decision-making and collective intelligence in multi-agent systems. + +## Overview + +The Board of Directors Swarm provides a sophisticated alternative to single-director architectures by implementing collective decision-making through voting, consensus, and role-based leadership. This example shows how to create and configure a board for strategic decision-making scenarios. + +## Basic Setup + +### 1. Import Required Modules + +```python +from swarms import Agent +from swarms.structs.board_of_directors_swarm import ( + BoardOfDirectorsSwarm, + BoardMember, + BoardMemberRole +) +from swarms.config.board_config import ( + enable_board_feature, + set_decision_threshold, + get_default_board_template +) +``` + +### 2. Enable Board Feature + +```python +# Enable the Board of Directors feature globally +enable_board_feature() + +# Set global decision threshold +set_decision_threshold(0.7) # 70% majority required +``` + +### 3. Create Board Members + +```python +# Create Chairman +chairman = Agent( + agent_name="Chairman", + agent_description="Chairman of the Board responsible for leading meetings and making final decisions", + model_name="gpt-4o-mini", + system_prompt="""You are the Chairman of the Board. Your responsibilities include: +1. Leading board meetings and discussions +2. Facilitating consensus among board members +3. Making final decisions when consensus cannot be reached +4. Ensuring all board members have an opportunity to contribute +5. Maintaining focus on the organization's goals and objectives + +You should be diplomatic, fair, and decisive in your leadership.""" +) + +# Create Vice Chairman +vice_chairman = Agent( + agent_name="Vice-Chairman", + agent_description="Vice Chairman who supports the Chairman and coordinates operations", + model_name="gpt-4o-mini", + system_prompt="""You are the Vice Chairman of the Board. Your responsibilities include: +1. Supporting the Chairman in leading board meetings +2. Coordinating operational activities and implementation +3. Ensuring effective communication between board members +4. Managing day-to-day board operations +5. Stepping in when the Chairman is unavailable + +You should be collaborative, organized, and supportive of the Chairman's leadership.""" +) + +# Create Secretary +secretary = Agent( + agent_name="Secretary", + agent_description="Secretary responsible for documentation and record keeping", + model_name="gpt-4o-mini", + system_prompt="""You are the Secretary of the Board. Your responsibilities include: +1. Documenting all board meetings and decisions +2. Maintaining accurate records and meeting minutes +3. Ensuring proper communication and notifications +4. Managing board documentation and archives +5. Supporting compliance and governance requirements + +You should be detail-oriented, organized, and thorough in your documentation.""" +) + +# Create Treasurer +treasurer = Agent( + agent_name="Treasurer", + agent_description="Treasurer responsible for financial oversight and resource management", + model_name="gpt-4o-mini", + system_prompt="""You are the Treasurer of the Board. Your responsibilities include: +1. Overseeing financial planning and budgeting +2. Monitoring resource allocation and utilization +3. Ensuring financial compliance and accountability +4. Providing financial insights for decision-making +5. Managing financial risk and controls + +You should be financially astute, analytical, and focused on value creation.""" +) + +# Create Executive Director +executive_director = Agent( + agent_name="Executive-Director", + agent_description="Executive Director responsible for strategic planning and operational oversight", + model_name="gpt-4o-mini", + system_prompt="""You are the Executive Director of the Board. Your responsibilities include: +1. Developing and implementing strategic plans +2. Overseeing operational performance and efficiency +3. Leading innovation and continuous improvement +4. Managing stakeholder relationships +5. Ensuring organizational effectiveness + +You should be strategic, results-oriented, and focused on organizational success.""" +) +``` + +### 4. Create BoardMember Objects + +```python +# Create BoardMember objects with roles, voting weights, and expertise areas +board_members = [ + BoardMember( + agent=chairman, + role=BoardMemberRole.CHAIRMAN, + voting_weight=1.5, + expertise_areas=["leadership", "strategy", "governance", "decision_making"] + ), + BoardMember( + agent=vice_chairman, + role=BoardMemberRole.VICE_CHAIRMAN, + voting_weight=1.2, + expertise_areas=["operations", "coordination", "communication", "implementation"] + ), + BoardMember( + agent=secretary, + role=BoardMemberRole.SECRETARY, + voting_weight=1.0, + expertise_areas=["documentation", "compliance", "record_keeping", "communication"] + ), + BoardMember( + agent=treasurer, + role=BoardMemberRole.TREASURER, + voting_weight=1.0, + expertise_areas=["finance", "budgeting", "risk_management", "resource_allocation"] + ), + BoardMember( + agent=executive_director, + role=BoardMemberRole.EXECUTIVE_DIRECTOR, + voting_weight=1.5, + expertise_areas=["strategy", "operations", "innovation", "performance_management"] + ) +] +``` + +### 5. Create Specialized Worker Agents + +```python +# Create specialized worker agents for different types of analysis +research_agent = Agent( + agent_name="Research-Specialist", + agent_description="Expert in market research, data analysis, and trend identification", + model_name="gpt-4o", + system_prompt="""You are a Research Specialist. Your responsibilities include: +1. Conducting comprehensive market research and analysis +2. Identifying trends, opportunities, and risks +3. Gathering and analyzing relevant data +4. Providing evidence-based insights and recommendations +5. Supporting strategic decision-making with research findings + +You should be thorough, analytical, and objective in your research.""" +) + +financial_agent = Agent( + agent_name="Financial-Analyst", + agent_description="Specialist in financial analysis, valuation, and investment assessment", + model_name="gpt-4o", + system_prompt="""You are a Financial Analyst. Your responsibilities include: +1. Conducting financial analysis and valuation +2. Assessing investment opportunities and risks +3. Analyzing financial performance and metrics +4. Providing financial insights and recommendations +5. Supporting financial decision-making + +You should be financially astute, analytical, and focused on value creation.""" +) + +technical_agent = Agent( + agent_name="Technical-Specialist", + agent_description="Expert in technical analysis, feasibility assessment, and implementation planning", + model_name="gpt-4o", + system_prompt="""You are a Technical Specialist. Your responsibilities include: +1. Conducting technical feasibility analysis +2. Assessing implementation requirements and challenges +3. Providing technical insights and recommendations +4. Supporting technical decision-making +5. Planning and coordinating technical implementations + +You should be technically proficient, practical, and solution-oriented.""" +) + +strategy_agent = Agent( + agent_name="Strategy-Specialist", + agent_description="Expert in strategic planning, competitive analysis, and business development", + model_name="gpt-4o", + system_prompt="""You are a Strategy Specialist. Your responsibilities include: +1. Developing strategic plans and initiatives +2. Conducting competitive analysis and market positioning +3. Identifying strategic opportunities and threats +4. Providing strategic insights and recommendations +5. Supporting strategic decision-making + +You should be strategic, forward-thinking, and focused on long-term success.""" +) +``` + +### 6. Initialize the Board of Directors Swarm + +```python +# Initialize the Board of Directors swarm with comprehensive configuration +board_swarm = BoardOfDirectorsSwarm( + name="Executive_Board_Swarm", + description="Executive board with specialized roles for strategic decision-making and collective intelligence", + board_members=board_members, + agents=[research_agent, financial_agent, technical_agent, strategy_agent], + max_loops=3, # Allow multiple iterations for complex analysis + verbose=True, # Enable detailed logging + decision_threshold=0.7, # 70% consensus required + enable_voting=True, # Enable voting mechanisms + enable_consensus=True, # Enable consensus building + max_workers=4, # Maximum parallel workers + output_type="dict" # Return results as dictionary +) +``` + +## Advanced Configuration + +### Custom Board Templates + +You can use pre-configured board templates for common use cases: + +```python +# Get a financial analysis board template +financial_board_template = get_default_board_template("financial_analysis") + +# Get a strategic planning board template +strategic_board_template = get_default_board_template("strategic_planning") + +# Get a technology assessment board template +tech_board_template = get_default_board_template("technology_assessment") +``` + +### Dynamic Role Assignment + +Automatically assign roles based on task requirements: + +```python +# Board members are automatically assigned roles based on expertise +board_swarm = BoardOfDirectorsSwarm( + board_members=board_members, + agents=agents, + auto_assign_roles=True, + role_mapping={ + "financial_analysis": ["Treasurer", "Financial_Member"], + "strategic_planning": ["Chairman", "Executive_Director"], + "technical_assessment": ["Technical_Member", "Executive_Director"], + "research_analysis": ["Research_Member", "Secretary"] + } +) +``` + +### Consensus Optimization + +Configure advanced consensus-building mechanisms: + +```python +# Enable advanced consensus features +board_swarm = BoardOfDirectorsSwarm( + board_members=board_members, + agents=agents, + enable_consensus=True, + consensus_timeout=300, # 5 minutes timeout + min_participation_rate=0.8, # 80% minimum participation + auto_fallback_to_chairman=True, # Chairman can make final decisions + consensus_rounds=3 # Maximum consensus building rounds +) +``` + +## Example Use Cases + +### 1. Strategic Investment Analysis + +```python +# Execute a complex strategic investment analysis +investment_task = """ +Analyze the strategic investment opportunity for a $50M Series B funding round in a +fintech startup. Consider market conditions, competitive landscape, financial projections, +technical feasibility, and strategic fit. Provide comprehensive recommendations including: +1. Investment recommendation (proceed/hold/decline) +2. Valuation analysis and suggested terms +3. Risk assessment and mitigation strategies +4. Strategic value and synergies +5. Implementation timeline and milestones +""" + +result = board_swarm.run(task=investment_task) +print("Investment Analysis Results:") +print(json.dumps(result, indent=2)) +``` + +### 2. Technology Strategy Development + +```python +# Develop a comprehensive technology strategy +tech_strategy_task = """ +Develop a comprehensive technology strategy for a mid-size manufacturing company +looking to digitize operations and implement Industry 4.0 technologies. Consider: +1. Current technology assessment and gaps +2. Technology roadmap and implementation plan +3. Investment requirements and ROI analysis +4. Risk assessment and mitigation strategies +5. Change management and training requirements +6. Competitive positioning and market advantages +""" + +result = board_swarm.run(task=tech_strategy_task) +print("Technology Strategy Results:") +print(json.dumps(result, indent=2)) +``` + +### 3. Market Entry Strategy + +```python +# Develop a market entry strategy for a new product +market_entry_task = """ +Develop a comprehensive market entry strategy for a new AI-powered productivity +software targeting the enterprise market. Consider: +1. Market analysis and opportunity assessment +2. Competitive landscape and positioning +3. Go-to-market strategy and channels +4. Pricing strategy and revenue model +5. Resource requirements and investment needs +6. Risk assessment and mitigation strategies +7. Success metrics and KPIs +""" + +result = board_swarm.run(task=market_entry_task) +print("Market Entry Strategy Results:") +print(json.dumps(result, indent=2)) +``` + +## Monitoring and Analysis + +### Board Performance Metrics + +```python +# Get board performance metrics +board_summary = board_swarm.get_board_summary() +print("Board Summary:") +print(f"Board Name: {board_summary['board_name']}") +print(f"Total Board Members: {board_summary['total_members']}") +print(f"Total Worker Agents: {board_summary['total_agents']}") +print(f"Decision Threshold: {board_summary['decision_threshold']}") +print(f"Max Loops: {board_summary['max_loops']}") + +# Display board member details +print("\nBoard Members:") +for member in board_summary['members']: + print(f"- {member['name']} (Role: {member['role']}, Weight: {member['voting_weight']})") + print(f" Expertise: {', '.join(member['expertise_areas'])}") + +# Display worker agent details +print("\nWorker Agents:") +for agent in board_summary['agents']: + print(f"- {agent['name']}: {agent['description']}") +``` + +### Decision Analysis + +```python +# Analyze decision-making patterns +if hasattr(result, 'get') and callable(result.get): + conversation_history = result.get('conversation_history', []) + + print(f"\nDecision Analysis:") + print(f"Total Messages: {len(conversation_history)}") + + # Count board member contributions + board_contributions = {} + for msg in conversation_history: + if 'Board' in msg.get('role', ''): + member_name = msg.get('agent_name', 'Unknown') + board_contributions[member_name] = board_contributions.get(member_name, 0) + 1 + + print(f"Board Member Contributions:") + for member, count in board_contributions.items(): + print(f"- {member}: {count} contributions") + + # Count agent executions + agent_executions = {} + for msg in conversation_history: + if any(agent.agent_name in msg.get('role', '') for agent in [research_agent, financial_agent, technical_agent, strategy_agent]): + agent_name = msg.get('agent_name', 'Unknown') + agent_executions[agent_name] = agent_executions.get(agent_name, 0) + 1 + + print(f"\nAgent Executions:") + for agent, count in agent_executions.items(): + print(f"- {agent}: {count} executions") +``` + +## Best Practices + +### 1. Role Definition +- Clearly define responsibilities for each board member +- Ensure expertise areas align with organizational needs +- Balance voting weights based on role importance + +### 2. Task Formulation +- Provide clear, specific task descriptions +- Include relevant context and constraints +- Specify expected outputs and deliverables + +### 3. Consensus Building +- Allow adequate time for discussion and consensus +- Encourage diverse perspectives and viewpoints +- Use structured decision-making processes + +### 4. Performance Monitoring +- Track decision quality and outcomes +- Monitor board member participation +- Analyze agent utilization and effectiveness + +### 5. Continuous Improvement +- Learn from each execution cycle +- Refine board composition and roles +- Optimize decision thresholds and processes + +## Troubleshooting + +### Common Issues + +1. **Consensus Failures**: Lower decision threshold or increase timeout +2. **Role Conflicts**: Ensure clear role definitions and responsibilities +3. **Agent Coordination**: Verify agent communication and task distribution +4. **Performance Issues**: Monitor resource usage and optimize configurations + +### Debug Commands + +```python +# Enable detailed logging +import logging +logging.basicConfig(level=logging.DEBUG) + +# Check board configuration +print(board_swarm.get_board_summary()) + +# Test individual components +for member in board_members: + print(f"Testing {member.agent.agent_name}...") + response = member.agent.run("Test message") + print(f"Response: {response[:100]}...") +``` + +## Conclusion + +This example demonstrates the comprehensive capabilities of the Board of Directors Swarm for democratic decision-making and collective intelligence. The feature provides a sophisticated alternative to single-director architectures, enabling more robust and well-considered decisions through voting, consensus, and role-based leadership. + +For more information, see the [Board of Directors Documentation](index.md) and [Configuration Guide](../config/board_config.md). \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_roles.md b/docs/swarms/structs/board_of_directors/board_of_directors_roles.md new file mode 100644 index 00000000..6f607c37 --- /dev/null +++ b/docs/swarms/structs/board_of_directors/board_of_directors_roles.md @@ -0,0 +1,1151 @@ +# Board of Directors Roles + +The Board of Directors system implements a hierarchical structure with clearly defined roles, responsibilities, and voting weights. Each role is designed to contribute specific expertise and authority to the decision-making process, ensuring comprehensive analysis and balanced decision-making. + +## Role Hierarchy + +```mermaid +graph TD + A[Chairman
Voting Weight: 1.5
Final Authority] --> B[Vice Chairman
Voting Weight: 1.2
Operational Support] + A --> C[Executive Director
Voting Weight: 1.5
Strategic Planning] + A --> D[Secretary
Voting Weight: 1.0
Documentation] + A --> E[Treasurer
Voting Weight: 1.0
Financial Oversight] + A --> F[Member
Voting Weight: 1.0
Expertise Contribution] + + B --> G[Operational Coordination] + C --> H[Strategic Initiatives] + D --> I[Record Keeping] + E --> J[Resource Management] + F --> K[Specialized Input] + + style A fill:#ffeb3b + style B fill:#2196f3 + style C fill:#4caf50 + style D fill:#ff9800 + style E fill:#9c27b0 + style F fill:#607d8b +``` + +**Diagram Explanation:** +This hierarchical diagram shows the organizational structure of the Board of Directors, with the Chairman at the top having final authority and the highest voting weight (1.5). The Chairman directly supervises all other board members, each with specific responsibilities and voting weights. The Vice Chairman and Executive Director have elevated voting weights (1.2 and 1.5 respectively) due to their senior positions, while the Secretary, Treasurer, and general Members have standard voting weights (1.0). Each role contributes specialized expertise to different aspects of the decision-making process. + +**Technical Implementation:** +```python +# Example: Role hierarchy implementation +class BoardRoleHierarchy: + def __init__(self): + self.roles = { + "CHAIRMAN": { + "voting_weight": 1.5, + "authority_level": "FINAL", + "supervises": ["VICE_CHAIRMAN", "EXECUTIVE_DIRECTOR", "SECRETARY", "TREASURER", "MEMBER"], + "responsibilities": ["leadership", "final_decision", "consensus_facilitation"], + "override_capability": True + }, + "VICE_CHAIRMAN": { + "voting_weight": 1.2, + "authority_level": "SENIOR", + "supervises": ["MEMBER"], + "responsibilities": ["operational_support", "coordination", "implementation"], + "backup_for": "CHAIRMAN" + }, + "EXECUTIVE_DIRECTOR": { + "voting_weight": 1.5, + "authority_level": "SENIOR", + "supervises": ["MEMBER"], + "responsibilities": ["strategic_planning", "execution_oversight", "performance_management"], + "strategic_authority": True + }, + "SECRETARY": { + "voting_weight": 1.0, + "authority_level": "STANDARD", + "supervises": [], + "responsibilities": ["documentation", "record_keeping", "communication"], + "administrative_authority": True + }, + "TREASURER": { + "voting_weight": 1.0, + "authority_level": "STANDARD", + "supervises": [], + "responsibilities": ["financial_oversight", "resource_management", "budget_control"], + "financial_authority": True + }, + "MEMBER": { + "voting_weight": 1.0, + "authority_level": "STANDARD", + "supervises": [], + "responsibilities": ["expertise_contribution", "analysis", "voting"], + "specialized_expertise": True + } + } + + def get_role_info(self, role_name): + """Get detailed information about a specific role""" + return self.roles.get(role_name, {}) + + def get_voting_weight(self, role_name): + """Get voting weight for a specific role""" + role_info = self.get_role_info(role_name) + return role_info.get("voting_weight", 1.0) + + def get_authority_level(self, role_name): + """Get authority level for a specific role""" + role_info = self.get_role_info(role_name) + return role_info.get("authority_level", "STANDARD") + + def can_override_decision(self, role_name): + """Check if a role can override board decisions""" + role_info = self.get_role_info(role_name) + return role_info.get("override_capability", False) + + def get_supervision_chain(self, role_name): + """Get the supervision chain for a specific role""" + supervision_chain = [] + current_role = role_name + + while current_role: + role_info = self.get_role_info(current_role) + if role_info: + supervision_chain.append(current_role) + # Find who supervises this role + current_role = None + for supervisor, info in self.roles.items(): + if current_role in info.get("supervises", []): + current_role = supervisor + break + else: + break + + return supervision_chain +``` + +## Chairman Role + +### Primary Responsibilities + +```mermaid +graph TD + A[Chairman] --> B[Meeting Leadership] + A --> C[Final Decision Authority] + A --> D[Consensus Facilitation] + A --> E[Strategic Direction] + A --> F[Stakeholder Communication] + + B --> G[Agenda Setting] + B --> H[Discussion Management] + B --> I[Time Management] + + C --> J[Approval Authority] + C --> K[Override Capability] + C --> L[Final Sign-off] + + D --> M[Conflict Resolution] + D --> N[Mediation] + D --> O[Compromise Facilitation] + + E --> P[Vision Setting] + E --> Q[Goal Definition] + E --> R[Priority Establishment] + + F --> S[External Relations] + F --> T[Stakeholder Updates] + F --> U[Public Communication] +``` + +**Diagram Explanation:** +This diagram illustrates the comprehensive responsibilities of the Chairman role, showing how the Chairman serves as the central authority figure with five main areas of responsibility. Meeting Leadership involves agenda setting, discussion management, and time management. Final Decision Authority includes approval authority, override capability, and final sign-off responsibilities. Consensus Facilitation covers conflict resolution, mediation, and compromise facilitation. Strategic Direction encompasses vision setting, goal definition, and priority establishment. Stakeholder Communication includes external relations, stakeholder updates, and public communication. + +**Technical Implementation:** +```python +# Example: Chairman role implementation +class Chairman: + def __init__(self, name, config): + self.name = name + self.config = config + self.authority_level = "FINAL" + self.voting_weight = 1.5 + self.override_capability = True + self.meeting_history = [] + self.decision_history = [] + + async def lead_meeting(self, task, board_members): + """Lead a board meeting for task discussion and decision-making""" + meeting_result = { + "meeting_id": self.generate_meeting_id(), + "task": task, + "participants": list(board_members.keys()), + "phases": [], + "decisions": [], + "consensus_achieved": False + } + + # Phase 1: Meeting Opening + opening_phase = await self.open_meeting(task, board_members) + meeting_result["phases"].append(opening_phase) + + # Phase 2: Agenda Review and Task Presentation + presentation_phase = await self.present_task(task, board_members) + meeting_result["phases"].append(presentation_phase) + + # Phase 3: Discussion Facilitation + discussion_phase = await self.facilitate_discussion(task, board_members) + meeting_result["phases"].append(discussion_phase) + + # Phase 4: Consensus Building + consensus_phase = await self.build_consensus(discussion_phase["proposals"], board_members) + meeting_result["phases"].append(consensus_phase) + + # Phase 5: Decision Making + decision_phase = await self.make_final_decision(consensus_phase, board_members) + meeting_result["phases"].append(decision_phase) + + meeting_result["decisions"] = decision_phase["decisions"] + meeting_result["consensus_achieved"] = consensus_phase["consensus_achieved"] + + # Record meeting in history + self.meeting_history.append(meeting_result) + + return meeting_result + + async def open_meeting(self, task, board_members): + """Open the board meeting and set the agenda""" + agenda = await self.create_agenda(task) + + opening_statement = f""" + Meeting called to order by Chairman {self.name}. + + Task: {task['description']} + Priority: {task.get('priority', 'Normal')} + Timeline: {task.get('timeline', 'Not specified')} + + Agenda: + {self.format_agenda(agenda)} + + Board members present: {', '.join(board_members.keys())} + """ + + return { + "phase": "meeting_opening", + "opening_statement": opening_statement, + "agenda": agenda, + "participants": list(board_members.keys()), + "timestamp": datetime.now().isoformat() + } + + async def create_agenda(self, task): + """Create a structured agenda for the meeting""" + agenda = { + "items": [ + { + "item": "Task Presentation", + "duration": "10 minutes", + "responsible": "Chairman", + "description": "Present task details and requirements" + }, + { + "item": "Expertise Assignment", + "duration": "5 minutes", + "responsible": "Chairman", + "description": "Assign analysis areas to board members" + }, + { + "item": "Individual Analysis", + "duration": "15 minutes", + "responsible": "All Members", + "description": "Board members analyze assigned areas" + }, + { + "item": "Group Discussion", + "duration": "20 minutes", + "responsible": "All Members", + "description": "Open discussion and debate" + }, + { + "item": "Proposal Development", + "duration": "15 minutes", + "responsible": "All Members", + "description": "Develop and refine proposals" + }, + { + "item": "Voting and Consensus", + "duration": "10 minutes", + "responsible": "All Members", + "description": "Vote on proposals and reach consensus" + }, + { + "item": "Decision Finalization", + "duration": "5 minutes", + "responsible": "Chairman", + "description": "Finalize decisions and assign execution" + } + ], + "total_duration": "80 minutes", + "break_time": "10 minutes" + } + + return agenda + + async def facilitate_discussion(self, task, board_members): + """Facilitate discussion among board members""" + discussion_result = { + "phase": "discussion_facilitation", + "discussion_points": [], + "conflicts": [], + "resolutions": [], + "proposals": [] + } + + # Guide discussion through structured phases + for member_role, member in board_members.items(): + # Get member's analysis + analysis = await member.analyze_task(task) + discussion_result["discussion_points"].append({ + "member": member_role, + "analysis": analysis, + "timestamp": datetime.now().isoformat() + }) + + # Identify conflicts + conflicts = await self.identify_conflicts(analysis, discussion_result["discussion_points"]) + discussion_result["conflicts"].extend(conflicts) + + # Facilitate conflict resolution + for conflict in conflicts: + resolution = await self.resolve_conflict(conflict, board_members) + discussion_result["resolutions"].append(resolution) + + # Develop proposals based on discussion + proposals = await self.develop_proposals(discussion_result["discussion_points"]) + discussion_result["proposals"] = proposals + + return discussion_result + + async def build_consensus(self, proposals, board_members): + """Build consensus among board members on proposals""" + consensus_result = { + "phase": "consensus_building", + "voting_rounds": [], + "consensus_achieved": False, + "final_proposal": None + } + + current_proposals = proposals + round_number = 1 + + while round_number <= self.config.get("max_consensus_rounds", 3): + # Conduct voting round + voting_result = await self.conduct_voting_round(current_proposals, board_members, round_number) + consensus_result["voting_rounds"].append(voting_result) + + # Check if consensus achieved + if voting_result["consensus_achieved"]: + consensus_result["consensus_achieved"] = True + consensus_result["final_proposal"] = voting_result["winning_proposal"] + break + + # Refine proposals for next round + current_proposals = await self.refine_proposals(current_proposals, voting_result) + round_number += 1 + + return consensus_result + + async def make_final_decision(self, consensus_result, board_members): + """Make final decision based on consensus or exercise authority""" + if consensus_result["consensus_achieved"]: + # Consensus reached, approve the decision + decision = { + "type": "consensus_decision", + "proposal": consensus_result["final_proposal"], + "approval_method": "consensus", + "board_support": "unanimous" + } + else: + # No consensus, exercise chairman authority + decision = await self.exercise_authority(consensus_result, board_members) + + decision_result = { + "phase": "final_decision", + "decision": decision, + "execution_plan": await self.create_execution_plan(decision), + "timestamp": datetime.now().isoformat() + } + + # Record decision in history + self.decision_history.append(decision_result) + + return decision_result + + async def exercise_authority(self, consensus_result, board_members): + """Exercise chairman authority when consensus cannot be reached""" + # Analyze all proposals and voting results + proposal_analysis = await self.analyze_proposals(consensus_result["voting_rounds"]) + + # Make decision based on best interests and available information + final_decision = await self.select_best_proposal(proposal_analysis) + + return { + "type": "authority_decision", + "proposal": final_decision, + "approval_method": "chairman_authority", + "rationale": final_decision["rationale"], + "board_support": final_decision["support_level"] + } +``` + +### Chairman's Decision Flow + +```mermaid +flowchart TD + A[Task Received] --> B[Assess Complexity] + B --> C[Determine Board Composition] + C --> D[Set Meeting Agenda] + D --> E[Lead Discussion] + E --> F[Facilitate Consensus] + F --> G{Consensus Reached?} + G -->|Yes| H[Approve Decision] + G -->|No| I[Exercise Authority] + I --> J[Make Final Decision] + H --> K[Oversee Execution] + J --> K + K --> L[Monitor Progress] + L --> M[Review Results] + M --> N[Final Approval] +``` + +**Diagram Explanation:** +This flowchart shows the Chairman's decision-making process from task reception to final approval. The process begins with task assessment and board composition determination, followed by agenda setting and discussion leadership. The Chairman then facilitates consensus building, and if consensus is reached, approves the decision. If consensus cannot be achieved, the Chairman exercises their authority to make a final decision. The Chairman then oversees execution, monitors progress, reviews results, and provides final approval. + +**Technical Implementation:** +```python +# Example: Chairman decision flow implementation +class ChairmanDecisionFlow: + def __init__(self, chairman): + self.chairman = chairman + self.decision_states = { + "TASK_RECEIVED": "Initial state when task is received", + "COMPLEXITY_ASSESSED": "Task complexity has been evaluated", + "BOARD_COMPOSED": "Board members have been selected", + "AGENDA_SET": "Meeting agenda has been created", + "DISCUSSION_LEAD": "Discussion has been facilitated", + "CONSENSUS_FACILITATED": "Consensus building has been attempted", + "DECISION_MADE": "Final decision has been made", + "EXECUTION_OVERSIGHT": "Execution is being monitored", + "PROGRESS_MONITORED": "Progress is being tracked", + "RESULTS_REVIEWED": "Results have been reviewed", + "FINAL_APPROVAL": "Final approval has been given" + } + + async def execute_decision_flow(self, task): + """Execute the complete chairman decision flow""" + flow_state = { + "current_state": "TASK_RECEIVED", + "task": task, + "transitions": [], + "decisions": [], + "timestamps": {} + } + + # Step 1: Assess Complexity + complexity_assessment = await self.assess_task_complexity(task) + flow_state["transitions"].append({ + "from": "TASK_RECEIVED", + "to": "COMPLEXITY_ASSESSED", + "assessment": complexity_assessment + }) + flow_state["current_state"] = "COMPLEXITY_ASSESSED" + flow_state["timestamps"]["complexity_assessed"] = datetime.now().isoformat() + + # Step 2: Determine Board Composition + board_composition = await self.determine_board_composition(complexity_assessment) + flow_state["transitions"].append({ + "from": "COMPLEXITY_ASSESSED", + "to": "BOARD_COMPOSED", + "composition": board_composition + }) + flow_state["current_state"] = "BOARD_COMPOSED" + flow_state["timestamps"]["board_composed"] = datetime.now().isoformat() + + # Step 3: Set Meeting Agenda + meeting_agenda = await self.set_meeting_agenda(task, board_composition) + flow_state["transitions"].append({ + "from": "BOARD_COMPOSED", + "to": "AGENDA_SET", + "agenda": meeting_agenda + }) + flow_state["current_state"] = "AGENDA_SET" + flow_state["timestamps"]["agenda_set"] = datetime.now().isoformat() + + # Step 4: Lead Discussion + discussion_result = await self.lead_discussion(task, board_composition, meeting_agenda) + flow_state["transitions"].append({ + "from": "AGENDA_SET", + "to": "DISCUSSION_LEAD", + "discussion": discussion_result + }) + flow_state["current_state"] = "DISCUSSION_LEAD" + flow_state["timestamps"]["discussion_led"] = datetime.now().isoformat() + + # Step 5: Facilitate Consensus + consensus_result = await self.facilitate_consensus(discussion_result) + flow_state["transitions"].append({ + "from": "DISCUSSION_LEAD", + "to": "CONSENSUS_FACILITATED", + "consensus": consensus_result + }) + flow_state["current_state"] = "CONSENSUS_FACILITATED" + flow_state["timestamps"]["consensus_facilitated"] = datetime.now().isoformat() + + # Step 6: Make Decision + if consensus_result["consensus_achieved"]: + decision = await self.approve_consensus_decision(consensus_result) + else: + decision = await self.exercise_authority(consensus_result) + + flow_state["decisions"].append(decision) + flow_state["transitions"].append({ + "from": "CONSENSUS_FACILITATED", + "to": "DECISION_MADE", + "decision": decision + }) + flow_state["current_state"] = "DECISION_MADE" + flow_state["timestamps"]["decision_made"] = datetime.now().isoformat() + + # Step 7: Oversee Execution + execution_oversight = await self.oversee_execution(decision) + flow_state["transitions"].append({ + "from": "DECISION_MADE", + "to": "EXECUTION_OVERSIGHT", + "oversight": execution_oversight + }) + flow_state["current_state"] = "EXECUTION_OVERSIGHT" + flow_state["timestamps"]["execution_oversight"] = datetime.now().isoformat() + + # Step 8: Monitor Progress + progress_monitoring = await self.monitor_progress(execution_oversight) + flow_state["transitions"].append({ + "from": "EXECUTION_OVERSIGHT", + "to": "PROGRESS_MONITORED", + "progress": progress_monitoring + }) + flow_state["current_state"] = "PROGRESS_MONITORED" + flow_state["timestamps"]["progress_monitored"] = datetime.now().isoformat() + + # Step 9: Review Results + results_review = await self.review_results(progress_monitoring) + flow_state["transitions"].append({ + "from": "PROGRESS_MONITORED", + "to": "RESULTS_REVIEWED", + "review": results_review + }) + flow_state["current_state"] = "RESULTS_REVIEWED" + flow_state["timestamps"]["results_reviewed"] = datetime.now().isoformat() + + # Step 10: Final Approval + final_approval = await self.give_final_approval(results_review) + flow_state["transitions"].append({ + "from": "RESULTS_REVIEWED", + "to": "FINAL_APPROVAL", + "approval": final_approval + }) + flow_state["current_state"] = "FINAL_APPROVAL" + flow_state["timestamps"]["final_approval"] = datetime.now().isoformat() + + return flow_state +``` + +### Key Competencies + +- **Leadership**: Ability to guide and inspire board members +- **Decision Making**: Strong analytical and judgment skills +- **Communication**: Excellent verbal and written communication +- **Conflict Resolution**: Skills in mediating disagreements +- **Strategic Thinking**: Long-term vision and planning ability +- **Stakeholder Management**: Relationship building and management + +## Vice Chairman Role + +### Supporting Responsibilities + +```mermaid +graph TD + A[Vice Chairman] --> B[Operational Support] + A --> C[Chairman Backup] + A --> D[Coordination] + A --> E[Implementation Oversight] + + B --> F[Meeting Support] + B --> G[Documentation Assistance] + B --> H[Logistics Management] + + C --> I[Acting Chairman] + C --> J[Decision Delegation] + C --> K[Authority Exercise] + + D --> L[Inter-Department Coordination] + D --> M[Resource Allocation] + D --> N[Timeline Management] + + E --> O[Execution Monitoring] + E --> P[Quality Control] + E --> Q[Performance Tracking] +``` + +**Diagram Explanation:** +This diagram shows the Vice Chairman's supporting role structure, highlighting four main areas of responsibility. Operational Support includes meeting support, documentation assistance, and logistics management. Chairman Backup involves acting as chairman when needed, decision delegation, and authority exercise. Coordination covers inter-department coordination, resource allocation, and timeline management. Implementation Oversight includes execution monitoring, quality control, and performance tracking. + +**Technical Implementation:** +```python +# Example: Vice Chairman role implementation +class ViceChairman: + def __init__(self, name, config): + self.name = name + self.config = config + self.authority_level = "SENIOR" + self.voting_weight = 1.2 + self.backup_for = "CHAIRMAN" + self.operational_areas = [] + self.coordination_history = [] + + async def provide_operational_support(self, chairman, task): + """Provide operational support to the chairman""" + support_areas = { + "meeting_support": await self.support_meeting_operations(chairman, task), + "documentation_assistance": await self.assist_with_documentation(task), + "logistics_management": await self.manage_logistics(task) + } + + return { + "support_provided": support_areas, + "timestamp": datetime.now().isoformat() + } + + async def act_as_chairman(self, chairman, reason): + """Act as chairman when the chairman is unavailable""" + acting_authority = { + "acting_chairman": self.name, + "original_chairman": chairman.name, + "reason": reason, + "authority_delegated": True, + "delegation_timestamp": datetime.now().isoformat() + } + + # Assume chairman responsibilities + acting_authority["capabilities"] = [ + "meeting_leadership", + "decision_making", + "consensus_facilitation", + "final_approval" + ] + + return acting_authority + + async def coordinate_operations(self, task, board_members): + """Coordinate operations across different areas""" + coordination_plan = { + "inter_department_coordination": await self.coordinate_departments(task), + "resource_allocation": await self.allocate_resources(task), + "timeline_management": await self.manage_timeline(task) + } + + self.coordination_history.append({ + "task": task, + "coordination_plan": coordination_plan, + "timestamp": datetime.now().isoformat() + }) + + return coordination_plan + + async def oversee_implementation(self, execution_plan): + """Oversee the implementation of board decisions""" + oversight_result = { + "execution_monitoring": await self.monitor_execution(execution_plan), + "quality_control": await self.control_quality(execution_plan), + "performance_tracking": await self.track_performance(execution_plan) + } + + return oversight_result +``` + +## Executive Director Role + +### Strategic Responsibilities + +```mermaid +graph TD + A[Executive Director] --> B[Strategic Planning] + A --> C[Execution Oversight] + A --> D[Performance Management] + A --> E[Strategic Initiatives] + + B --> F[Vision Development] + B --> G[Goal Setting] + B --> H[Strategy Formulation] + + C --> I[Implementation Monitoring] + C --> J[Progress Tracking] + C --> K[Issue Resolution] + + D --> L[KPI Definition] + D --> M[Performance Measurement] + D --> N[Improvement Planning] + + E --> O[Innovation Leadership] + E --> P[Change Management] + E --> Q[Strategic Partnerships] +``` + +**Diagram Explanation:** +This diagram illustrates the Executive Director's strategic role, showing four main areas of responsibility. Strategic Planning includes vision development, goal setting, and strategy formulation. Execution Oversight involves implementation monitoring, progress tracking, and issue resolution. Performance Management covers KPI definition, performance measurement, and improvement planning. Strategic Initiatives includes innovation leadership, change management, and strategic partnerships. + +**Technical Implementation:** +```python +# Example: Executive Director role implementation +class ExecutiveDirector: + def __init__(self, name, config): + self.name = name + self.config = config + self.authority_level = "SENIOR" + self.voting_weight = 1.5 + self.strategic_authority = True + self.performance_metrics = {} + self.strategic_initiatives = [] + + async def develop_strategic_plan(self, task, board_context): + """Develop strategic plan for task execution""" + strategic_plan = { + "vision": await self.develop_vision(task), + "goals": await self.set_goals(task), + "strategy": await self.formulate_strategy(task, board_context), + "timeline": await self.create_strategic_timeline(task), + "resources": await self.plan_strategic_resources(task) + } + + return strategic_plan + + async def oversee_execution(self, execution_plan): + """Oversee execution of strategic plans""" + oversight_result = { + "implementation_monitoring": await self.monitor_implementation(execution_plan), + "progress_tracking": await self.track_progress(execution_plan), + "issue_resolution": await self.resolve_issues(execution_plan) + } + + return oversight_result + + async def manage_performance(self, execution_results): + """Manage performance and define KPIs""" + performance_management = { + "kpi_definition": await self.define_kpis(execution_results), + "performance_measurement": await self.measure_performance(execution_results), + "improvement_planning": await self.plan_improvements(execution_results) + } + + return performance_management + + async def lead_strategic_initiatives(self, task): + """Lead strategic initiatives and innovation""" + strategic_initiatives = { + "innovation_leadership": await self.lead_innovation(task), + "change_management": await self.manage_change(task), + "strategic_partnerships": await self.develop_partnerships(task) + } + + self.strategic_initiatives.append({ + "task": task, + "initiatives": strategic_initiatives, + "timestamp": datetime.now().isoformat() + }) + + return strategic_initiatives +``` + +## Secretary Role + +### Administrative Responsibilities + +```mermaid +graph TD + A[Secretary] --> B[Documentation] + A --> C[Record Keeping] + A --> D[Communication] + A --> E[Administrative Support] + + B --> F[Meeting Minutes] + B --> G[Decision Records] + B --> H[Policy Documentation] + + C --> I[File Management] + C --> J[Record Maintenance] + C --> K[Archive Management] + + D --> L[Internal Communication] + D --> M[External Communication] + D --> N[Stakeholder Updates] + + E --> O[Meeting Coordination] + E --> P[Agenda Preparation] + E --> Q[Follow-up Actions] +``` + +**Diagram Explanation:** +This diagram shows the Secretary's administrative role structure, highlighting four main areas of responsibility. Documentation includes meeting minutes, decision records, and policy documentation. Record Keeping involves file management, record maintenance, and archive management. Communication covers internal communication, external communication, and stakeholder updates. Administrative Support includes meeting coordination, agenda preparation, and follow-up actions. + +**Technical Implementation:** +```python +# Example: Secretary role implementation +class Secretary: + def __init__(self, name, config): + self.name = name + self.config = config + self.authority_level = "STANDARD" + self.voting_weight = 1.0 + self.administrative_authority = True + self.documentation_repository = {} + self.communication_log = [] + + async def document_meeting(self, meeting_data): + """Document board meeting proceedings""" + meeting_documentation = { + "meeting_id": meeting_data["meeting_id"], + "date": meeting_data["timestamp"], + "participants": meeting_data["participants"], + "agenda": meeting_data["agenda"], + "minutes": await self.create_meeting_minutes(meeting_data), + "decisions": meeting_data["decisions"], + "action_items": await self.extract_action_items(meeting_data) + } + + # Store in documentation repository + self.documentation_repository[meeting_data["meeting_id"]] = meeting_documentation + + return meeting_documentation + + async def maintain_records(self, record_type, data): + """Maintain various types of records""" + record_entry = { + "type": record_type, + "data": data, + "timestamp": datetime.now().isoformat(), + "secretary": self.name + } + + if record_type not in self.documentation_repository: + self.documentation_repository[record_type] = [] + + self.documentation_repository[record_type].append(record_entry) + + return record_entry + + async def manage_communication(self, communication_type, content, recipients): + """Manage internal and external communication""" + communication = { + "type": communication_type, + "content": content, + "recipients": recipients, + "timestamp": datetime.now().isoformat(), + "secretary": self.name + } + + self.communication_log.append(communication) + + # Send communication based on type + if communication_type == "internal": + await self.send_internal_communication(communication) + elif communication_type == "external": + await self.send_external_communication(communication) + elif communication_type == "stakeholder_update": + await self.send_stakeholder_update(communication) + + return communication + + async def provide_administrative_support(self, board_members, task): + """Provide administrative support to board members""" + administrative_support = { + "meeting_coordination": await self.coordinate_meetings(board_members, task), + "agenda_preparation": await self.prepare_agendas(task), + "follow_up_actions": await self.manage_follow_up_actions(task) + } + + return administrative_support +``` + +## Treasurer Role + +### Financial Responsibilities + +```mermaid +graph TD + A[Treasurer] --> B[Financial Oversight] + A --> C[Resource Management] + A --> D[Budget Control] + A --> E[Financial Reporting] + + B --> F[Financial Analysis] + B --> G[Risk Assessment] + B --> H[Compliance Monitoring] + + C --> I[Resource Allocation] + C --> J[Cost Management] + C --> K[Efficiency Optimization] + + D --> L[Budget Planning] + D --> M[Expense Monitoring] + D --> N[Budget Adjustments] + + E --> O[Financial Statements] + E --> P[Performance Reports] + E --> Q[Stakeholder Reports] +``` + +**Diagram Explanation:** +This diagram illustrates the Treasurer's financial role structure, showing four main areas of responsibility. Financial Oversight includes financial analysis, risk assessment, and compliance monitoring. Resource Management involves resource allocation, cost management, and efficiency optimization. Budget Control covers budget planning, expense monitoring, and budget adjustments. Financial Reporting includes financial statements, performance reports, and stakeholder reports. + +**Technical Implementation:** +```python +# Example: Treasurer role implementation +class Treasurer: + def __init__(self, name, config): + self.name = name + self.config = config + self.authority_level = "STANDARD" + self.voting_weight = 1.0 + self.financial_authority = True + self.financial_records = {} + self.budget_tracking = {} + + async def provide_financial_oversight(self, task, budget): + """Provide financial oversight for task execution""" + financial_oversight = { + "financial_analysis": await self.analyze_financial_implications(task, budget), + "risk_assessment": await self.assess_financial_risks(task, budget), + "compliance_monitoring": await self.monitor_compliance(task, budget) + } + + return financial_oversight + + async def manage_resources(self, task, available_resources): + """Manage resource allocation and optimization""" + resource_management = { + "resource_allocation": await self.allocate_resources(task, available_resources), + "cost_management": await self.manage_costs(task), + "efficiency_optimization": await self.optimize_efficiency(task) + } + + return resource_management + + async def control_budget(self, task, budget_limits): + """Control budget and monitor expenses""" + budget_control = { + "budget_planning": await self.plan_budget(task, budget_limits), + "expense_monitoring": await self.monitor_expenses(task), + "budget_adjustments": await self.adjust_budget(task) + } + + # Track budget usage + self.budget_tracking[task["id"]] = budget_control + + return budget_control + + async def generate_financial_reports(self, task, financial_data): + """Generate financial reports and statements""" + financial_reports = { + "financial_statements": await self.create_financial_statements(financial_data), + "performance_reports": await self.create_performance_reports(financial_data), + "stakeholder_reports": await self.create_stakeholder_reports(financial_data) + } + + # Store financial records + self.financial_records[task["id"]] = financial_reports + + return financial_reports +``` + +## Member Role + +### General Responsibilities + +```mermaid +graph TD + A[Member] --> B[Expertise Contribution] + A --> C[Analysis] + A --> D[Voting] + A --> E[Specialized Input] + + B --> F[Domain Knowledge] + B --> G[Technical Expertise] + B --> H[Industry Experience] + + C --> I[Data Analysis] + C --> J[Impact Assessment] + C --> K[Feasibility Study] + + D --> L[Informed Voting] + D --> M[Proposal Evaluation] + D --> N[Consensus Building] + + E --> O[Specialized Recommendations] + E --> P[Risk Identification] + E --> Q[Opportunity Assessment] +``` + +**Diagram Explanation:** +This diagram shows the general Member role structure, highlighting four main areas of responsibility. Expertise Contribution includes domain knowledge, technical expertise, and industry experience. Analysis involves data analysis, impact assessment, and feasibility study. Voting covers informed voting, proposal evaluation, and consensus building. Specialized Input includes specialized recommendations, risk identification, and opportunity assessment. + +**Technical Implementation:** +```python +# Example: Member role implementation +class BoardMember: + def __init__(self, name, expertise_areas, config): + self.name = name + self.expertise_areas = expertise_areas + self.config = config + self.authority_level = "STANDARD" + self.voting_weight = 1.0 + self.specialized_expertise = True + self.analysis_history = [] + self.voting_history = [] + + async def contribute_expertise(self, task, expertise_areas): + """Contribute specialized expertise to task analysis""" + expertise_contribution = { + "domain_knowledge": await self.apply_domain_knowledge(task, expertise_areas), + "technical_expertise": await self.apply_technical_expertise(task, expertise_areas), + "industry_experience": await self.apply_industry_experience(task, expertise_areas) + } + + return expertise_contribution + + async def perform_analysis(self, task, data): + """Perform comprehensive analysis of task and data""" + analysis_result = { + "data_analysis": await self.analyze_data(task, data), + "impact_assessment": await self.assess_impact(task, data), + "feasibility_study": await self.study_feasibility(task, data) + } + + # Store analysis in history + self.analysis_history.append({ + "task": task, + "analysis": analysis_result, + "timestamp": datetime.now().isoformat() + }) + + return analysis_result + + async def vote_on_proposals(self, proposals, context): + """Vote on proposals based on analysis and expertise""" + voting_decision = { + "proposal_evaluations": await self.evaluate_proposals(proposals, context), + "informed_vote": await self.make_informed_vote(proposals, context), + "rationale": await self.provide_voting_rationale(proposals, context) + } + + # Store voting decision in history + self.voting_history.append({ + "proposals": proposals, + "decision": voting_decision, + "timestamp": datetime.now().isoformat() + }) + + return voting_decision + + async def provide_specialized_input(self, task, context): + """Provide specialized input based on expertise areas""" + specialized_input = { + "specialized_recommendations": await self.make_specialized_recommendations(task, context), + "risk_identification": await self.identify_risks(task, context), + "opportunity_assessment": await self.assess_opportunities(task, context) + } + + return specialized_input +``` + +## Role Interaction Patterns + +### Communication Flow + +```mermaid +graph TD + A[Chairman] --> B[Vice Chairman] + A --> C[Executive Director] + A --> D[Secretary] + A --> E[Treasurer] + A --> F[Members] + + B --> G[Operational Coordination] + C --> H[Strategic Alignment] + D --> I[Documentation Flow] + E --> J[Financial Oversight] + F --> K[Expertise Input] + + G --> L[Implementation] + H --> M[Strategic Execution] + I --> N[Record Keeping] + J --> O[Budget Control] + K --> P[Decision Support] +``` + +**Diagram Explanation:** +This diagram shows the communication flow and interaction patterns between different board roles. The Chairman serves as the central communication hub, coordinating with all other board members. Each role has specific communication channels and responsibilities: Vice Chairman handles operational coordination, Executive Director manages strategic alignment, Secretary manages documentation flow, Treasurer oversees financial matters, and Members provide expertise input. These interactions support implementation, strategic execution, record keeping, budget control, and decision support. + +**Technical Implementation:** +```python +# Example: Role interaction system +class RoleInteractionSystem: + def __init__(self, board_members): + self.board_members = board_members + self.communication_channels = {} + self.interaction_patterns = {} + + async def establish_communication_flow(self): + """Establish communication flow between board members""" + communication_flow = { + "chairman_communications": await self.setup_chairman_communications(), + "operational_coordination": await self.setup_operational_coordination(), + "strategic_alignment": await self.setup_strategic_alignment(), + "documentation_flow": await self.setup_documentation_flow(), + "financial_oversight": await self.setup_financial_oversight(), + "expertise_input": await self.setup_expertise_input() + } + + return communication_flow + + async def coordinate_role_interactions(self, task): + """Coordinate interactions between different roles""" + interactions = { + "chairman_vice_chairman": await self.coordinate_chairman_vice_chairman(task), + "chairman_executive_director": await self.coordinate_chairman_executive_director(task), + "secretary_documentation": await self.coordinate_secretary_documentation(task), + "treasurer_financial": await self.coordinate_treasurer_financial(task), + "member_expertise": await self.coordinate_member_expertise(task) + } + + return interactions +``` + +## Best Practices for Role Management + +### 1. Clear Role Definition +- Define specific responsibilities for each role +- Establish clear authority boundaries +- Document role interactions and communication protocols + +### 2. Balanced Voting Weights +- Ensure fair representation while maintaining leadership hierarchy +- Consider expertise and experience in weight assignment +- Regularly review and adjust weights based on performance + +### 3. Effective Communication +- Establish clear communication channels +- Implement regular reporting mechanisms +- Ensure transparency in decision-making processes + +### 4. Continuous Improvement +- Regularly assess role effectiveness +- Gather feedback from board members +- Implement improvements based on lessons learned + +### 5. Conflict Resolution +- Establish clear conflict resolution procedures +- Provide mediation mechanisms +- Ensure fair and impartial resolution processes \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_swarm.md b/docs/swarms/structs/board_of_directors/board_of_directors_swarm.md new file mode 100644 index 00000000..20223c49 --- /dev/null +++ b/docs/swarms/structs/board_of_directors/board_of_directors_swarm.md @@ -0,0 +1,704 @@ +# `BoardOfDirectorsSwarm` + +The `BoardOfDirectorsSwarm` is a sophisticated multi-agent orchestration system that implements a collective decision-making approach as an alternative to the single Director pattern. It consists of a board of directors that convenes to discuss, vote, and reach consensus on task distribution and execution strategies. + +## Overview + +The Board of Directors Swarm follows a democratic workflow pattern that mimics real-world corporate governance structures: + +1. **Task Reception**: User provides a task to the swarm +2. **Board Meeting**: Board of Directors convenes to discuss and create a plan +3. **Voting & Consensus**: Board members vote and reach consensus on task distribution +4. **Order Distribution**: Board distributes orders to specialized worker agents +5. **Execution**: Individual agents execute their assigned tasks +6. **Feedback Loop**: Board evaluates results and issues new orders if needed (up to `max_loops`) +7. **Context Preservation**: All conversation history and context is maintained throughout the process + +## Architecture + +### High-Level Workflow + +```mermaid +graph TD + A[User Task] --> B[Board of Directors] + B --> C[Board Meeting & Discussion] + C --> D[Voting & Consensus] + D --> E[Create Plan & Orders] + E --> F[Distribute to Agents] + F --> G[Agent 1] + F --> H[Agent 2] + F --> I[Agent N] + G --> J[Execute Task] + H --> J + I --> J + J --> K[Report Results] + K --> L[Board Evaluation] + L --> M{More Loops?} + M -->|Yes| C + M -->|No| N[Final Output] +``` + +**Diagram Explanation:** +This diagram illustrates the complete lifecycle of a task through the Board of Directors Swarm system. The workflow begins when a user submits a task, which triggers the board to convene for discussion and planning. The board then votes on the approach and creates detailed execution orders. These orders are distributed to multiple specialized agents who execute their tasks in parallel. Results are collected and evaluated by the board, which can trigger additional refinement loops if needed. The process continues until the board is satisfied with the results or the maximum number of loops is reached. + +**Key Technical Points:** +- **Parallel Execution**: Multiple agents can work simultaneously on different aspects of the task +- **Iterative Refinement**: The system supports multiple feedback loops for continuous improvement +- **Centralized Coordination**: The board maintains control over the entire process while delegating execution +- **Result Aggregation**: All agent outputs are collected and evaluated before proceeding + +### Detailed Decision-Making Process + +```mermaid +flowchart TD + A[Task Received] --> B[Board Convenes] + B --> C[Chairman Opens Meeting] + C --> D[Task Analysis Phase] + D --> E[Expertise Assignment] + E --> F[Individual Member Analysis] + F --> G[Discussion & Debate] + G --> H[Proposal Generation] + H --> I[Voting Process] + I --> J{Consensus Reached?} + J -->|No| K[Reconciliation Phase] + K --> G + J -->|Yes| L[Plan Finalization] + L --> M[Order Creation] + M --> N[Agent Assignment] + N --> O[Execution Phase] + O --> P[Result Collection] + P --> Q[Board Review] + Q --> R{Approval?} + R -->|No| S[Refinement Loop] + S --> G + R -->|Yes| T[Final Delivery] +``` + +**Diagram Explanation:** +This detailed flowchart shows the internal decision-making process within the board. The process begins with task reception and board convening, followed by a structured analysis phase where each board member contributes based on their expertise. The discussion and debate phase allows for thorough consideration of different approaches, leading to proposal generation and voting. If consensus isn't reached, the system enters a reconciliation phase to resolve conflicts. Once consensus is achieved, the plan is finalized and orders are created for agent assignment. The execution phase is followed by result collection and board review, with the option to enter refinement loops if the results don't meet approval criteria. + +**Technical Implementation Details:** +- **Expertise Assignment**: Board members are assigned tasks based on their specialized knowledge areas +- **Voting Mechanisms**: Configurable voting weights and decision thresholds ensure fair representation +- **Conflict Resolution**: Built-in reconciliation mechanisms handle disagreements among board members +- **Quality Gates**: Approval checkpoints ensure output quality before final delivery + +### Board Member Interaction Flow + +```mermaid +sequenceDiagram + participant User + participant Chairman + participant ViceChair + participant Secretary + participant Treasurer + participant ExecDir + participant Agents + + User->>Chairman: Submit Task + Chairman->>ViceChair: Notify Board Meeting + Chairman->>Secretary: Request Meeting Setup + Chairman->>Treasurer: Resource Assessment + Chairman->>ExecDir: Strategic Planning + + Note over Chairman,ExecDir: Board Discussion Phase + + Chairman->>ViceChair: Lead Discussion + ViceChair->>Secretary: Document Decisions + Secretary->>Treasurer: Budget Considerations + Treasurer->>ExecDir: Resource Allocation + ExecDir->>Chairman: Strategic Recommendations + + Note over Chairman,ExecDir: Voting & Consensus + + Chairman->>ViceChair: Call for Vote + ViceChair->>Secretary: Record Votes + Secretary->>Treasurer: Financial Approval + Treasurer->>ExecDir: Resource Approval + ExecDir->>Chairman: Final Decision + + Note over Chairman,Agents: Execution Phase + + Chairman->>Agents: Distribute Orders + Agents->>Chairman: Execute Tasks + Agents->>ViceChair: Progress Reports + Agents->>Secretary: Documentation + Agents->>Treasurer: Resource Usage + Agents->>ExecDir: Strategic Updates + + Note over Chairman,ExecDir: Review & Feedback + + Chairman->>User: Deliver Results +``` + +**Diagram Explanation:** +This sequence diagram shows the detailed interaction patterns between different board members and agents throughout the entire process. The interaction begins with the Chairman receiving a task from the user and immediately coordinating with other board members. Each board member has specific responsibilities: the Vice Chairman leads discussions, the Secretary documents decisions, the Treasurer handles resource assessment, and the Executive Director provides strategic planning. During the voting phase, each member contributes their expertise and votes are recorded systematically. In the execution phase, the Chairman distributes orders to agents while maintaining communication channels with all board members for progress monitoring and strategic updates. + +**Technical Communication Patterns:** +- **Hierarchical Communication**: Chairman serves as the central coordinator +- **Specialized Reporting**: Each agent reports to the appropriate board member based on their role +- **Parallel Coordination**: Multiple board members can work simultaneously on different aspects +- **Feedback Channels**: Continuous communication ensures real-time monitoring and adjustment + +### Agent Execution and Feedback Loop + +```mermaid +graph LR + subgraph "Board of Directors" + A[Chairman] + B[Vice Chairman] + C[Secretary] + D[Treasurer] + E[Executive Director] + end + + subgraph "Worker Agents" + F[Research Agent] + G[Analysis Agent] + H[Technical Agent] + I[Financial Agent] + J[Strategy Agent] + end + + subgraph "Execution Flow" + K[Task Distribution] + L[Parallel Execution] + M[Result Aggregation] + N[Quality Assessment] + O[Feedback Loop] + end + + A --> K + B --> K + C --> K + D --> K + E --> K + + K --> L + L --> F + L --> G + L --> H + L --> I + L --> J + + F --> M + G --> M + H --> M + I --> M + J --> M + + M --> N + N --> O + O --> K +``` + +**Diagram Explanation:** +This diagram illustrates the relationship between the Board of Directors and Worker Agents, showing how tasks flow from decision-making to execution and back through feedback loops. The Board of Directors collectively participates in task distribution, ensuring that all perspectives are considered. Worker agents execute tasks in parallel, each specializing in different areas (research, analysis, technical implementation, financial considerations, and strategic planning). Results are aggregated and assessed for quality before determining whether additional feedback loops are needed. + +**Technical Architecture Benefits:** +- **Separation of Concerns**: Clear distinction between decision-making (Board) and execution (Agents) +- **Scalability**: Additional agents can be added without changing the board structure +- **Fault Tolerance**: If one agent fails, others can continue working +- **Quality Control**: Centralized assessment ensures consistent output quality + +## Technical Implementation + +### Core Components + +The `BoardOfDirectorsSwarm` consists of several key components: + +1. **Board Members**: Specialized agents with specific roles and voting weights +2. **Worker Agents**: Execution agents that perform the actual tasks +3. **Voting System**: Configurable voting mechanisms for decision-making +4. **Communication Protocol**: Structured communication between board members and agents +5. **Feedback Loop Controller**: Manages iterative refinement processes + +### Configuration Options + +```python +# Example configuration for BoardOfDirectorsSwarm +board_config = { + "max_loops": 3, # Maximum number of refinement loops + "voting_threshold": 0.7, # Consensus threshold (70%) + "enable_voting_weights": True, # Use weighted voting + "consensus_method": "majority", # Voting method: "majority" or "unanimous" + "board_size": 5, # Number of board members + "enable_feedback_loops": True, # Enable iterative refinement + "output_format": "structured", # Output format: "structured", "text", "json" + "enable_logging": True, # Enable detailed logging + "parallel_execution": True, # Enable parallel agent execution + "quality_gates": True, # Enable quality checkpoints +} +``` + +### Voting Mechanisms + +The system supports multiple voting mechanisms: + +1. **Majority Voting**: Simple majority of votes required +2. **Weighted Voting**: Votes weighted by board member importance +3. **Unanimous Consensus**: All board members must agree +4. **Threshold-based**: Configurable percentage of agreement required + +```python +# Example voting configuration +voting_config = { + "method": "weighted_majority", + "threshold": 0.75, + "weights": { + "CHAIRMAN": 1.5, + "VICE_CHAIRMAN": 1.2, + "SECRETARY": 1.0, + "TREASURER": 1.0, + "EXECUTIVE_DIRECTOR": 1.5 + }, + "tie_breaker": "CHAIRMAN", # Chairman breaks ties + "allow_abstention": True, # Allow board members to abstain +} +``` + +### Communication Protocols + +The system uses structured communication protocols: + +1. **Task Distribution Protocol**: Standardized format for distributing tasks to agents +2. **Progress Reporting Protocol**: Regular status updates from agents to board +3. **Decision Communication Protocol**: Clear communication of board decisions +4. **Feedback Protocol**: Structured feedback for iterative improvement + +```python +# Example communication message format +message_format = { + "sender": "CHAIRMAN", + "recipient": "RESEARCH_AGENT", + "message_type": "TASK_DISTRIBUTION", + "content": { + "task_id": "task_123", + "task_description": "Research market trends for Q4", + "deadline": "2024-01-15T10:00:00Z", + "priority": "HIGH", + "resources": ["market_data", "analytics_tools"], + "expected_output": "structured_report" + }, + "metadata": { + "timestamp": "2024-01-10T09:00:00Z", + "session_id": "session_456", + "board_decision_id": "decision_789" + } +} +``` + +## Usage Examples + +### Basic Usage + +```python +from swarms import BoardOfDirectorsSwarm, Agent + +# Create specialized agents +research_agent = Agent( + name="Research Agent", + system_prompt="You are a research specialist focused on market analysis and data gathering.", + llm="gpt-4" +) + +analysis_agent = Agent( + name="Analysis Agent", + system_prompt="You are an analysis expert who interprets data and provides insights.", + llm="gpt-4" +) + +technical_agent = Agent( + name="Technical Agent", + system_prompt="You are a technical specialist who handles implementation and technical details.", + llm="gpt-4" +) + +# Create the Board of Directors Swarm +board_swarm = BoardOfDirectorsSwarm( + agents=[research_agent, analysis_agent, technical_agent], + max_loops=3, + voting_threshold=0.7, + enable_voting_weights=True +) + +# Execute a task +task = "Analyze the current market trends in AI and provide strategic recommendations for our company." +result = board_swarm.run(task) +print(result) +``` + +### Advanced Configuration + +```python +from swarms import BoardOfDirectorsSwarm, Agent +from swarms.structs.board_of_directors import BoardConfig + +# Create a custom board configuration +custom_config = BoardConfig( + max_loops=5, + voting_threshold=0.8, + consensus_method="unanimous", + enable_feedback_loops=True, + output_format="structured", + board_roles={ + "CHAIRMAN": {"weight": 1.5, "responsibilities": ["leadership", "final_decision"]}, + "VICE_CHAIRMAN": {"weight": 1.2, "responsibilities": ["operations", "coordination"]}, + "SECRETARY": {"weight": 1.0, "responsibilities": ["documentation", "record_keeping"]}, + "TREASURER": {"weight": 1.0, "responsibilities": ["financial_oversight", "resource_allocation"]}, + "EXECUTIVE_DIRECTOR": {"weight": 1.5, "responsibilities": ["strategic_planning", "execution"]} + } +) + +# Create specialized agents with custom prompts +agents = [ + Agent( + name="Market Research Agent", + system_prompt="""You are a market research specialist with expertise in: + - Competitive analysis + - Market sizing and segmentation + - Customer behavior analysis + - Industry trend identification + Provide detailed, data-driven insights.""", + llm="gpt-4" + ), + Agent( + name="Financial Analysis Agent", + system_prompt="""You are a financial analyst specializing in: + - Financial modeling and forecasting + - Risk assessment and mitigation + - Investment analysis + - Cost-benefit analysis + Provide comprehensive financial insights.""", + llm="gpt-4" + ), + Agent( + name="Technical Strategy Agent", + system_prompt="""You are a technical strategist focused on: + - Technology roadmap planning + - Technical feasibility assessment + - Implementation strategy + - Technology risk evaluation + Provide strategic technical guidance.""", + llm="gpt-4" + ) +] + +# Create the swarm with custom configuration +board_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=custom_config +) + +# Execute a complex task +complex_task = """ +Analyze the feasibility of launching a new AI-powered product in the healthcare sector. +Consider: +1. Market opportunity and competitive landscape +2. Financial viability and investment requirements +3. Technical implementation challenges and timeline +4. Regulatory compliance requirements +5. Risk assessment and mitigation strategies + +Provide a comprehensive report with recommendations for next steps. +""" + +result = board_swarm.run(complex_task) +print(result) +``` + +### Real-World Use Cases + +#### 1. Strategic Business Planning + +```python +# Example: Strategic business planning with multiple stakeholders +business_planning_task = """ +Develop a comprehensive 5-year strategic plan for our technology company. +Include: +- Market analysis and competitive positioning +- Product development roadmap +- Financial projections and funding requirements +- Operational scaling strategy +- Risk management framework +- Success metrics and KPIs +""" + +# Configure board for strategic planning +strategic_config = BoardConfig( + max_loops=4, + voting_threshold=0.8, + consensus_method="weighted_majority", + enable_feedback_loops=True, + output_format="structured" +) + +strategic_swarm = BoardOfDirectorsSwarm( + agents=[market_agent, financial_agent, technical_agent, strategy_agent], + config=strategic_config +) + +strategic_plan = strategic_swarm.run(business_planning_task) +``` + +#### 2. Product Development Decision Making + +```python +# Example: Product development decision making +product_decision_task = """ +Evaluate the feasibility of developing a new AI-powered customer service chatbot. +Consider: +- Technical requirements and development timeline +- Market demand and competitive analysis +- Cost-benefit analysis and ROI projections +- Implementation challenges and resource requirements +- Success criteria and measurement metrics + +Provide a go/no-go recommendation with detailed rationale. +""" + +# Configure board for product decisions +product_config = BoardConfig( + max_loops=3, + voting_threshold=0.75, + consensus_method="majority", + enable_feedback_loops=True, + output_format="structured" +) + +product_swarm = BoardOfDirectorsSwarm( + agents=[technical_agent, market_agent, financial_agent], + config=product_config +) + +product_recommendation = product_swarm.run(product_decision_task) +``` + +#### 3. Crisis Management and Response + +```python +# Example: Crisis management and response planning +crisis_task = """ +Our company is facing a major data breach. Develop an immediate response plan. +Include: +- Immediate containment and mitigation steps +- Communication strategy for stakeholders +- Legal and regulatory compliance requirements +- Financial impact assessment +- Long-term recovery and prevention measures +- Timeline and resource allocation +""" + +# Configure board for crisis management +crisis_config = BoardConfig( + max_loops=2, # Faster response needed + voting_threshold=0.6, # Lower threshold for urgent decisions + consensus_method="majority", + enable_feedback_loops=False, # No time for multiple iterations + output_format="structured" +) + +crisis_swarm = BoardOfDirectorsSwarm( + agents=[security_agent, legal_agent, communications_agent, financial_agent], + config=crisis_config +) + +crisis_response = crisis_swarm.run(crisis_task) +``` + +## Performance Optimization + +### Parallel Execution Strategies + +The Board of Directors Swarm supports various parallel execution strategies: + +1. **Task-Level Parallelism**: Multiple agents work on different aspects simultaneously +2. **Board-Level Parallelism**: Board members can analyze different aspects in parallel +3. **Iteration-Level Parallelism**: Multiple refinement loops can run concurrently + +```python +# Example: Optimizing for parallel execution +parallel_config = BoardConfig( + max_loops=3, + parallel_execution=True, + max_concurrent_agents=5, + enable_async_processing=True, + timeout_per_agent=300, # 5 minutes per agent + enable_agent_pooling=True +) + +# Create agent pool for better resource utilization +agent_pool = [ + Agent(name=f"Research_Agent_{i}", system_prompt="...", llm="gpt-4") + for i in range(3) +] + [ + Agent(name=f"Analysis_Agent_{i}", system_prompt="...", llm="gpt-4") + for i in range(2) +] + +parallel_swarm = BoardOfDirectorsSwarm( + agents=agent_pool, + config=parallel_config +) +``` + +### Quality Control Mechanisms + +```python +# Example: Quality control configuration +quality_config = BoardConfig( + max_loops=3, + quality_gates=True, + quality_threshold=0.8, + enable_peer_review=True, + review_required=True, + output_validation=True, + enable_metrics_tracking=True +) + +# Define quality metrics +quality_metrics = { + "completeness": 0.9, # 90% completeness required + "accuracy": 0.85, # 85% accuracy required + "relevance": 0.9, # 90% relevance required + "clarity": 0.8 # 80% clarity required +} + +quality_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=quality_config, + quality_metrics=quality_metrics +) +``` + +## Monitoring and Debugging + +### Logging and Observability + +```python +import logging +from swarms import BoardOfDirectorsSwarm + +# Configure detailed logging +logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) + +# Create swarm with logging enabled +logging_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=BoardConfig( + enable_logging=True, + log_level="DEBUG", + enable_metrics=True, + enable_tracing=True + ) +) + +# Execute with detailed logging +result = logging_swarm.run(task) +``` + +### Performance Metrics + +```python +# Example: Performance monitoring +from swarms.metrics import SwarmMetrics + +# Create metrics collector +metrics = SwarmMetrics() + +# Configure swarm with metrics +monitored_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=BoardConfig(enable_metrics=True), + metrics_collector=metrics +) + +# Execute and collect metrics +result = monitored_swarm.run(task) + +# Analyze performance +performance_report = metrics.generate_report() +print(f"Total execution time: {performance_report['total_time']}") +print(f"Average agent response time: {performance_report['avg_agent_time']}") +print(f"Number of voting rounds: {performance_report['voting_rounds']}") +print(f"Consensus achieved: {performance_report['consensus_achieved']}") +``` + +## Best Practices + +### 1. Agent Design + +- **Specialized Expertise**: Design agents with specific, complementary expertise +- **Clear Responsibilities**: Define clear boundaries for each agent's responsibilities +- **Consistent Communication**: Use standardized communication protocols +- **Error Handling**: Implement robust error handling and recovery mechanisms + +### 2. Board Configuration + +- **Appropriate Voting Thresholds**: Set thresholds based on decision criticality +- **Balanced Voting Weights**: Ensure fair representation while maintaining leadership hierarchy +- **Flexible Consensus Methods**: Choose consensus methods based on decision type +- **Reasonable Loop Limits**: Balance quality with efficiency + +### 3. Task Design + +- **Clear Objectives**: Define clear, measurable objectives +- **Structured Requirements**: Provide structured, detailed requirements +- **Appropriate Scope**: Ensure tasks are appropriately scoped for the board size +- **Context Provision**: Provide sufficient context for informed decision-making + +### 4. Performance Optimization + +- **Parallel Execution**: Leverage parallel execution where possible +- **Resource Management**: Monitor and optimize resource usage +- **Quality Gates**: Implement appropriate quality control mechanisms +- **Continuous Monitoring**: Monitor performance and adjust configurations as needed + +## Troubleshooting + +### Common Issues and Solutions + +1. **Consensus Not Reached** + - **Issue**: Board cannot reach consensus within loop limit + - **Solution**: Lower voting threshold, increase max_loops, or adjust voting weights + +2. **Agent Timeout** + - **Issue**: Individual agents take too long to respond + - **Solution**: Increase timeout settings or optimize agent prompts + +3. **Poor Quality Output** + - **Issue**: Final output doesn't meet quality standards + - **Solution**: Enable quality gates, increase max_loops, or improve agent prompts + +4. **Resource Exhaustion** + - **Issue**: System runs out of resources during execution + - **Solution**: Implement resource limits, use agent pooling, or optimize parallel execution + +### Debugging Techniques + +```python +# Example: Debugging configuration +debug_config = BoardConfig( + max_loops=1, # Limit loops for debugging + enable_logging=True, + log_level="DEBUG", + enable_tracing=True, + debug_mode=True +) + +# Create debug swarm +debug_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=debug_config +) + +# Execute with debugging +try: + result = debug_swarm.run(task) +except Exception as e: + print(f"Error: {e}") + print(f"Debug info: {debug_swarm.get_debug_info()}") +``` \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_workflow.md b/docs/swarms/structs/board_of_directors/board_of_directors_workflow.md new file mode 100644 index 00000000..3e913ea7 --- /dev/null +++ b/docs/swarms/structs/board_of_directors/board_of_directors_workflow.md @@ -0,0 +1,908 @@ +# Board of Directors Workflow + +The Board of Directors workflow is a sophisticated multi-stage process that ensures comprehensive task analysis, collaborative decision-making, and effective execution through specialized agents. This workflow implements a corporate governance model that balances efficiency with thoroughness, ensuring high-quality outcomes through structured collaboration. + +## Workflow Overview + +```mermaid +graph TD + A[Task Input] --> B[Initial Assessment] + B --> C[Board Assembly] + C --> D[Meeting Phase] + D --> E[Decision Phase] + E --> F[Execution Phase] + F --> G[Review Phase] + G --> H{Approval?} + H -->|No| I[Refinement] + I --> D + H -->|Yes| J[Final Delivery] + + style A fill:#e1f5fe + style J fill:#c8e6c9 + style H fill:#fff3e0 +``` + +**Diagram Explanation:** +This high-level workflow diagram shows the complete lifecycle of a task through the Board of Directors system. The process begins with task input, followed by an initial assessment to understand requirements and complexity. The board then assembles with appropriate members, conducts a structured meeting phase for analysis and discussion, makes decisions through voting and consensus, executes the plan through specialized agents, reviews results, and either approves for final delivery or returns to refinement loops for improvement. + +**Technical Implementation Details:** +- **Task Input Validation**: System validates task format, requirements, and constraints +- **Dynamic Board Assembly**: Board members are selected based on task requirements and availability +- **Structured Meeting Protocol**: Follows corporate governance best practices +- **Iterative Refinement**: Quality gates ensure output meets standards before final delivery + +## Phase 1: Initial Assessment + +### Task Analysis and Board Preparation + +```mermaid +flowchart LR + A[Task Received] --> B[Complexity Assessment] + B --> C[Resource Requirements] + C --> D[Expertise Mapping] + D --> E[Board Member Selection] + E --> F[Meeting Scheduling] + + subgraph "Assessment Criteria" + G[Task Complexity] + H[Time Constraints] + I[Resource Availability] + J[Expertise Requirements] + end + + B --> G + B --> H + C --> I + D --> J +``` + +**Diagram Explanation:** +This flowchart illustrates the systematic approach to task analysis and board preparation. When a task is received, the system performs a comprehensive assessment including complexity evaluation, resource requirement analysis, expertise mapping, and board member selection. The assessment criteria include task complexity, time constraints, resource availability, and specific expertise requirements needed for successful completion. + +**Technical Implementation:** +```python +# Example: Task assessment implementation +class TaskAssessment: + def __init__(self): + self.complexity_metrics = { + "scope": 0.0, # Task scope (0-1) + "technical_depth": 0.0, # Technical complexity (0-1) + "stakeholder_count": 0, # Number of stakeholders + "timeline_constraints": 0.0, # Time pressure (0-1) + "resource_intensity": 0.0 # Resource requirements (0-1) + } + + def assess_task(self, task_description): + """Assess task complexity and requirements""" + assessment = { + "complexity_score": self.calculate_complexity(), + "required_expertise": self.identify_expertise_needs(), + "resource_requirements": self.estimate_resources(), + "timeline_estimate": self.estimate_timeline(), + "recommended_board_size": self.calculate_board_size() + } + return assessment + + def calculate_complexity(self): + """Calculate overall task complexity score""" + weights = { + "scope": 0.25, + "technical_depth": 0.3, + "stakeholder_count": 0.15, + "timeline_constraints": 0.2, + "resource_intensity": 0.1 + } + + complexity_score = sum( + self.complexity_metrics[key] * weights[key] + for key in weights + ) + return min(complexity_score, 1.0) + + def identify_expertise_needs(self): + """Identify required expertise areas""" + expertise_areas = [] + + if self.complexity_metrics["technical_depth"] > 0.5: + expertise_areas.append("technical") + + if self.complexity_metrics["stakeholder_count"] > 3: + expertise_areas.append("stakeholder_management") + + if self.complexity_metrics["resource_intensity"] > 0.5: + expertise_areas.append("resource_management") + + return expertise_areas +``` + +### Board Member Activation + +```mermaid +sequenceDiagram + participant System + participant Chairman + participant Members + participant Agents + + System->>Chairman: Notify New Task + Chairman->>System: Assess Task Requirements + System->>Members: Activate Relevant Members + Members->>Chairman: Confirm Availability + Chairman->>Agents: Prepare Agent Pool + Agents->>Chairman: Confirm Readiness + Chairman->>System: Board Ready for Meeting +``` + +**Diagram Explanation:** +This sequence diagram shows the systematic process of board member activation and preparation. The system notifies the Chairman of a new task, who then assesses requirements and determines which board members are needed. The system activates relevant members, who confirm their availability. The Chairman prepares the agent pool and confirms readiness before declaring the board ready for the meeting. + +**Technical Implementation:** +```python +# Example: Board member activation system +class BoardActivation: + def __init__(self, board_members, agents): + self.board_members = board_members + self.agents = agents + self.activation_status = {} + + async def activate_board(self, task_assessment): + """Activate board members based on task requirements""" + # Determine required members + required_members = self.select_required_members(task_assessment) + + # Activate members + activation_results = [] + for member in required_members: + status = await self.activate_member(member, task_assessment) + activation_results.append(status) + + # Prepare agent pool + agent_pool = self.prepare_agent_pool(task_assessment) + + # Confirm readiness + readiness_status = await self.confirm_readiness(activation_results, agent_pool) + + return { + "board_ready": readiness_status["ready"], + "active_members": readiness_status["active_members"], + "agent_pool": readiness_status["agent_pool"], + "estimated_start_time": readiness_status["start_time"] + } + + def select_required_members(self, assessment): + """Select board members based on task requirements""" + required_members = ["CHAIRMAN"] # Chairman always required + + if assessment["complexity_score"] > 0.7: + required_members.extend(["VICE_CHAIRMAN", "EXECUTIVE_DIRECTOR"]) + + if "technical" in assessment["required_expertise"]: + required_members.append("TECHNICAL_DIRECTOR") + + if "financial" in assessment["required_expertise"]: + required_members.append("TREASURER") + + if assessment["stakeholder_count"] > 5: + required_members.append("SECRETARY") + + return list(set(required_members)) # Remove duplicates + + async def activate_member(self, member_role, assessment): + """Activate individual board member""" + member = self.board_members.get(member_role) + if not member: + return {"status": "error", "message": f"Member {member_role} not found"} + + # Check availability + availability = await member.check_availability() + if not availability["available"]: + return {"status": "unavailable", "member": member_role, "reason": availability["reason"]} + + # Prepare member for task + preparation_status = await member.prepare_for_task(assessment) + + return { + "status": "activated", + "member": member_role, + "preparation_time": preparation_status["preparation_time"], + "expertise_areas": preparation_status["expertise_areas"] + } +``` + +## Phase 2: Board Meeting + +### Meeting Structure + +```mermaid +graph TD + A[Meeting Opens] --> B[Agenda Review] + B --> C[Task Presentation] + C --> D[Expertise Assignment] + D --> E[Individual Analysis] + E --> F[Group Discussion] + F --> G[Proposal Development] + G --> H[Voting Process] + H --> I[Consensus Building] + I --> J[Plan Finalization] + + subgraph "Meeting Components" + K[Time Management] + L[Documentation] + M[Conflict Resolution] + N[Decision Recording] + end + + A --> K + F --> L + I --> M + J --> N +``` + +**Diagram Explanation:** +This diagram shows the structured meeting process that follows corporate governance best practices. The meeting begins with agenda review and task presentation, followed by expertise assignment where board members are given specific areas to analyze. Individual analysis leads to group discussion, proposal development, voting, consensus building, and plan finalization. Throughout the process, time management, documentation, conflict resolution, and decision recording ensure effective governance. + +**Technical Implementation:** +```python +# Example: Meeting management system +class BoardMeeting: + def __init__(self, board_members, task, config): + self.board_members = board_members + self.task = task + self.config = config + self.meeting_phases = [] + self.decisions = [] + self.documentation = {} + + async def conduct_meeting(self): + """Conduct the board meeting following structured phases""" + meeting_result = { + "phases": [], + "decisions": [], + "documentation": {}, + "consensus_achieved": False, + "final_plan": None + } + + # Phase 1: Meeting Opening and Agenda Review + opening_phase = await self.conduct_opening_phase() + meeting_result["phases"].append(opening_phase) + + # Phase 2: Task Presentation and Expertise Assignment + presentation_phase = await self.conduct_presentation_phase() + meeting_result["phases"].append(presentation_phase) + + # Phase 3: Individual Analysis + analysis_phase = await self.conduct_analysis_phase() + meeting_result["phases"].append(analysis_phase) + + # Phase 4: Group Discussion + discussion_phase = await self.conduct_discussion_phase() + meeting_result["phases"].append(discussion_phase) + + # Phase 5: Proposal Development + proposal_phase = await self.conduct_proposal_phase() + meeting_result["phases"].append(proposal_phase) + + # Phase 6: Voting and Consensus + voting_phase = await self.conduct_voting_phase() + meeting_result["phases"].append(voting_phase) + + # Phase 7: Plan Finalization + finalization_phase = await self.conduct_finalization_phase() + meeting_result["phases"].append(finalization_phase) + + meeting_result["decisions"] = self.decisions + meeting_result["documentation"] = self.documentation + meeting_result["consensus_achieved"] = voting_phase["consensus_achieved"] + meeting_result["final_plan"] = finalization_phase["final_plan"] + + return meeting_result + + async def conduct_opening_phase(self): + """Conduct meeting opening and agenda review""" + chairman = self.board_members["CHAIRMAN"] + + # Open meeting + opening_statement = await chairman.open_meeting(self.task) + + # Review agenda + agenda_review = await chairman.review_agenda(self.task) + + # Set meeting parameters + meeting_params = { + "time_limit": self.config.get("meeting_time_limit", 3600), # 1 hour default + "voting_threshold": self.config.get("voting_threshold", 0.7), + "consensus_method": self.config.get("consensus_method", "majority") + } + + return { + "phase": "opening", + "opening_statement": opening_statement, + "agenda_review": agenda_review, + "meeting_params": meeting_params, + "timestamp": datetime.now().isoformat() + } + + async def conduct_presentation_phase(self): + """Conduct task presentation and expertise assignment""" + chairman = self.board_members["CHAIRMAN"] + + # Present task details + task_presentation = await chairman.present_task(self.task) + + # Assign expertise areas + expertise_assignments = await chairman.assign_expertise_areas( + self.board_members, self.task + ) + + return { + "phase": "presentation", + "task_presentation": task_presentation, + "expertise_assignments": expertise_assignments, + "timestamp": datetime.now().isoformat() + } +``` + +### Discussion and Debate Process + +```mermaid +flowchart TD + A[Discussion Opens] --> B[Expertise-Based Input] + B --> C[Cross-Examination] + C --> D[Alternative Proposals] + D --> E[Impact Analysis] + E --> F[Risk Assessment] + F --> G[Stakeholder Consideration] + G --> H[Resource Evaluation] + H --> I[Timeline Assessment] + I --> J[Consensus Check] + J -->|No Consensus| K[Conflict Resolution] + K --> L[Mediation Process] + L --> J + J -->|Consensus| M[Proposal Finalization] + + subgraph "Discussion Elements" + N[Evidence-Based Arguments] + O[Stakeholder Perspectives] + P[Risk-Benefit Analysis] + Q[Implementation Feasibility] + end + + B --> N + G --> O + E --> P + H --> Q +``` + +**Diagram Explanation:** +This flowchart details the discussion and debate process that ensures thorough consideration of all aspects before decision-making. The process begins with expertise-based input from each board member, followed by cross-examination to validate claims. Alternative proposals are considered, and comprehensive impact analysis, risk assessment, stakeholder consideration, resource evaluation, and timeline assessment are conducted. If consensus isn't reached, conflict resolution and mediation processes are employed until agreement is achieved. + +**Technical Implementation:** +```python +# Example: Discussion and debate management +class DiscussionManager: + def __init__(self, board_members, config): + self.board_members = board_members + self.config = config + self.discussion_points = [] + self.conflicts = [] + self.consensus_status = False + + async def conduct_discussion(self, task, expertise_assignments): + """Conduct structured discussion and debate""" + discussion_result = { + "phases": [], + "consensus_achieved": False, + "final_proposal": None, + "conflicts_resolved": [] + } + + # Phase 1: Expertise-based input + expertise_input = await self.gather_expertise_input(task, expertise_assignments) + discussion_result["phases"].append(expertise_input) + + # Phase 2: Cross-examination + cross_examination = await self.conduct_cross_examination(expertise_input) + discussion_result["phases"].append(cross_examination) + + # Phase 3: Alternative proposals + alternatives = await self.generate_alternatives(task, expertise_input) + discussion_result["phases"].append(alternatives) + + # Phase 4: Comprehensive analysis + analysis = await self.conduct_comprehensive_analysis(task, alternatives) + discussion_result["phases"].append(analysis) + + # Phase 5: Consensus building + consensus = await self.build_consensus(analysis) + discussion_result["phases"].append(consensus) + + discussion_result["consensus_achieved"] = consensus["achieved"] + discussion_result["final_proposal"] = consensus["final_proposal"] + discussion_result["conflicts_resolved"] = consensus["conflicts_resolved"] + + return discussion_result + + async def gather_expertise_input(self, task, expertise_assignments): + """Gather input from each board member based on their expertise""" + expertise_inputs = {} + + for member_role, expertise_areas in expertise_assignments.items(): + member = self.board_members[member_role] + + # Generate expertise-based analysis + analysis = await member.analyze_task_areas(task, expertise_areas) + + expertise_inputs[member_role] = { + "expertise_areas": expertise_areas, + "analysis": analysis, + "recommendations": analysis.get("recommendations", []), + "concerns": analysis.get("concerns", []), + "proposals": analysis.get("proposals", []) + } + + return { + "phase": "expertise_input", + "inputs": expertise_inputs, + "timestamp": datetime.now().isoformat() + } + + async def conduct_cross_examination(self, expertise_input): + """Conduct cross-examination of expertise inputs""" + cross_examination_results = {} + + for member_role, input_data in expertise_input["inputs"].items(): + member = self.board_members[member_role] + + # Other members examine this member's input + examinations = [] + for examiner_role, examiner in self.board_members.items(): + if examiner_role != member_role: + examination = await examiner.examine_input( + input_data, member_role + ) + examinations.append({ + "examiner": examiner_role, + "examination": examination + }) + + cross_examination_results[member_role] = { + "original_input": input_data, + "examinations": examinations, + "validation_status": self.assess_validation_status(examinations) + } + + return { + "phase": "cross_examination", + "results": cross_examination_results, + "timestamp": datetime.now().isoformat() + } + + async def generate_alternatives(self, task, expertise_input): + """Generate alternative proposals based on expertise input""" + alternatives = [] + + # Generate alternatives from each expertise area + for member_role, input_data in expertise_input["inputs"].items(): + member = self.board_members[member_role] + + member_alternatives = await member.generate_alternatives( + task, input_data + ) + + alternatives.extend(member_alternatives) + + # Combine and synthesize alternatives + synthesized_alternatives = await self.synthesize_alternatives(alternatives) + + return { + "phase": "alternatives", + "individual_alternatives": alternatives, + "synthesized_alternatives": synthesized_alternatives, + "timestamp": datetime.now().isoformat() + } +``` + +## Phase 3: Decision Making + +### Voting and Consensus Process + +```mermaid +graph TD + A[Proposal Review] --> B[Voting Preparation] + B --> C[Individual Voting] + C --> D[Vote Aggregation] + D --> E[Threshold Check] + E -->|Below Threshold| F[Consensus Building] + F --> G[Proposal Refinement] + G --> C + E -->|Above Threshold| H[Decision Finalization] + H --> I[Plan Creation] + I --> J[Execution Orders] + + subgraph "Voting Components" + K[Weighted Voting] + L[Secret Ballot] + M[Transparent Process] + N[Conflict Resolution] + end + + C --> K + C --> L + D --> M + F --> N +``` + +**Diagram Explanation:** +This diagram shows the structured voting and consensus process that ensures fair and transparent decision-making. The process begins with proposal review and voting preparation, followed by individual voting where each board member casts their vote. Votes are aggregated and checked against the consensus threshold. If the threshold isn't met, consensus building and proposal refinement processes are initiated. Once the threshold is achieved, the decision is finalized, a plan is created, and execution orders are generated. + +**Technical Implementation:** +```python +# Example: Voting and consensus system +class VotingSystem: + def __init__(self, board_members, config): + self.board_members = board_members + self.config = config + self.voting_history = [] + self.consensus_threshold = config.get("voting_threshold", 0.7) + self.voting_weights = config.get("voting_weights", {}) + + async def conduct_voting(self, proposals): + """Conduct voting on proposals""" + voting_result = { + "rounds": [], + "final_decision": None, + "consensus_achieved": False, + "voting_summary": {} + } + + current_proposals = proposals + round_number = 1 + + while round_number <= self.config.get("max_voting_rounds", 3): + # Conduct voting round + round_result = await self.conduct_voting_round( + current_proposals, round_number + ) + voting_result["rounds"].append(round_result) + + # Check if consensus achieved + if round_result["consensus_achieved"]: + voting_result["final_decision"] = round_result["winning_proposal"] + voting_result["consensus_achieved"] = True + break + + # Refine proposals for next round + current_proposals = await self.refine_proposals( + current_proposals, round_result + ) + + round_number += 1 + + # Generate voting summary + voting_result["voting_summary"] = self.generate_voting_summary( + voting_result["rounds"] + ) + + return voting_result + + async def conduct_voting_round(self, proposals, round_number): + """Conduct a single voting round""" + round_result = { + "round": round_number, + "proposals": proposals, + "votes": {}, + "aggregated_results": {}, + "consensus_achieved": False, + "winning_proposal": None + } + + # Collect votes from each board member + for member_role, member in self.board_members.items(): + vote = await member.vote_on_proposals(proposals, round_number) + round_result["votes"][member_role] = vote + + # Aggregate votes + aggregated_results = self.aggregate_votes( + round_result["votes"], proposals + ) + round_result["aggregated_results"] = aggregated_results + + # Check consensus + consensus_check = self.check_consensus(aggregated_results) + round_result["consensus_achieved"] = consensus_check["achieved"] + round_result["winning_proposal"] = consensus_check["winning_proposal"] + + return round_result + + def aggregate_votes(self, votes, proposals): + """Aggregate votes using weighted voting system""" + aggregated_results = {} + + for proposal_id in [p["id"] for p in proposals]: + total_weighted_score = 0 + total_weight = 0 + vote_counts = {} + + for member_role, vote in votes.items(): + member_weight = self.voting_weights.get(member_role, 1.0) + + if proposal_id in vote["scores"]: + score = vote["scores"][proposal_id] + weighted_score = score * member_weight + total_weighted_score += weighted_score + total_weight += member_weight + + # Track vote distribution + vote_counts[member_role] = { + "score": score, + "weight": member_weight, + "weighted_score": weighted_score + } + + # Calculate final score + final_score = total_weighted_score / total_weight if total_weight > 0 else 0 + + aggregated_results[proposal_id] = { + "final_score": final_score, + "total_weight": total_weight, + "vote_counts": vote_counts, + "consensus_percentage": final_score + } + + return aggregated_results + + def check_consensus(self, aggregated_results): + """Check if consensus threshold is met""" + best_proposal = None + best_score = 0 + + for proposal_id, result in aggregated_results.items(): + if result["final_score"] > best_score: + best_score = result["final_score"] + best_proposal = proposal_id + + consensus_achieved = best_score >= self.consensus_threshold + + return { + "achieved": consensus_achieved, + "winning_proposal": best_proposal if consensus_achieved else None, + "best_score": best_score, + "threshold": self.consensus_threshold + } +``` + +## Phase 4: Execution and Monitoring + +### Agent Execution Management + +```mermaid +graph TD + A[Execution Orders] --> B[Agent Assignment] + B --> C[Task Distribution] + C --> D[Parallel Execution] + D --> E[Progress Monitoring] + E --> F[Result Collection] + F --> G[Quality Assessment] + G --> H{Quality Met?} + H -->|No| I[Refinement Request] + I --> J[Agent Re-execution] + J --> E + H -->|Yes| K[Result Aggregation] + K --> L[Board Review] + + subgraph "Execution Components" + M[Resource Allocation] + N[Deadline Management] + O[Error Handling] + P[Performance Tracking] + end + + B --> M + C --> N + D --> O + E --> P +``` + +**Diagram Explanation:** +This diagram illustrates the execution and monitoring phase where the board's decisions are implemented through specialized agents. Execution orders are created and distributed to appropriate agents, who execute tasks in parallel while being monitored for progress. Results are collected, assessed for quality, and either approved or sent back for refinement. Once quality standards are met, results are aggregated and presented to the board for final review. + +**Technical Implementation:** +```python +# Example: Execution management system +class ExecutionManager: + def __init__(self, agents, config): + self.agents = agents + self.config = config + self.execution_status = {} + self.performance_metrics = {} + + async def execute_plan(self, execution_plan): + """Execute the board's approved plan""" + execution_result = { + "phases": [], + "final_results": None, + "quality_metrics": {}, + "performance_summary": {} + } + + # Phase 1: Agent assignment and task distribution + assignment_phase = await self.assign_agents(execution_plan) + execution_result["phases"].append(assignment_phase) + + # Phase 2: Parallel execution with monitoring + execution_phase = await self.execute_tasks(assignment_phase["assignments"]) + execution_result["phases"].append(execution_phase) + + # Phase 3: Result collection and quality assessment + assessment_phase = await self.assess_results(execution_phase["results"]) + execution_result["phases"].append(assessment_phase) + + # Phase 4: Result aggregation and board review + review_phase = await self.prepare_board_review(assessment_phase) + execution_result["phases"].append(review_phase) + + execution_result["final_results"] = review_phase["final_results"] + execution_result["quality_metrics"] = assessment_phase["quality_metrics"] + execution_result["performance_summary"] = execution_phase["performance_summary"] + + return execution_result + + async def assign_agents(self, execution_plan): + """Assign agents to tasks based on execution plan""" + assignments = {} + + for task_id, task_details in execution_plan["tasks"].items(): + # Select appropriate agent based on task requirements + selected_agent = await self.select_agent_for_task(task_details) + + # Prepare task assignment + assignment = { + "task_id": task_id, + "agent": selected_agent, + "task_details": task_details, + "deadline": task_details.get("deadline"), + "priority": task_details.get("priority", "normal"), + "resources": task_details.get("resources", []), + "expected_output": task_details.get("expected_output") + } + + assignments[task_id] = assignment + + return { + "phase": "agent_assignment", + "assignments": assignments, + "timestamp": datetime.now().isoformat() + } + + async def execute_tasks(self, assignments): + """Execute tasks in parallel with monitoring""" + execution_tasks = [] + execution_results = {} + performance_metrics = {} + + # Create execution tasks + for task_id, assignment in assignments.items(): + task = self.create_execution_task(assignment) + execution_tasks.append(task) + + # Execute tasks in parallel + results = await asyncio.gather(*execution_tasks, return_exceptions=True) + + # Process results + for i, result in enumerate(results): + task_id = list(assignments.keys())[i] + + if isinstance(result, Exception): + execution_results[task_id] = { + "status": "error", + "error": str(result), + "retry_count": 0 + } + else: + execution_results[task_id] = { + "status": "completed", + "result": result, + "execution_time": result.get("execution_time"), + "quality_score": result.get("quality_score") + } + + # Collect performance metrics + performance_metrics[task_id] = self.collect_performance_metrics( + task_id, result + ) + + return { + "phase": "task_execution", + "results": execution_results, + "performance_summary": self.summarize_performance(performance_metrics), + "timestamp": datetime.now().isoformat() + } + + async def assess_results(self, execution_results): + """Assess quality of execution results""" + quality_metrics = {} + overall_quality_score = 0 + total_tasks = len(execution_results) + + for task_id, result in execution_results.items(): + if result["status"] == "completed": + # Assess individual task quality + task_quality = await self.assess_task_quality(result) + quality_metrics[task_id] = task_quality + overall_quality_score += task_quality["overall_score"] + else: + quality_metrics[task_id] = { + "overall_score": 0, + "completeness": 0, + "accuracy": 0, + "relevance": 0, + "issues": ["Task failed to execute"] + } + + # Calculate overall quality + overall_quality_score = overall_quality_score / total_tasks if total_tasks > 0 else 0 + + return { + "phase": "quality_assessment", + "quality_metrics": quality_metrics, + "overall_quality_score": overall_quality_score, + "quality_threshold_met": overall_quality_score >= self.config.get("quality_threshold", 0.8), + "timestamp": datetime.now().isoformat() + } +``` + +## Best Practices and Optimization + +### Performance Optimization Strategies + +1. **Parallel Execution**: Maximize parallel agent execution for faster results +2. **Resource Pooling**: Implement agent pooling for better resource utilization +3. **Caching**: Cache common analysis results to avoid redundant computation +4. **Load Balancing**: Distribute tasks evenly across available agents + +### Quality Assurance + +1. **Quality Gates**: Implement quality checkpoints throughout the process +2. **Peer Review**: Enable peer review mechanisms for critical decisions +3. **Validation**: Validate outputs against predefined criteria +4. **Continuous Improvement**: Learn from previous executions to improve future performance + +### Monitoring and Analytics + +```python +# Example: Performance monitoring system +class PerformanceMonitor: + def __init__(self): + self.metrics = { + "execution_times": [], + "quality_scores": [], + "consensus_rounds": [], + "error_rates": [] + } + + def track_execution_time(self, phase, duration): + """Track execution time for different phases""" + self.metrics["execution_times"].append({ + "phase": phase, + "duration": duration, + "timestamp": datetime.now().isoformat() + }) + + def track_quality_score(self, score): + """Track quality scores""" + self.metrics["quality_scores"].append({ + "score": score, + "timestamp": datetime.now().isoformat() + }) + + def generate_performance_report(self): + """Generate comprehensive performance report""" + return { + "average_execution_time": self.calculate_average_execution_time(), + "quality_trends": self.analyze_quality_trends(), + "consensus_efficiency": self.analyze_consensus_efficiency(), + "error_analysis": self.analyze_errors(), + "recommendations": self.generate_recommendations() + } +``` \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/index.md b/docs/swarms/structs/board_of_directors/index.md new file mode 100644 index 00000000..136fdea8 --- /dev/null +++ b/docs/swarms/structs/board_of_directors/index.md @@ -0,0 +1,291 @@ +# Board of Directors - Multi-Agent Architecture + +The Board of Directors is a sophisticated multi-agent architecture that implements collective decision-making through democratic processes, voting mechanisms, and role-based leadership. This architecture provides an alternative to single-director patterns by enabling collaborative intelligence through structured governance. + +## šŸ›ļø Overview + +The Board of Directors architecture follows a democratic workflow pattern: + +1. **Task Reception**: User provides a task to the swarm +2. **Board Meeting**: Board of Directors convenes to discuss and create a plan +3. **Voting & Consensus**: Board members vote and reach consensus on task distribution +4. **Order Distribution**: Board distributes orders to specialized worker agents +5. **Execution**: Individual agents execute their assigned tasks +6. **Feedback Loop**: Board evaluates results and issues new orders if needed (up to `max_loops`) +7. **Context Preservation**: All conversation history and context is maintained throughout the process + +## šŸ—ļø Architecture Components + +### Core Components + +| Component | Description | Purpose | +|-----------|-------------|---------| +| **[BoardOfDirectorsSwarm](board_of_directors_swarm.md)** | Main orchestration class | Manages the entire board workflow and agent coordination | +| **[Board Member Roles](board_of_directors_roles.md)** | Role definitions and hierarchy | Defines responsibilities and voting weights for each board member | +| **[Decision Making Process](board_of_directors_decision_making.md)** | Voting and consensus mechanisms | Implements democratic decision-making with weighted voting | +| **[Workflow Management](board_of_directors_workflow.md)** | Process orchestration | Manages the complete lifecycle from task reception to final delivery | + +### Architecture Diagram + +```mermaid +graph TD + A[User Task] --> B[Board of Directors] + B --> C[Board Meeting & Discussion] + C --> D[Voting & Consensus] + D --> E[Create Plan & Orders] + E --> F[Distribute to Agents] + F --> G[Agent 1] + F --> H[Agent 2] + F --> I[Agent N] + G --> J[Execute Task] + H --> J + I --> J + J --> K[Report Results] + K --> L[Board Evaluation] + L --> M{More Loops?} + M -->|Yes| C + M -->|No| N[Final Output] +``` + +## šŸŽÆ Key Features + +### Democratic Decision Making +- **Collective Intelligence**: Multiple perspectives through board member collaboration +- **Weighted Voting**: Different voting weights based on roles and expertise +- **Consensus Building**: Support for both majority voting and consensus approaches +- **Conflict Resolution**: Structured processes for handling disagreements + +### Role-Based Leadership +- **Hierarchical Structure**: Clear roles with defined responsibilities +- **Specialized Expertise**: Each board member brings unique domain knowledge +- **Authority Distribution**: Balanced power distribution across roles +- **Accountability**: Clear lines of responsibility and decision ownership + +### Operational Excellence +- **Iterative Refinement**: Multiple feedback loops for improved results +- **Context Preservation**: Full conversation history maintained +- **Flexible Output Formats**: Support for various output types (dict, str, list) +- **Comprehensive Logging**: Detailed logging for debugging and monitoring + +## šŸ‘„ Board Member Roles + +The Board of Directors supports various roles with different responsibilities and voting weights: + +| Role | Description | Voting Weight | Responsibilities | +|------|-------------|---------------|------------------| +| `CHAIRMAN` | Primary leader responsible for board meetings and final decisions | 1.5 | Leading meetings, facilitating consensus, making final decisions | +| `VICE_CHAIRMAN` | Secondary leader who supports the chairman | 1.2 | Supporting chairman, coordinating operations | +| `SECRETARY` | Responsible for documentation and meeting minutes | 1.0 | Documenting meetings, maintaining records | +| `TREASURER` | Manages financial aspects and resource allocation | 1.0 | Financial oversight, resource management | +| `EXECUTIVE_DIRECTOR` | Executive-level board member with operational authority | 1.5 | Strategic planning, operational oversight | +| `MEMBER` | General board member with specific expertise | 1.0 | Contributing expertise, participating in decisions | + +## šŸš€ Quick Start + +### Basic Setup + +```python +from swarms import Agent +from swarms.structs.board_of_directors_swarm import ( + BoardOfDirectorsSwarm, + BoardMember, + BoardMemberRole +) +from swarms.config.board_config import enable_board_feature + +# Enable the Board of Directors feature +enable_board_feature() + +# Create board members with specific roles +chairman = Agent( + agent_name="Chairman", + agent_description="Chairman of the Board responsible for leading meetings", + model_name="gpt-4o-mini", + system_prompt="You are the Chairman of the Board..." +) + +vice_chairman = Agent( + agent_name="Vice-Chairman", + agent_description="Vice Chairman who supports the Chairman", + model_name="gpt-4o-mini", + system_prompt="You are the Vice Chairman..." +) + +# Create BoardMember objects with roles and expertise +board_members = [ + BoardMember(chairman, BoardMemberRole.CHAIRMAN, 1.5, ["leadership", "strategy"]), + BoardMember(vice_chairman, BoardMemberRole.VICE_CHAIRMAN, 1.2, ["operations", "coordination"]), +] + +# Create worker agents +research_agent = Agent( + agent_name="Research-Specialist", + agent_description="Expert in market research and analysis", + model_name="gpt-4o", +) + +financial_agent = Agent( + agent_name="Financial-Analyst", + agent_description="Specialist in financial analysis and valuation", + model_name="gpt-4o", +) + +# Initialize the Board of Directors swarm +board_swarm = BoardOfDirectorsSwarm( + name="Executive_Board_Swarm", + description="Executive board with specialized roles for strategic decision-making", + board_members=board_members, + agents=[research_agent, financial_agent], + max_loops=2, + verbose=True, + decision_threshold=0.6, + enable_voting=True, + enable_consensus=True, +) + +# Execute a complex task with democratic decision-making +result = board_swarm.run(task="Analyze the market potential for Tesla (TSLA) stock") +print(result) +``` + +## šŸ“‹ Use Cases + +### Corporate Governance +- **Strategic Planning**: Long-term business strategy development +- **Risk Management**: Comprehensive risk assessment and mitigation +- **Resource Allocation**: Optimal distribution of company resources +- **Performance Oversight**: Monitoring and evaluating organizational performance + +### Financial Analysis +- **Portfolio Management**: Investment portfolio optimization and rebalancing +- **Market Analysis**: Comprehensive market research and trend analysis +- **Risk Assessment**: Financial risk evaluation and management +- **Compliance Monitoring**: Regulatory compliance and audit preparation + +### Research & Development +- **Technology Assessment**: Evaluation of emerging technologies +- **Product Development**: Strategic product planning and development +- **Innovation Management**: Managing innovation pipelines and initiatives +- **Quality Assurance**: Ensuring high standards across development processes + +### Project Management +- **Complex Project Planning**: Multi-faceted project strategy development +- **Resource Optimization**: Efficient allocation of project resources +- **Stakeholder Management**: Coordinating diverse stakeholder interests +- **Risk Mitigation**: Identifying and addressing project risks + +## āš™ļø Configuration + +### Decision Thresholds +- **Default Threshold**: 60% consensus required for decisions +- **Configurable**: Adjustable based on organizational needs +- **Role-Based**: Different thresholds for different types of decisions +- **Fallback Mechanisms**: Chairman can make final decisions when consensus fails + +### Voting Mechanisms +- **Weighted Voting**: Different voting weights based on roles +- **Consensus Building**: Support for both majority and consensus approaches +- **Conflict Resolution**: Structured processes for handling disagreements +- **Transparency**: Clear visibility into decision-making processes + +### Operational Settings +- **Meeting Duration**: Configurable board meeting time limits +- **Participation Requirements**: Minimum participation rates for valid decisions +- **Feedback Loops**: Multiple iterations for complex problem-solving +- **Documentation**: Comprehensive record-keeping of all decisions + +## šŸ”§ Advanced Features + +### Custom Board Templates +Pre-configured board templates for common use cases: + +```python +from swarms.config.board_config import get_default_board_template + +# Get a financial analysis board template +financial_board = get_default_board_template("financial_analysis") + +# Get a strategic planning board template +strategic_board = get_default_board_template("strategic_planning") +``` + +### Dynamic Role Assignment +Automatically assign roles based on task requirements: + +```python +# Board members are automatically assigned roles based on expertise +board_swarm = BoardOfDirectorsSwarm( + board_members=board_members, + auto_assign_roles=True, + role_mapping={ + "financial_analysis": ["Treasurer", "Financial_Member"], + "strategic_planning": ["Chairman", "Executive_Director"] + } +) +``` + +### Consensus Optimization +Advanced consensus-building mechanisms: + +```python +# Enable advanced consensus features +board_swarm = BoardOfDirectorsSwarm( + enable_consensus=True, + consensus_timeout=300, # 5 minutes + min_participation_rate=0.5, # 50% minimum participation + auto_fallback_to_chairman=True +) +``` + +## šŸ“Š Performance Monitoring + +### Decision Metrics +- **Consensus Rate**: Percentage of decisions reached by consensus +- **Voting Participation**: Board member participation rates +- **Decision Quality**: Assessment of decision outcomes +- **Execution Efficiency**: Time from decision to implementation + +### Operational Metrics +- **Meeting Duration**: Average board meeting length +- **Agent Utilization**: How effectively worker agents are utilized +- **Feedback Loop Efficiency**: Speed of iterative improvements +- **Resource Optimization**: Efficient use of computational resources + +## šŸ› ļø Troubleshooting + +### Common Issues + +1. **Consensus Failures**: Lower decision threshold or increase timeout +2. **Role Conflicts**: Ensure clear role definitions and responsibilities +3. **Agent Coordination**: Verify agent communication and task distribution +4. **Performance Issues**: Monitor resource usage and optimize configurations + +### Best Practices + +1. **Role Clarity**: Define clear responsibilities for each board member +2. **Expertise Alignment**: Match board member expertise to task requirements +3. **Consensus Building**: Allow adequate time for discussion and consensus +4. **Documentation**: Maintain comprehensive records of all decisions +5. **Continuous Improvement**: Learn from each execution cycle + +## šŸ“š Documentation Sections + +- **[BoardOfDirectorsSwarm](board_of_directors_swarm.md)**: Complete API reference and implementation details +- **[Board Member Roles](board_of_directors_roles.md)**: Detailed role definitions and responsibilities +- **[Decision Making Process](board_of_directors_decision_making.md)**: Voting mechanisms and consensus building +- **[Workflow Management](board_of_directors_workflow.md)**: Complete process orchestration guide + +## šŸŽÆ Success Criteria + +A successful Board of Directors implementation should demonstrate: + +- āœ… **Democratic Decision Making**: All board members contribute to decisions +- āœ… **Consensus Achievement**: Decisions reached through collaborative processes +- āœ… **Role Effectiveness**: Each board member fulfills their responsibilities +- āœ… **Agent Coordination**: Worker agents execute tasks efficiently +- āœ… **Quality Output**: High-quality results through collective intelligence +- āœ… **Process Transparency**: Clear visibility into decision-making processes + +--- + +The Board of Directors architecture represents a sophisticated approach to multi-agent collaboration, enabling organizations to leverage collective intelligence through structured governance and democratic decision-making processes. \ No newline at end of file From 8d48dcaf2ae4a49b8e7490085681b707080a37c3 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sat, 26 Jul 2025 23:48:43 +0300 Subject: [PATCH 02/18] Delete docs/swarms/structs/board_of_directors directory --- .../board_of_directors_decision_making.md | 885 ------------- .../board_of_directors_example.md | 466 ------- .../board_of_directors_roles.md | 1151 ----------------- .../board_of_directors_swarm.md | 704 ---------- .../board_of_directors_workflow.md | 908 ------------- .../structs/board_of_directors/index.md | 291 ----- 6 files changed, 4405 deletions(-) delete mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md delete mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_example.md delete mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_roles.md delete mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_swarm.md delete mode 100644 docs/swarms/structs/board_of_directors/board_of_directors_workflow.md delete mode 100644 docs/swarms/structs/board_of_directors/index.md diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md b/docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md deleted file mode 100644 index 22a3cb35..00000000 --- a/docs/swarms/structs/board_of_directors/board_of_directors_decision_making.md +++ /dev/null @@ -1,885 +0,0 @@ -# Board of Directors Decision Making - -The Board of Directors decision-making process is a sophisticated, multi-layered system that ensures comprehensive analysis, balanced consideration, and effective consensus building. This process combines democratic principles with hierarchical authority to achieve optimal outcomes. - -## Decision-Making Framework - -### Overview of the Decision Process - -```mermaid -graph TD - A[Task Analysis] --> B[Expertise Assignment] - B --> C[Individual Analysis] - C --> D[Group Discussion] - D --> E[Proposal Development] - E --> F[Voting Process] - F --> G[Consensus Building] - G --> H{Consensus Achieved?} - H -->|Yes| I[Decision Finalization] - H -->|No| J[Conflict Resolution] - J --> K[Proposal Refinement] - K --> F - I --> L[Execution Planning] - L --> M[Implementation Oversight] - - style A fill:#e3f2fd - style I fill:#c8e6c9 - style H fill:#fff3e0 -``` - -**Diagram Explanation:** -This comprehensive decision-making framework shows the complete process from initial task analysis to final implementation oversight. The process begins with task analysis and expertise assignment, followed by individual analysis where each board member contributes their specialized knowledge. Group discussion facilitates information sharing and debate, leading to proposal development. The voting process and consensus building ensure democratic decision-making, with conflict resolution mechanisms for when consensus cannot be reached. Once consensus is achieved, decisions are finalized and execution planning begins, followed by implementation oversight. - -**Technical Implementation:** -```python -# Example: Decision-making framework implementation -class DecisionMakingFramework: - def __init__(self, board_members, config): - self.board_members = board_members - self.config = config - self.decision_history = [] - self.consensus_threshold = config.get("consensus_threshold", 0.7) - self.max_voting_rounds = config.get("max_voting_rounds", 3) - - async def execute_decision_process(self, task): - """Execute the complete decision-making process""" - decision_result = { - "task": task, - "phases": [], - "final_decision": None, - "consensus_achieved": False, - "execution_plan": None - } - - # Phase 1: Task Analysis and Expertise Assignment - analysis_phase = await self.analyze_task_and_assign_expertise(task) - decision_result["phases"].append(analysis_phase) - - # Phase 2: Individual Analysis - individual_analysis = await self.conduct_individual_analysis(task, analysis_phase["expertise_assignments"]) - decision_result["phases"].append(individual_analysis) - - # Phase 3: Group Discussion - group_discussion = await self.facilitate_group_discussion(individual_analysis) - decision_result["phases"].append(group_discussion) - - # Phase 4: Proposal Development - proposal_development = await self.develop_proposals(group_discussion) - decision_result["phases"].append(proposal_development) - - # Phase 5: Voting and Consensus Building - consensus_result = await self.build_consensus(proposal_development["proposals"]) - decision_result["phases"].append(consensus_result) - - # Phase 6: Decision Finalization - if consensus_result["consensus_achieved"]: - finalization = await self.finalize_decision(consensus_result) - decision_result["phases"].append(finalization) - decision_result["final_decision"] = finalization["decision"] - decision_result["consensus_achieved"] = True - else: - # Handle conflict resolution - conflict_resolution = await self.resolve_conflicts(consensus_result) - decision_result["phases"].append(conflict_resolution) - decision_result["final_decision"] = conflict_resolution["decision"] - decision_result["consensus_achieved"] = False - - # Phase 7: Execution Planning - execution_planning = await self.plan_execution(decision_result["final_decision"]) - decision_result["phases"].append(execution_planning) - decision_result["execution_plan"] = execution_planning["plan"] - - # Store decision in history - self.decision_history.append(decision_result) - - return decision_result - - async def analyze_task_and_assign_expertise(self, task): - """Analyze task and assign expertise areas to board members""" - # Analyze task complexity and requirements - task_analysis = await self.analyze_task_complexity(task) - - # Identify required expertise areas - required_expertise = await self.identify_required_expertise(task_analysis) - - # Assign expertise areas to board members - expertise_assignments = await self.assign_expertise_to_members(required_expertise) - - return { - "phase": "task_analysis_and_expertise_assignment", - "task_analysis": task_analysis, - "required_expertise": required_expertise, - "expertise_assignments": expertise_assignments, - "timestamp": datetime.now().isoformat() - } - - async def conduct_individual_analysis(self, task, expertise_assignments): - """Conduct individual analysis by each board member""" - individual_analyses = {} - - for member_role, expertise_areas in expertise_assignments.items(): - member = self.board_members[member_role] - - # Conduct analysis based on assigned expertise - analysis = await member.analyze_task_areas(task, expertise_areas) - - individual_analyses[member_role] = { - "expertise_areas": expertise_areas, - "analysis": analysis, - "recommendations": analysis.get("recommendations", []), - "concerns": analysis.get("concerns", []), - "proposals": analysis.get("proposals", []) - } - - return { - "phase": "individual_analysis", - "analyses": individual_analyses, - "timestamp": datetime.now().isoformat() - } -``` - -## Voting Mechanisms - -### Weighted Voting System - -```mermaid -graph TD - A[Proposal Submission] --> B[Vote Collection] - B --> C[Weight Application] - C --> D[Score Calculation] - D --> E[Threshold Check] - E -->|Above Threshold| F[Consensus Achieved] - E -->|Below Threshold| G[Additional Rounds] - G --> H[Proposal Refinement] - H --> B - - subgraph "Voting Components" - I[Individual Votes] - J[Role Weights] - K[Consensus Threshold] - L[Conflict Resolution] - end - - B --> I - C --> J - E --> K - G --> L -``` - -**Diagram Explanation:** -This diagram illustrates the weighted voting system used by the Board of Directors. The process begins with proposal submission, followed by vote collection from all board members. Each vote is weighted according to the member's role and authority level. Scores are calculated using the weighted voting formula, and results are checked against the consensus threshold. If the threshold is met, consensus is achieved. If not, additional voting rounds with proposal refinement are conducted until consensus is reached or maximum rounds are exceeded. - -**Technical Implementation:** -```python -# Example: Weighted voting system implementation -class WeightedVotingSystem: - def __init__(self, board_members, config): - self.board_members = board_members - self.config = config - self.voting_weights = { - "CHAIRMAN": 1.5, - "VICE_CHAIRMAN": 1.2, - "EXECUTIVE_DIRECTOR": 1.5, - "SECRETARY": 1.0, - "TREASURER": 1.0, - "MEMBER": 1.0 - } - self.consensus_threshold = config.get("consensus_threshold", 0.7) - self.max_voting_rounds = config.get("max_voting_rounds", 3) - - async def conduct_weighted_voting(self, proposals): - """Conduct weighted voting on proposals""" - voting_result = { - "rounds": [], - "final_decision": None, - "consensus_achieved": False, - "voting_summary": {} - } - - current_proposals = proposals - round_number = 1 - - while round_number <= self.max_voting_rounds: - # Collect votes from all board members - votes = await self.collect_votes(current_proposals) - - # Apply voting weights - weighted_votes = self.apply_voting_weights(votes) - - # Calculate scores - scores = self.calculate_weighted_scores(weighted_votes, current_proposals) - - # Check consensus threshold - consensus_check = self.check_consensus_threshold(scores) - - round_result = { - "round": round_number, - "votes": votes, - "weighted_votes": weighted_votes, - "scores": scores, - "consensus_achieved": consensus_check["achieved"], - "winning_proposal": consensus_check["winning_proposal"] - } - - voting_result["rounds"].append(round_result) - - if consensus_check["achieved"]: - voting_result["final_decision"] = consensus_check["winning_proposal"] - voting_result["consensus_achieved"] = True - break - - # Refine proposals for next round - current_proposals = await self.refine_proposals(current_proposals, round_result) - round_number += 1 - - # Generate voting summary - voting_result["voting_summary"] = self.generate_voting_summary(voting_result["rounds"]) - - return voting_result - - async def collect_votes(self, proposals): - """Collect votes from all board members""" - votes = {} - - for member_role, member in self.board_members.items(): - # Each member votes on all proposals - member_votes = await member.vote_on_proposals(proposals) - - votes[member_role] = { - "proposal_scores": member_votes["scores"], - "rationale": member_votes["rationale"], - "confidence_level": member_votes.get("confidence_level", 1.0), - "timestamp": datetime.now().isoformat() - } - - return votes - - def apply_voting_weights(self, votes): - """Apply voting weights to member votes""" - weighted_votes = {} - - for member_role, vote_data in votes.items(): - weight = self.voting_weights.get(member_role, 1.0) - - weighted_scores = {} - for proposal_id, score in vote_data["proposal_scores"].items(): - weighted_scores[proposal_id] = score * weight - - weighted_votes[member_role] = { - "original_scores": vote_data["proposal_scores"], - "weighted_scores": weighted_scores, - "weight": weight, - "rationale": vote_data["rationale"], - "confidence_level": vote_data["confidence_level"] - } - - return weighted_votes - - def calculate_weighted_scores(self, weighted_votes, proposals): - """Calculate final weighted scores for each proposal""" - proposal_scores = {} - - for proposal in proposals: - proposal_id = proposal["id"] - total_weighted_score = 0 - total_weight = 0 - vote_count = 0 - - for member_role, vote_data in weighted_votes.items(): - if proposal_id in vote_data["weighted_scores"]: - weighted_score = vote_data["weighted_scores"][proposal_id] - weight = vote_data["weight"] - - total_weighted_score += weighted_score - total_weight += weight - vote_count += 1 - - # Calculate average weighted score - if total_weight > 0: - final_score = total_weighted_score / total_weight - else: - final_score = 0 - - proposal_scores[proposal_id] = { - "final_score": final_score, - "total_weight": total_weight, - "vote_count": vote_count, - "consensus_percentage": final_score - } - - return proposal_scores - - def check_consensus_threshold(self, scores): - """Check if any proposal meets the consensus threshold""" - best_proposal = None - best_score = 0 - - for proposal_id, score_data in scores.items(): - if score_data["final_score"] > best_score: - best_score = score_data["final_score"] - best_proposal = proposal_id - - consensus_achieved = best_score >= self.consensus_threshold - - return { - "achieved": consensus_achieved, - "winning_proposal": best_proposal if consensus_achieved else None, - "best_score": best_score, - "threshold": self.consensus_threshold - } -``` - -## Consensus Building Process - -### Multi-Round Consensus Building - -```mermaid -flowchart TD - A[Initial Proposals] --> B[Round 1 Voting] - B --> C[Score Calculation] - C --> D{Consensus?} - D -->|Yes| E[Consensus Achieved] - D -->|No| F[Proposal Refinement] - F --> G[Round 2 Voting] - G --> H[Score Calculation] - H --> I{Consensus?} - I -->|Yes| J[Consensus Achieved] - I -->|No| K[Final Round] - K --> L[Round 3 Voting] - L --> M[Score Calculation] - M --> N{Consensus?} - N -->|Yes| O[Consensus Achieved] - N -->|No| P[Authority Decision] - - subgraph "Consensus Building Elements" - Q[Discussion Facilitation] - R[Conflict Resolution] - S[Proposal Synthesis] - T[Mediation Process] - end - - F --> Q - F --> R - F --> S - K --> T -``` - -**Diagram Explanation:** -This flowchart shows the multi-round consensus building process used by the Board of Directors. The process begins with initial proposals and proceeds through multiple voting rounds. After each round, scores are calculated and consensus is checked. If consensus is not achieved, proposals are refined through discussion facilitation, conflict resolution, proposal synthesis, and mediation processes. The process continues for up to three rounds, after which authority decision-making is used if consensus still cannot be reached. - -**Technical Implementation:** -```python -# Example: Consensus building system -class ConsensusBuildingSystem: - def __init__(self, board_members, config): - self.board_members = board_members - self.config = config - self.max_rounds = config.get("max_consensus_rounds", 3) - self.consensus_threshold = config.get("consensus_threshold", 0.7) - self.discussion_facilitator = board_members.get("CHAIRMAN") - - async def build_consensus(self, initial_proposals): - """Build consensus through multiple rounds""" - consensus_result = { - "rounds": [], - "consensus_achieved": False, - "final_proposal": None, - "authority_decision": None - } - - current_proposals = initial_proposals - round_number = 1 - - while round_number <= self.max_rounds: - # Conduct voting round - voting_result = await self.conduct_voting_round(current_proposals, round_number) - - # Check consensus - if voting_result["consensus_achieved"]: - consensus_result["rounds"].append(voting_result) - consensus_result["consensus_achieved"] = True - consensus_result["final_proposal"] = voting_result["winning_proposal"] - break - - # If no consensus and not final round, refine proposals - if round_number < self.max_rounds: - refinement_result = await self.refine_proposals(current_proposals, voting_result) - consensus_result["rounds"].append(voting_result) - current_proposals = refinement_result["refined_proposals"] - else: - # Final round - use authority decision - authority_decision = await self.make_authority_decision(voting_result) - consensus_result["rounds"].append(voting_result) - consensus_result["authority_decision"] = authority_decision - consensus_result["final_proposal"] = authority_decision["selected_proposal"] - - round_number += 1 - - return consensus_result - - async def conduct_voting_round(self, proposals, round_number): - """Conduct a single voting round""" - round_result = { - "round": round_number, - "proposals": proposals, - "votes": {}, - "scores": {}, - "consensus_achieved": False, - "winning_proposal": None - } - - # Collect votes from all board members - for member_role, member in self.board_members.items(): - vote = await member.vote_on_proposals(proposals, round_number) - round_result["votes"][member_role] = vote - - # Calculate weighted scores - weighted_scores = self.calculate_weighted_scores(round_result["votes"], proposals) - round_result["scores"] = weighted_scores - - # Check consensus - consensus_check = self.check_consensus(weighted_scores) - round_result["consensus_achieved"] = consensus_check["achieved"] - round_result["winning_proposal"] = consensus_check["winning_proposal"] - - return round_result - - async def refine_proposals(self, current_proposals, voting_result): - """Refine proposals based on voting results and discussion""" - refinement_result = { - "refined_proposals": [], - "discussion_summary": "", - "conflicts_resolved": [] - } - - # Analyze voting patterns - voting_analysis = self.analyze_voting_patterns(voting_result) - - # Identify areas of disagreement - disagreements = self.identify_disagreements(voting_result) - - # Facilitate discussion to resolve conflicts - discussion_result = await self.facilitate_discussion(disagreements, current_proposals) - refinement_result["discussion_summary"] = discussion_result["summary"] - refinement_result["conflicts_resolved"] = discussion_result["resolved_conflicts"] - - # Synthesize refined proposals - refined_proposals = await self.synthesize_proposals(current_proposals, discussion_result) - refinement_result["refined_proposals"] = refined_proposals - - return refinement_result - - async def facilitate_discussion(self, disagreements, proposals): - """Facilitate discussion to resolve disagreements""" - discussion_result = { - "summary": "", - "resolved_conflicts": [], - "new_insights": [] - } - - # Chairman facilitates discussion - if self.discussion_facilitator: - facilitation_result = await self.discussion_facilitator.facilitate_discussion( - disagreements, proposals - ) - - discussion_result["summary"] = facilitation_result["summary"] - discussion_result["resolved_conflicts"] = facilitation_result["resolved_conflicts"] - discussion_result["new_insights"] = facilitation_result["new_insights"] - - return discussion_result - - async def make_authority_decision(self, final_voting_result): - """Make authority decision when consensus cannot be reached""" - # Chairman makes final decision based on best available information - authority_decision = { - "decision_maker": "CHAIRMAN", - "decision_method": "authority_decision", - "selected_proposal": None, - "rationale": "", - "board_support_level": 0.0 - } - - # Analyze all proposals and select the best one - best_proposal = self.select_best_proposal(final_voting_result["scores"]) - authority_decision["selected_proposal"] = best_proposal["proposal_id"] - authority_decision["rationale"] = best_proposal["rationale"] - authority_decision["board_support_level"] = best_proposal["support_level"] - - return authority_decision -``` - -## Conflict Resolution Mechanisms - -### Structured Conflict Resolution - -```mermaid -graph TD - A[Conflict Identification] --> B[Conflict Analysis] - B --> C[Stakeholder Mapping] - C --> D[Root Cause Analysis] - D --> E[Resolution Strategy] - E --> F[Mediation Process] - F --> G[Compromise Facilitation] - G --> H[Agreement Building] - H --> I[Resolution Implementation] - - subgraph "Conflict Resolution Tools" - J[Mediation Techniques] - K[Compromise Strategies] - L[Consensus Building] - M[Authority Intervention] - end - - F --> J - G --> K - H --> L - I --> M -``` - -**Diagram Explanation:** -This diagram illustrates the structured conflict resolution process used by the Board of Directors. The process begins with conflict identification and proceeds through systematic analysis including stakeholder mapping and root cause analysis. A resolution strategy is developed, followed by mediation processes and compromise facilitation. The process culminates in agreement building and resolution implementation, using various tools including mediation techniques, compromise strategies, consensus building, and authority intervention when necessary. - -**Technical Implementation:** -```python -# Example: Conflict resolution system -class ConflictResolutionSystem: - def __init__(self, board_members, config): - self.board_members = board_members - self.config = config - self.mediation_techniques = [ - "active_listening", - "interest_based_negotiation", - "brainstorming", - "consensus_building" - ] - self.resolution_strategies = [ - "compromise", - "collaboration", - "accommodation", - "authority_decision" - ] - - async def resolve_conflicts(self, conflicts, context): - """Resolve conflicts using structured approach""" - resolution_result = { - "conflicts": conflicts, - "resolution_process": [], - "final_resolution": None, - "implementation_plan": None - } - - for conflict in conflicts: - # Step 1: Analyze conflict - conflict_analysis = await self.analyze_conflict(conflict, context) - resolution_result["resolution_process"].append({ - "step": "conflict_analysis", - "conflict_id": conflict["id"], - "analysis": conflict_analysis - }) - - # Step 2: Map stakeholders - stakeholder_mapping = await self.map_stakeholders(conflict, context) - resolution_result["resolution_process"].append({ - "step": "stakeholder_mapping", - "conflict_id": conflict["id"], - "mapping": stakeholder_mapping - }) - - # Step 3: Analyze root causes - root_cause_analysis = await self.analyze_root_causes(conflict, context) - resolution_result["resolution_process"].append({ - "step": "root_cause_analysis", - "conflict_id": conflict["id"], - "analysis": root_cause_analysis - }) - - # Step 4: Develop resolution strategy - resolution_strategy = await self.develop_resolution_strategy( - conflict, conflict_analysis, stakeholder_mapping, root_cause_analysis - ) - resolution_result["resolution_process"].append({ - "step": "resolution_strategy", - "conflict_id": conflict["id"], - "strategy": resolution_strategy - }) - - # Step 5: Implement resolution - resolution_implementation = await self.implement_resolution( - conflict, resolution_strategy - ) - resolution_result["resolution_process"].append({ - "step": "resolution_implementation", - "conflict_id": conflict["id"], - "implementation": resolution_implementation - }) - - # Generate final resolution - resolution_result["final_resolution"] = await self.generate_final_resolution( - resolution_result["resolution_process"] - ) - - # Create implementation plan - resolution_result["implementation_plan"] = await self.create_implementation_plan( - resolution_result["final_resolution"] - ) - - return resolution_result - - async def analyze_conflict(self, conflict, context): - """Analyze the nature and scope of a conflict""" - analysis = { - "conflict_type": self.categorize_conflict(conflict), - "severity_level": self.assess_severity(conflict), - "scope": self.define_scope(conflict), - "impact_assessment": await self.assess_impact(conflict, context), - "urgency_level": self.assess_urgency(conflict) - } - - return analysis - - async def map_stakeholders(self, conflict, context): - """Map stakeholders involved in the conflict""" - stakeholders = { - "primary_stakeholders": [], - "secondary_stakeholders": [], - "influencers": [], - "decision_makers": [] - } - - # Identify stakeholders based on conflict type - if conflict["type"] == "resource_allocation": - stakeholders["primary_stakeholders"] = self.identify_resource_stakeholders(conflict) - elif conflict["type"] == "strategic_direction": - stakeholders["primary_stakeholders"] = self.identify_strategic_stakeholders(conflict) - elif conflict["type"] == "implementation_approach": - stakeholders["primary_stakeholders"] = self.identify_implementation_stakeholders(conflict) - - # Map stakeholder interests and positions - for stakeholder in stakeholders["primary_stakeholders"]: - stakeholder["interests"] = await self.identify_stakeholder_interests(stakeholder, conflict) - stakeholder["position"] = await self.identify_stakeholder_position(stakeholder, conflict) - stakeholder["influence_level"] = self.assess_influence_level(stakeholder) - - return stakeholders - - async def analyze_root_causes(self, conflict, context): - """Analyze root causes of the conflict""" - root_causes = { - "structural_causes": [], - "communication_causes": [], - "resource_causes": [], - "process_causes": [] - } - - # Analyze based on conflict type - if conflict["type"] == "resource_allocation": - root_causes["resource_causes"] = await self.analyze_resource_causes(conflict) - elif conflict["type"] == "strategic_direction": - root_causes["structural_causes"] = await self.analyze_structural_causes(conflict) - elif conflict["type"] == "implementation_approach": - root_causes["process_causes"] = await self.analyze_process_causes(conflict) - - # Identify communication issues - root_causes["communication_causes"] = await self.analyze_communication_causes(conflict) - - return root_causes - - async def develop_resolution_strategy(self, conflict, analysis, stakeholders, root_causes): - """Develop appropriate resolution strategy""" - strategy = { - "approach": self.select_resolution_approach(analysis, stakeholders), - "techniques": self.select_mediation_techniques(conflict, stakeholders), - "timeline": self.estimate_resolution_timeline(analysis), - "resources": self.identify_resolution_resources(analysis), - "success_criteria": self.define_success_criteria(conflict) - } - - return strategy - - async def implement_resolution(self, conflict, strategy): - """Implement the resolution strategy""" - implementation = { - "mediation_process": await self.conduct_mediation(conflict, strategy), - "compromise_facilitation": await self.facilitate_compromise(conflict, strategy), - "agreement_building": await self.build_agreement(conflict, strategy), - "implementation_oversight": await self.oversee_implementation(conflict, strategy) - } - - return implementation -``` - -## Decision Quality Assurance - -### Quality Assessment Framework - -```mermaid -graph TD - A[Decision Made] --> B[Quality Assessment] - B --> C[Completeness Check] - C --> D[Accuracy Verification] - D --> E[Feasibility Analysis] - E --> F[Risk Assessment] - F --> G[Stakeholder Impact] - G --> H[Quality Score] - H --> I{Quality Threshold?} - I -->|Yes| J[Decision Approved] - I -->|No| K[Decision Refinement] - K --> L[Additional Analysis] - L --> B - - subgraph "Quality Metrics" - M[Completeness Score] - N[Accuracy Score] - O[Feasibility Score] - P[Risk Score] - Q[Impact Score] - end - - C --> M - D --> N - E --> O - F --> P - G --> Q -``` - -**Diagram Explanation:** -This diagram shows the quality assessment framework used to ensure high-quality decisions. After a decision is made, it undergoes comprehensive quality assessment including completeness checks, accuracy verification, feasibility analysis, risk assessment, and stakeholder impact evaluation. A quality score is calculated based on these metrics, and the decision is either approved if it meets the quality threshold or sent back for refinement and additional analysis. - -**Technical Implementation:** -```python -# Example: Decision quality assurance system -class DecisionQualityAssurance: - def __init__(self, config): - self.config = config - self.quality_threshold = config.get("quality_threshold", 0.8) - self.quality_metrics = { - "completeness": {"weight": 0.2, "threshold": 0.8}, - "accuracy": {"weight": 0.25, "threshold": 0.85}, - "feasibility": {"weight": 0.2, "threshold": 0.8}, - "risk": {"weight": 0.15, "threshold": 0.7}, - "impact": {"weight": 0.2, "threshold": 0.8} - } - - async def assess_decision_quality(self, decision, context): - """Assess the quality of a decision""" - quality_assessment = { - "decision": decision, - "metrics": {}, - "overall_score": 0.0, - "threshold_met": False, - "recommendations": [] - } - - # Assess completeness - completeness_score = await self.assess_completeness(decision, context) - quality_assessment["metrics"]["completeness"] = completeness_score - - # Assess accuracy - accuracy_score = await self.assess_accuracy(decision, context) - quality_assessment["metrics"]["accuracy"] = accuracy_score - - # Assess feasibility - feasibility_score = await self.assess_feasibility(decision, context) - quality_assessment["metrics"]["feasibility"] = feasibility_score - - # Assess risk - risk_score = await self.assess_risk(decision, context) - quality_assessment["metrics"]["risk"] = risk_score - - # Assess stakeholder impact - impact_score = await self.assess_stakeholder_impact(decision, context) - quality_assessment["metrics"]["impact"] = impact_score - - # Calculate overall score - overall_score = self.calculate_overall_score(quality_assessment["metrics"]) - quality_assessment["overall_score"] = overall_score - - # Check if threshold is met - quality_assessment["threshold_met"] = overall_score >= self.quality_threshold - - # Generate recommendations - quality_assessment["recommendations"] = await self.generate_quality_recommendations( - quality_assessment["metrics"], overall_score - ) - - return quality_assessment - - async def assess_completeness(self, decision, context): - """Assess the completeness of the decision""" - completeness_factors = { - "all_aspects_covered": self.check_aspect_coverage(decision, context), - "stakeholder_consideration": self.check_stakeholder_consideration(decision, context), - "implementation_details": self.check_implementation_details(decision), - "resource_allocation": self.check_resource_allocation(decision), - "timeline_definition": self.check_timeline_definition(decision) - } - - # Calculate completeness score - completeness_score = sum(completeness_factors.values()) / len(completeness_factors) - - return { - "score": completeness_score, - "factors": completeness_factors, - "threshold_met": completeness_score >= self.quality_metrics["completeness"]["threshold"] - } - - async def assess_accuracy(self, decision, context): - """Assess the accuracy of the decision""" - accuracy_factors = { - "data_quality": self.assess_data_quality(decision, context), - "analysis_quality": self.assess_analysis_quality(decision, context), - "assumption_validity": self.assess_assumption_validity(decision, context), - "conclusion_soundness": self.assess_conclusion_soundness(decision, context) - } - - # Calculate accuracy score - accuracy_score = sum(accuracy_factors.values()) / len(accuracy_factors) - - return { - "score": accuracy_score, - "factors": accuracy_factors, - "threshold_met": accuracy_score >= self.quality_metrics["accuracy"]["threshold"] - } - - def calculate_overall_score(self, metrics): - """Calculate overall quality score""" - weighted_score = 0.0 - total_weight = 0.0 - - for metric_name, metric_data in metrics.items(): - weight = self.quality_metrics[metric_name]["weight"] - score = metric_data["score"] - - weighted_score += score * weight - total_weight += weight - - return weighted_score / total_weight if total_weight > 0 else 0.0 -``` - -## Best Practices for Decision Making - -### 1. Structured Approach -- Follow the defined decision-making framework -- Ensure all phases are completed thoroughly -- Document decisions and rationale - -### 2. Inclusive Participation -- Encourage all board members to contribute -- Value diverse perspectives and expertise -- Ensure fair representation in voting - -### 3. Quality Assurance -- Implement quality checkpoints throughout the process -- Assess decision quality before implementation -- Continuously monitor and improve decision-making processes - -### 4. Conflict Management -- Address conflicts promptly and constructively -- Use appropriate resolution strategies -- Maintain focus on organizational objectives - -### 5. Continuous Improvement -- Learn from previous decisions -- Refine decision-making processes based on outcomes -- Adapt to changing circumstances and requirements \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_example.md b/docs/swarms/structs/board_of_directors/board_of_directors_example.md deleted file mode 100644 index 34c5edc3..00000000 --- a/docs/swarms/structs/board_of_directors/board_of_directors_example.md +++ /dev/null @@ -1,466 +0,0 @@ -# Board of Directors Example - -This example demonstrates how to use the Board of Directors swarm feature for democratic decision-making and collective intelligence in multi-agent systems. - -## Overview - -The Board of Directors Swarm provides a sophisticated alternative to single-director architectures by implementing collective decision-making through voting, consensus, and role-based leadership. This example shows how to create and configure a board for strategic decision-making scenarios. - -## Basic Setup - -### 1. Import Required Modules - -```python -from swarms import Agent -from swarms.structs.board_of_directors_swarm import ( - BoardOfDirectorsSwarm, - BoardMember, - BoardMemberRole -) -from swarms.config.board_config import ( - enable_board_feature, - set_decision_threshold, - get_default_board_template -) -``` - -### 2. Enable Board Feature - -```python -# Enable the Board of Directors feature globally -enable_board_feature() - -# Set global decision threshold -set_decision_threshold(0.7) # 70% majority required -``` - -### 3. Create Board Members - -```python -# Create Chairman -chairman = Agent( - agent_name="Chairman", - agent_description="Chairman of the Board responsible for leading meetings and making final decisions", - model_name="gpt-4o-mini", - system_prompt="""You are the Chairman of the Board. Your responsibilities include: -1. Leading board meetings and discussions -2. Facilitating consensus among board members -3. Making final decisions when consensus cannot be reached -4. Ensuring all board members have an opportunity to contribute -5. Maintaining focus on the organization's goals and objectives - -You should be diplomatic, fair, and decisive in your leadership.""" -) - -# Create Vice Chairman -vice_chairman = Agent( - agent_name="Vice-Chairman", - agent_description="Vice Chairman who supports the Chairman and coordinates operations", - model_name="gpt-4o-mini", - system_prompt="""You are the Vice Chairman of the Board. Your responsibilities include: -1. Supporting the Chairman in leading board meetings -2. Coordinating operational activities and implementation -3. Ensuring effective communication between board members -4. Managing day-to-day board operations -5. Stepping in when the Chairman is unavailable - -You should be collaborative, organized, and supportive of the Chairman's leadership.""" -) - -# Create Secretary -secretary = Agent( - agent_name="Secretary", - agent_description="Secretary responsible for documentation and record keeping", - model_name="gpt-4o-mini", - system_prompt="""You are the Secretary of the Board. Your responsibilities include: -1. Documenting all board meetings and decisions -2. Maintaining accurate records and meeting minutes -3. Ensuring proper communication and notifications -4. Managing board documentation and archives -5. Supporting compliance and governance requirements - -You should be detail-oriented, organized, and thorough in your documentation.""" -) - -# Create Treasurer -treasurer = Agent( - agent_name="Treasurer", - agent_description="Treasurer responsible for financial oversight and resource management", - model_name="gpt-4o-mini", - system_prompt="""You are the Treasurer of the Board. Your responsibilities include: -1. Overseeing financial planning and budgeting -2. Monitoring resource allocation and utilization -3. Ensuring financial compliance and accountability -4. Providing financial insights for decision-making -5. Managing financial risk and controls - -You should be financially astute, analytical, and focused on value creation.""" -) - -# Create Executive Director -executive_director = Agent( - agent_name="Executive-Director", - agent_description="Executive Director responsible for strategic planning and operational oversight", - model_name="gpt-4o-mini", - system_prompt="""You are the Executive Director of the Board. Your responsibilities include: -1. Developing and implementing strategic plans -2. Overseeing operational performance and efficiency -3. Leading innovation and continuous improvement -4. Managing stakeholder relationships -5. Ensuring organizational effectiveness - -You should be strategic, results-oriented, and focused on organizational success.""" -) -``` - -### 4. Create BoardMember Objects - -```python -# Create BoardMember objects with roles, voting weights, and expertise areas -board_members = [ - BoardMember( - agent=chairman, - role=BoardMemberRole.CHAIRMAN, - voting_weight=1.5, - expertise_areas=["leadership", "strategy", "governance", "decision_making"] - ), - BoardMember( - agent=vice_chairman, - role=BoardMemberRole.VICE_CHAIRMAN, - voting_weight=1.2, - expertise_areas=["operations", "coordination", "communication", "implementation"] - ), - BoardMember( - agent=secretary, - role=BoardMemberRole.SECRETARY, - voting_weight=1.0, - expertise_areas=["documentation", "compliance", "record_keeping", "communication"] - ), - BoardMember( - agent=treasurer, - role=BoardMemberRole.TREASURER, - voting_weight=1.0, - expertise_areas=["finance", "budgeting", "risk_management", "resource_allocation"] - ), - BoardMember( - agent=executive_director, - role=BoardMemberRole.EXECUTIVE_DIRECTOR, - voting_weight=1.5, - expertise_areas=["strategy", "operations", "innovation", "performance_management"] - ) -] -``` - -### 5. Create Specialized Worker Agents - -```python -# Create specialized worker agents for different types of analysis -research_agent = Agent( - agent_name="Research-Specialist", - agent_description="Expert in market research, data analysis, and trend identification", - model_name="gpt-4o", - system_prompt="""You are a Research Specialist. Your responsibilities include: -1. Conducting comprehensive market research and analysis -2. Identifying trends, opportunities, and risks -3. Gathering and analyzing relevant data -4. Providing evidence-based insights and recommendations -5. Supporting strategic decision-making with research findings - -You should be thorough, analytical, and objective in your research.""" -) - -financial_agent = Agent( - agent_name="Financial-Analyst", - agent_description="Specialist in financial analysis, valuation, and investment assessment", - model_name="gpt-4o", - system_prompt="""You are a Financial Analyst. Your responsibilities include: -1. Conducting financial analysis and valuation -2. Assessing investment opportunities and risks -3. Analyzing financial performance and metrics -4. Providing financial insights and recommendations -5. Supporting financial decision-making - -You should be financially astute, analytical, and focused on value creation.""" -) - -technical_agent = Agent( - agent_name="Technical-Specialist", - agent_description="Expert in technical analysis, feasibility assessment, and implementation planning", - model_name="gpt-4o", - system_prompt="""You are a Technical Specialist. Your responsibilities include: -1. Conducting technical feasibility analysis -2. Assessing implementation requirements and challenges -3. Providing technical insights and recommendations -4. Supporting technical decision-making -5. Planning and coordinating technical implementations - -You should be technically proficient, practical, and solution-oriented.""" -) - -strategy_agent = Agent( - agent_name="Strategy-Specialist", - agent_description="Expert in strategic planning, competitive analysis, and business development", - model_name="gpt-4o", - system_prompt="""You are a Strategy Specialist. Your responsibilities include: -1. Developing strategic plans and initiatives -2. Conducting competitive analysis and market positioning -3. Identifying strategic opportunities and threats -4. Providing strategic insights and recommendations -5. Supporting strategic decision-making - -You should be strategic, forward-thinking, and focused on long-term success.""" -) -``` - -### 6. Initialize the Board of Directors Swarm - -```python -# Initialize the Board of Directors swarm with comprehensive configuration -board_swarm = BoardOfDirectorsSwarm( - name="Executive_Board_Swarm", - description="Executive board with specialized roles for strategic decision-making and collective intelligence", - board_members=board_members, - agents=[research_agent, financial_agent, technical_agent, strategy_agent], - max_loops=3, # Allow multiple iterations for complex analysis - verbose=True, # Enable detailed logging - decision_threshold=0.7, # 70% consensus required - enable_voting=True, # Enable voting mechanisms - enable_consensus=True, # Enable consensus building - max_workers=4, # Maximum parallel workers - output_type="dict" # Return results as dictionary -) -``` - -## Advanced Configuration - -### Custom Board Templates - -You can use pre-configured board templates for common use cases: - -```python -# Get a financial analysis board template -financial_board_template = get_default_board_template("financial_analysis") - -# Get a strategic planning board template -strategic_board_template = get_default_board_template("strategic_planning") - -# Get a technology assessment board template -tech_board_template = get_default_board_template("technology_assessment") -``` - -### Dynamic Role Assignment - -Automatically assign roles based on task requirements: - -```python -# Board members are automatically assigned roles based on expertise -board_swarm = BoardOfDirectorsSwarm( - board_members=board_members, - agents=agents, - auto_assign_roles=True, - role_mapping={ - "financial_analysis": ["Treasurer", "Financial_Member"], - "strategic_planning": ["Chairman", "Executive_Director"], - "technical_assessment": ["Technical_Member", "Executive_Director"], - "research_analysis": ["Research_Member", "Secretary"] - } -) -``` - -### Consensus Optimization - -Configure advanced consensus-building mechanisms: - -```python -# Enable advanced consensus features -board_swarm = BoardOfDirectorsSwarm( - board_members=board_members, - agents=agents, - enable_consensus=True, - consensus_timeout=300, # 5 minutes timeout - min_participation_rate=0.8, # 80% minimum participation - auto_fallback_to_chairman=True, # Chairman can make final decisions - consensus_rounds=3 # Maximum consensus building rounds -) -``` - -## Example Use Cases - -### 1. Strategic Investment Analysis - -```python -# Execute a complex strategic investment analysis -investment_task = """ -Analyze the strategic investment opportunity for a $50M Series B funding round in a -fintech startup. Consider market conditions, competitive landscape, financial projections, -technical feasibility, and strategic fit. Provide comprehensive recommendations including: -1. Investment recommendation (proceed/hold/decline) -2. Valuation analysis and suggested terms -3. Risk assessment and mitigation strategies -4. Strategic value and synergies -5. Implementation timeline and milestones -""" - -result = board_swarm.run(task=investment_task) -print("Investment Analysis Results:") -print(json.dumps(result, indent=2)) -``` - -### 2. Technology Strategy Development - -```python -# Develop a comprehensive technology strategy -tech_strategy_task = """ -Develop a comprehensive technology strategy for a mid-size manufacturing company -looking to digitize operations and implement Industry 4.0 technologies. Consider: -1. Current technology assessment and gaps -2. Technology roadmap and implementation plan -3. Investment requirements and ROI analysis -4. Risk assessment and mitigation strategies -5. Change management and training requirements -6. Competitive positioning and market advantages -""" - -result = board_swarm.run(task=tech_strategy_task) -print("Technology Strategy Results:") -print(json.dumps(result, indent=2)) -``` - -### 3. Market Entry Strategy - -```python -# Develop a market entry strategy for a new product -market_entry_task = """ -Develop a comprehensive market entry strategy for a new AI-powered productivity -software targeting the enterprise market. Consider: -1. Market analysis and opportunity assessment -2. Competitive landscape and positioning -3. Go-to-market strategy and channels -4. Pricing strategy and revenue model -5. Resource requirements and investment needs -6. Risk assessment and mitigation strategies -7. Success metrics and KPIs -""" - -result = board_swarm.run(task=market_entry_task) -print("Market Entry Strategy Results:") -print(json.dumps(result, indent=2)) -``` - -## Monitoring and Analysis - -### Board Performance Metrics - -```python -# Get board performance metrics -board_summary = board_swarm.get_board_summary() -print("Board Summary:") -print(f"Board Name: {board_summary['board_name']}") -print(f"Total Board Members: {board_summary['total_members']}") -print(f"Total Worker Agents: {board_summary['total_agents']}") -print(f"Decision Threshold: {board_summary['decision_threshold']}") -print(f"Max Loops: {board_summary['max_loops']}") - -# Display board member details -print("\nBoard Members:") -for member in board_summary['members']: - print(f"- {member['name']} (Role: {member['role']}, Weight: {member['voting_weight']})") - print(f" Expertise: {', '.join(member['expertise_areas'])}") - -# Display worker agent details -print("\nWorker Agents:") -for agent in board_summary['agents']: - print(f"- {agent['name']}: {agent['description']}") -``` - -### Decision Analysis - -```python -# Analyze decision-making patterns -if hasattr(result, 'get') and callable(result.get): - conversation_history = result.get('conversation_history', []) - - print(f"\nDecision Analysis:") - print(f"Total Messages: {len(conversation_history)}") - - # Count board member contributions - board_contributions = {} - for msg in conversation_history: - if 'Board' in msg.get('role', ''): - member_name = msg.get('agent_name', 'Unknown') - board_contributions[member_name] = board_contributions.get(member_name, 0) + 1 - - print(f"Board Member Contributions:") - for member, count in board_contributions.items(): - print(f"- {member}: {count} contributions") - - # Count agent executions - agent_executions = {} - for msg in conversation_history: - if any(agent.agent_name in msg.get('role', '') for agent in [research_agent, financial_agent, technical_agent, strategy_agent]): - agent_name = msg.get('agent_name', 'Unknown') - agent_executions[agent_name] = agent_executions.get(agent_name, 0) + 1 - - print(f"\nAgent Executions:") - for agent, count in agent_executions.items(): - print(f"- {agent}: {count} executions") -``` - -## Best Practices - -### 1. Role Definition -- Clearly define responsibilities for each board member -- Ensure expertise areas align with organizational needs -- Balance voting weights based on role importance - -### 2. Task Formulation -- Provide clear, specific task descriptions -- Include relevant context and constraints -- Specify expected outputs and deliverables - -### 3. Consensus Building -- Allow adequate time for discussion and consensus -- Encourage diverse perspectives and viewpoints -- Use structured decision-making processes - -### 4. Performance Monitoring -- Track decision quality and outcomes -- Monitor board member participation -- Analyze agent utilization and effectiveness - -### 5. Continuous Improvement -- Learn from each execution cycle -- Refine board composition and roles -- Optimize decision thresholds and processes - -## Troubleshooting - -### Common Issues - -1. **Consensus Failures**: Lower decision threshold or increase timeout -2. **Role Conflicts**: Ensure clear role definitions and responsibilities -3. **Agent Coordination**: Verify agent communication and task distribution -4. **Performance Issues**: Monitor resource usage and optimize configurations - -### Debug Commands - -```python -# Enable detailed logging -import logging -logging.basicConfig(level=logging.DEBUG) - -# Check board configuration -print(board_swarm.get_board_summary()) - -# Test individual components -for member in board_members: - print(f"Testing {member.agent.agent_name}...") - response = member.agent.run("Test message") - print(f"Response: {response[:100]}...") -``` - -## Conclusion - -This example demonstrates the comprehensive capabilities of the Board of Directors Swarm for democratic decision-making and collective intelligence. The feature provides a sophisticated alternative to single-director architectures, enabling more robust and well-considered decisions through voting, consensus, and role-based leadership. - -For more information, see the [Board of Directors Documentation](index.md) and [Configuration Guide](../config/board_config.md). \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_roles.md b/docs/swarms/structs/board_of_directors/board_of_directors_roles.md deleted file mode 100644 index 6f607c37..00000000 --- a/docs/swarms/structs/board_of_directors/board_of_directors_roles.md +++ /dev/null @@ -1,1151 +0,0 @@ -# Board of Directors Roles - -The Board of Directors system implements a hierarchical structure with clearly defined roles, responsibilities, and voting weights. Each role is designed to contribute specific expertise and authority to the decision-making process, ensuring comprehensive analysis and balanced decision-making. - -## Role Hierarchy - -```mermaid -graph TD - A[Chairman
Voting Weight: 1.5
Final Authority] --> B[Vice Chairman
Voting Weight: 1.2
Operational Support] - A --> C[Executive Director
Voting Weight: 1.5
Strategic Planning] - A --> D[Secretary
Voting Weight: 1.0
Documentation] - A --> E[Treasurer
Voting Weight: 1.0
Financial Oversight] - A --> F[Member
Voting Weight: 1.0
Expertise Contribution] - - B --> G[Operational Coordination] - C --> H[Strategic Initiatives] - D --> I[Record Keeping] - E --> J[Resource Management] - F --> K[Specialized Input] - - style A fill:#ffeb3b - style B fill:#2196f3 - style C fill:#4caf50 - style D fill:#ff9800 - style E fill:#9c27b0 - style F fill:#607d8b -``` - -**Diagram Explanation:** -This hierarchical diagram shows the organizational structure of the Board of Directors, with the Chairman at the top having final authority and the highest voting weight (1.5). The Chairman directly supervises all other board members, each with specific responsibilities and voting weights. The Vice Chairman and Executive Director have elevated voting weights (1.2 and 1.5 respectively) due to their senior positions, while the Secretary, Treasurer, and general Members have standard voting weights (1.0). Each role contributes specialized expertise to different aspects of the decision-making process. - -**Technical Implementation:** -```python -# Example: Role hierarchy implementation -class BoardRoleHierarchy: - def __init__(self): - self.roles = { - "CHAIRMAN": { - "voting_weight": 1.5, - "authority_level": "FINAL", - "supervises": ["VICE_CHAIRMAN", "EXECUTIVE_DIRECTOR", "SECRETARY", "TREASURER", "MEMBER"], - "responsibilities": ["leadership", "final_decision", "consensus_facilitation"], - "override_capability": True - }, - "VICE_CHAIRMAN": { - "voting_weight": 1.2, - "authority_level": "SENIOR", - "supervises": ["MEMBER"], - "responsibilities": ["operational_support", "coordination", "implementation"], - "backup_for": "CHAIRMAN" - }, - "EXECUTIVE_DIRECTOR": { - "voting_weight": 1.5, - "authority_level": "SENIOR", - "supervises": ["MEMBER"], - "responsibilities": ["strategic_planning", "execution_oversight", "performance_management"], - "strategic_authority": True - }, - "SECRETARY": { - "voting_weight": 1.0, - "authority_level": "STANDARD", - "supervises": [], - "responsibilities": ["documentation", "record_keeping", "communication"], - "administrative_authority": True - }, - "TREASURER": { - "voting_weight": 1.0, - "authority_level": "STANDARD", - "supervises": [], - "responsibilities": ["financial_oversight", "resource_management", "budget_control"], - "financial_authority": True - }, - "MEMBER": { - "voting_weight": 1.0, - "authority_level": "STANDARD", - "supervises": [], - "responsibilities": ["expertise_contribution", "analysis", "voting"], - "specialized_expertise": True - } - } - - def get_role_info(self, role_name): - """Get detailed information about a specific role""" - return self.roles.get(role_name, {}) - - def get_voting_weight(self, role_name): - """Get voting weight for a specific role""" - role_info = self.get_role_info(role_name) - return role_info.get("voting_weight", 1.0) - - def get_authority_level(self, role_name): - """Get authority level for a specific role""" - role_info = self.get_role_info(role_name) - return role_info.get("authority_level", "STANDARD") - - def can_override_decision(self, role_name): - """Check if a role can override board decisions""" - role_info = self.get_role_info(role_name) - return role_info.get("override_capability", False) - - def get_supervision_chain(self, role_name): - """Get the supervision chain for a specific role""" - supervision_chain = [] - current_role = role_name - - while current_role: - role_info = self.get_role_info(current_role) - if role_info: - supervision_chain.append(current_role) - # Find who supervises this role - current_role = None - for supervisor, info in self.roles.items(): - if current_role in info.get("supervises", []): - current_role = supervisor - break - else: - break - - return supervision_chain -``` - -## Chairman Role - -### Primary Responsibilities - -```mermaid -graph TD - A[Chairman] --> B[Meeting Leadership] - A --> C[Final Decision Authority] - A --> D[Consensus Facilitation] - A --> E[Strategic Direction] - A --> F[Stakeholder Communication] - - B --> G[Agenda Setting] - B --> H[Discussion Management] - B --> I[Time Management] - - C --> J[Approval Authority] - C --> K[Override Capability] - C --> L[Final Sign-off] - - D --> M[Conflict Resolution] - D --> N[Mediation] - D --> O[Compromise Facilitation] - - E --> P[Vision Setting] - E --> Q[Goal Definition] - E --> R[Priority Establishment] - - F --> S[External Relations] - F --> T[Stakeholder Updates] - F --> U[Public Communication] -``` - -**Diagram Explanation:** -This diagram illustrates the comprehensive responsibilities of the Chairman role, showing how the Chairman serves as the central authority figure with five main areas of responsibility. Meeting Leadership involves agenda setting, discussion management, and time management. Final Decision Authority includes approval authority, override capability, and final sign-off responsibilities. Consensus Facilitation covers conflict resolution, mediation, and compromise facilitation. Strategic Direction encompasses vision setting, goal definition, and priority establishment. Stakeholder Communication includes external relations, stakeholder updates, and public communication. - -**Technical Implementation:** -```python -# Example: Chairman role implementation -class Chairman: - def __init__(self, name, config): - self.name = name - self.config = config - self.authority_level = "FINAL" - self.voting_weight = 1.5 - self.override_capability = True - self.meeting_history = [] - self.decision_history = [] - - async def lead_meeting(self, task, board_members): - """Lead a board meeting for task discussion and decision-making""" - meeting_result = { - "meeting_id": self.generate_meeting_id(), - "task": task, - "participants": list(board_members.keys()), - "phases": [], - "decisions": [], - "consensus_achieved": False - } - - # Phase 1: Meeting Opening - opening_phase = await self.open_meeting(task, board_members) - meeting_result["phases"].append(opening_phase) - - # Phase 2: Agenda Review and Task Presentation - presentation_phase = await self.present_task(task, board_members) - meeting_result["phases"].append(presentation_phase) - - # Phase 3: Discussion Facilitation - discussion_phase = await self.facilitate_discussion(task, board_members) - meeting_result["phases"].append(discussion_phase) - - # Phase 4: Consensus Building - consensus_phase = await self.build_consensus(discussion_phase["proposals"], board_members) - meeting_result["phases"].append(consensus_phase) - - # Phase 5: Decision Making - decision_phase = await self.make_final_decision(consensus_phase, board_members) - meeting_result["phases"].append(decision_phase) - - meeting_result["decisions"] = decision_phase["decisions"] - meeting_result["consensus_achieved"] = consensus_phase["consensus_achieved"] - - # Record meeting in history - self.meeting_history.append(meeting_result) - - return meeting_result - - async def open_meeting(self, task, board_members): - """Open the board meeting and set the agenda""" - agenda = await self.create_agenda(task) - - opening_statement = f""" - Meeting called to order by Chairman {self.name}. - - Task: {task['description']} - Priority: {task.get('priority', 'Normal')} - Timeline: {task.get('timeline', 'Not specified')} - - Agenda: - {self.format_agenda(agenda)} - - Board members present: {', '.join(board_members.keys())} - """ - - return { - "phase": "meeting_opening", - "opening_statement": opening_statement, - "agenda": agenda, - "participants": list(board_members.keys()), - "timestamp": datetime.now().isoformat() - } - - async def create_agenda(self, task): - """Create a structured agenda for the meeting""" - agenda = { - "items": [ - { - "item": "Task Presentation", - "duration": "10 minutes", - "responsible": "Chairman", - "description": "Present task details and requirements" - }, - { - "item": "Expertise Assignment", - "duration": "5 minutes", - "responsible": "Chairman", - "description": "Assign analysis areas to board members" - }, - { - "item": "Individual Analysis", - "duration": "15 minutes", - "responsible": "All Members", - "description": "Board members analyze assigned areas" - }, - { - "item": "Group Discussion", - "duration": "20 minutes", - "responsible": "All Members", - "description": "Open discussion and debate" - }, - { - "item": "Proposal Development", - "duration": "15 minutes", - "responsible": "All Members", - "description": "Develop and refine proposals" - }, - { - "item": "Voting and Consensus", - "duration": "10 minutes", - "responsible": "All Members", - "description": "Vote on proposals and reach consensus" - }, - { - "item": "Decision Finalization", - "duration": "5 minutes", - "responsible": "Chairman", - "description": "Finalize decisions and assign execution" - } - ], - "total_duration": "80 minutes", - "break_time": "10 minutes" - } - - return agenda - - async def facilitate_discussion(self, task, board_members): - """Facilitate discussion among board members""" - discussion_result = { - "phase": "discussion_facilitation", - "discussion_points": [], - "conflicts": [], - "resolutions": [], - "proposals": [] - } - - # Guide discussion through structured phases - for member_role, member in board_members.items(): - # Get member's analysis - analysis = await member.analyze_task(task) - discussion_result["discussion_points"].append({ - "member": member_role, - "analysis": analysis, - "timestamp": datetime.now().isoformat() - }) - - # Identify conflicts - conflicts = await self.identify_conflicts(analysis, discussion_result["discussion_points"]) - discussion_result["conflicts"].extend(conflicts) - - # Facilitate conflict resolution - for conflict in conflicts: - resolution = await self.resolve_conflict(conflict, board_members) - discussion_result["resolutions"].append(resolution) - - # Develop proposals based on discussion - proposals = await self.develop_proposals(discussion_result["discussion_points"]) - discussion_result["proposals"] = proposals - - return discussion_result - - async def build_consensus(self, proposals, board_members): - """Build consensus among board members on proposals""" - consensus_result = { - "phase": "consensus_building", - "voting_rounds": [], - "consensus_achieved": False, - "final_proposal": None - } - - current_proposals = proposals - round_number = 1 - - while round_number <= self.config.get("max_consensus_rounds", 3): - # Conduct voting round - voting_result = await self.conduct_voting_round(current_proposals, board_members, round_number) - consensus_result["voting_rounds"].append(voting_result) - - # Check if consensus achieved - if voting_result["consensus_achieved"]: - consensus_result["consensus_achieved"] = True - consensus_result["final_proposal"] = voting_result["winning_proposal"] - break - - # Refine proposals for next round - current_proposals = await self.refine_proposals(current_proposals, voting_result) - round_number += 1 - - return consensus_result - - async def make_final_decision(self, consensus_result, board_members): - """Make final decision based on consensus or exercise authority""" - if consensus_result["consensus_achieved"]: - # Consensus reached, approve the decision - decision = { - "type": "consensus_decision", - "proposal": consensus_result["final_proposal"], - "approval_method": "consensus", - "board_support": "unanimous" - } - else: - # No consensus, exercise chairman authority - decision = await self.exercise_authority(consensus_result, board_members) - - decision_result = { - "phase": "final_decision", - "decision": decision, - "execution_plan": await self.create_execution_plan(decision), - "timestamp": datetime.now().isoformat() - } - - # Record decision in history - self.decision_history.append(decision_result) - - return decision_result - - async def exercise_authority(self, consensus_result, board_members): - """Exercise chairman authority when consensus cannot be reached""" - # Analyze all proposals and voting results - proposal_analysis = await self.analyze_proposals(consensus_result["voting_rounds"]) - - # Make decision based on best interests and available information - final_decision = await self.select_best_proposal(proposal_analysis) - - return { - "type": "authority_decision", - "proposal": final_decision, - "approval_method": "chairman_authority", - "rationale": final_decision["rationale"], - "board_support": final_decision["support_level"] - } -``` - -### Chairman's Decision Flow - -```mermaid -flowchart TD - A[Task Received] --> B[Assess Complexity] - B --> C[Determine Board Composition] - C --> D[Set Meeting Agenda] - D --> E[Lead Discussion] - E --> F[Facilitate Consensus] - F --> G{Consensus Reached?} - G -->|Yes| H[Approve Decision] - G -->|No| I[Exercise Authority] - I --> J[Make Final Decision] - H --> K[Oversee Execution] - J --> K - K --> L[Monitor Progress] - L --> M[Review Results] - M --> N[Final Approval] -``` - -**Diagram Explanation:** -This flowchart shows the Chairman's decision-making process from task reception to final approval. The process begins with task assessment and board composition determination, followed by agenda setting and discussion leadership. The Chairman then facilitates consensus building, and if consensus is reached, approves the decision. If consensus cannot be achieved, the Chairman exercises their authority to make a final decision. The Chairman then oversees execution, monitors progress, reviews results, and provides final approval. - -**Technical Implementation:** -```python -# Example: Chairman decision flow implementation -class ChairmanDecisionFlow: - def __init__(self, chairman): - self.chairman = chairman - self.decision_states = { - "TASK_RECEIVED": "Initial state when task is received", - "COMPLEXITY_ASSESSED": "Task complexity has been evaluated", - "BOARD_COMPOSED": "Board members have been selected", - "AGENDA_SET": "Meeting agenda has been created", - "DISCUSSION_LEAD": "Discussion has been facilitated", - "CONSENSUS_FACILITATED": "Consensus building has been attempted", - "DECISION_MADE": "Final decision has been made", - "EXECUTION_OVERSIGHT": "Execution is being monitored", - "PROGRESS_MONITORED": "Progress is being tracked", - "RESULTS_REVIEWED": "Results have been reviewed", - "FINAL_APPROVAL": "Final approval has been given" - } - - async def execute_decision_flow(self, task): - """Execute the complete chairman decision flow""" - flow_state = { - "current_state": "TASK_RECEIVED", - "task": task, - "transitions": [], - "decisions": [], - "timestamps": {} - } - - # Step 1: Assess Complexity - complexity_assessment = await self.assess_task_complexity(task) - flow_state["transitions"].append({ - "from": "TASK_RECEIVED", - "to": "COMPLEXITY_ASSESSED", - "assessment": complexity_assessment - }) - flow_state["current_state"] = "COMPLEXITY_ASSESSED" - flow_state["timestamps"]["complexity_assessed"] = datetime.now().isoformat() - - # Step 2: Determine Board Composition - board_composition = await self.determine_board_composition(complexity_assessment) - flow_state["transitions"].append({ - "from": "COMPLEXITY_ASSESSED", - "to": "BOARD_COMPOSED", - "composition": board_composition - }) - flow_state["current_state"] = "BOARD_COMPOSED" - flow_state["timestamps"]["board_composed"] = datetime.now().isoformat() - - # Step 3: Set Meeting Agenda - meeting_agenda = await self.set_meeting_agenda(task, board_composition) - flow_state["transitions"].append({ - "from": "BOARD_COMPOSED", - "to": "AGENDA_SET", - "agenda": meeting_agenda - }) - flow_state["current_state"] = "AGENDA_SET" - flow_state["timestamps"]["agenda_set"] = datetime.now().isoformat() - - # Step 4: Lead Discussion - discussion_result = await self.lead_discussion(task, board_composition, meeting_agenda) - flow_state["transitions"].append({ - "from": "AGENDA_SET", - "to": "DISCUSSION_LEAD", - "discussion": discussion_result - }) - flow_state["current_state"] = "DISCUSSION_LEAD" - flow_state["timestamps"]["discussion_led"] = datetime.now().isoformat() - - # Step 5: Facilitate Consensus - consensus_result = await self.facilitate_consensus(discussion_result) - flow_state["transitions"].append({ - "from": "DISCUSSION_LEAD", - "to": "CONSENSUS_FACILITATED", - "consensus": consensus_result - }) - flow_state["current_state"] = "CONSENSUS_FACILITATED" - flow_state["timestamps"]["consensus_facilitated"] = datetime.now().isoformat() - - # Step 6: Make Decision - if consensus_result["consensus_achieved"]: - decision = await self.approve_consensus_decision(consensus_result) - else: - decision = await self.exercise_authority(consensus_result) - - flow_state["decisions"].append(decision) - flow_state["transitions"].append({ - "from": "CONSENSUS_FACILITATED", - "to": "DECISION_MADE", - "decision": decision - }) - flow_state["current_state"] = "DECISION_MADE" - flow_state["timestamps"]["decision_made"] = datetime.now().isoformat() - - # Step 7: Oversee Execution - execution_oversight = await self.oversee_execution(decision) - flow_state["transitions"].append({ - "from": "DECISION_MADE", - "to": "EXECUTION_OVERSIGHT", - "oversight": execution_oversight - }) - flow_state["current_state"] = "EXECUTION_OVERSIGHT" - flow_state["timestamps"]["execution_oversight"] = datetime.now().isoformat() - - # Step 8: Monitor Progress - progress_monitoring = await self.monitor_progress(execution_oversight) - flow_state["transitions"].append({ - "from": "EXECUTION_OVERSIGHT", - "to": "PROGRESS_MONITORED", - "progress": progress_monitoring - }) - flow_state["current_state"] = "PROGRESS_MONITORED" - flow_state["timestamps"]["progress_monitored"] = datetime.now().isoformat() - - # Step 9: Review Results - results_review = await self.review_results(progress_monitoring) - flow_state["transitions"].append({ - "from": "PROGRESS_MONITORED", - "to": "RESULTS_REVIEWED", - "review": results_review - }) - flow_state["current_state"] = "RESULTS_REVIEWED" - flow_state["timestamps"]["results_reviewed"] = datetime.now().isoformat() - - # Step 10: Final Approval - final_approval = await self.give_final_approval(results_review) - flow_state["transitions"].append({ - "from": "RESULTS_REVIEWED", - "to": "FINAL_APPROVAL", - "approval": final_approval - }) - flow_state["current_state"] = "FINAL_APPROVAL" - flow_state["timestamps"]["final_approval"] = datetime.now().isoformat() - - return flow_state -``` - -### Key Competencies - -- **Leadership**: Ability to guide and inspire board members -- **Decision Making**: Strong analytical and judgment skills -- **Communication**: Excellent verbal and written communication -- **Conflict Resolution**: Skills in mediating disagreements -- **Strategic Thinking**: Long-term vision and planning ability -- **Stakeholder Management**: Relationship building and management - -## Vice Chairman Role - -### Supporting Responsibilities - -```mermaid -graph TD - A[Vice Chairman] --> B[Operational Support] - A --> C[Chairman Backup] - A --> D[Coordination] - A --> E[Implementation Oversight] - - B --> F[Meeting Support] - B --> G[Documentation Assistance] - B --> H[Logistics Management] - - C --> I[Acting Chairman] - C --> J[Decision Delegation] - C --> K[Authority Exercise] - - D --> L[Inter-Department Coordination] - D --> M[Resource Allocation] - D --> N[Timeline Management] - - E --> O[Execution Monitoring] - E --> P[Quality Control] - E --> Q[Performance Tracking] -``` - -**Diagram Explanation:** -This diagram shows the Vice Chairman's supporting role structure, highlighting four main areas of responsibility. Operational Support includes meeting support, documentation assistance, and logistics management. Chairman Backup involves acting as chairman when needed, decision delegation, and authority exercise. Coordination covers inter-department coordination, resource allocation, and timeline management. Implementation Oversight includes execution monitoring, quality control, and performance tracking. - -**Technical Implementation:** -```python -# Example: Vice Chairman role implementation -class ViceChairman: - def __init__(self, name, config): - self.name = name - self.config = config - self.authority_level = "SENIOR" - self.voting_weight = 1.2 - self.backup_for = "CHAIRMAN" - self.operational_areas = [] - self.coordination_history = [] - - async def provide_operational_support(self, chairman, task): - """Provide operational support to the chairman""" - support_areas = { - "meeting_support": await self.support_meeting_operations(chairman, task), - "documentation_assistance": await self.assist_with_documentation(task), - "logistics_management": await self.manage_logistics(task) - } - - return { - "support_provided": support_areas, - "timestamp": datetime.now().isoformat() - } - - async def act_as_chairman(self, chairman, reason): - """Act as chairman when the chairman is unavailable""" - acting_authority = { - "acting_chairman": self.name, - "original_chairman": chairman.name, - "reason": reason, - "authority_delegated": True, - "delegation_timestamp": datetime.now().isoformat() - } - - # Assume chairman responsibilities - acting_authority["capabilities"] = [ - "meeting_leadership", - "decision_making", - "consensus_facilitation", - "final_approval" - ] - - return acting_authority - - async def coordinate_operations(self, task, board_members): - """Coordinate operations across different areas""" - coordination_plan = { - "inter_department_coordination": await self.coordinate_departments(task), - "resource_allocation": await self.allocate_resources(task), - "timeline_management": await self.manage_timeline(task) - } - - self.coordination_history.append({ - "task": task, - "coordination_plan": coordination_plan, - "timestamp": datetime.now().isoformat() - }) - - return coordination_plan - - async def oversee_implementation(self, execution_plan): - """Oversee the implementation of board decisions""" - oversight_result = { - "execution_monitoring": await self.monitor_execution(execution_plan), - "quality_control": await self.control_quality(execution_plan), - "performance_tracking": await self.track_performance(execution_plan) - } - - return oversight_result -``` - -## Executive Director Role - -### Strategic Responsibilities - -```mermaid -graph TD - A[Executive Director] --> B[Strategic Planning] - A --> C[Execution Oversight] - A --> D[Performance Management] - A --> E[Strategic Initiatives] - - B --> F[Vision Development] - B --> G[Goal Setting] - B --> H[Strategy Formulation] - - C --> I[Implementation Monitoring] - C --> J[Progress Tracking] - C --> K[Issue Resolution] - - D --> L[KPI Definition] - D --> M[Performance Measurement] - D --> N[Improvement Planning] - - E --> O[Innovation Leadership] - E --> P[Change Management] - E --> Q[Strategic Partnerships] -``` - -**Diagram Explanation:** -This diagram illustrates the Executive Director's strategic role, showing four main areas of responsibility. Strategic Planning includes vision development, goal setting, and strategy formulation. Execution Oversight involves implementation monitoring, progress tracking, and issue resolution. Performance Management covers KPI definition, performance measurement, and improvement planning. Strategic Initiatives includes innovation leadership, change management, and strategic partnerships. - -**Technical Implementation:** -```python -# Example: Executive Director role implementation -class ExecutiveDirector: - def __init__(self, name, config): - self.name = name - self.config = config - self.authority_level = "SENIOR" - self.voting_weight = 1.5 - self.strategic_authority = True - self.performance_metrics = {} - self.strategic_initiatives = [] - - async def develop_strategic_plan(self, task, board_context): - """Develop strategic plan for task execution""" - strategic_plan = { - "vision": await self.develop_vision(task), - "goals": await self.set_goals(task), - "strategy": await self.formulate_strategy(task, board_context), - "timeline": await self.create_strategic_timeline(task), - "resources": await self.plan_strategic_resources(task) - } - - return strategic_plan - - async def oversee_execution(self, execution_plan): - """Oversee execution of strategic plans""" - oversight_result = { - "implementation_monitoring": await self.monitor_implementation(execution_plan), - "progress_tracking": await self.track_progress(execution_plan), - "issue_resolution": await self.resolve_issues(execution_plan) - } - - return oversight_result - - async def manage_performance(self, execution_results): - """Manage performance and define KPIs""" - performance_management = { - "kpi_definition": await self.define_kpis(execution_results), - "performance_measurement": await self.measure_performance(execution_results), - "improvement_planning": await self.plan_improvements(execution_results) - } - - return performance_management - - async def lead_strategic_initiatives(self, task): - """Lead strategic initiatives and innovation""" - strategic_initiatives = { - "innovation_leadership": await self.lead_innovation(task), - "change_management": await self.manage_change(task), - "strategic_partnerships": await self.develop_partnerships(task) - } - - self.strategic_initiatives.append({ - "task": task, - "initiatives": strategic_initiatives, - "timestamp": datetime.now().isoformat() - }) - - return strategic_initiatives -``` - -## Secretary Role - -### Administrative Responsibilities - -```mermaid -graph TD - A[Secretary] --> B[Documentation] - A --> C[Record Keeping] - A --> D[Communication] - A --> E[Administrative Support] - - B --> F[Meeting Minutes] - B --> G[Decision Records] - B --> H[Policy Documentation] - - C --> I[File Management] - C --> J[Record Maintenance] - C --> K[Archive Management] - - D --> L[Internal Communication] - D --> M[External Communication] - D --> N[Stakeholder Updates] - - E --> O[Meeting Coordination] - E --> P[Agenda Preparation] - E --> Q[Follow-up Actions] -``` - -**Diagram Explanation:** -This diagram shows the Secretary's administrative role structure, highlighting four main areas of responsibility. Documentation includes meeting minutes, decision records, and policy documentation. Record Keeping involves file management, record maintenance, and archive management. Communication covers internal communication, external communication, and stakeholder updates. Administrative Support includes meeting coordination, agenda preparation, and follow-up actions. - -**Technical Implementation:** -```python -# Example: Secretary role implementation -class Secretary: - def __init__(self, name, config): - self.name = name - self.config = config - self.authority_level = "STANDARD" - self.voting_weight = 1.0 - self.administrative_authority = True - self.documentation_repository = {} - self.communication_log = [] - - async def document_meeting(self, meeting_data): - """Document board meeting proceedings""" - meeting_documentation = { - "meeting_id": meeting_data["meeting_id"], - "date": meeting_data["timestamp"], - "participants": meeting_data["participants"], - "agenda": meeting_data["agenda"], - "minutes": await self.create_meeting_minutes(meeting_data), - "decisions": meeting_data["decisions"], - "action_items": await self.extract_action_items(meeting_data) - } - - # Store in documentation repository - self.documentation_repository[meeting_data["meeting_id"]] = meeting_documentation - - return meeting_documentation - - async def maintain_records(self, record_type, data): - """Maintain various types of records""" - record_entry = { - "type": record_type, - "data": data, - "timestamp": datetime.now().isoformat(), - "secretary": self.name - } - - if record_type not in self.documentation_repository: - self.documentation_repository[record_type] = [] - - self.documentation_repository[record_type].append(record_entry) - - return record_entry - - async def manage_communication(self, communication_type, content, recipients): - """Manage internal and external communication""" - communication = { - "type": communication_type, - "content": content, - "recipients": recipients, - "timestamp": datetime.now().isoformat(), - "secretary": self.name - } - - self.communication_log.append(communication) - - # Send communication based on type - if communication_type == "internal": - await self.send_internal_communication(communication) - elif communication_type == "external": - await self.send_external_communication(communication) - elif communication_type == "stakeholder_update": - await self.send_stakeholder_update(communication) - - return communication - - async def provide_administrative_support(self, board_members, task): - """Provide administrative support to board members""" - administrative_support = { - "meeting_coordination": await self.coordinate_meetings(board_members, task), - "agenda_preparation": await self.prepare_agendas(task), - "follow_up_actions": await self.manage_follow_up_actions(task) - } - - return administrative_support -``` - -## Treasurer Role - -### Financial Responsibilities - -```mermaid -graph TD - A[Treasurer] --> B[Financial Oversight] - A --> C[Resource Management] - A --> D[Budget Control] - A --> E[Financial Reporting] - - B --> F[Financial Analysis] - B --> G[Risk Assessment] - B --> H[Compliance Monitoring] - - C --> I[Resource Allocation] - C --> J[Cost Management] - C --> K[Efficiency Optimization] - - D --> L[Budget Planning] - D --> M[Expense Monitoring] - D --> N[Budget Adjustments] - - E --> O[Financial Statements] - E --> P[Performance Reports] - E --> Q[Stakeholder Reports] -``` - -**Diagram Explanation:** -This diagram illustrates the Treasurer's financial role structure, showing four main areas of responsibility. Financial Oversight includes financial analysis, risk assessment, and compliance monitoring. Resource Management involves resource allocation, cost management, and efficiency optimization. Budget Control covers budget planning, expense monitoring, and budget adjustments. Financial Reporting includes financial statements, performance reports, and stakeholder reports. - -**Technical Implementation:** -```python -# Example: Treasurer role implementation -class Treasurer: - def __init__(self, name, config): - self.name = name - self.config = config - self.authority_level = "STANDARD" - self.voting_weight = 1.0 - self.financial_authority = True - self.financial_records = {} - self.budget_tracking = {} - - async def provide_financial_oversight(self, task, budget): - """Provide financial oversight for task execution""" - financial_oversight = { - "financial_analysis": await self.analyze_financial_implications(task, budget), - "risk_assessment": await self.assess_financial_risks(task, budget), - "compliance_monitoring": await self.monitor_compliance(task, budget) - } - - return financial_oversight - - async def manage_resources(self, task, available_resources): - """Manage resource allocation and optimization""" - resource_management = { - "resource_allocation": await self.allocate_resources(task, available_resources), - "cost_management": await self.manage_costs(task), - "efficiency_optimization": await self.optimize_efficiency(task) - } - - return resource_management - - async def control_budget(self, task, budget_limits): - """Control budget and monitor expenses""" - budget_control = { - "budget_planning": await self.plan_budget(task, budget_limits), - "expense_monitoring": await self.monitor_expenses(task), - "budget_adjustments": await self.adjust_budget(task) - } - - # Track budget usage - self.budget_tracking[task["id"]] = budget_control - - return budget_control - - async def generate_financial_reports(self, task, financial_data): - """Generate financial reports and statements""" - financial_reports = { - "financial_statements": await self.create_financial_statements(financial_data), - "performance_reports": await self.create_performance_reports(financial_data), - "stakeholder_reports": await self.create_stakeholder_reports(financial_data) - } - - # Store financial records - self.financial_records[task["id"]] = financial_reports - - return financial_reports -``` - -## Member Role - -### General Responsibilities - -```mermaid -graph TD - A[Member] --> B[Expertise Contribution] - A --> C[Analysis] - A --> D[Voting] - A --> E[Specialized Input] - - B --> F[Domain Knowledge] - B --> G[Technical Expertise] - B --> H[Industry Experience] - - C --> I[Data Analysis] - C --> J[Impact Assessment] - C --> K[Feasibility Study] - - D --> L[Informed Voting] - D --> M[Proposal Evaluation] - D --> N[Consensus Building] - - E --> O[Specialized Recommendations] - E --> P[Risk Identification] - E --> Q[Opportunity Assessment] -``` - -**Diagram Explanation:** -This diagram shows the general Member role structure, highlighting four main areas of responsibility. Expertise Contribution includes domain knowledge, technical expertise, and industry experience. Analysis involves data analysis, impact assessment, and feasibility study. Voting covers informed voting, proposal evaluation, and consensus building. Specialized Input includes specialized recommendations, risk identification, and opportunity assessment. - -**Technical Implementation:** -```python -# Example: Member role implementation -class BoardMember: - def __init__(self, name, expertise_areas, config): - self.name = name - self.expertise_areas = expertise_areas - self.config = config - self.authority_level = "STANDARD" - self.voting_weight = 1.0 - self.specialized_expertise = True - self.analysis_history = [] - self.voting_history = [] - - async def contribute_expertise(self, task, expertise_areas): - """Contribute specialized expertise to task analysis""" - expertise_contribution = { - "domain_knowledge": await self.apply_domain_knowledge(task, expertise_areas), - "technical_expertise": await self.apply_technical_expertise(task, expertise_areas), - "industry_experience": await self.apply_industry_experience(task, expertise_areas) - } - - return expertise_contribution - - async def perform_analysis(self, task, data): - """Perform comprehensive analysis of task and data""" - analysis_result = { - "data_analysis": await self.analyze_data(task, data), - "impact_assessment": await self.assess_impact(task, data), - "feasibility_study": await self.study_feasibility(task, data) - } - - # Store analysis in history - self.analysis_history.append({ - "task": task, - "analysis": analysis_result, - "timestamp": datetime.now().isoformat() - }) - - return analysis_result - - async def vote_on_proposals(self, proposals, context): - """Vote on proposals based on analysis and expertise""" - voting_decision = { - "proposal_evaluations": await self.evaluate_proposals(proposals, context), - "informed_vote": await self.make_informed_vote(proposals, context), - "rationale": await self.provide_voting_rationale(proposals, context) - } - - # Store voting decision in history - self.voting_history.append({ - "proposals": proposals, - "decision": voting_decision, - "timestamp": datetime.now().isoformat() - }) - - return voting_decision - - async def provide_specialized_input(self, task, context): - """Provide specialized input based on expertise areas""" - specialized_input = { - "specialized_recommendations": await self.make_specialized_recommendations(task, context), - "risk_identification": await self.identify_risks(task, context), - "opportunity_assessment": await self.assess_opportunities(task, context) - } - - return specialized_input -``` - -## Role Interaction Patterns - -### Communication Flow - -```mermaid -graph TD - A[Chairman] --> B[Vice Chairman] - A --> C[Executive Director] - A --> D[Secretary] - A --> E[Treasurer] - A --> F[Members] - - B --> G[Operational Coordination] - C --> H[Strategic Alignment] - D --> I[Documentation Flow] - E --> J[Financial Oversight] - F --> K[Expertise Input] - - G --> L[Implementation] - H --> M[Strategic Execution] - I --> N[Record Keeping] - J --> O[Budget Control] - K --> P[Decision Support] -``` - -**Diagram Explanation:** -This diagram shows the communication flow and interaction patterns between different board roles. The Chairman serves as the central communication hub, coordinating with all other board members. Each role has specific communication channels and responsibilities: Vice Chairman handles operational coordination, Executive Director manages strategic alignment, Secretary manages documentation flow, Treasurer oversees financial matters, and Members provide expertise input. These interactions support implementation, strategic execution, record keeping, budget control, and decision support. - -**Technical Implementation:** -```python -# Example: Role interaction system -class RoleInteractionSystem: - def __init__(self, board_members): - self.board_members = board_members - self.communication_channels = {} - self.interaction_patterns = {} - - async def establish_communication_flow(self): - """Establish communication flow between board members""" - communication_flow = { - "chairman_communications": await self.setup_chairman_communications(), - "operational_coordination": await self.setup_operational_coordination(), - "strategic_alignment": await self.setup_strategic_alignment(), - "documentation_flow": await self.setup_documentation_flow(), - "financial_oversight": await self.setup_financial_oversight(), - "expertise_input": await self.setup_expertise_input() - } - - return communication_flow - - async def coordinate_role_interactions(self, task): - """Coordinate interactions between different roles""" - interactions = { - "chairman_vice_chairman": await self.coordinate_chairman_vice_chairman(task), - "chairman_executive_director": await self.coordinate_chairman_executive_director(task), - "secretary_documentation": await self.coordinate_secretary_documentation(task), - "treasurer_financial": await self.coordinate_treasurer_financial(task), - "member_expertise": await self.coordinate_member_expertise(task) - } - - return interactions -``` - -## Best Practices for Role Management - -### 1. Clear Role Definition -- Define specific responsibilities for each role -- Establish clear authority boundaries -- Document role interactions and communication protocols - -### 2. Balanced Voting Weights -- Ensure fair representation while maintaining leadership hierarchy -- Consider expertise and experience in weight assignment -- Regularly review and adjust weights based on performance - -### 3. Effective Communication -- Establish clear communication channels -- Implement regular reporting mechanisms -- Ensure transparency in decision-making processes - -### 4. Continuous Improvement -- Regularly assess role effectiveness -- Gather feedback from board members -- Implement improvements based on lessons learned - -### 5. Conflict Resolution -- Establish clear conflict resolution procedures -- Provide mediation mechanisms -- Ensure fair and impartial resolution processes \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_swarm.md b/docs/swarms/structs/board_of_directors/board_of_directors_swarm.md deleted file mode 100644 index 20223c49..00000000 --- a/docs/swarms/structs/board_of_directors/board_of_directors_swarm.md +++ /dev/null @@ -1,704 +0,0 @@ -# `BoardOfDirectorsSwarm` - -The `BoardOfDirectorsSwarm` is a sophisticated multi-agent orchestration system that implements a collective decision-making approach as an alternative to the single Director pattern. It consists of a board of directors that convenes to discuss, vote, and reach consensus on task distribution and execution strategies. - -## Overview - -The Board of Directors Swarm follows a democratic workflow pattern that mimics real-world corporate governance structures: - -1. **Task Reception**: User provides a task to the swarm -2. **Board Meeting**: Board of Directors convenes to discuss and create a plan -3. **Voting & Consensus**: Board members vote and reach consensus on task distribution -4. **Order Distribution**: Board distributes orders to specialized worker agents -5. **Execution**: Individual agents execute their assigned tasks -6. **Feedback Loop**: Board evaluates results and issues new orders if needed (up to `max_loops`) -7. **Context Preservation**: All conversation history and context is maintained throughout the process - -## Architecture - -### High-Level Workflow - -```mermaid -graph TD - A[User Task] --> B[Board of Directors] - B --> C[Board Meeting & Discussion] - C --> D[Voting & Consensus] - D --> E[Create Plan & Orders] - E --> F[Distribute to Agents] - F --> G[Agent 1] - F --> H[Agent 2] - F --> I[Agent N] - G --> J[Execute Task] - H --> J - I --> J - J --> K[Report Results] - K --> L[Board Evaluation] - L --> M{More Loops?} - M -->|Yes| C - M -->|No| N[Final Output] -``` - -**Diagram Explanation:** -This diagram illustrates the complete lifecycle of a task through the Board of Directors Swarm system. The workflow begins when a user submits a task, which triggers the board to convene for discussion and planning. The board then votes on the approach and creates detailed execution orders. These orders are distributed to multiple specialized agents who execute their tasks in parallel. Results are collected and evaluated by the board, which can trigger additional refinement loops if needed. The process continues until the board is satisfied with the results or the maximum number of loops is reached. - -**Key Technical Points:** -- **Parallel Execution**: Multiple agents can work simultaneously on different aspects of the task -- **Iterative Refinement**: The system supports multiple feedback loops for continuous improvement -- **Centralized Coordination**: The board maintains control over the entire process while delegating execution -- **Result Aggregation**: All agent outputs are collected and evaluated before proceeding - -### Detailed Decision-Making Process - -```mermaid -flowchart TD - A[Task Received] --> B[Board Convenes] - B --> C[Chairman Opens Meeting] - C --> D[Task Analysis Phase] - D --> E[Expertise Assignment] - E --> F[Individual Member Analysis] - F --> G[Discussion & Debate] - G --> H[Proposal Generation] - H --> I[Voting Process] - I --> J{Consensus Reached?} - J -->|No| K[Reconciliation Phase] - K --> G - J -->|Yes| L[Plan Finalization] - L --> M[Order Creation] - M --> N[Agent Assignment] - N --> O[Execution Phase] - O --> P[Result Collection] - P --> Q[Board Review] - Q --> R{Approval?} - R -->|No| S[Refinement Loop] - S --> G - R -->|Yes| T[Final Delivery] -``` - -**Diagram Explanation:** -This detailed flowchart shows the internal decision-making process within the board. The process begins with task reception and board convening, followed by a structured analysis phase where each board member contributes based on their expertise. The discussion and debate phase allows for thorough consideration of different approaches, leading to proposal generation and voting. If consensus isn't reached, the system enters a reconciliation phase to resolve conflicts. Once consensus is achieved, the plan is finalized and orders are created for agent assignment. The execution phase is followed by result collection and board review, with the option to enter refinement loops if the results don't meet approval criteria. - -**Technical Implementation Details:** -- **Expertise Assignment**: Board members are assigned tasks based on their specialized knowledge areas -- **Voting Mechanisms**: Configurable voting weights and decision thresholds ensure fair representation -- **Conflict Resolution**: Built-in reconciliation mechanisms handle disagreements among board members -- **Quality Gates**: Approval checkpoints ensure output quality before final delivery - -### Board Member Interaction Flow - -```mermaid -sequenceDiagram - participant User - participant Chairman - participant ViceChair - participant Secretary - participant Treasurer - participant ExecDir - participant Agents - - User->>Chairman: Submit Task - Chairman->>ViceChair: Notify Board Meeting - Chairman->>Secretary: Request Meeting Setup - Chairman->>Treasurer: Resource Assessment - Chairman->>ExecDir: Strategic Planning - - Note over Chairman,ExecDir: Board Discussion Phase - - Chairman->>ViceChair: Lead Discussion - ViceChair->>Secretary: Document Decisions - Secretary->>Treasurer: Budget Considerations - Treasurer->>ExecDir: Resource Allocation - ExecDir->>Chairman: Strategic Recommendations - - Note over Chairman,ExecDir: Voting & Consensus - - Chairman->>ViceChair: Call for Vote - ViceChair->>Secretary: Record Votes - Secretary->>Treasurer: Financial Approval - Treasurer->>ExecDir: Resource Approval - ExecDir->>Chairman: Final Decision - - Note over Chairman,Agents: Execution Phase - - Chairman->>Agents: Distribute Orders - Agents->>Chairman: Execute Tasks - Agents->>ViceChair: Progress Reports - Agents->>Secretary: Documentation - Agents->>Treasurer: Resource Usage - Agents->>ExecDir: Strategic Updates - - Note over Chairman,ExecDir: Review & Feedback - - Chairman->>User: Deliver Results -``` - -**Diagram Explanation:** -This sequence diagram shows the detailed interaction patterns between different board members and agents throughout the entire process. The interaction begins with the Chairman receiving a task from the user and immediately coordinating with other board members. Each board member has specific responsibilities: the Vice Chairman leads discussions, the Secretary documents decisions, the Treasurer handles resource assessment, and the Executive Director provides strategic planning. During the voting phase, each member contributes their expertise and votes are recorded systematically. In the execution phase, the Chairman distributes orders to agents while maintaining communication channels with all board members for progress monitoring and strategic updates. - -**Technical Communication Patterns:** -- **Hierarchical Communication**: Chairman serves as the central coordinator -- **Specialized Reporting**: Each agent reports to the appropriate board member based on their role -- **Parallel Coordination**: Multiple board members can work simultaneously on different aspects -- **Feedback Channels**: Continuous communication ensures real-time monitoring and adjustment - -### Agent Execution and Feedback Loop - -```mermaid -graph LR - subgraph "Board of Directors" - A[Chairman] - B[Vice Chairman] - C[Secretary] - D[Treasurer] - E[Executive Director] - end - - subgraph "Worker Agents" - F[Research Agent] - G[Analysis Agent] - H[Technical Agent] - I[Financial Agent] - J[Strategy Agent] - end - - subgraph "Execution Flow" - K[Task Distribution] - L[Parallel Execution] - M[Result Aggregation] - N[Quality Assessment] - O[Feedback Loop] - end - - A --> K - B --> K - C --> K - D --> K - E --> K - - K --> L - L --> F - L --> G - L --> H - L --> I - L --> J - - F --> M - G --> M - H --> M - I --> M - J --> M - - M --> N - N --> O - O --> K -``` - -**Diagram Explanation:** -This diagram illustrates the relationship between the Board of Directors and Worker Agents, showing how tasks flow from decision-making to execution and back through feedback loops. The Board of Directors collectively participates in task distribution, ensuring that all perspectives are considered. Worker agents execute tasks in parallel, each specializing in different areas (research, analysis, technical implementation, financial considerations, and strategic planning). Results are aggregated and assessed for quality before determining whether additional feedback loops are needed. - -**Technical Architecture Benefits:** -- **Separation of Concerns**: Clear distinction between decision-making (Board) and execution (Agents) -- **Scalability**: Additional agents can be added without changing the board structure -- **Fault Tolerance**: If one agent fails, others can continue working -- **Quality Control**: Centralized assessment ensures consistent output quality - -## Technical Implementation - -### Core Components - -The `BoardOfDirectorsSwarm` consists of several key components: - -1. **Board Members**: Specialized agents with specific roles and voting weights -2. **Worker Agents**: Execution agents that perform the actual tasks -3. **Voting System**: Configurable voting mechanisms for decision-making -4. **Communication Protocol**: Structured communication between board members and agents -5. **Feedback Loop Controller**: Manages iterative refinement processes - -### Configuration Options - -```python -# Example configuration for BoardOfDirectorsSwarm -board_config = { - "max_loops": 3, # Maximum number of refinement loops - "voting_threshold": 0.7, # Consensus threshold (70%) - "enable_voting_weights": True, # Use weighted voting - "consensus_method": "majority", # Voting method: "majority" or "unanimous" - "board_size": 5, # Number of board members - "enable_feedback_loops": True, # Enable iterative refinement - "output_format": "structured", # Output format: "structured", "text", "json" - "enable_logging": True, # Enable detailed logging - "parallel_execution": True, # Enable parallel agent execution - "quality_gates": True, # Enable quality checkpoints -} -``` - -### Voting Mechanisms - -The system supports multiple voting mechanisms: - -1. **Majority Voting**: Simple majority of votes required -2. **Weighted Voting**: Votes weighted by board member importance -3. **Unanimous Consensus**: All board members must agree -4. **Threshold-based**: Configurable percentage of agreement required - -```python -# Example voting configuration -voting_config = { - "method": "weighted_majority", - "threshold": 0.75, - "weights": { - "CHAIRMAN": 1.5, - "VICE_CHAIRMAN": 1.2, - "SECRETARY": 1.0, - "TREASURER": 1.0, - "EXECUTIVE_DIRECTOR": 1.5 - }, - "tie_breaker": "CHAIRMAN", # Chairman breaks ties - "allow_abstention": True, # Allow board members to abstain -} -``` - -### Communication Protocols - -The system uses structured communication protocols: - -1. **Task Distribution Protocol**: Standardized format for distributing tasks to agents -2. **Progress Reporting Protocol**: Regular status updates from agents to board -3. **Decision Communication Protocol**: Clear communication of board decisions -4. **Feedback Protocol**: Structured feedback for iterative improvement - -```python -# Example communication message format -message_format = { - "sender": "CHAIRMAN", - "recipient": "RESEARCH_AGENT", - "message_type": "TASK_DISTRIBUTION", - "content": { - "task_id": "task_123", - "task_description": "Research market trends for Q4", - "deadline": "2024-01-15T10:00:00Z", - "priority": "HIGH", - "resources": ["market_data", "analytics_tools"], - "expected_output": "structured_report" - }, - "metadata": { - "timestamp": "2024-01-10T09:00:00Z", - "session_id": "session_456", - "board_decision_id": "decision_789" - } -} -``` - -## Usage Examples - -### Basic Usage - -```python -from swarms import BoardOfDirectorsSwarm, Agent - -# Create specialized agents -research_agent = Agent( - name="Research Agent", - system_prompt="You are a research specialist focused on market analysis and data gathering.", - llm="gpt-4" -) - -analysis_agent = Agent( - name="Analysis Agent", - system_prompt="You are an analysis expert who interprets data and provides insights.", - llm="gpt-4" -) - -technical_agent = Agent( - name="Technical Agent", - system_prompt="You are a technical specialist who handles implementation and technical details.", - llm="gpt-4" -) - -# Create the Board of Directors Swarm -board_swarm = BoardOfDirectorsSwarm( - agents=[research_agent, analysis_agent, technical_agent], - max_loops=3, - voting_threshold=0.7, - enable_voting_weights=True -) - -# Execute a task -task = "Analyze the current market trends in AI and provide strategic recommendations for our company." -result = board_swarm.run(task) -print(result) -``` - -### Advanced Configuration - -```python -from swarms import BoardOfDirectorsSwarm, Agent -from swarms.structs.board_of_directors import BoardConfig - -# Create a custom board configuration -custom_config = BoardConfig( - max_loops=5, - voting_threshold=0.8, - consensus_method="unanimous", - enable_feedback_loops=True, - output_format="structured", - board_roles={ - "CHAIRMAN": {"weight": 1.5, "responsibilities": ["leadership", "final_decision"]}, - "VICE_CHAIRMAN": {"weight": 1.2, "responsibilities": ["operations", "coordination"]}, - "SECRETARY": {"weight": 1.0, "responsibilities": ["documentation", "record_keeping"]}, - "TREASURER": {"weight": 1.0, "responsibilities": ["financial_oversight", "resource_allocation"]}, - "EXECUTIVE_DIRECTOR": {"weight": 1.5, "responsibilities": ["strategic_planning", "execution"]} - } -) - -# Create specialized agents with custom prompts -agents = [ - Agent( - name="Market Research Agent", - system_prompt="""You are a market research specialist with expertise in: - - Competitive analysis - - Market sizing and segmentation - - Customer behavior analysis - - Industry trend identification - Provide detailed, data-driven insights.""", - llm="gpt-4" - ), - Agent( - name="Financial Analysis Agent", - system_prompt="""You are a financial analyst specializing in: - - Financial modeling and forecasting - - Risk assessment and mitigation - - Investment analysis - - Cost-benefit analysis - Provide comprehensive financial insights.""", - llm="gpt-4" - ), - Agent( - name="Technical Strategy Agent", - system_prompt="""You are a technical strategist focused on: - - Technology roadmap planning - - Technical feasibility assessment - - Implementation strategy - - Technology risk evaluation - Provide strategic technical guidance.""", - llm="gpt-4" - ) -] - -# Create the swarm with custom configuration -board_swarm = BoardOfDirectorsSwarm( - agents=agents, - config=custom_config -) - -# Execute a complex task -complex_task = """ -Analyze the feasibility of launching a new AI-powered product in the healthcare sector. -Consider: -1. Market opportunity and competitive landscape -2. Financial viability and investment requirements -3. Technical implementation challenges and timeline -4. Regulatory compliance requirements -5. Risk assessment and mitigation strategies - -Provide a comprehensive report with recommendations for next steps. -""" - -result = board_swarm.run(complex_task) -print(result) -``` - -### Real-World Use Cases - -#### 1. Strategic Business Planning - -```python -# Example: Strategic business planning with multiple stakeholders -business_planning_task = """ -Develop a comprehensive 5-year strategic plan for our technology company. -Include: -- Market analysis and competitive positioning -- Product development roadmap -- Financial projections and funding requirements -- Operational scaling strategy -- Risk management framework -- Success metrics and KPIs -""" - -# Configure board for strategic planning -strategic_config = BoardConfig( - max_loops=4, - voting_threshold=0.8, - consensus_method="weighted_majority", - enable_feedback_loops=True, - output_format="structured" -) - -strategic_swarm = BoardOfDirectorsSwarm( - agents=[market_agent, financial_agent, technical_agent, strategy_agent], - config=strategic_config -) - -strategic_plan = strategic_swarm.run(business_planning_task) -``` - -#### 2. Product Development Decision Making - -```python -# Example: Product development decision making -product_decision_task = """ -Evaluate the feasibility of developing a new AI-powered customer service chatbot. -Consider: -- Technical requirements and development timeline -- Market demand and competitive analysis -- Cost-benefit analysis and ROI projections -- Implementation challenges and resource requirements -- Success criteria and measurement metrics - -Provide a go/no-go recommendation with detailed rationale. -""" - -# Configure board for product decisions -product_config = BoardConfig( - max_loops=3, - voting_threshold=0.75, - consensus_method="majority", - enable_feedback_loops=True, - output_format="structured" -) - -product_swarm = BoardOfDirectorsSwarm( - agents=[technical_agent, market_agent, financial_agent], - config=product_config -) - -product_recommendation = product_swarm.run(product_decision_task) -``` - -#### 3. Crisis Management and Response - -```python -# Example: Crisis management and response planning -crisis_task = """ -Our company is facing a major data breach. Develop an immediate response plan. -Include: -- Immediate containment and mitigation steps -- Communication strategy for stakeholders -- Legal and regulatory compliance requirements -- Financial impact assessment -- Long-term recovery and prevention measures -- Timeline and resource allocation -""" - -# Configure board for crisis management -crisis_config = BoardConfig( - max_loops=2, # Faster response needed - voting_threshold=0.6, # Lower threshold for urgent decisions - consensus_method="majority", - enable_feedback_loops=False, # No time for multiple iterations - output_format="structured" -) - -crisis_swarm = BoardOfDirectorsSwarm( - agents=[security_agent, legal_agent, communications_agent, financial_agent], - config=crisis_config -) - -crisis_response = crisis_swarm.run(crisis_task) -``` - -## Performance Optimization - -### Parallel Execution Strategies - -The Board of Directors Swarm supports various parallel execution strategies: - -1. **Task-Level Parallelism**: Multiple agents work on different aspects simultaneously -2. **Board-Level Parallelism**: Board members can analyze different aspects in parallel -3. **Iteration-Level Parallelism**: Multiple refinement loops can run concurrently - -```python -# Example: Optimizing for parallel execution -parallel_config = BoardConfig( - max_loops=3, - parallel_execution=True, - max_concurrent_agents=5, - enable_async_processing=True, - timeout_per_agent=300, # 5 minutes per agent - enable_agent_pooling=True -) - -# Create agent pool for better resource utilization -agent_pool = [ - Agent(name=f"Research_Agent_{i}", system_prompt="...", llm="gpt-4") - for i in range(3) -] + [ - Agent(name=f"Analysis_Agent_{i}", system_prompt="...", llm="gpt-4") - for i in range(2) -] - -parallel_swarm = BoardOfDirectorsSwarm( - agents=agent_pool, - config=parallel_config -) -``` - -### Quality Control Mechanisms - -```python -# Example: Quality control configuration -quality_config = BoardConfig( - max_loops=3, - quality_gates=True, - quality_threshold=0.8, - enable_peer_review=True, - review_required=True, - output_validation=True, - enable_metrics_tracking=True -) - -# Define quality metrics -quality_metrics = { - "completeness": 0.9, # 90% completeness required - "accuracy": 0.85, # 85% accuracy required - "relevance": 0.9, # 90% relevance required - "clarity": 0.8 # 80% clarity required -} - -quality_swarm = BoardOfDirectorsSwarm( - agents=agents, - config=quality_config, - quality_metrics=quality_metrics -) -``` - -## Monitoring and Debugging - -### Logging and Observability - -```python -import logging -from swarms import BoardOfDirectorsSwarm - -# Configure detailed logging -logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' -) - -# Create swarm with logging enabled -logging_swarm = BoardOfDirectorsSwarm( - agents=agents, - config=BoardConfig( - enable_logging=True, - log_level="DEBUG", - enable_metrics=True, - enable_tracing=True - ) -) - -# Execute with detailed logging -result = logging_swarm.run(task) -``` - -### Performance Metrics - -```python -# Example: Performance monitoring -from swarms.metrics import SwarmMetrics - -# Create metrics collector -metrics = SwarmMetrics() - -# Configure swarm with metrics -monitored_swarm = BoardOfDirectorsSwarm( - agents=agents, - config=BoardConfig(enable_metrics=True), - metrics_collector=metrics -) - -# Execute and collect metrics -result = monitored_swarm.run(task) - -# Analyze performance -performance_report = metrics.generate_report() -print(f"Total execution time: {performance_report['total_time']}") -print(f"Average agent response time: {performance_report['avg_agent_time']}") -print(f"Number of voting rounds: {performance_report['voting_rounds']}") -print(f"Consensus achieved: {performance_report['consensus_achieved']}") -``` - -## Best Practices - -### 1. Agent Design - -- **Specialized Expertise**: Design agents with specific, complementary expertise -- **Clear Responsibilities**: Define clear boundaries for each agent's responsibilities -- **Consistent Communication**: Use standardized communication protocols -- **Error Handling**: Implement robust error handling and recovery mechanisms - -### 2. Board Configuration - -- **Appropriate Voting Thresholds**: Set thresholds based on decision criticality -- **Balanced Voting Weights**: Ensure fair representation while maintaining leadership hierarchy -- **Flexible Consensus Methods**: Choose consensus methods based on decision type -- **Reasonable Loop Limits**: Balance quality with efficiency - -### 3. Task Design - -- **Clear Objectives**: Define clear, measurable objectives -- **Structured Requirements**: Provide structured, detailed requirements -- **Appropriate Scope**: Ensure tasks are appropriately scoped for the board size -- **Context Provision**: Provide sufficient context for informed decision-making - -### 4. Performance Optimization - -- **Parallel Execution**: Leverage parallel execution where possible -- **Resource Management**: Monitor and optimize resource usage -- **Quality Gates**: Implement appropriate quality control mechanisms -- **Continuous Monitoring**: Monitor performance and adjust configurations as needed - -## Troubleshooting - -### Common Issues and Solutions - -1. **Consensus Not Reached** - - **Issue**: Board cannot reach consensus within loop limit - - **Solution**: Lower voting threshold, increase max_loops, or adjust voting weights - -2. **Agent Timeout** - - **Issue**: Individual agents take too long to respond - - **Solution**: Increase timeout settings or optimize agent prompts - -3. **Poor Quality Output** - - **Issue**: Final output doesn't meet quality standards - - **Solution**: Enable quality gates, increase max_loops, or improve agent prompts - -4. **Resource Exhaustion** - - **Issue**: System runs out of resources during execution - - **Solution**: Implement resource limits, use agent pooling, or optimize parallel execution - -### Debugging Techniques - -```python -# Example: Debugging configuration -debug_config = BoardConfig( - max_loops=1, # Limit loops for debugging - enable_logging=True, - log_level="DEBUG", - enable_tracing=True, - debug_mode=True -) - -# Create debug swarm -debug_swarm = BoardOfDirectorsSwarm( - agents=agents, - config=debug_config -) - -# Execute with debugging -try: - result = debug_swarm.run(task) -except Exception as e: - print(f"Error: {e}") - print(f"Debug info: {debug_swarm.get_debug_info()}") -``` \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/board_of_directors_workflow.md b/docs/swarms/structs/board_of_directors/board_of_directors_workflow.md deleted file mode 100644 index 3e913ea7..00000000 --- a/docs/swarms/structs/board_of_directors/board_of_directors_workflow.md +++ /dev/null @@ -1,908 +0,0 @@ -# Board of Directors Workflow - -The Board of Directors workflow is a sophisticated multi-stage process that ensures comprehensive task analysis, collaborative decision-making, and effective execution through specialized agents. This workflow implements a corporate governance model that balances efficiency with thoroughness, ensuring high-quality outcomes through structured collaboration. - -## Workflow Overview - -```mermaid -graph TD - A[Task Input] --> B[Initial Assessment] - B --> C[Board Assembly] - C --> D[Meeting Phase] - D --> E[Decision Phase] - E --> F[Execution Phase] - F --> G[Review Phase] - G --> H{Approval?} - H -->|No| I[Refinement] - I --> D - H -->|Yes| J[Final Delivery] - - style A fill:#e1f5fe - style J fill:#c8e6c9 - style H fill:#fff3e0 -``` - -**Diagram Explanation:** -This high-level workflow diagram shows the complete lifecycle of a task through the Board of Directors system. The process begins with task input, followed by an initial assessment to understand requirements and complexity. The board then assembles with appropriate members, conducts a structured meeting phase for analysis and discussion, makes decisions through voting and consensus, executes the plan through specialized agents, reviews results, and either approves for final delivery or returns to refinement loops for improvement. - -**Technical Implementation Details:** -- **Task Input Validation**: System validates task format, requirements, and constraints -- **Dynamic Board Assembly**: Board members are selected based on task requirements and availability -- **Structured Meeting Protocol**: Follows corporate governance best practices -- **Iterative Refinement**: Quality gates ensure output meets standards before final delivery - -## Phase 1: Initial Assessment - -### Task Analysis and Board Preparation - -```mermaid -flowchart LR - A[Task Received] --> B[Complexity Assessment] - B --> C[Resource Requirements] - C --> D[Expertise Mapping] - D --> E[Board Member Selection] - E --> F[Meeting Scheduling] - - subgraph "Assessment Criteria" - G[Task Complexity] - H[Time Constraints] - I[Resource Availability] - J[Expertise Requirements] - end - - B --> G - B --> H - C --> I - D --> J -``` - -**Diagram Explanation:** -This flowchart illustrates the systematic approach to task analysis and board preparation. When a task is received, the system performs a comprehensive assessment including complexity evaluation, resource requirement analysis, expertise mapping, and board member selection. The assessment criteria include task complexity, time constraints, resource availability, and specific expertise requirements needed for successful completion. - -**Technical Implementation:** -```python -# Example: Task assessment implementation -class TaskAssessment: - def __init__(self): - self.complexity_metrics = { - "scope": 0.0, # Task scope (0-1) - "technical_depth": 0.0, # Technical complexity (0-1) - "stakeholder_count": 0, # Number of stakeholders - "timeline_constraints": 0.0, # Time pressure (0-1) - "resource_intensity": 0.0 # Resource requirements (0-1) - } - - def assess_task(self, task_description): - """Assess task complexity and requirements""" - assessment = { - "complexity_score": self.calculate_complexity(), - "required_expertise": self.identify_expertise_needs(), - "resource_requirements": self.estimate_resources(), - "timeline_estimate": self.estimate_timeline(), - "recommended_board_size": self.calculate_board_size() - } - return assessment - - def calculate_complexity(self): - """Calculate overall task complexity score""" - weights = { - "scope": 0.25, - "technical_depth": 0.3, - "stakeholder_count": 0.15, - "timeline_constraints": 0.2, - "resource_intensity": 0.1 - } - - complexity_score = sum( - self.complexity_metrics[key] * weights[key] - for key in weights - ) - return min(complexity_score, 1.0) - - def identify_expertise_needs(self): - """Identify required expertise areas""" - expertise_areas = [] - - if self.complexity_metrics["technical_depth"] > 0.5: - expertise_areas.append("technical") - - if self.complexity_metrics["stakeholder_count"] > 3: - expertise_areas.append("stakeholder_management") - - if self.complexity_metrics["resource_intensity"] > 0.5: - expertise_areas.append("resource_management") - - return expertise_areas -``` - -### Board Member Activation - -```mermaid -sequenceDiagram - participant System - participant Chairman - participant Members - participant Agents - - System->>Chairman: Notify New Task - Chairman->>System: Assess Task Requirements - System->>Members: Activate Relevant Members - Members->>Chairman: Confirm Availability - Chairman->>Agents: Prepare Agent Pool - Agents->>Chairman: Confirm Readiness - Chairman->>System: Board Ready for Meeting -``` - -**Diagram Explanation:** -This sequence diagram shows the systematic process of board member activation and preparation. The system notifies the Chairman of a new task, who then assesses requirements and determines which board members are needed. The system activates relevant members, who confirm their availability. The Chairman prepares the agent pool and confirms readiness before declaring the board ready for the meeting. - -**Technical Implementation:** -```python -# Example: Board member activation system -class BoardActivation: - def __init__(self, board_members, agents): - self.board_members = board_members - self.agents = agents - self.activation_status = {} - - async def activate_board(self, task_assessment): - """Activate board members based on task requirements""" - # Determine required members - required_members = self.select_required_members(task_assessment) - - # Activate members - activation_results = [] - for member in required_members: - status = await self.activate_member(member, task_assessment) - activation_results.append(status) - - # Prepare agent pool - agent_pool = self.prepare_agent_pool(task_assessment) - - # Confirm readiness - readiness_status = await self.confirm_readiness(activation_results, agent_pool) - - return { - "board_ready": readiness_status["ready"], - "active_members": readiness_status["active_members"], - "agent_pool": readiness_status["agent_pool"], - "estimated_start_time": readiness_status["start_time"] - } - - def select_required_members(self, assessment): - """Select board members based on task requirements""" - required_members = ["CHAIRMAN"] # Chairman always required - - if assessment["complexity_score"] > 0.7: - required_members.extend(["VICE_CHAIRMAN", "EXECUTIVE_DIRECTOR"]) - - if "technical" in assessment["required_expertise"]: - required_members.append("TECHNICAL_DIRECTOR") - - if "financial" in assessment["required_expertise"]: - required_members.append("TREASURER") - - if assessment["stakeholder_count"] > 5: - required_members.append("SECRETARY") - - return list(set(required_members)) # Remove duplicates - - async def activate_member(self, member_role, assessment): - """Activate individual board member""" - member = self.board_members.get(member_role) - if not member: - return {"status": "error", "message": f"Member {member_role} not found"} - - # Check availability - availability = await member.check_availability() - if not availability["available"]: - return {"status": "unavailable", "member": member_role, "reason": availability["reason"]} - - # Prepare member for task - preparation_status = await member.prepare_for_task(assessment) - - return { - "status": "activated", - "member": member_role, - "preparation_time": preparation_status["preparation_time"], - "expertise_areas": preparation_status["expertise_areas"] - } -``` - -## Phase 2: Board Meeting - -### Meeting Structure - -```mermaid -graph TD - A[Meeting Opens] --> B[Agenda Review] - B --> C[Task Presentation] - C --> D[Expertise Assignment] - D --> E[Individual Analysis] - E --> F[Group Discussion] - F --> G[Proposal Development] - G --> H[Voting Process] - H --> I[Consensus Building] - I --> J[Plan Finalization] - - subgraph "Meeting Components" - K[Time Management] - L[Documentation] - M[Conflict Resolution] - N[Decision Recording] - end - - A --> K - F --> L - I --> M - J --> N -``` - -**Diagram Explanation:** -This diagram shows the structured meeting process that follows corporate governance best practices. The meeting begins with agenda review and task presentation, followed by expertise assignment where board members are given specific areas to analyze. Individual analysis leads to group discussion, proposal development, voting, consensus building, and plan finalization. Throughout the process, time management, documentation, conflict resolution, and decision recording ensure effective governance. - -**Technical Implementation:** -```python -# Example: Meeting management system -class BoardMeeting: - def __init__(self, board_members, task, config): - self.board_members = board_members - self.task = task - self.config = config - self.meeting_phases = [] - self.decisions = [] - self.documentation = {} - - async def conduct_meeting(self): - """Conduct the board meeting following structured phases""" - meeting_result = { - "phases": [], - "decisions": [], - "documentation": {}, - "consensus_achieved": False, - "final_plan": None - } - - # Phase 1: Meeting Opening and Agenda Review - opening_phase = await self.conduct_opening_phase() - meeting_result["phases"].append(opening_phase) - - # Phase 2: Task Presentation and Expertise Assignment - presentation_phase = await self.conduct_presentation_phase() - meeting_result["phases"].append(presentation_phase) - - # Phase 3: Individual Analysis - analysis_phase = await self.conduct_analysis_phase() - meeting_result["phases"].append(analysis_phase) - - # Phase 4: Group Discussion - discussion_phase = await self.conduct_discussion_phase() - meeting_result["phases"].append(discussion_phase) - - # Phase 5: Proposal Development - proposal_phase = await self.conduct_proposal_phase() - meeting_result["phases"].append(proposal_phase) - - # Phase 6: Voting and Consensus - voting_phase = await self.conduct_voting_phase() - meeting_result["phases"].append(voting_phase) - - # Phase 7: Plan Finalization - finalization_phase = await self.conduct_finalization_phase() - meeting_result["phases"].append(finalization_phase) - - meeting_result["decisions"] = self.decisions - meeting_result["documentation"] = self.documentation - meeting_result["consensus_achieved"] = voting_phase["consensus_achieved"] - meeting_result["final_plan"] = finalization_phase["final_plan"] - - return meeting_result - - async def conduct_opening_phase(self): - """Conduct meeting opening and agenda review""" - chairman = self.board_members["CHAIRMAN"] - - # Open meeting - opening_statement = await chairman.open_meeting(self.task) - - # Review agenda - agenda_review = await chairman.review_agenda(self.task) - - # Set meeting parameters - meeting_params = { - "time_limit": self.config.get("meeting_time_limit", 3600), # 1 hour default - "voting_threshold": self.config.get("voting_threshold", 0.7), - "consensus_method": self.config.get("consensus_method", "majority") - } - - return { - "phase": "opening", - "opening_statement": opening_statement, - "agenda_review": agenda_review, - "meeting_params": meeting_params, - "timestamp": datetime.now().isoformat() - } - - async def conduct_presentation_phase(self): - """Conduct task presentation and expertise assignment""" - chairman = self.board_members["CHAIRMAN"] - - # Present task details - task_presentation = await chairman.present_task(self.task) - - # Assign expertise areas - expertise_assignments = await chairman.assign_expertise_areas( - self.board_members, self.task - ) - - return { - "phase": "presentation", - "task_presentation": task_presentation, - "expertise_assignments": expertise_assignments, - "timestamp": datetime.now().isoformat() - } -``` - -### Discussion and Debate Process - -```mermaid -flowchart TD - A[Discussion Opens] --> B[Expertise-Based Input] - B --> C[Cross-Examination] - C --> D[Alternative Proposals] - D --> E[Impact Analysis] - E --> F[Risk Assessment] - F --> G[Stakeholder Consideration] - G --> H[Resource Evaluation] - H --> I[Timeline Assessment] - I --> J[Consensus Check] - J -->|No Consensus| K[Conflict Resolution] - K --> L[Mediation Process] - L --> J - J -->|Consensus| M[Proposal Finalization] - - subgraph "Discussion Elements" - N[Evidence-Based Arguments] - O[Stakeholder Perspectives] - P[Risk-Benefit Analysis] - Q[Implementation Feasibility] - end - - B --> N - G --> O - E --> P - H --> Q -``` - -**Diagram Explanation:** -This flowchart details the discussion and debate process that ensures thorough consideration of all aspects before decision-making. The process begins with expertise-based input from each board member, followed by cross-examination to validate claims. Alternative proposals are considered, and comprehensive impact analysis, risk assessment, stakeholder consideration, resource evaluation, and timeline assessment are conducted. If consensus isn't reached, conflict resolution and mediation processes are employed until agreement is achieved. - -**Technical Implementation:** -```python -# Example: Discussion and debate management -class DiscussionManager: - def __init__(self, board_members, config): - self.board_members = board_members - self.config = config - self.discussion_points = [] - self.conflicts = [] - self.consensus_status = False - - async def conduct_discussion(self, task, expertise_assignments): - """Conduct structured discussion and debate""" - discussion_result = { - "phases": [], - "consensus_achieved": False, - "final_proposal": None, - "conflicts_resolved": [] - } - - # Phase 1: Expertise-based input - expertise_input = await self.gather_expertise_input(task, expertise_assignments) - discussion_result["phases"].append(expertise_input) - - # Phase 2: Cross-examination - cross_examination = await self.conduct_cross_examination(expertise_input) - discussion_result["phases"].append(cross_examination) - - # Phase 3: Alternative proposals - alternatives = await self.generate_alternatives(task, expertise_input) - discussion_result["phases"].append(alternatives) - - # Phase 4: Comprehensive analysis - analysis = await self.conduct_comprehensive_analysis(task, alternatives) - discussion_result["phases"].append(analysis) - - # Phase 5: Consensus building - consensus = await self.build_consensus(analysis) - discussion_result["phases"].append(consensus) - - discussion_result["consensus_achieved"] = consensus["achieved"] - discussion_result["final_proposal"] = consensus["final_proposal"] - discussion_result["conflicts_resolved"] = consensus["conflicts_resolved"] - - return discussion_result - - async def gather_expertise_input(self, task, expertise_assignments): - """Gather input from each board member based on their expertise""" - expertise_inputs = {} - - for member_role, expertise_areas in expertise_assignments.items(): - member = self.board_members[member_role] - - # Generate expertise-based analysis - analysis = await member.analyze_task_areas(task, expertise_areas) - - expertise_inputs[member_role] = { - "expertise_areas": expertise_areas, - "analysis": analysis, - "recommendations": analysis.get("recommendations", []), - "concerns": analysis.get("concerns", []), - "proposals": analysis.get("proposals", []) - } - - return { - "phase": "expertise_input", - "inputs": expertise_inputs, - "timestamp": datetime.now().isoformat() - } - - async def conduct_cross_examination(self, expertise_input): - """Conduct cross-examination of expertise inputs""" - cross_examination_results = {} - - for member_role, input_data in expertise_input["inputs"].items(): - member = self.board_members[member_role] - - # Other members examine this member's input - examinations = [] - for examiner_role, examiner in self.board_members.items(): - if examiner_role != member_role: - examination = await examiner.examine_input( - input_data, member_role - ) - examinations.append({ - "examiner": examiner_role, - "examination": examination - }) - - cross_examination_results[member_role] = { - "original_input": input_data, - "examinations": examinations, - "validation_status": self.assess_validation_status(examinations) - } - - return { - "phase": "cross_examination", - "results": cross_examination_results, - "timestamp": datetime.now().isoformat() - } - - async def generate_alternatives(self, task, expertise_input): - """Generate alternative proposals based on expertise input""" - alternatives = [] - - # Generate alternatives from each expertise area - for member_role, input_data in expertise_input["inputs"].items(): - member = self.board_members[member_role] - - member_alternatives = await member.generate_alternatives( - task, input_data - ) - - alternatives.extend(member_alternatives) - - # Combine and synthesize alternatives - synthesized_alternatives = await self.synthesize_alternatives(alternatives) - - return { - "phase": "alternatives", - "individual_alternatives": alternatives, - "synthesized_alternatives": synthesized_alternatives, - "timestamp": datetime.now().isoformat() - } -``` - -## Phase 3: Decision Making - -### Voting and Consensus Process - -```mermaid -graph TD - A[Proposal Review] --> B[Voting Preparation] - B --> C[Individual Voting] - C --> D[Vote Aggregation] - D --> E[Threshold Check] - E -->|Below Threshold| F[Consensus Building] - F --> G[Proposal Refinement] - G --> C - E -->|Above Threshold| H[Decision Finalization] - H --> I[Plan Creation] - I --> J[Execution Orders] - - subgraph "Voting Components" - K[Weighted Voting] - L[Secret Ballot] - M[Transparent Process] - N[Conflict Resolution] - end - - C --> K - C --> L - D --> M - F --> N -``` - -**Diagram Explanation:** -This diagram shows the structured voting and consensus process that ensures fair and transparent decision-making. The process begins with proposal review and voting preparation, followed by individual voting where each board member casts their vote. Votes are aggregated and checked against the consensus threshold. If the threshold isn't met, consensus building and proposal refinement processes are initiated. Once the threshold is achieved, the decision is finalized, a plan is created, and execution orders are generated. - -**Technical Implementation:** -```python -# Example: Voting and consensus system -class VotingSystem: - def __init__(self, board_members, config): - self.board_members = board_members - self.config = config - self.voting_history = [] - self.consensus_threshold = config.get("voting_threshold", 0.7) - self.voting_weights = config.get("voting_weights", {}) - - async def conduct_voting(self, proposals): - """Conduct voting on proposals""" - voting_result = { - "rounds": [], - "final_decision": None, - "consensus_achieved": False, - "voting_summary": {} - } - - current_proposals = proposals - round_number = 1 - - while round_number <= self.config.get("max_voting_rounds", 3): - # Conduct voting round - round_result = await self.conduct_voting_round( - current_proposals, round_number - ) - voting_result["rounds"].append(round_result) - - # Check if consensus achieved - if round_result["consensus_achieved"]: - voting_result["final_decision"] = round_result["winning_proposal"] - voting_result["consensus_achieved"] = True - break - - # Refine proposals for next round - current_proposals = await self.refine_proposals( - current_proposals, round_result - ) - - round_number += 1 - - # Generate voting summary - voting_result["voting_summary"] = self.generate_voting_summary( - voting_result["rounds"] - ) - - return voting_result - - async def conduct_voting_round(self, proposals, round_number): - """Conduct a single voting round""" - round_result = { - "round": round_number, - "proposals": proposals, - "votes": {}, - "aggregated_results": {}, - "consensus_achieved": False, - "winning_proposal": None - } - - # Collect votes from each board member - for member_role, member in self.board_members.items(): - vote = await member.vote_on_proposals(proposals, round_number) - round_result["votes"][member_role] = vote - - # Aggregate votes - aggregated_results = self.aggregate_votes( - round_result["votes"], proposals - ) - round_result["aggregated_results"] = aggregated_results - - # Check consensus - consensus_check = self.check_consensus(aggregated_results) - round_result["consensus_achieved"] = consensus_check["achieved"] - round_result["winning_proposal"] = consensus_check["winning_proposal"] - - return round_result - - def aggregate_votes(self, votes, proposals): - """Aggregate votes using weighted voting system""" - aggregated_results = {} - - for proposal_id in [p["id"] for p in proposals]: - total_weighted_score = 0 - total_weight = 0 - vote_counts = {} - - for member_role, vote in votes.items(): - member_weight = self.voting_weights.get(member_role, 1.0) - - if proposal_id in vote["scores"]: - score = vote["scores"][proposal_id] - weighted_score = score * member_weight - total_weighted_score += weighted_score - total_weight += member_weight - - # Track vote distribution - vote_counts[member_role] = { - "score": score, - "weight": member_weight, - "weighted_score": weighted_score - } - - # Calculate final score - final_score = total_weighted_score / total_weight if total_weight > 0 else 0 - - aggregated_results[proposal_id] = { - "final_score": final_score, - "total_weight": total_weight, - "vote_counts": vote_counts, - "consensus_percentage": final_score - } - - return aggregated_results - - def check_consensus(self, aggregated_results): - """Check if consensus threshold is met""" - best_proposal = None - best_score = 0 - - for proposal_id, result in aggregated_results.items(): - if result["final_score"] > best_score: - best_score = result["final_score"] - best_proposal = proposal_id - - consensus_achieved = best_score >= self.consensus_threshold - - return { - "achieved": consensus_achieved, - "winning_proposal": best_proposal if consensus_achieved else None, - "best_score": best_score, - "threshold": self.consensus_threshold - } -``` - -## Phase 4: Execution and Monitoring - -### Agent Execution Management - -```mermaid -graph TD - A[Execution Orders] --> B[Agent Assignment] - B --> C[Task Distribution] - C --> D[Parallel Execution] - D --> E[Progress Monitoring] - E --> F[Result Collection] - F --> G[Quality Assessment] - G --> H{Quality Met?} - H -->|No| I[Refinement Request] - I --> J[Agent Re-execution] - J --> E - H -->|Yes| K[Result Aggregation] - K --> L[Board Review] - - subgraph "Execution Components" - M[Resource Allocation] - N[Deadline Management] - O[Error Handling] - P[Performance Tracking] - end - - B --> M - C --> N - D --> O - E --> P -``` - -**Diagram Explanation:** -This diagram illustrates the execution and monitoring phase where the board's decisions are implemented through specialized agents. Execution orders are created and distributed to appropriate agents, who execute tasks in parallel while being monitored for progress. Results are collected, assessed for quality, and either approved or sent back for refinement. Once quality standards are met, results are aggregated and presented to the board for final review. - -**Technical Implementation:** -```python -# Example: Execution management system -class ExecutionManager: - def __init__(self, agents, config): - self.agents = agents - self.config = config - self.execution_status = {} - self.performance_metrics = {} - - async def execute_plan(self, execution_plan): - """Execute the board's approved plan""" - execution_result = { - "phases": [], - "final_results": None, - "quality_metrics": {}, - "performance_summary": {} - } - - # Phase 1: Agent assignment and task distribution - assignment_phase = await self.assign_agents(execution_plan) - execution_result["phases"].append(assignment_phase) - - # Phase 2: Parallel execution with monitoring - execution_phase = await self.execute_tasks(assignment_phase["assignments"]) - execution_result["phases"].append(execution_phase) - - # Phase 3: Result collection and quality assessment - assessment_phase = await self.assess_results(execution_phase["results"]) - execution_result["phases"].append(assessment_phase) - - # Phase 4: Result aggregation and board review - review_phase = await self.prepare_board_review(assessment_phase) - execution_result["phases"].append(review_phase) - - execution_result["final_results"] = review_phase["final_results"] - execution_result["quality_metrics"] = assessment_phase["quality_metrics"] - execution_result["performance_summary"] = execution_phase["performance_summary"] - - return execution_result - - async def assign_agents(self, execution_plan): - """Assign agents to tasks based on execution plan""" - assignments = {} - - for task_id, task_details in execution_plan["tasks"].items(): - # Select appropriate agent based on task requirements - selected_agent = await self.select_agent_for_task(task_details) - - # Prepare task assignment - assignment = { - "task_id": task_id, - "agent": selected_agent, - "task_details": task_details, - "deadline": task_details.get("deadline"), - "priority": task_details.get("priority", "normal"), - "resources": task_details.get("resources", []), - "expected_output": task_details.get("expected_output") - } - - assignments[task_id] = assignment - - return { - "phase": "agent_assignment", - "assignments": assignments, - "timestamp": datetime.now().isoformat() - } - - async def execute_tasks(self, assignments): - """Execute tasks in parallel with monitoring""" - execution_tasks = [] - execution_results = {} - performance_metrics = {} - - # Create execution tasks - for task_id, assignment in assignments.items(): - task = self.create_execution_task(assignment) - execution_tasks.append(task) - - # Execute tasks in parallel - results = await asyncio.gather(*execution_tasks, return_exceptions=True) - - # Process results - for i, result in enumerate(results): - task_id = list(assignments.keys())[i] - - if isinstance(result, Exception): - execution_results[task_id] = { - "status": "error", - "error": str(result), - "retry_count": 0 - } - else: - execution_results[task_id] = { - "status": "completed", - "result": result, - "execution_time": result.get("execution_time"), - "quality_score": result.get("quality_score") - } - - # Collect performance metrics - performance_metrics[task_id] = self.collect_performance_metrics( - task_id, result - ) - - return { - "phase": "task_execution", - "results": execution_results, - "performance_summary": self.summarize_performance(performance_metrics), - "timestamp": datetime.now().isoformat() - } - - async def assess_results(self, execution_results): - """Assess quality of execution results""" - quality_metrics = {} - overall_quality_score = 0 - total_tasks = len(execution_results) - - for task_id, result in execution_results.items(): - if result["status"] == "completed": - # Assess individual task quality - task_quality = await self.assess_task_quality(result) - quality_metrics[task_id] = task_quality - overall_quality_score += task_quality["overall_score"] - else: - quality_metrics[task_id] = { - "overall_score": 0, - "completeness": 0, - "accuracy": 0, - "relevance": 0, - "issues": ["Task failed to execute"] - } - - # Calculate overall quality - overall_quality_score = overall_quality_score / total_tasks if total_tasks > 0 else 0 - - return { - "phase": "quality_assessment", - "quality_metrics": quality_metrics, - "overall_quality_score": overall_quality_score, - "quality_threshold_met": overall_quality_score >= self.config.get("quality_threshold", 0.8), - "timestamp": datetime.now().isoformat() - } -``` - -## Best Practices and Optimization - -### Performance Optimization Strategies - -1. **Parallel Execution**: Maximize parallel agent execution for faster results -2. **Resource Pooling**: Implement agent pooling for better resource utilization -3. **Caching**: Cache common analysis results to avoid redundant computation -4. **Load Balancing**: Distribute tasks evenly across available agents - -### Quality Assurance - -1. **Quality Gates**: Implement quality checkpoints throughout the process -2. **Peer Review**: Enable peer review mechanisms for critical decisions -3. **Validation**: Validate outputs against predefined criteria -4. **Continuous Improvement**: Learn from previous executions to improve future performance - -### Monitoring and Analytics - -```python -# Example: Performance monitoring system -class PerformanceMonitor: - def __init__(self): - self.metrics = { - "execution_times": [], - "quality_scores": [], - "consensus_rounds": [], - "error_rates": [] - } - - def track_execution_time(self, phase, duration): - """Track execution time for different phases""" - self.metrics["execution_times"].append({ - "phase": phase, - "duration": duration, - "timestamp": datetime.now().isoformat() - }) - - def track_quality_score(self, score): - """Track quality scores""" - self.metrics["quality_scores"].append({ - "score": score, - "timestamp": datetime.now().isoformat() - }) - - def generate_performance_report(self): - """Generate comprehensive performance report""" - return { - "average_execution_time": self.calculate_average_execution_time(), - "quality_trends": self.analyze_quality_trends(), - "consensus_efficiency": self.analyze_consensus_efficiency(), - "error_analysis": self.analyze_errors(), - "recommendations": self.generate_recommendations() - } -``` \ No newline at end of file diff --git a/docs/swarms/structs/board_of_directors/index.md b/docs/swarms/structs/board_of_directors/index.md deleted file mode 100644 index 136fdea8..00000000 --- a/docs/swarms/structs/board_of_directors/index.md +++ /dev/null @@ -1,291 +0,0 @@ -# Board of Directors - Multi-Agent Architecture - -The Board of Directors is a sophisticated multi-agent architecture that implements collective decision-making through democratic processes, voting mechanisms, and role-based leadership. This architecture provides an alternative to single-director patterns by enabling collaborative intelligence through structured governance. - -## šŸ›ļø Overview - -The Board of Directors architecture follows a democratic workflow pattern: - -1. **Task Reception**: User provides a task to the swarm -2. **Board Meeting**: Board of Directors convenes to discuss and create a plan -3. **Voting & Consensus**: Board members vote and reach consensus on task distribution -4. **Order Distribution**: Board distributes orders to specialized worker agents -5. **Execution**: Individual agents execute their assigned tasks -6. **Feedback Loop**: Board evaluates results and issues new orders if needed (up to `max_loops`) -7. **Context Preservation**: All conversation history and context is maintained throughout the process - -## šŸ—ļø Architecture Components - -### Core Components - -| Component | Description | Purpose | -|-----------|-------------|---------| -| **[BoardOfDirectorsSwarm](board_of_directors_swarm.md)** | Main orchestration class | Manages the entire board workflow and agent coordination | -| **[Board Member Roles](board_of_directors_roles.md)** | Role definitions and hierarchy | Defines responsibilities and voting weights for each board member | -| **[Decision Making Process](board_of_directors_decision_making.md)** | Voting and consensus mechanisms | Implements democratic decision-making with weighted voting | -| **[Workflow Management](board_of_directors_workflow.md)** | Process orchestration | Manages the complete lifecycle from task reception to final delivery | - -### Architecture Diagram - -```mermaid -graph TD - A[User Task] --> B[Board of Directors] - B --> C[Board Meeting & Discussion] - C --> D[Voting & Consensus] - D --> E[Create Plan & Orders] - E --> F[Distribute to Agents] - F --> G[Agent 1] - F --> H[Agent 2] - F --> I[Agent N] - G --> J[Execute Task] - H --> J - I --> J - J --> K[Report Results] - K --> L[Board Evaluation] - L --> M{More Loops?} - M -->|Yes| C - M -->|No| N[Final Output] -``` - -## šŸŽÆ Key Features - -### Democratic Decision Making -- **Collective Intelligence**: Multiple perspectives through board member collaboration -- **Weighted Voting**: Different voting weights based on roles and expertise -- **Consensus Building**: Support for both majority voting and consensus approaches -- **Conflict Resolution**: Structured processes for handling disagreements - -### Role-Based Leadership -- **Hierarchical Structure**: Clear roles with defined responsibilities -- **Specialized Expertise**: Each board member brings unique domain knowledge -- **Authority Distribution**: Balanced power distribution across roles -- **Accountability**: Clear lines of responsibility and decision ownership - -### Operational Excellence -- **Iterative Refinement**: Multiple feedback loops for improved results -- **Context Preservation**: Full conversation history maintained -- **Flexible Output Formats**: Support for various output types (dict, str, list) -- **Comprehensive Logging**: Detailed logging for debugging and monitoring - -## šŸ‘„ Board Member Roles - -The Board of Directors supports various roles with different responsibilities and voting weights: - -| Role | Description | Voting Weight | Responsibilities | -|------|-------------|---------------|------------------| -| `CHAIRMAN` | Primary leader responsible for board meetings and final decisions | 1.5 | Leading meetings, facilitating consensus, making final decisions | -| `VICE_CHAIRMAN` | Secondary leader who supports the chairman | 1.2 | Supporting chairman, coordinating operations | -| `SECRETARY` | Responsible for documentation and meeting minutes | 1.0 | Documenting meetings, maintaining records | -| `TREASURER` | Manages financial aspects and resource allocation | 1.0 | Financial oversight, resource management | -| `EXECUTIVE_DIRECTOR` | Executive-level board member with operational authority | 1.5 | Strategic planning, operational oversight | -| `MEMBER` | General board member with specific expertise | 1.0 | Contributing expertise, participating in decisions | - -## šŸš€ Quick Start - -### Basic Setup - -```python -from swarms import Agent -from swarms.structs.board_of_directors_swarm import ( - BoardOfDirectorsSwarm, - BoardMember, - BoardMemberRole -) -from swarms.config.board_config import enable_board_feature - -# Enable the Board of Directors feature -enable_board_feature() - -# Create board members with specific roles -chairman = Agent( - agent_name="Chairman", - agent_description="Chairman of the Board responsible for leading meetings", - model_name="gpt-4o-mini", - system_prompt="You are the Chairman of the Board..." -) - -vice_chairman = Agent( - agent_name="Vice-Chairman", - agent_description="Vice Chairman who supports the Chairman", - model_name="gpt-4o-mini", - system_prompt="You are the Vice Chairman..." -) - -# Create BoardMember objects with roles and expertise -board_members = [ - BoardMember(chairman, BoardMemberRole.CHAIRMAN, 1.5, ["leadership", "strategy"]), - BoardMember(vice_chairman, BoardMemberRole.VICE_CHAIRMAN, 1.2, ["operations", "coordination"]), -] - -# Create worker agents -research_agent = Agent( - agent_name="Research-Specialist", - agent_description="Expert in market research and analysis", - model_name="gpt-4o", -) - -financial_agent = Agent( - agent_name="Financial-Analyst", - agent_description="Specialist in financial analysis and valuation", - model_name="gpt-4o", -) - -# Initialize the Board of Directors swarm -board_swarm = BoardOfDirectorsSwarm( - name="Executive_Board_Swarm", - description="Executive board with specialized roles for strategic decision-making", - board_members=board_members, - agents=[research_agent, financial_agent], - max_loops=2, - verbose=True, - decision_threshold=0.6, - enable_voting=True, - enable_consensus=True, -) - -# Execute a complex task with democratic decision-making -result = board_swarm.run(task="Analyze the market potential for Tesla (TSLA) stock") -print(result) -``` - -## šŸ“‹ Use Cases - -### Corporate Governance -- **Strategic Planning**: Long-term business strategy development -- **Risk Management**: Comprehensive risk assessment and mitigation -- **Resource Allocation**: Optimal distribution of company resources -- **Performance Oversight**: Monitoring and evaluating organizational performance - -### Financial Analysis -- **Portfolio Management**: Investment portfolio optimization and rebalancing -- **Market Analysis**: Comprehensive market research and trend analysis -- **Risk Assessment**: Financial risk evaluation and management -- **Compliance Monitoring**: Regulatory compliance and audit preparation - -### Research & Development -- **Technology Assessment**: Evaluation of emerging technologies -- **Product Development**: Strategic product planning and development -- **Innovation Management**: Managing innovation pipelines and initiatives -- **Quality Assurance**: Ensuring high standards across development processes - -### Project Management -- **Complex Project Planning**: Multi-faceted project strategy development -- **Resource Optimization**: Efficient allocation of project resources -- **Stakeholder Management**: Coordinating diverse stakeholder interests -- **Risk Mitigation**: Identifying and addressing project risks - -## āš™ļø Configuration - -### Decision Thresholds -- **Default Threshold**: 60% consensus required for decisions -- **Configurable**: Adjustable based on organizational needs -- **Role-Based**: Different thresholds for different types of decisions -- **Fallback Mechanisms**: Chairman can make final decisions when consensus fails - -### Voting Mechanisms -- **Weighted Voting**: Different voting weights based on roles -- **Consensus Building**: Support for both majority and consensus approaches -- **Conflict Resolution**: Structured processes for handling disagreements -- **Transparency**: Clear visibility into decision-making processes - -### Operational Settings -- **Meeting Duration**: Configurable board meeting time limits -- **Participation Requirements**: Minimum participation rates for valid decisions -- **Feedback Loops**: Multiple iterations for complex problem-solving -- **Documentation**: Comprehensive record-keeping of all decisions - -## šŸ”§ Advanced Features - -### Custom Board Templates -Pre-configured board templates for common use cases: - -```python -from swarms.config.board_config import get_default_board_template - -# Get a financial analysis board template -financial_board = get_default_board_template("financial_analysis") - -# Get a strategic planning board template -strategic_board = get_default_board_template("strategic_planning") -``` - -### Dynamic Role Assignment -Automatically assign roles based on task requirements: - -```python -# Board members are automatically assigned roles based on expertise -board_swarm = BoardOfDirectorsSwarm( - board_members=board_members, - auto_assign_roles=True, - role_mapping={ - "financial_analysis": ["Treasurer", "Financial_Member"], - "strategic_planning": ["Chairman", "Executive_Director"] - } -) -``` - -### Consensus Optimization -Advanced consensus-building mechanisms: - -```python -# Enable advanced consensus features -board_swarm = BoardOfDirectorsSwarm( - enable_consensus=True, - consensus_timeout=300, # 5 minutes - min_participation_rate=0.5, # 50% minimum participation - auto_fallback_to_chairman=True -) -``` - -## šŸ“Š Performance Monitoring - -### Decision Metrics -- **Consensus Rate**: Percentage of decisions reached by consensus -- **Voting Participation**: Board member participation rates -- **Decision Quality**: Assessment of decision outcomes -- **Execution Efficiency**: Time from decision to implementation - -### Operational Metrics -- **Meeting Duration**: Average board meeting length -- **Agent Utilization**: How effectively worker agents are utilized -- **Feedback Loop Efficiency**: Speed of iterative improvements -- **Resource Optimization**: Efficient use of computational resources - -## šŸ› ļø Troubleshooting - -### Common Issues - -1. **Consensus Failures**: Lower decision threshold or increase timeout -2. **Role Conflicts**: Ensure clear role definitions and responsibilities -3. **Agent Coordination**: Verify agent communication and task distribution -4. **Performance Issues**: Monitor resource usage and optimize configurations - -### Best Practices - -1. **Role Clarity**: Define clear responsibilities for each board member -2. **Expertise Alignment**: Match board member expertise to task requirements -3. **Consensus Building**: Allow adequate time for discussion and consensus -4. **Documentation**: Maintain comprehensive records of all decisions -5. **Continuous Improvement**: Learn from each execution cycle - -## šŸ“š Documentation Sections - -- **[BoardOfDirectorsSwarm](board_of_directors_swarm.md)**: Complete API reference and implementation details -- **[Board Member Roles](board_of_directors_roles.md)**: Detailed role definitions and responsibilities -- **[Decision Making Process](board_of_directors_decision_making.md)**: Voting mechanisms and consensus building -- **[Workflow Management](board_of_directors_workflow.md)**: Complete process orchestration guide - -## šŸŽÆ Success Criteria - -A successful Board of Directors implementation should demonstrate: - -- āœ… **Democratic Decision Making**: All board members contribute to decisions -- āœ… **Consensus Achievement**: Decisions reached through collaborative processes -- āœ… **Role Effectiveness**: Each board member fulfills their responsibilities -- āœ… **Agent Coordination**: Worker agents execute tasks efficiently -- āœ… **Quality Output**: High-quality results through collective intelligence -- āœ… **Process Transparency**: Clear visibility into decision-making processes - ---- - -The Board of Directors architecture represents a sophisticated approach to multi-agent collaboration, enabling organizations to leverage collective intelligence through structured governance and democratic decision-making processes. \ No newline at end of file From 091fc59f6943b39bd220cc75651598f76f831bf5 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sat, 26 Jul 2025 23:50:25 +0300 Subject: [PATCH 03/18] Add files via upload --- docs/swarms/structs/BoardOfDirectors.md | 903 ++++++++++++++++++++++++ 1 file changed, 903 insertions(+) create mode 100644 docs/swarms/structs/BoardOfDirectors.md diff --git a/docs/swarms/structs/BoardOfDirectors.md b/docs/swarms/structs/BoardOfDirectors.md new file mode 100644 index 00000000..1b1664a9 --- /dev/null +++ b/docs/swarms/structs/BoardOfDirectors.md @@ -0,0 +1,903 @@ +# Board of Directors - Multi-Agent Architecture + +The Board of Directors is a sophisticated multi-agent architecture that implements collective decision-making through democratic processes, voting mechanisms, and role-based leadership. This architecture provides an alternative to single-director patterns by enabling collaborative intelligence through structured governance. + +## šŸ›ļø Overview + +The Board of Directors architecture follows a democratic workflow pattern: + +1. **Task Reception**: User provides a task to the swarm +2. **Board Meeting**: Board of Directors convenes to discuss and create a plan +3. **Voting & Consensus**: Board members vote and reach consensus on task distribution +4. **Order Distribution**: Board distributes orders to specialized worker agents +5. **Execution**: Individual agents execute their assigned tasks +6. **Feedback Loop**: Board evaluates results and issues new orders if needed (up to `max_loops`) +7. **Context Preservation**: All conversation history and context is maintained throughout the process + +## šŸ—ļø Architecture Components + +### Core Components + +| Component | Description | Purpose | +|-----------|-------------|---------| +| **BoardOfDirectorsSwarm** | Main orchestration class | Manages the entire board workflow and agent coordination | +| **Board Member Roles** | Role definitions and hierarchy | Defines responsibilities and voting weights for each board member | +| **Decision Making Process** | Voting and consensus mechanisms | Implements democratic decision-making with weighted voting | +| **Workflow Management** | Process orchestration | Manages the complete lifecycle from task reception to final delivery | + +### Board Member Interaction Flow + +```mermaid +sequenceDiagram + participant User + participant Chairman + participant ViceChair + participant Secretary + participant Treasurer + participant ExecDir + participant Agents + + User->>Chairman: Submit Task + Chairman->>ViceChair: Notify Board Meeting + Chairman->>Secretary: Request Meeting Setup + Chairman->>Treasurer: Resource Assessment + Chairman->>ExecDir: Strategic Planning + + Note over Chairman,ExecDir: Board Discussion Phase + + Chairman->>ViceChair: Lead Discussion + ViceChair->>Secretary: Document Decisions + Secretary->>Treasurer: Budget Considerations + Treasurer->>ExecDir: Resource Allocation + ExecDir->>Chairman: Strategic Recommendations + + Note over Chairman,ExecDir: Voting & Consensus + + Chairman->>ViceChair: Call for Vote + ViceChair->>Secretary: Record Votes + Secretary->>Treasurer: Financial Approval + Treasurer->>ExecDir: Resource Approval + ExecDir->>Chairman: Final Decision + + Note over Chairman,Agents: Execution Phase + + Chairman->>Agents: Distribute Orders + Agents->>Chairman: Execute Tasks + Agents->>ViceChair: Progress Reports + Agents->>Secretary: Documentation + Agents->>Treasurer: Resource Usage + Agents->>ExecDir: Strategic Updates + + Note over Chairman,ExecDir: Review & Feedback + + Chairman->>User: Deliver Results +``` + +## šŸ‘„ Board Member Roles + +The Board of Directors supports various roles with different responsibilities and voting weights: + +| Role | Description | Voting Weight | Responsibilities | +|------|-------------|---------------|------------------| +| `CHAIRMAN` | Primary leader responsible for board meetings and final decisions | 1.5 | Leading meetings, facilitating consensus, making final decisions | +| `VICE_CHAIRMAN` | Secondary leader who supports the chairman | 1.2 | Supporting chairman, coordinating operations | +| `SECRETARY` | Responsible for documentation and meeting minutes | 1.0 | Documenting meetings, maintaining records | +| `TREASURER` | Manages financial aspects and resource allocation | 1.0 | Financial oversight, resource management | +| `EXECUTIVE_DIRECTOR` | Executive-level board member with operational authority | 1.5 | Strategic planning, operational oversight | +| `MEMBER` | General board member with specific expertise | 1.0 | Contributing expertise, participating in decisions | + +### Role Hierarchy and Authority + +```python +# Example: Role hierarchy implementation +class BoardRoleHierarchy: + def __init__(self): + self.roles = { + "CHAIRMAN": { + "voting_weight": 1.5, + "authority_level": "FINAL", + "supervises": ["VICE_CHAIRMAN", "EXECUTIVE_DIRECTOR", "SECRETARY", "TREASURER", "MEMBER"], + "responsibilities": ["leadership", "final_decision", "consensus_facilitation"], + "override_capability": True + }, + "VICE_CHAIRMAN": { + "voting_weight": 1.2, + "authority_level": "SENIOR", + "supervises": ["MEMBER"], + "responsibilities": ["operational_support", "coordination", "implementation"], + "backup_for": "CHAIRMAN" + }, + "EXECUTIVE_DIRECTOR": { + "voting_weight": 1.5, + "authority_level": "SENIOR", + "supervises": ["MEMBER"], + "responsibilities": ["strategic_planning", "execution_oversight", "performance_management"], + "strategic_authority": True + }, + "SECRETARY": { + "voting_weight": 1.0, + "authority_level": "STANDARD", + "supervises": [], + "responsibilities": ["documentation", "record_keeping", "communication"], + "administrative_authority": True + }, + "TREASURER": { + "voting_weight": 1.0, + "authority_level": "STANDARD", + "supervises": [], + "responsibilities": ["financial_oversight", "resource_management", "budget_control"], + "financial_authority": True + }, + "MEMBER": { + "voting_weight": 1.0, + "authority_level": "STANDARD", + "supervises": [], + "responsibilities": ["expertise_contribution", "analysis", "voting"], + "specialized_expertise": True + } + } +``` + +## šŸš€ Quick Start + +### Basic Setup + +```python +from swarms import Agent +from swarms.structs.board_of_directors_swarm import ( + BoardOfDirectorsSwarm, + BoardMember, + BoardMemberRole +) +from swarms.config.board_config import enable_board_feature + +# Enable the Board of Directors feature +enable_board_feature() + +# Create board members with specific roles +chairman = Agent( + agent_name="Chairman", + agent_description="Chairman of the Board responsible for leading meetings", + model_name="gpt-4o-mini", + system_prompt="You are the Chairman of the Board..." +) + +vice_chairman = Agent( + agent_name="Vice-Chairman", + agent_description="Vice Chairman who supports the Chairman", + model_name="gpt-4o-mini", + system_prompt="You are the Vice Chairman..." +) + +# Create BoardMember objects with roles and expertise +board_members = [ + BoardMember(chairman, BoardMemberRole.CHAIRMAN, 1.5, ["leadership", "strategy"]), + BoardMember(vice_chairman, BoardMemberRole.VICE_CHAIRMAN, 1.2, ["operations", "coordination"]), +] + +# Create worker agents +research_agent = Agent( + agent_name="Research-Specialist", + agent_description="Expert in market research and analysis", + model_name="gpt-4o", +) + +financial_agent = Agent( + agent_name="Financial-Analyst", + agent_description="Specialist in financial analysis and valuation", + model_name="gpt-4o", +) + +# Initialize the Board of Directors swarm +board_swarm = BoardOfDirectorsSwarm( + name="Executive_Board_Swarm", + description="Executive board with specialized roles for strategic decision-making", + board_members=board_members, + agents=[research_agent, financial_agent], + max_loops=2, + verbose=True, + decision_threshold=0.6, + enable_voting=True, + enable_consensus=True, +) + +# Execute a complex task with democratic decision-making +result = board_swarm.run(task="Analyze the market potential for Tesla (TSLA) stock") +print(result) +``` + +## šŸ“‹ Comprehensive Examples + +### 1. Strategic Investment Analysis + +```python +# Create specialized agents for investment analysis +market_research_agent = Agent( + agent_name="Market-Research-Specialist", + agent_description="Expert in market research, competitive analysis, and industry trends", + model_name="gpt-4o", + system_prompt="""You are a Market Research Specialist. Your responsibilities include: +1. Conducting comprehensive market research and analysis +2. Identifying market trends, opportunities, and risks +3. Analyzing competitive landscape and positioning +4. Providing market size and growth projections +5. Supporting strategic decision-making with research findings + +You should be thorough, analytical, and objective in your research.""" +) + +financial_analyst_agent = Agent( + agent_name="Financial-Analyst", + agent_description="Specialist in financial analysis, valuation, and investment assessment", + model_name="gpt-4o", + system_prompt="""You are a Financial Analyst. Your responsibilities include: +1. Conducting financial analysis and valuation +2. Assessing investment opportunities and risks +3. Analyzing financial performance and metrics +4. Providing financial insights and recommendations +5. Supporting financial decision-making + +You should be financially astute, analytical, and focused on value creation.""" +) + +technical_assessor_agent = Agent( + agent_name="Technical-Assessor", + agent_description="Expert in technical feasibility and implementation assessment", + model_name="gpt-4o", + system_prompt="""You are a Technical Assessor. Your responsibilities include: +1. Evaluating technical feasibility and requirements +2. Assessing implementation challenges and risks +3. Analyzing technology stack and architecture +4. Providing technical insights and recommendations +5. Supporting technical decision-making + +You should be technically proficient, practical, and solution-oriented.""" +) + +# Create comprehensive board members +board_members = [ + BoardMember( + chairman, + BoardMemberRole.CHAIRMAN, + 1.5, + ["leadership", "strategy", "governance", "decision_making"] + ), + BoardMember( + vice_chairman, + BoardMemberRole.VICE_CHAIRMAN, + 1.2, + ["operations", "coordination", "communication", "implementation"] + ), + BoardMember( + secretary, + BoardMemberRole.SECRETARY, + 1.0, + ["documentation", "compliance", "record_keeping", "communication"] + ), + BoardMember( + treasurer, + BoardMemberRole.TREASURER, + 1.0, + ["finance", "budgeting", "risk_management", "resource_allocation"] + ), + BoardMember( + executive_director, + BoardMemberRole.EXECUTIVE_DIRECTOR, + 1.5, + ["strategy", "operations", "innovation", "performance_management"] + ) +] + +# Initialize the investment analysis board +investment_board = BoardOfDirectorsSwarm( + name="Investment_Analysis_Board", + description="Specialized board for investment analysis and decision-making", + board_members=board_members, + agents=[market_research_agent, financial_analyst_agent, technical_assessor_agent], + max_loops=3, + verbose=True, + decision_threshold=0.75, # Higher threshold for investment decisions + enable_voting=True, + enable_consensus=True, + max_workers=3, + output_type="dict" +) + +# Execute investment analysis +investment_task = """ +Analyze the strategic investment opportunity for a $50M Series B funding round in a +fintech startup. Consider market conditions, competitive landscape, financial projections, +technical feasibility, and strategic fit. Provide comprehensive recommendations including: +1. Investment recommendation (proceed/hold/decline) +2. Valuation analysis and suggested terms +3. Risk assessment and mitigation strategies +4. Strategic value and synergies +5. Implementation timeline and milestones +""" + +result = investment_board.run(task=investment_task) +print("Investment Analysis Results:") +print(json.dumps(result, indent=2)) +``` + +### 2. Technology Strategy Development + +```python +# Create technology-focused agents +tech_strategy_agent = Agent( + agent_name="Tech-Strategy-Specialist", + agent_description="Expert in technology strategy and digital transformation", + model_name="gpt-4o", + system_prompt="""You are a Technology Strategy Specialist. Your responsibilities include: +1. Developing technology roadmaps and strategies +2. Assessing digital transformation opportunities +3. Evaluating emerging technologies and trends +4. Planning technology investments and priorities +5. Supporting technology decision-making + +You should be strategic, forward-thinking, and technology-savvy.""" +) + +implementation_planner_agent = Agent( + agent_name="Implementation-Planner", + agent_description="Expert in implementation planning and project management", + model_name="gpt-4o", + system_prompt="""You are an Implementation Planner. Your responsibilities include: +1. Creating detailed implementation plans +2. Assessing resource requirements and timelines +3. Identifying implementation risks and challenges +4. Planning change management strategies +5. Supporting implementation decision-making + +You should be practical, organized, and execution-focused.""" +) + +# Technology strategy board configuration +tech_board = BoardOfDirectorsSwarm( + name="Technology_Strategy_Board", + description="Specialized board for technology strategy and digital transformation", + board_members=board_members, + agents=[tech_strategy_agent, implementation_planner_agent, technical_assessor_agent], + max_loops=4, # More loops for complex technology planning + verbose=True, + decision_threshold=0.7, + enable_voting=True, + enable_consensus=True, + max_workers=3, + output_type="dict" +) + +# Execute technology strategy development +tech_strategy_task = """ +Develop a comprehensive technology strategy for a mid-size manufacturing company +looking to digitize operations and implement Industry 4.0 technologies. Consider: +1. Current technology assessment and gaps +2. Technology roadmap and implementation plan +3. Investment requirements and ROI analysis +4. Risk assessment and mitigation strategies +5. Change management and training requirements +6. Competitive positioning and market advantages +""" + +result = tech_board.run(task=tech_strategy_task) +print("Technology Strategy Results:") +print(json.dumps(result, indent=2)) +``` + +### 3. Crisis Management and Response + +```python +# Create crisis management agents +crisis_coordinator_agent = Agent( + agent_name="Crisis-Coordinator", + agent_description="Expert in crisis management and emergency response", + model_name="gpt-4o", + system_prompt="""You are a Crisis Coordinator. Your responsibilities include: +1. Coordinating crisis response efforts +2. Assessing crisis severity and impact +3. Developing immediate response plans +4. Managing stakeholder communications +5. Supporting crisis decision-making + +You should be calm, decisive, and action-oriented.""" +) + +communications_specialist_agent = Agent( + agent_name="Communications-Specialist", + agent_description="Expert in crisis communications and stakeholder management", + model_name="gpt-4o", + system_prompt="""You are a Communications Specialist. Your responsibilities include: +1. Developing crisis communication strategies +2. Managing stakeholder communications +3. Coordinating public relations efforts +4. Ensuring message consistency and accuracy +5. Supporting communication decision-making + +You should be clear, empathetic, and strategic in communications.""" +) + +# Crisis management board configuration +crisis_board = BoardOfDirectorsSwarm( + name="Crisis_Management_Board", + description="Specialized board for crisis management and emergency response", + board_members=board_members, + agents=[crisis_coordinator_agent, communications_specialist_agent, financial_analyst_agent], + max_loops=2, # Faster response needed + verbose=True, + decision_threshold=0.6, # Lower threshold for urgent decisions + enable_voting=True, + enable_consensus=True, + max_workers=3, + output_type="dict" +) + +# Execute crisis management +crisis_task = """ +Our company is facing a major data breach. Develop an immediate response plan. +Include: +1. Immediate containment and mitigation steps +2. Communication strategy for stakeholders +3. Legal and regulatory compliance requirements +4. Financial impact assessment +5. Long-term recovery and prevention measures +6. Timeline and resource allocation +""" + +result = crisis_board.run(task=crisis_task) +print("Crisis Management Results:") +print(json.dumps(result, indent=2)) +``` + +## āš™ļø Configuration and Parameters + +### BoardOfDirectorsSwarm Parameters + +```python +# Complete parameter reference +board_swarm = BoardOfDirectorsSwarm( + # Basic Configuration + name="Board_Name", # Name of the board + description="Board description", # Description of the board's purpose + + # Board Members and Agents + board_members=board_members, # List of BoardMember objects + agents=worker_agents, # List of worker Agent objects + + # Execution Control + max_loops=3, # Maximum number of refinement loops + max_workers=4, # Maximum parallel workers + + # Decision Making + decision_threshold=0.7, # Consensus threshold (0.0-1.0) + enable_voting=True, # Enable voting mechanisms + enable_consensus=True, # Enable consensus building + + # Advanced Features + auto_assign_roles=True, # Auto-assign roles based on expertise + role_mapping={ # Custom role mapping + "financial_analysis": ["Treasurer", "Financial_Member"], + "strategic_planning": ["Chairman", "Executive_Director"] + }, + + # Consensus Configuration + consensus_timeout=300, # Consensus timeout in seconds + min_participation_rate=0.8, # Minimum participation rate + auto_fallback_to_chairman=True, # Chairman can make final decisions + consensus_rounds=3, # Maximum consensus building rounds + + # Output Configuration + output_type="dict", # Output format: "dict", "str", "list" + verbose=True, # Enable detailed logging + + # Quality Control + quality_threshold=0.8, # Quality threshold for outputs + enable_quality_gates=True, # Enable quality checkpoints + enable_peer_review=True, # Enable peer review mechanisms + + # Performance Optimization + parallel_execution=True, # Enable parallel execution + enable_agent_pooling=True, # Enable agent pooling + timeout_per_agent=300, # Timeout per agent in seconds + + # Monitoring and Logging + enable_logging=True, # Enable detailed logging + log_level="INFO", # Logging level + enable_metrics=True, # Enable performance metrics + enable_tracing=True # Enable request tracing +) +``` + +### Voting Configuration + +```python +# Voting system configuration +voting_config = { + "method": "weighted_majority", # Voting method + "threshold": 0.75, # Consensus threshold + "weights": { # Role-based voting weights + "CHAIRMAN": 1.5, + "VICE_CHAIRMAN": 1.2, + "SECRETARY": 1.0, + "TREASURER": 1.0, + "EXECUTIVE_DIRECTOR": 1.5 + }, + "tie_breaker": "CHAIRMAN", # Tie breaker role + "allow_abstention": True, # Allow board members to abstain + "secret_ballot": False, # Use secret ballot voting + "transparent_process": True # Transparent voting process +} +``` + +### Quality Control Configuration + +```python +# Quality control configuration +quality_config = { + "quality_gates": True, # Enable quality checkpoints + "quality_threshold": 0.8, # Quality threshold + "enable_peer_review": True, # Enable peer review + "review_required": True, # Require peer review + "output_validation": True, # Validate outputs + "enable_metrics_tracking": True, # Track quality metrics + + # Quality metrics + "quality_metrics": { + "completeness": {"weight": 0.2, "threshold": 0.8}, + "accuracy": {"weight": 0.25, "threshold": 0.85}, + "feasibility": {"weight": 0.2, "threshold": 0.8}, + "risk": {"weight": 0.15, "threshold": 0.7}, + "impact": {"weight": 0.2, "threshold": 0.8} + } +} +``` + +## šŸ“Š Performance Monitoring and Analytics + +### Board Performance Metrics + +```python +# Get comprehensive board performance metrics +board_summary = board_swarm.get_board_summary() +print("Board Summary:") +print(f"Board Name: {board_summary['board_name']}") +print(f"Total Board Members: {board_summary['total_members']}") +print(f"Total Worker Agents: {board_summary['total_agents']}") +print(f"Decision Threshold: {board_summary['decision_threshold']}") +print(f"Max Loops: {board_summary['max_loops']}") + +# Display board member details +print("\nBoard Members:") +for member in board_summary['members']: + print(f"- {member['name']} (Role: {member['role']}, Weight: {member['voting_weight']})") + print(f" Expertise: {', '.join(member['expertise_areas'])}") + +# Display worker agent details +print("\nWorker Agents:") +for agent in board_summary['agents']: + print(f"- {agent['name']}: {agent['description']}") +``` + +### Decision Analysis + +```python +# Analyze decision-making patterns +if hasattr(result, 'get') and callable(result.get): + conversation_history = result.get('conversation_history', []) + + print(f"\nDecision Analysis:") + print(f"Total Messages: {len(conversation_history)}") + + # Count board member contributions + board_contributions = {} + for msg in conversation_history: + if 'Board' in msg.get('role', ''): + member_name = msg.get('agent_name', 'Unknown') + board_contributions[member_name] = board_contributions.get(member_name, 0) + 1 + + print(f"Board Member Contributions:") + for member, count in board_contributions.items(): + print(f"- {member}: {count} contributions") + + # Count agent executions + agent_executions = {} + for msg in conversation_history: + if any(agent.agent_name in msg.get('role', '') for agent in worker_agents): + agent_name = msg.get('agent_name', 'Unknown') + agent_executions[agent_name] = agent_executions.get(agent_name, 0) + 1 + + print(f"\nAgent Executions:") + for agent, count in agent_executions.items(): + print(f"- {agent}: {count} executions") +``` + +### Performance Monitoring System + +```python +# Performance monitoring system +class PerformanceMonitor: + def __init__(self): + self.metrics = { + "execution_times": [], + "quality_scores": [], + "consensus_rounds": [], + "error_rates": [] + } + + def track_execution_time(self, phase, duration): + """Track execution time for different phases""" + self.metrics["execution_times"].append({ + "phase": phase, + "duration": duration, + "timestamp": datetime.now().isoformat() + }) + + def track_quality_score(self, score): + """Track quality scores""" + self.metrics["quality_scores"].append({ + "score": score, + "timestamp": datetime.now().isoformat() + }) + + def generate_performance_report(self): + """Generate comprehensive performance report""" + return { + "average_execution_time": self.calculate_average_execution_time(), + "quality_trends": self.analyze_quality_trends(), + "consensus_efficiency": self.analyze_consensus_efficiency(), + "error_analysis": self.analyze_errors(), + "recommendations": self.generate_recommendations() + } + +# Usage example +monitor = PerformanceMonitor() +# ... track metrics during execution ... +report = monitor.generate_performance_report() +print("Performance Report:") +print(json.dumps(report, indent=2)) +``` + +## šŸ”§ Advanced Features and Customization + +### Custom Board Templates + +```python +from swarms.config.board_config import get_default_board_template + +# Get pre-configured board templates +financial_board = get_default_board_template("financial_analysis") +strategic_board = get_default_board_template("strategic_planning") +tech_board = get_default_board_template("technology_assessment") +crisis_board = get_default_board_template("crisis_management") + +# Custom board template +custom_template = { + "name": "Custom_Board", + "description": "Custom board for specific use case", + "board_members": [ + {"role": "CHAIRMAN", "expertise": ["leadership", "strategy"]}, + {"role": "VICE_CHAIRMAN", "expertise": ["operations", "coordination"]}, + {"role": "SECRETARY", "expertise": ["documentation", "communication"]}, + {"role": "TREASURER", "expertise": ["finance", "budgeting"]}, + {"role": "EXECUTIVE_DIRECTOR", "expertise": ["strategy", "operations"]} + ], + "agents": [ + {"name": "Research_Agent", "expertise": ["research", "analysis"]}, + {"name": "Technical_Agent", "expertise": ["technical", "implementation"]} + ], + "config": { + "max_loops": 3, + "decision_threshold": 0.7, + "enable_voting": True, + "enable_consensus": True + } +} +``` + +### Dynamic Role Assignment + +```python +# Automatically assign roles based on task requirements +board_swarm = BoardOfDirectorsSwarm( + board_members=board_members, + agents=agents, + auto_assign_roles=True, + role_mapping={ + "financial_analysis": ["Treasurer", "Financial_Member"], + "strategic_planning": ["Chairman", "Executive_Director"], + "technical_assessment": ["Technical_Member", "Executive_Director"], + "research_analysis": ["Research_Member", "Secretary"], + "crisis_management": ["Chairman", "Vice_Chairman", "Communications_Member"] + } +) +``` + +### Consensus Optimization + +```python +# Advanced consensus-building mechanisms +board_swarm = BoardOfDirectorsSwarm( + board_members=board_members, + agents=agents, + enable_consensus=True, + consensus_timeout=300, # 5 minutes timeout + min_participation_rate=0.8, # 80% minimum participation + auto_fallback_to_chairman=True, # Chairman can make final decisions + consensus_rounds=3, # Maximum consensus building rounds + consensus_method="weighted_majority", # Consensus method + enable_mediation=True, # Enable mediation for conflicts + mediation_timeout=120 # Mediation timeout in seconds +) +``` + +## šŸ› ļø Troubleshooting and Debugging + +### Common Issues and Solutions + +1. **Consensus Failures** + - **Issue**: Board cannot reach consensus within loop limit + - **Solution**: Lower voting threshold, increase max_loops, or adjust voting weights + ```python + board_swarm = BoardOfDirectorsSwarm( + decision_threshold=0.6, # Lower threshold + max_loops=5, # More loops + consensus_timeout=600 # Longer timeout + ) + ``` + +2. **Agent Timeout** + - **Issue**: Individual agents take too long to respond + - **Solution**: Increase timeout settings or optimize agent prompts + ```python + board_swarm = BoardOfDirectorsSwarm( + timeout_per_agent=600, # 10 minutes per agent + enable_agent_pooling=True # Use agent pooling + ) + ``` + +3. **Poor Quality Output** + - **Issue**: Final output doesn't meet quality standards + - **Solution**: Enable quality gates, increase max_loops, or improve agent prompts + ```python + board_swarm = BoardOfDirectorsSwarm( + enable_quality_gates=True, + quality_threshold=0.8, + enable_peer_review=True, + max_loops=4 + ) + ``` + +4. **Resource Exhaustion** + - **Issue**: System runs out of resources during execution + - **Solution**: Implement resource limits, use agent pooling, or optimize parallel execution + ```python + board_swarm = BoardOfDirectorsSwarm( + max_workers=2, # Limit parallel workers + enable_agent_pooling=True, + parallel_execution=False # Disable parallel execution + ) + ``` + +### Debugging Techniques + +```python +# Debugging configuration +debug_config = BoardConfig( + max_loops=1, # Limit loops for debugging + enable_logging=True, + log_level="DEBUG", + enable_tracing=True, + debug_mode=True +) + +# Create debug swarm +debug_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=debug_config +) + +# Execute with debugging +try: + result = debug_swarm.run(task) +except Exception as e: + print(f"Error: {e}") + print(f"Debug info: {debug_swarm.get_debug_info()}") + +# Enable detailed logging +import logging +logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) + +# Create swarm with logging enabled +logging_swarm = BoardOfDirectorsSwarm( + agents=agents, + config=BoardConfig( + enable_logging=True, + log_level="DEBUG", + enable_metrics=True, + enable_tracing=True + ) +) +``` + +## šŸ“‹ Use Cases + +### Corporate Governance +- **Strategic Planning**: Long-term business strategy development +- **Risk Management**: Comprehensive risk assessment and mitigation +- **Resource Allocation**: Optimal distribution of company resources +- **Performance Oversight**: Monitoring and evaluating organizational performance + +### Financial Analysis +- **Portfolio Management**: Investment portfolio optimization and rebalancing +- **Market Analysis**: Comprehensive market research and trend analysis +- **Risk Assessment**: Financial risk evaluation and management +- **Compliance Monitoring**: Regulatory compliance and audit preparation + +### Research & Development +- **Technology Assessment**: Evaluation of emerging technologies +- **Product Development**: Strategic product planning and development +- **Innovation Management**: Managing innovation pipelines and initiatives +- **Quality Assurance**: Ensuring high standards across development processes + +### Project Management +- **Complex Project Planning**: Multi-faceted project strategy development +- **Resource Optimization**: Efficient allocation of project resources +- **Stakeholder Management**: Coordinating diverse stakeholder interests +- **Risk Mitigation**: Identifying and addressing project risks + +### Crisis Management +- **Emergency Response**: Rapid response to critical situations +- **Stakeholder Communication**: Managing communications during crises +- **Recovery Planning**: Developing recovery and prevention strategies +- **Legal Compliance**: Ensuring compliance during crisis situations + +## šŸŽÆ Success Criteria + +A successful Board of Directors implementation should demonstrate: + +- āœ… **Democratic Decision Making**: All board members contribute to decisions +- āœ… **Consensus Achievement**: Decisions reached through collaborative processes +- āœ… **Role Effectiveness**: Each board member fulfills their responsibilities +- āœ… **Agent Coordination**: Worker agents execute tasks efficiently +- āœ… **Quality Output**: High-quality results through collective intelligence +- āœ… **Process Transparency**: Clear visibility into decision-making processes +- āœ… **Performance Optimization**: Efficient resource utilization and execution +- āœ… **Continuous Improvement**: Learning from each execution cycle + +## šŸ“š Best Practices + +### 1. Role Definition +- Clearly define responsibilities for each board member +- Ensure expertise areas align with organizational needs +- Balance voting weights based on role importance +- Document role interactions and communication protocols + +### 2. Task Formulation +- Provide clear, specific task descriptions +- Include relevant context and constraints +- Specify expected outputs and deliverables +- Define quality criteria and success metrics + +### 3. Consensus Building +- Allow adequate time for discussion and consensus +- Encourage diverse perspectives and viewpoints +- Use structured decision-making processes +- Implement conflict resolution mechanisms + +### 4. Performance Monitoring +- Track decision quality and outcomes +- Monitor board member participation +- Analyze agent utilization and effectiveness +- Implement continuous improvement processes + +### 5. Resource Management +- Optimize agent allocation and utilization +- Implement parallel execution where appropriate +- Monitor resource usage and performance +- Scale resources based on task complexity + +--- + +The Board of Directors architecture represents a sophisticated approach to multi-agent collaboration, enabling organizations to leverage collective intelligence through structured governance and democratic decision-making processes. This comprehensive implementation provides the tools and frameworks needed to build effective, scalable, and intelligent decision-making systems. \ No newline at end of file From 7f4f5481df70fd717660c2b951b5d6e62b77a74d Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sat, 26 Jul 2025 23:52:30 +0300 Subject: [PATCH 05/18] Update mkdocs.yml --- docs/mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e48e92a7..0b5c13a4 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -277,7 +277,7 @@ nav: - Overview: "swarms/structs/overview.md" - Custom Multi Agent Architectures: "swarms/structs/custom_swarm.md" - + - Board of Directors: "swarms/structs/BoardOfDirectors.md" - MajorityVoting: "swarms/structs/majorityvoting.md" - RoundRobin: "swarms/structs/round_robin_swarm.md" - Mixture of Agents: "swarms/structs/moa.md" From 485c42c7aecc1cd9e8f65de86a3c31a6993c2403 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sun, 27 Jul 2025 12:04:30 +0300 Subject: [PATCH 06/18] Add files via upload --- swarms/structs/board_of_directors_swarm.py | 1144 ++++++++++++++++++++ 1 file changed, 1144 insertions(+) create mode 100644 swarms/structs/board_of_directors_swarm.py diff --git a/swarms/structs/board_of_directors_swarm.py b/swarms/structs/board_of_directors_swarm.py new file mode 100644 index 00000000..a6d24794 --- /dev/null +++ b/swarms/structs/board_of_directors_swarm.py @@ -0,0 +1,1144 @@ +""" +Board of Directors Swarm Implementation + +This module implements a Board of Directors feature as an alternative to the Director feature +in the Swarms Framework. The Board of Directors operates as a collective decision-making body +that can be enabled manually through configuration. + +The implementation follows the Swarms philosophy of: +- Readable code with comprehensive type annotations and documentation +- Performance optimization through concurrency and parallelism +- Simplified abstractions for multi-agent collaboration + +Flow: +1. User provides a task +2. Board of Directors convenes to discuss and create a plan +3. Board distributes orders to agents through voting and consensus +4. Agents execute tasks and report back to the board +5. Board evaluates results and issues new orders if needed (up to max_loops) +6. All context and conversation history is preserved throughout the process +""" + +import asyncio +import json +import os +import re +import traceback +from concurrent.futures import ThreadPoolExecutor, as_completed +from dataclasses import dataclass, field +from enum import Enum +from typing import Any, Callable, Dict, List, Optional, Union, Tuple + +from loguru import logger +from pydantic import BaseModel, Field + +from swarms.structs.agent import Agent +from swarms.structs.base_swarm import BaseSwarm +from swarms.structs.conversation import Conversation +from swarms.structs.ma_utils import list_all_agents +from swarms.utils.history_output_formatter import history_output_formatter +from swarms.utils.loguru_logger import initialize_logger +from swarms.utils.output_types import OutputType + +# Initialize logger for Board of Directors swarm +board_logger = initialize_logger(log_folder="board_of_directors_swarm") + + +class BoardMemberRole(str, Enum): + """Enumeration of possible board member roles. + + This enum defines the various roles that board members can have within + the Board of Directors swarm. Each role has specific responsibilities + and voting weights associated with it. + + Attributes: + CHAIRMAN: Primary leader responsible for board meetings and final decisions + VICE_CHAIRMAN: Secondary leader who supports the chairman + SECRETARY: Responsible for documentation and meeting minutes + TREASURER: Manages financial aspects and resource allocation + MEMBER: General board member with specific expertise + EXECUTIVE_DIRECTOR: Executive-level board member with operational authority + """ + + CHAIRMAN = "chairman" + VICE_CHAIRMAN = "vice_chairman" + SECRETARY = "secretary" + TREASURER = "treasurer" + MEMBER = "member" + EXECUTIVE_DIRECTOR = "executive_director" + + +class BoardDecisionType(str, Enum): + """Enumeration of board decision types. + + This enum defines the different types of decisions that can be made + by the Board of Directors, including voting mechanisms and consensus + approaches. + + Attributes: + UNANIMOUS: All board members agree on the decision + MAJORITY: More than 50% of votes are in favor + CONSENSUS: General agreement without formal voting + CHAIRMAN_DECISION: Final decision made by the chairman + """ + + UNANIMOUS = "unanimous" + MAJORITY = "majority" + CONSENSUS = "consensus" + CHAIRMAN_DECISION = "chairman_decision" + + +@dataclass +class BoardMember: + """ + Represents a member of the Board of Directors. + + This dataclass encapsulates all information about a board member, + including their agent representation, role, voting weight, and + areas of expertise. + + Attributes: + agent: The agent representing this board member + role: The role of this board member within the board + voting_weight: The weight of this member's vote (default: 1.0) + expertise_areas: Areas of expertise for this board member + """ + + agent: Agent + role: BoardMemberRole + voting_weight: float = 1.0 + expertise_areas: List[str] = field(default_factory=list) + + def __post_init__(self) -> None: + """Initialize default values after object creation. + + This method ensures that the expertise_areas list is properly + initialized as an empty list if not provided. + """ + if self.expertise_areas is None: + self.expertise_areas = [] + + +class BoardOrder(BaseModel): + """ + Represents an order issued by the Board of Directors. + + This model defines the structure of orders that the board issues + to worker agents, including task assignments, priorities, and + deadlines. + + Attributes: + agent_name: The name of the agent to which the task is assigned + task: The specific task to be executed by the assigned agent + priority: Priority level of the task (1-5, where 1 is highest) + deadline: Optional deadline for task completion + assigned_by: The board member who assigned this task + """ + + agent_name: str = Field( + ..., + description="Specifies the name of the agent to which the task is assigned.", + ) + task: str = Field( + ..., + description="Defines the specific task to be executed by the assigned agent.", + ) + priority: int = Field( + default=3, + ge=1, + le=5, + description="Priority level of the task (1-5, where 1 is highest priority).", + ) + deadline: Optional[str] = Field( + default=None, + description="Optional deadline for task completion.", + ) + assigned_by: str = Field( + default="Board of Directors", + description="The board member who assigned this task.", + ) + + +class BoardDecision(BaseModel): + """ + Represents a decision made by the Board of Directors. + + This model tracks the details of decisions made by the board, + including voting results, decision types, and reasoning. + + Attributes: + decision_type: The type of decision (unanimous, majority, etc.) + decision: The actual decision made + votes_for: Number of votes in favor + votes_against: Number of votes against + abstentions: Number of abstentions + reasoning: The reasoning behind the decision + """ + + decision_type: BoardDecisionType = Field( + ..., + description="The type of decision made by the board.", + ) + decision: str = Field( + ..., + description="The actual decision made by the board.", + ) + votes_for: int = Field( + default=0, + ge=0, + description="Number of votes in favor of the decision.", + ) + votes_against: int = Field( + default=0, + ge=0, + description="Number of votes against the decision.", + ) + abstentions: int = Field( + default=0, + ge=0, + description="Number of abstentions.", + ) + reasoning: str = Field( + default="", + description="The reasoning behind the decision.", + ) + + +class BoardSpec(BaseModel): + """ + Specification for Board of Directors operations. + + This model represents the complete output of a board meeting, + including the plan, orders, decisions, and meeting summary. + + Attributes: + plan: The overall plan created by the board + orders: List of orders issued by the board + decisions: List of decisions made by the board + meeting_summary: Summary of the board meeting + """ + + plan: str = Field( + ..., + description="Outlines the sequence of actions to be taken by the swarm as decided by the board.", + ) + orders: List[BoardOrder] = Field( + ..., + description="A collection of task assignments to specific agents within the swarm.", + ) + decisions: List[BoardDecision] = Field( + default_factory=list, + description="List of decisions made by the board during the meeting.", + ) + meeting_summary: str = Field( + default="", + description="Summary of the board meeting and key outcomes.", + ) + + +class BoardOfDirectorsSwarm(BaseSwarm): + """ + A hierarchical swarm of agents with a Board of Directors that orchestrates tasks. + + The Board of Directors operates as a collective decision-making body that can be + enabled manually through configuration. It provides an alternative to the single + Director approach with more democratic and collaborative decision-making. + + The workflow follows a hierarchical pattern: + 1. Task is received and sent to the Board of Directors + 2. Board convenes to discuss and create a plan through voting and consensus + 3. Board distributes orders to agents based on collective decisions + 4. Agents execute tasks and report back to the board + 5. Board evaluates results and issues new orders if needed (up to max_loops) + 6. All context and conversation history is preserved throughout the process + + Attributes: + name: The name of the swarm + description: A description of the swarm + board_members: List of board members with their roles and expertise + agents: A list of agents within the swarm + max_loops: The maximum number of feedback loops between the board and agents + output_type: The format in which to return the output (dict, str, or list) + board_model_name: The model name for board member agents + verbose: Enable detailed logging with loguru + add_collaboration_prompt: Add collaboration prompts to agents + board_feedback_on: Enable board feedback on agent outputs + decision_threshold: Threshold for majority decisions (0.0-1.0) + enable_voting: Enable voting mechanisms for board decisions + enable_consensus: Enable consensus-building mechanisms + max_workers: Maximum number of workers for parallel execution + """ + + def __init__( + self, + name: str = "BoardOfDirectorsSwarm", + description: str = "Distributed task swarm with collective decision-making", + board_members: Optional[List[BoardMember]] = None, + agents: Optional[List[Union[Agent, Callable, Any]]] = None, + max_loops: int = 1, + output_type: OutputType = "dict-all-except-first", + board_model_name: str = "gpt-4o-mini", + verbose: bool = False, + add_collaboration_prompt: bool = True, + board_feedback_on: bool = True, + decision_threshold: float = 0.6, + enable_voting: bool = True, + enable_consensus: bool = True, + max_workers: Optional[int] = None, + *args: Any, + **kwargs: Any, + ) -> None: + """ + Initialize the Board of Directors Swarm with the given parameters. + + Args: + name: The name of the swarm + description: A description of the swarm + board_members: List of board members with their roles and expertise + agents: A list of agents within the swarm + max_loops: The maximum number of feedback loops between the board and agents + output_type: The format in which to return the output (dict, str, or list) + board_model_name: The model name for board member agents + verbose: Enable detailed logging with loguru + add_collaboration_prompt: Add collaboration prompts to agents + board_feedback_on: Enable board feedback on agent outputs + decision_threshold: Threshold for majority decisions (0.0-1.0) + enable_voting: Enable voting mechanisms for board decisions + enable_consensus: Enable consensus-building mechanisms + max_workers: Maximum number of workers for parallel execution + *args: Additional positional arguments passed to BaseSwarm + **kwargs: Additional keyword arguments passed to BaseSwarm + + Raises: + ValueError: If critical requirements are not met during initialization + """ + super().__init__( + name=name, + description=description, + agents=agents, + ) + + self.name = name + self.board_members = board_members or [] + self.agents = agents or [] + self.max_loops = max_loops + self.output_type = output_type + self.board_model_name = board_model_name + self.verbose = verbose + self.add_collaboration_prompt = add_collaboration_prompt + self.board_feedback_on = board_feedback_on + self.decision_threshold = decision_threshold + self.enable_voting = enable_voting + self.enable_consensus = enable_consensus + self.max_workers = max_workers or min(32, (os.cpu_count() or 1) + 4) + + # Initialize the swarm + self._init_board_swarm() + + def _init_board_swarm(self) -> None: + """ + Initialize the Board of Directors swarm. + + This method sets up the board members, initializes the conversation, + performs reliability checks, and prepares the board for operation. + + Raises: + ValueError: If reliability checks fail + """ + if self.verbose: + board_logger.info(f"šŸš€ Initializing Board of Directors Swarm: {self.name}") + board_logger.info(f"šŸ“Š Configuration - Max loops: {self.max_loops}") + + self.conversation = Conversation(time_enabled=False) + + # Perform reliability checks + self._perform_reliability_checks() + + # Setup board members if not provided + if not self.board_members: + self._setup_default_board() + + # Add context to board members + self._add_context_to_board() + + if self.verbose: + board_logger.success(f"āœ… Board of Directors Swarm initialized successfully: {self.name}") + + def _setup_default_board(self) -> None: + """ + Set up a default Board of Directors if none is provided. + + Creates a basic board structure with Chairman, Vice Chairman, and Secretary roles. + This method is called automatically if no board members are provided during initialization. + """ + if self.verbose: + board_logger.info("šŸŽÆ Setting up default Board of Directors") + + # Create default board members + chairman = Agent( + agent_name="Chairman", + agent_description="Chairman of the Board responsible for leading meetings and making final decisions", + model_name=self.board_model_name, + max_loops=1, + system_prompt=self._get_chairman_prompt(), + ) + + vice_chairman = Agent( + agent_name="Vice-Chairman", + agent_description="Vice Chairman who supports the Chairman and leads in their absence", + model_name=self.board_model_name, + max_loops=1, + system_prompt=self._get_vice_chairman_prompt(), + ) + + secretary = Agent( + agent_name="Secretary", + agent_description="Board Secretary responsible for documentation and meeting minutes", + model_name=self.board_model_name, + max_loops=1, + system_prompt=self._get_secretary_prompt(), + ) + + self.board_members = [ + BoardMember(chairman, BoardMemberRole.CHAIRMAN, 1.5, ["leadership", "strategy"]), + BoardMember(vice_chairman, BoardMemberRole.VICE_CHAIRMAN, 1.2, ["operations", "coordination"]), + BoardMember(secretary, BoardMemberRole.SECRETARY, 1.0, ["documentation", "communication"]), + ] + + if self.verbose: + board_logger.success("āœ… Default Board of Directors setup completed") + + def _get_chairman_prompt(self) -> str: + """ + Get the system prompt for the Chairman role. + + Returns: + str: The system prompt defining the Chairman's responsibilities and behavior + """ + return """You are the Chairman of the Board of Directors. Your responsibilities include: +1. Leading board meetings and discussions +2. Facilitating consensus among board members +3. Making final decisions when consensus cannot be reached +4. Ensuring all board members have an opportunity to contribute +5. Maintaining focus on the organization's goals and objectives +6. Providing strategic direction and oversight + +You should be diplomatic, fair, and decisive in your leadership.""" + + def _get_vice_chairman_prompt(self) -> str: + """ + Get the system prompt for the Vice Chairman role. + + Returns: + str: The system prompt defining the Vice Chairman's responsibilities and behavior + """ + return """You are the Vice Chairman of the Board of Directors. Your responsibilities include: +1. Supporting the Chairman in leading board meetings +2. Taking leadership when the Chairman is unavailable +3. Coordinating with other board members +4. Ensuring operational efficiency +5. Providing strategic input and analysis +6. Maintaining board cohesion and effectiveness + +You should be collaborative, analytical, and supportive in your role.""" + + def _get_secretary_prompt(self) -> str: + """ + Get the system prompt for the Secretary role. + + Returns: + str: The system prompt defining the Secretary's responsibilities and behavior + """ + return """You are the Secretary of the Board of Directors. Your responsibilities include: +1. Documenting all board meetings and decisions +2. Maintaining accurate records of board proceedings +3. Ensuring proper communication between board members +4. Tracking action items and follow-ups +5. Providing administrative support to the board +6. Ensuring compliance with governance requirements + +You should be thorough, organized, and detail-oriented in your documentation.""" + + def _add_context_to_board(self) -> None: + """ + Add agent context to all board members' conversations. + + This ensures that board members are aware of all available agents + and their capabilities when making decisions. + + Raises: + Exception: If context addition fails + """ + try: + if self.verbose: + board_logger.info("šŸ“ Adding agent context to board members") + + # Add context to each board member + for board_member in self.board_members: + list_all_agents( + agents=self.agents, + conversation=self.conversation, + add_to_conversation=True, + add_collaboration_prompt=self.add_collaboration_prompt, + ) + + if self.verbose: + board_logger.success("āœ… Agent context added to board members successfully") + + except Exception as e: + error_msg = f"āŒ Failed to add context to board members: {str(e)}" + board_logger.error(f"{error_msg}\nšŸ” Traceback: {traceback.format_exc()}") + raise + + def _perform_reliability_checks(self) -> None: + """ + Perform reliability checks for the Board of Directors swarm. + + This method validates critical requirements and configuration + parameters to ensure the swarm can operate correctly. + + Raises: + ValueError: If critical requirements are not met + """ + try: + if self.verbose: + board_logger.info(f"šŸ” Running reliability checks for swarm: {self.name}") + + if not self.agents or len(self.agents) == 0: + raise ValueError( + "No agents found in the swarm. At least one agent must be provided to create a Board of Directors swarm." + ) + + if self.max_loops <= 0: + raise ValueError( + "Max loops must be greater than 0. Please set a valid number of loops." + ) + + if self.decision_threshold < 0.0 or self.decision_threshold > 1.0: + raise ValueError( + "Decision threshold must be between 0.0 and 1.0." + ) + + if self.verbose: + board_logger.success(f"āœ… Reliability checks passed for swarm: {self.name}") + board_logger.info(f"šŸ“Š Swarm stats - Agents: {len(self.agents)}, Max loops: {self.max_loops}") + + except Exception as e: + error_msg = f"āŒ Failed reliability checks: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + def run_board_meeting( + self, + task: str, + img: Optional[str] = None, + ) -> BoardSpec: + """ + Run a board meeting to discuss and decide on the given task. + + This method orchestrates a complete board meeting, including discussion, + decision-making, and task distribution to worker agents. + + Args: + task: The task to be discussed and planned by the board + img: Optional image to be used with the task + + Returns: + BoardSpec: The board's plan and orders + + Raises: + Exception: If board meeting execution fails + """ + try: + if self.verbose: + board_logger.info(f"šŸ›ļø Running board meeting with task: {task[:100]}...") + + # Create board meeting prompt + meeting_prompt = self._create_board_meeting_prompt(task) + + # Run board discussion + board_discussion = self._conduct_board_discussion(meeting_prompt, img) + + # Parse board decisions + board_spec = self._parse_board_decisions(board_discussion) + + # Add to conversation history + self.conversation.add(role="Board of Directors", content=board_discussion) + + if self.verbose: + board_logger.success("āœ… Board meeting completed") + board_logger.debug(f"šŸ“‹ Board output type: {type(board_spec)}") + + return board_spec + + except Exception as e: + error_msg = f"āŒ Failed to run board meeting: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + def _create_board_meeting_prompt(self, task: str) -> str: + """ + Create a prompt for the board meeting. + + This method generates a comprehensive prompt that guides the board + through the meeting process, including task discussion, decision-making, + and task distribution. + + Args: + task: The task to be discussed + + Returns: + str: The board meeting prompt + """ + return f"""BOARD OF DIRECTORS MEETING + +TASK: {task} + +CONVERSATION HISTORY: {self.conversation.get_str()} + +AVAILABLE AGENTS: {[agent.agent_name for agent in self.agents]} + +BOARD MEMBERS: +{self._format_board_members_info()} + +INSTRUCTIONS: +1. Discuss the task thoroughly as a board +2. Consider all perspectives and expertise areas +3. Reach consensus or majority decision on the approach +4. Create a detailed plan for task execution +5. Assign specific tasks to appropriate agents +6. Document all decisions and reasoning + +Please provide your response in the following format: +{{ + "plan": "Detailed plan for task execution", + "orders": [ + {{ + "agent_name": "Agent Name", + "task": "Specific task description", + "priority": 1-5, + "deadline": "Optional deadline", + "assigned_by": "Board Member Name" + }} + ], + "decisions": [ + {{ + "decision_type": "unanimous/majority/consensus/chairman_decision", + "decision": "Description of the decision", + "votes_for": 0, + "votes_against": 0, + "abstentions": 0, + "reasoning": "Reasoning behind the decision" + }} + ], + "meeting_summary": "Summary of the board meeting and key outcomes" +}}""" + + def _format_board_members_info(self) -> str: + """ + Format board members information for the prompt. + + This method creates a formatted string containing information about + all board members, their roles, and expertise areas. + + Returns: + str: Formatted board members information + """ + info = [] + for member in self.board_members: + info.append(f"- {member.agent.agent_name} ({member.role.value}): {member.agent.agent_description}") + if member.expertise_areas: + info.append(f" Expertise: {', '.join(member.expertise_areas)}") + return "\n".join(info) + + def _conduct_board_discussion(self, prompt: str, img: Optional[str] = None) -> str: + """ + Conduct the board discussion using the chairman as the primary speaker. + + This method uses the chairman agent to lead the board discussion + and generate the meeting output. + + Args: + prompt: The board meeting prompt + img: Optional image input + + Returns: + str: The board discussion output + + Raises: + ValueError: If no chairman is found in board members + """ + # Use the chairman to lead the discussion + chairman = next((member.agent for member in self.board_members + if member.role == BoardMemberRole.CHAIRMAN), + self.board_members[0].agent if self.board_members else None) + + if not chairman: + raise ValueError("No chairman found in board members") + + return chairman.run(task=prompt, img=img) + + def _parse_board_decisions(self, board_output: str) -> BoardSpec: + """ + Parse the board output into a BoardSpec object. + + This method attempts to parse the board discussion output as JSON + and convert it into a structured BoardSpec object. If parsing fails, + it returns a basic BoardSpec with the raw output. + + Args: + board_output: The output from the board discussion + + Returns: + BoardSpec: Parsed board specification + """ + try: + # Try to parse as JSON first + if isinstance(board_output, str): + # Try to extract JSON from the response + json_match = re.search(r'\{.*\}', board_output, re.DOTALL) + if json_match: + board_output = json_match.group() + + parsed = json.loads(board_output) + else: + parsed = board_output + + # Extract components + plan = parsed.get("plan", "") + orders_data = parsed.get("orders", []) + decisions_data = parsed.get("decisions", []) + meeting_summary = parsed.get("meeting_summary", "") + + # Create BoardOrder objects + orders = [] + for order_data in orders_data: + order = BoardOrder( + agent_name=order_data.get("agent_name", ""), + task=order_data.get("task", ""), + priority=order_data.get("priority", 3), + deadline=order_data.get("deadline"), + assigned_by=order_data.get("assigned_by", "Board of Directors") + ) + orders.append(order) + + # Create BoardDecision objects + decisions = [] + for decision_data in decisions_data: + decision = BoardDecision( + decision_type=BoardDecisionType(decision_data.get("decision_type", "consensus")), + decision=decision_data.get("decision", ""), + votes_for=decision_data.get("votes_for", 0), + votes_against=decision_data.get("votes_against", 0), + abstentions=decision_data.get("abstentions", 0), + reasoning=decision_data.get("reasoning", "") + ) + decisions.append(decision) + + return BoardSpec( + plan=plan, + orders=orders, + decisions=decisions, + meeting_summary=meeting_summary + ) + + except Exception as e: + board_logger.error(f"Failed to parse board decisions: {str(e)}") + # Return a basic BoardSpec if parsing fails + return BoardSpec( + plan=board_output, + orders=[], + decisions=[], + meeting_summary="Parsing failed, using raw output" + ) + + def step(self, task: str, img: Optional[str] = None, *args: Any, **kwargs: Any) -> Any: + """ + Execute a single step of the Board of Directors swarm. + + This method runs one complete cycle of board meeting and task execution. + It includes board discussion, task distribution, and optional feedback. + + Args: + task: The task to be executed + img: Optional image input + *args: Additional positional arguments + **kwargs: Additional keyword arguments + + Returns: + Any: The result of the step execution + + Raises: + Exception: If step execution fails + """ + try: + if self.verbose: + board_logger.info(f"šŸ‘£ Executing single step for task: {task[:100]}...") + + # Run board meeting + board_spec = self.run_board_meeting(task=task, img=img) + + if self.verbose: + board_logger.info(f"šŸ“‹ Board created plan and {len(board_spec.orders)} orders") + + # Execute the orders + outputs = self._execute_orders(board_spec.orders) + + if self.verbose: + board_logger.info(f"⚔ Executed {len(outputs)} orders") + + # Provide board feedback if enabled + if self.board_feedback_on: + feedback = self._generate_board_feedback(outputs) + else: + feedback = outputs + + if self.verbose: + board_logger.success("āœ… Step completed successfully") + + return feedback + + except Exception as e: + error_msg = f"āŒ Failed to execute step: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + def run(self, task: str, img: Optional[str] = None, *args: Any, **kwargs: Any) -> Any: + """ + Run the Board of Directors swarm for the specified number of loops. + + This method executes the complete swarm workflow, including multiple + iterations if max_loops is greater than 1. Each iteration includes + board meeting, task execution, and feedback generation. + + Args: + task: The task to be executed + img: Optional image input + *args: Additional positional arguments + **kwargs: Additional keyword arguments + + Returns: + Any: The final result of the swarm execution + + Raises: + Exception: If swarm execution fails + """ + try: + if self.verbose: + board_logger.info(f"šŸ›ļø Starting Board of Directors swarm execution: {self.name}") + board_logger.info(f"šŸ“‹ Task: {task[:100]}...") + + current_loop = 0 + while current_loop < self.max_loops: + if self.verbose: + board_logger.info(f"šŸ”„ Executing loop {current_loop + 1}/{self.max_loops}") + + # Execute step + result = self.step(task=task, img=img, *args, **kwargs) + + # Add to conversation + self.conversation.add(role="System", content=f"Loop {current_loop + 1} completed") + + current_loop += 1 + + if self.verbose: + board_logger.success(f"šŸŽ‰ Board of Directors swarm run completed: {self.name}") + board_logger.info(f"šŸ“Š Total loops executed: {current_loop}") + + return history_output_formatter( + conversation=self.conversation, type=self.output_type + ) + + except Exception as e: + error_msg = f"āŒ Failed to run Board of Directors swarm: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + async def arun(self, task: str, img: Optional[str] = None, *args: Any, **kwargs: Any) -> Any: + """ + Run the Board of Directors swarm asynchronously. + + This method provides an asynchronous interface for running the swarm, + allowing for non-blocking execution in async contexts. + + Args: + task: The task to be executed + img: Optional image input + *args: Additional positional arguments + **kwargs: Additional keyword arguments + + Returns: + Any: The final result of the swarm execution + """ + loop = asyncio.get_event_loop() + result = await loop.run_in_executor( + None, self.run, task, img, *args, **kwargs + ) + return result + + def _generate_board_feedback(self, outputs: List[Any]) -> str: + """ + Provide feedback from the Board of Directors based on agent outputs. + + This method uses the chairman to review and provide feedback on + the outputs generated by worker agents. + + Args: + outputs: List of outputs from agents + + Returns: + str: Board feedback on the outputs + + Raises: + ValueError: If no chairman is found for feedback + Exception: If feedback generation fails + """ + try: + if self.verbose: + board_logger.info("šŸ“ Generating board feedback") + + task = f"History: {self.conversation.get_str()} \n\n" + + # Use the chairman for feedback + chairman = next((member.agent for member in self.board_members + if member.role == BoardMemberRole.CHAIRMAN), + self.board_members[0].agent if self.board_members else None) + + if not chairman: + raise ValueError("No chairman found for feedback") + + feedback_prompt = ( + "You are the Chairman of the Board. Review the outputs generated by all the worker agents " + "in the previous step. Provide specific, actionable feedback for each agent, highlighting " + "strengths, weaknesses, and concrete suggestions for improvement. " + "If any outputs are unclear, incomplete, or could be enhanced, explain exactly how. " + f"Your feedback should help the agents refine their work in the next iteration. " + f"Worker Agent Responses: {task}" + ) + + output = chairman.run(task=feedback_prompt) + self.conversation.add(role=chairman.agent_name, content=output) + + if self.verbose: + board_logger.success("āœ… Board feedback generated successfully") + + return output + + except Exception as e: + error_msg = f"āŒ Failed to generate board feedback: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + def _call_single_agent( + self, + agent_name: str, + task: str, + *args: Any, + **kwargs: Any + ) -> Any: + """ + Call a single agent with the given task. + + This method finds and executes a specific agent with the provided task. + It includes error handling and logging for agent execution. + + Args: + agent_name: The name of the agent to call + task: The task to assign to the agent + *args: Additional positional arguments + **kwargs: Additional keyword arguments + + Returns: + Any: The output from the agent + + Raises: + ValueError: If the specified agent is not found + Exception: If agent execution fails + """ + try: + if self.verbose: + board_logger.info(f"šŸ“ž Calling agent: {agent_name}") + + # Find agent by name + agent = None + for a in self.agents: + if hasattr(a, "agent_name") and a.agent_name == agent_name: + agent = a + break + + if agent is None: + available_agents = [ + a.agent_name for a in self.agents if hasattr(a, "agent_name") + ] + raise ValueError( + f"Agent '{agent_name}' not found in swarm. Available agents: {available_agents}" + ) + + output = agent.run( + task=f"History: {self.conversation.get_str()} \n\n Task: {task}", + *args, + **kwargs, + ) + self.conversation.add(role=agent_name, content=output) + + if self.verbose: + board_logger.success(f"āœ… Agent {agent_name} completed task successfully") + + return output + + except Exception as e: + error_msg = f"āŒ Failed to call agent {agent_name}: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + def _execute_orders(self, orders: List[BoardOrder]) -> List[Dict[str, Any]]: + """ + Execute the orders issued by the Board of Directors. + + This method uses ThreadPoolExecutor to execute multiple orders in parallel, + improving performance for complex task distributions. + + Args: + orders: List of board orders to execute + + Returns: + List[Dict[str, Any]]: List of outputs from executed orders + + Raises: + Exception: If order execution fails + """ + try: + if self.verbose: + board_logger.info(f"⚔ Executing {len(orders)} board orders") + + # Use ThreadPoolExecutor for parallel execution + outputs = [] + with ThreadPoolExecutor(max_workers=self.max_workers) as executor: + # Submit all orders for execution + future_to_order = { + executor.submit(self._execute_single_order, order): order + for order in orders + } + + # Collect results as they complete + for future in as_completed(future_to_order): + order = future_to_order[future] + try: + output = future.result() + outputs.append({ + "agent_name": order.agent_name, + "task": order.task, + "output": output, + "priority": order.priority, + "assigned_by": order.assigned_by, + }) + except Exception as e: + board_logger.error(f"Failed to execute order for {order.agent_name}: {str(e)}") + outputs.append({ + "agent_name": order.agent_name, + "task": order.task, + "output": f"Error: {str(e)}", + "priority": order.priority, + "assigned_by": order.assigned_by, + }) + + if self.verbose: + board_logger.success(f"āœ… Executed {len(outputs)} orders successfully") + + return outputs + + except Exception as e: + error_msg = f"āŒ Failed to execute orders: {str(e)}\nšŸ” Traceback: {traceback.format_exc()}" + board_logger.error(error_msg) + raise + + def _execute_single_order(self, order: BoardOrder) -> Any: + """ + Execute a single board order. + + This method is a wrapper around _call_single_agent for executing + individual board orders. + + Args: + order: The board order to execute + + Returns: + Any: The output from the executed order + """ + return self._call_single_agent( + agent_name=order.agent_name, + task=order.task, + ) + + def add_board_member(self, board_member: BoardMember) -> None: + """ + Add a new member to the Board of Directors. + + This method allows dynamic addition of board members after swarm initialization. + + Args: + board_member: The board member to add + """ + self.board_members.append(board_member) + if self.verbose: + board_logger.info(f"āœ… Added board member: {board_member.agent.agent_name}") + + def remove_board_member(self, agent_name: str) -> None: + """ + Remove a board member by agent name. + + This method allows dynamic removal of board members after swarm initialization. + + Args: + agent_name: The name of the agent to remove from the board + """ + self.board_members = [ + member for member in self.board_members + if member.agent.agent_name != agent_name + ] + if self.verbose: + board_logger.info(f"āœ… Removed board member: {agent_name}") + + def get_board_member(self, agent_name: str) -> Optional[BoardMember]: + """ + Get a board member by agent name. + + This method retrieves a specific board member by their agent name. + + Args: + agent_name: The name of the agent + + Returns: + Optional[BoardMember]: The board member if found, None otherwise + """ + for member in self.board_members: + if member.agent.agent_name == agent_name: + return member + return None + + def get_board_summary(self) -> Dict[str, Any]: + """ + Get a summary of the Board of Directors. + + This method provides a comprehensive summary of the board structure, + including member information, configuration, and statistics. + + Returns: + Dict[str, Any]: Summary of the board structure and members + """ + return { + "board_name": self.name, + "total_members": len(self.board_members), + "members": [ + { + "name": member.agent.agent_name, + "role": member.role.value, + "voting_weight": member.voting_weight, + "expertise_areas": member.expertise_areas, + } + for member in self.board_members + ], + "total_agents": len(self.agents), + "max_loops": self.max_loops, + "decision_threshold": self.decision_threshold, + } \ No newline at end of file From cb0ca8f2a708274d909e362578ebe940d3f9d5af Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sun, 27 Jul 2025 12:06:32 +0300 Subject: [PATCH 07/18] Add files via upload --- swarms/config/board_config.py | 596 ++++++++++++++++++++++++++++++++++ 1 file changed, 596 insertions(+) create mode 100644 swarms/config/board_config.py diff --git a/swarms/config/board_config.py b/swarms/config/board_config.py new file mode 100644 index 00000000..8b29c0ae --- /dev/null +++ b/swarms/config/board_config.py @@ -0,0 +1,596 @@ +""" +Board of Directors Configuration Module + +This module provides configuration management for the Board of Directors feature +in the Swarms Framework. It allows users to enable and configure the Board of +Directors feature manually through environment variables or configuration files. + +The implementation follows the Swarms philosophy of: +- Readable code with comprehensive type annotations and documentation +- Performance optimization through caching and efficient loading +- Simplified abstractions for configuration management +""" + +import os +from typing import Dict, Any, Optional, List, Union +from dataclasses import dataclass, field +from enum import Enum +from pathlib import Path +from functools import lru_cache + +from pydantic import BaseModel, Field +from loguru import logger + + +class BoardFeatureStatus(str, Enum): + """Enumeration of Board of Directors feature status. + + This enum defines the possible states of the Board of Directors feature + within the Swarms Framework. + + Attributes: + ENABLED: Feature is explicitly enabled + DISABLED: Feature is explicitly disabled + AUTO: Feature state is determined automatically + """ + + ENABLED = "enabled" + DISABLED = "disabled" + AUTO = "auto" + + +class BoardConfigModel(BaseModel): + """ + Configuration model for Board of Directors feature. + + This model defines all configurable parameters for the Board of Directors + feature, including feature status, board composition, and operational settings. + + Attributes: + board_feature_enabled: Whether the Board of Directors feature is enabled globally + default_board_size: Default number of board members when creating a new board + decision_threshold: Threshold for majority decisions (0.0-1.0) + enable_voting: Enable voting mechanisms for board decisions + enable_consensus: Enable consensus-building mechanisms + default_board_model: Default model for board member agents + verbose_logging: Enable verbose logging for board operations + max_board_meeting_duration: Maximum duration for board meetings in seconds + auto_fallback_to_director: Automatically fall back to Director mode if Board fails + custom_board_templates: Custom board templates for different use cases + """ + + # Feature control + board_feature_enabled: bool = Field( + default=False, + description="Whether the Board of Directors feature is enabled globally." + ) + + # Board composition + default_board_size: int = Field( + default=3, + ge=1, + le=10, + description="Default number of board members when creating a new board." + ) + + # Operational settings + decision_threshold: float = Field( + default=0.6, + ge=0.0, + le=1.0, + description="Threshold for majority decisions (0.0-1.0)." + ) + + enable_voting: bool = Field( + default=True, + description="Enable voting mechanisms for board decisions." + ) + + enable_consensus: bool = Field( + default=True, + description="Enable consensus-building mechanisms." + ) + + # Model settings + default_board_model: str = Field( + default="gpt-4o-mini", + description="Default model for board member agents." + ) + + # Logging and monitoring + verbose_logging: bool = Field( + default=False, + description="Enable verbose logging for board operations." + ) + + # Performance settings + max_board_meeting_duration: int = Field( + default=300, + ge=60, + le=3600, + description="Maximum duration for board meetings in seconds." + ) + + # Integration settings + auto_fallback_to_director: bool = Field( + default=True, + description="Automatically fall back to Director mode if Board fails." + ) + + # Custom board templates + custom_board_templates: Dict[str, Dict[str, Any]] = Field( + default_factory=dict, + description="Custom board templates for different use cases." + ) + + +@dataclass +class BoardConfig: + """ + Board of Directors configuration manager. + + This class manages the configuration for the Board of Directors feature, + including loading from environment variables, configuration files, and + providing default values. + + Attributes: + config_file_path: Optional path to configuration file + config_data: Optional configuration data dictionary + config: The current configuration model instance + """ + + config_file_path: Optional[str] = None + config_data: Optional[Dict[str, Any]] = None + config: BoardConfigModel = field(init=False) + + def __post_init__(self) -> None: + """Initialize the configuration after object creation.""" + self._load_config() + + def _load_config(self) -> None: + """ + Load configuration from various sources. + + Priority order: + 1. Environment variables + 2. Configuration file + 3. Default values + + Raises: + Exception: If configuration loading fails + """ + try: + # Start with default configuration + self.config = BoardConfigModel() + + # Load from configuration file if specified + if self.config_file_path and os.path.exists(self.config_file_path): + self._load_from_file() + + # Override with environment variables + self._load_from_environment() + + # Override with explicit config data + if self.config_data: + self._load_from_dict(self.config_data) + + except Exception as e: + logger.error(f"Failed to load Board of Directors configuration: {str(e)}") + raise + + def _load_from_file(self) -> None: + """ + Load configuration from file. + + Raises: + Exception: If file loading fails + """ + try: + import yaml + with open(self.config_file_path, 'r') as f: + file_config = yaml.safe_load(f) + self._load_from_dict(file_config) + logger.info(f"Loaded Board of Directors config from: {self.config_file_path}") + except Exception as e: + logger.warning(f"Failed to load config file {self.config_file_path}: {e}") + raise + + def _load_from_environment(self) -> None: + """ + Load configuration from environment variables. + + This method maps environment variables to configuration parameters + and handles type conversion appropriately. + """ + env_mappings = { + 'SWARMS_BOARD_FEATURE_ENABLED': 'board_feature_enabled', + 'SWARMS_BOARD_DEFAULT_SIZE': 'default_board_size', + 'SWARMS_BOARD_DECISION_THRESHOLD': 'decision_threshold', + 'SWARMS_BOARD_ENABLE_VOTING': 'enable_voting', + 'SWARMS_BOARD_ENABLE_CONSENSUS': 'enable_consensus', + 'SWARMS_BOARD_DEFAULT_MODEL': 'default_board_model', + 'SWARMS_BOARD_VERBOSE_LOGGING': 'verbose_logging', + 'SWARMS_BOARD_MAX_MEETING_DURATION': 'max_board_meeting_duration', + 'SWARMS_BOARD_AUTO_FALLBACK': 'auto_fallback_to_director', + } + + for env_var, config_key in env_mappings.items(): + value = os.getenv(env_var) + if value is not None: + try: + # Convert string values to appropriate types + if config_key in ['board_feature_enabled', 'enable_voting', 'enable_consensus', 'verbose_logging', 'auto_fallback_to_director']: + converted_value = value.lower() in ['true', '1', 'yes', 'on'] + elif config_key in ['default_board_size', 'max_board_meeting_duration']: + converted_value = int(value) + elif config_key in ['decision_threshold']: + converted_value = float(value) + else: + converted_value = value + + setattr(self.config, config_key, converted_value) + logger.debug(f"Loaded {config_key} from environment: {converted_value}") + except (ValueError, TypeError) as e: + logger.warning(f"Failed to parse environment variable {env_var}: {e}") + + def _load_from_dict(self, config_dict: Dict[str, Any]) -> None: + """ + Load configuration from dictionary. + + Args: + config_dict: Dictionary containing configuration values + + Raises: + ValueError: If configuration values are invalid + """ + for key, value in config_dict.items(): + if hasattr(self.config, key): + try: + setattr(self.config, key, value) + except (ValueError, TypeError) as e: + logger.warning(f"Failed to set config {key}: {e}") + raise ValueError(f"Invalid configuration value for {key}: {e}") + + def is_enabled(self) -> bool: + """ + Check if the Board of Directors feature is enabled. + + Returns: + bool: True if the feature is enabled, False otherwise + """ + return self.config.board_feature_enabled + + def get_config(self) -> BoardConfigModel: + """ + Get the current configuration. + + Returns: + BoardConfigModel: The current configuration + """ + return self.config + + def update_config(self, updates: Dict[str, Any]) -> None: + """ + Update the configuration with new values. + + Args: + updates: Dictionary of configuration updates + + Raises: + ValueError: If any update values are invalid + """ + try: + self._load_from_dict(updates) + except ValueError as e: + logger.error(f"Failed to update configuration: {e}") + raise + + def save_config(self, file_path: Optional[str] = None) -> None: + """ + Save the current configuration to a file. + + Args: + file_path: Optional file path to save to (uses config_file_path if not provided) + + Raises: + Exception: If saving fails + """ + save_path = file_path or self.config_file_path + if not save_path: + logger.warning("No file path specified for saving configuration") + return + + try: + import yaml + # Convert config to dictionary + config_dict = self.config.model_dump() + + # Ensure directory exists + os.makedirs(os.path.dirname(save_path), exist_ok=True) + + with open(save_path, 'w') as f: + yaml.dump(config_dict, f, default_flow_style=False, indent=2) + + logger.info(f"Saved Board of Directors config to: {save_path}") + except Exception as e: + logger.error(f"Failed to save config to {save_path}: {e}") + raise + + @lru_cache(maxsize=128) + def get_default_board_template(self, template_name: str = "standard") -> Dict[str, Any]: + """ + Get a default board template. + + This method provides predefined board templates for common use cases. + Templates are cached for improved performance. + + Args: + template_name: Name of the template to retrieve + + Returns: + Dict[str, Any]: Board template configuration + """ + templates = { + "standard": { + "roles": [ + {"name": "Chairman", "weight": 1.5, "expertise": ["leadership", "strategy"]}, + {"name": "Vice-Chairman", "weight": 1.2, "expertise": ["operations", "coordination"]}, + {"name": "Secretary", "weight": 1.0, "expertise": ["documentation", "communication"]}, + ] + }, + "executive": { + "roles": [ + {"name": "CEO", "weight": 2.0, "expertise": ["executive_leadership", "strategy"]}, + {"name": "CFO", "weight": 1.5, "expertise": ["finance", "risk_management"]}, + {"name": "CTO", "weight": 1.5, "expertise": ["technology", "innovation"]}, + {"name": "COO", "weight": 1.3, "expertise": ["operations", "efficiency"]}, + ] + }, + "advisory": { + "roles": [ + {"name": "Lead_Advisor", "weight": 1.3, "expertise": ["strategy", "consulting"]}, + {"name": "Technical_Advisor", "weight": 1.2, "expertise": ["technology", "architecture"]}, + {"name": "Business_Advisor", "weight": 1.2, "expertise": ["business", "market_analysis"]}, + {"name": "Legal_Advisor", "weight": 1.1, "expertise": ["legal", "compliance"]}, + ] + }, + "minimal": { + "roles": [ + {"name": "Chairman", "weight": 1.0, "expertise": ["leadership"]}, + {"name": "Member", "weight": 1.0, "expertise": ["general"]}, + ] + } + } + + # Check custom templates first + if template_name in self.config.custom_board_templates: + return self.config.custom_board_templates[template_name] + + # Return standard template if requested template not found + return templates.get(template_name, templates["standard"]) + + def validate_config(self) -> List[str]: + """ + Validate the current configuration. + + This method performs comprehensive validation of the configuration + to ensure all values are within acceptable ranges and constraints. + + Returns: + List[str]: List of validation errors (empty if valid) + """ + errors = [] + + try: + # Validate the configuration model + self.config.model_validate(self.config.model_dump()) + except Exception as e: + errors.append(f"Configuration validation failed: {e}") + + # Additional custom validations + if self.config.decision_threshold < 0.5: + errors.append("Decision threshold should be at least 0.5 for meaningful majority decisions") + + if self.config.default_board_size < 2: + errors.append("Board size should be at least 2 for meaningful discussions") + + if self.config.max_board_meeting_duration < 60: + errors.append("Board meeting duration should be at least 60 seconds") + + return errors + + +# Global configuration instance +_board_config: Optional[BoardConfig] = None + + +@lru_cache(maxsize=1) +def get_board_config(config_file_path: Optional[str] = None) -> BoardConfig: + """ + Get the global Board of Directors configuration instance. + + This function provides a singleton pattern for accessing the Board of Directors + configuration. The configuration is cached for improved performance. + + Args: + config_file_path: Optional path to configuration file + + Returns: + BoardConfig: The global configuration instance + """ + global _board_config + + if _board_config is None: + _board_config = BoardConfig(config_file_path=config_file_path) + + return _board_config + + +def enable_board_feature(config_file_path: Optional[str] = None) -> None: + """ + Enable the Board of Directors feature globally. + + This function enables the Board of Directors feature and saves the configuration + to the specified file path. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"board_feature_enabled": True}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Board of Directors feature enabled") + + +def disable_board_feature(config_file_path: Optional[str] = None) -> None: + """ + Disable the Board of Directors feature globally. + + This function disables the Board of Directors feature and saves the configuration + to the specified file path. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"board_feature_enabled": False}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Board of Directors feature disabled") + + +def is_board_feature_enabled(config_file_path: Optional[str] = None) -> bool: + """ + Check if the Board of Directors feature is enabled. + + Args: + config_file_path: Optional path to configuration file + + Returns: + bool: True if the feature is enabled, False otherwise + """ + config = get_board_config(config_file_path) + return config.is_enabled() + + +def create_default_config_file(file_path: str = "swarms_board_config.yaml") -> None: + """ + Create a default configuration file. + + This function creates a default Board of Directors configuration file + with recommended settings. + + Args: + file_path: Path where to create the configuration file + """ + default_config = { + "board_feature_enabled": False, + "default_board_size": 3, + "decision_threshold": 0.6, + "enable_voting": True, + "enable_consensus": True, + "default_board_model": "gpt-4o-mini", + "verbose_logging": False, + "max_board_meeting_duration": 300, + "auto_fallback_to_director": True, + "custom_board_templates": {} + } + + config = BoardConfig(config_file_path=file_path, config_data=default_config) + config.save_config(file_path) + + logger.info(f"Created default Board of Directors config file: {file_path}") + + +def set_board_size(size: int, config_file_path: Optional[str] = None) -> None: + """ + Set the default board size. + + Args: + size: The default board size (1-10) + config_file_path: Optional path to save the configuration + """ + if not 1 <= size <= 10: + raise ValueError("Board size must be between 1 and 10") + + config = get_board_config(config_file_path) + config.update_config({"default_board_size": size}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info(f"Default board size set to: {size}") + + +def set_decision_threshold(threshold: float, config_file_path: Optional[str] = None) -> None: + """ + Set the decision threshold for majority decisions. + + Args: + threshold: The decision threshold (0.0-1.0) + config_file_path: Optional path to save the configuration + """ + if not 0.0 <= threshold <= 1.0: + raise ValueError("Decision threshold must be between 0.0 and 1.0") + + config = get_board_config(config_file_path) + config.update_config({"decision_threshold": threshold}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info(f"Decision threshold set to: {threshold}") + + +def set_board_model(model: str, config_file_path: Optional[str] = None) -> None: + """ + Set the default board model. + + Args: + model: The default model name for board members + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"default_board_model": model}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info(f"Default board model set to: {model}") + + +def enable_verbose_logging(config_file_path: Optional[str] = None) -> None: + """ + Enable verbose logging for board operations. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"verbose_logging": True}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Verbose logging enabled for Board of Directors") + + +def disable_verbose_logging(config_file_path: Optional[str] = None) -> None: + """ + Disable verbose logging for board operations. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"verbose_logging": False}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Verbose logging disabled for Board of Directors") \ No newline at end of file From b207a879614945bf71942420ce9eaef6ea7ba142 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sun, 27 Jul 2025 12:07:39 +0300 Subject: [PATCH 08/18] Add files via upload --- .../structs/test_board_of_directors_swarm.py | 1020 +++++++++++++++++ 1 file changed, 1020 insertions(+) create mode 100644 tests/structs/test_board_of_directors_swarm.py diff --git a/tests/structs/test_board_of_directors_swarm.py b/tests/structs/test_board_of_directors_swarm.py new file mode 100644 index 00000000..b87e563c --- /dev/null +++ b/tests/structs/test_board_of_directors_swarm.py @@ -0,0 +1,1020 @@ +""" +Comprehensive test suite for Board of Directors Swarm. + +This module contains extensive tests for the Board of Directors swarm implementation, +covering all aspects including initialization, board operations, task execution, +error handling, and performance characteristics. + +The test suite follows the Swarms testing philosophy: +- Comprehensive coverage of all functionality +- Proper mocking and isolation +- Performance and integration testing +- Error handling validation +""" + +import os +import pytest +import asyncio +from unittest.mock import Mock, patch, MagicMock, AsyncMock +from typing import List, Dict, Any, Optional + +from swarms.structs.board_of_directors_swarm import ( + BoardOfDirectorsSwarm, + BoardMember, + BoardMemberRole, + BoardDecisionType, + BoardOrder, + BoardDecision, + BoardSpec, +) +from swarms.structs.agent import Agent +from swarms.structs.conversation import Conversation + + +# Test fixtures +@pytest.fixture +def mock_agent(): + """Create a mock agent for testing.""" + agent = Mock(spec=Agent) + agent.agent_name = "TestAgent" + agent.agent_description = "A test agent for unit testing" + agent.run = Mock(return_value="Test agent response") + agent.arun = AsyncMock(return_value="Async test agent response") + return agent + + +@pytest.fixture +def mock_board_member(mock_agent): + """Create a mock board member for testing.""" + return BoardMember( + agent=mock_agent, + role=BoardMemberRole.CHAIRMAN, + voting_weight=1.5, + expertise_areas=["leadership", "strategy"] + ) + + +@pytest.fixture +def sample_agents(): + """Create sample agents for testing.""" + agents = [] + for i in range(3): + agent = Mock(spec=Agent) + agent.agent_name = f"Agent{i+1}" + agent.agent_description = f"Test agent {i+1}" + agent.run = Mock(return_value=f"Response from Agent{i+1}") + agents.append(agent) + return agents + + +@pytest.fixture +def sample_board_members(sample_agents): + """Create sample board members for testing.""" + roles = [BoardMemberRole.CHAIRMAN, BoardMemberRole.VICE_CHAIRMAN, BoardMemberRole.SECRETARY] + board_members = [] + + for i, (agent, role) in enumerate(zip(sample_agents, roles)): + board_member = BoardMember( + agent=agent, + role=role, + voting_weight=1.0 + (i * 0.2), + expertise_areas=[f"expertise_{i+1}"] + ) + board_members.append(board_member) + + return board_members + + +@pytest.fixture +def basic_board_swarm(sample_agents): + """Create a basic Board of Directors swarm for testing.""" + return BoardOfDirectorsSwarm( + name="TestBoard", + agents=sample_agents, + verbose=False, + max_loops=1 + ) + + +@pytest.fixture +def configured_board_swarm(sample_agents, sample_board_members): + """Create a configured Board of Directors swarm for testing.""" + return BoardOfDirectorsSwarm( + name="ConfiguredBoard", + description="A configured board for testing", + board_members=sample_board_members, + agents=sample_agents, + max_loops=2, + verbose=True, + decision_threshold=0.7, + enable_voting=True, + enable_consensus=True, + max_workers=4 + ) + + +# Unit tests for enums and data models +class TestBoardMemberRole: + """Test BoardMemberRole enum.""" + + def test_enum_values(self): + """Test that all enum values are correctly defined.""" + assert BoardMemberRole.CHAIRMAN == "chairman" + assert BoardMemberRole.VICE_CHAIRMAN == "vice_chairman" + assert BoardMemberRole.SECRETARY == "secretary" + assert BoardMemberRole.TREASURER == "treasurer" + assert BoardMemberRole.MEMBER == "member" + assert BoardMemberRole.EXECUTIVE_DIRECTOR == "executive_director" + + +class TestBoardDecisionType: + """Test BoardDecisionType enum.""" + + def test_enum_values(self): + """Test that all enum values are correctly defined.""" + assert BoardDecisionType.UNANIMOUS == "unanimous" + assert BoardDecisionType.MAJORITY == "majority" + assert BoardDecisionType.CONSENSUS == "consensus" + assert BoardDecisionType.CHAIRMAN_DECISION == "chairman_decision" + + +class TestBoardMember: + """Test BoardMember dataclass.""" + + def test_board_member_creation(self, mock_agent): + """Test creating a board member.""" + board_member = BoardMember( + agent=mock_agent, + role=BoardMemberRole.CHAIRMAN, + voting_weight=1.5, + expertise_areas=["leadership", "strategy"] + ) + + assert board_member.agent == mock_agent + assert board_member.role == BoardMemberRole.CHAIRMAN + assert board_member.voting_weight == 1.5 + assert board_member.expertise_areas == ["leadership", "strategy"] + + def test_board_member_defaults(self, mock_agent): + """Test board member with default values.""" + board_member = BoardMember( + agent=mock_agent, + role=BoardMemberRole.MEMBER + ) + + assert board_member.voting_weight == 1.0 + assert board_member.expertise_areas == [] + + def test_board_member_post_init(self, mock_agent): + """Test board member post-init with None expertise areas.""" + board_member = BoardMember( + agent=mock_agent, + role=BoardMemberRole.MEMBER, + expertise_areas=None + ) + + assert board_member.expertise_areas == [] + + +class TestBoardOrder: + """Test BoardOrder model.""" + + def test_board_order_creation(self): + """Test creating a board order.""" + order = BoardOrder( + agent_name="TestAgent", + task="Test task", + priority=1, + deadline="2024-01-01", + assigned_by="Chairman" + ) + + assert order.agent_name == "TestAgent" + assert order.task == "Test task" + assert order.priority == 1 + assert order.deadline == "2024-01-01" + assert order.assigned_by == "Chairman" + + def test_board_order_defaults(self): + """Test board order with default values.""" + order = BoardOrder( + agent_name="TestAgent", + task="Test task" + ) + + assert order.priority == 3 + assert order.deadline is None + assert order.assigned_by == "Board of Directors" + + def test_board_order_validation(self): + """Test board order validation.""" + # Test priority validation + with pytest.raises(ValueError): + BoardOrder( + agent_name="TestAgent", + task="Test task", + priority=0 # Invalid priority + ) + + with pytest.raises(ValueError): + BoardOrder( + agent_name="TestAgent", + task="Test task", + priority=6 # Invalid priority + ) + + +class TestBoardDecision: + """Test BoardDecision model.""" + + def test_board_decision_creation(self): + """Test creating a board decision.""" + decision = BoardDecision( + decision_type=BoardDecisionType.MAJORITY, + decision="Approve the proposal", + votes_for=3, + votes_against=1, + abstentions=0, + reasoning="The proposal aligns with our strategic goals" + ) + + assert decision.decision_type == BoardDecisionType.MAJORITY + assert decision.decision == "Approve the proposal" + assert decision.votes_for == 3 + assert decision.votes_against == 1 + assert decision.abstentions == 0 + assert decision.reasoning == "The proposal aligns with our strategic goals" + + def test_board_decision_defaults(self): + """Test board decision with default values.""" + decision = BoardDecision( + decision_type=BoardDecisionType.CONSENSUS, + decision="Test decision" + ) + + assert decision.votes_for == 0 + assert decision.votes_against == 0 + assert decision.abstentions == 0 + assert decision.reasoning == "" + + +class TestBoardSpec: + """Test BoardSpec model.""" + + def test_board_spec_creation(self): + """Test creating a board spec.""" + orders = [ + BoardOrder(agent_name="Agent1", task="Task 1"), + BoardOrder(agent_name="Agent2", task="Task 2") + ] + decisions = [ + BoardDecision( + decision_type=BoardDecisionType.MAJORITY, + decision="Decision 1" + ) + ] + + spec = BoardSpec( + plan="Test plan", + orders=orders, + decisions=decisions, + meeting_summary="Test meeting summary" + ) + + assert spec.plan == "Test plan" + assert len(spec.orders) == 2 + assert len(spec.decisions) == 1 + assert spec.meeting_summary == "Test meeting summary" + + def test_board_spec_defaults(self): + """Test board spec with default values.""" + spec = BoardSpec( + plan="Test plan", + orders=[] + ) + + assert spec.decisions == [] + assert spec.meeting_summary == "" + + +# Unit tests for BoardOfDirectorsSwarm +class TestBoardOfDirectorsSwarmInitialization: + """Test BoardOfDirectorsSwarm initialization.""" + + def test_basic_initialization(self, sample_agents): + """Test basic swarm initialization.""" + swarm = BoardOfDirectorsSwarm( + name="TestSwarm", + agents=sample_agents + ) + + assert swarm.name == "TestSwarm" + assert len(swarm.agents) == 3 + assert swarm.max_loops == 1 + assert swarm.verbose is False + assert swarm.decision_threshold == 0.6 + + def test_configured_initialization(self, sample_agents, sample_board_members): + """Test configured swarm initialization.""" + swarm = BoardOfDirectorsSwarm( + name="ConfiguredSwarm", + description="Test description", + board_members=sample_board_members, + agents=sample_agents, + max_loops=3, + verbose=True, + decision_threshold=0.8, + enable_voting=False, + enable_consensus=False, + max_workers=8 + ) + + assert swarm.name == "ConfiguredSwarm" + assert swarm.description == "Test description" + assert len(swarm.board_members) == 3 + assert len(swarm.agents) == 3 + assert swarm.max_loops == 3 + assert swarm.verbose is True + assert swarm.decision_threshold == 0.8 + assert swarm.enable_voting is False + assert swarm.enable_consensus is False + assert swarm.max_workers == 8 + + def test_default_board_setup(self, sample_agents): + """Test default board setup when no board members provided.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + + assert len(swarm.board_members) == 3 + assert swarm.board_members[0].role == BoardMemberRole.CHAIRMAN + assert swarm.board_members[1].role == BoardMemberRole.VICE_CHAIRMAN + assert swarm.board_members[2].role == BoardMemberRole.SECRETARY + + def test_initialization_without_agents(self): + """Test initialization without agents should raise error.""" + with pytest.raises(ValueError, match="No agents found in the swarm"): + BoardOfDirectorsSwarm(agents=[]) + + def test_initialization_with_invalid_max_loops(self, sample_agents): + """Test initialization with invalid max_loops.""" + with pytest.raises(ValueError, match="Max loops must be greater than 0"): + BoardOfDirectorsSwarm(agents=sample_agents, max_loops=0) + + def test_initialization_with_invalid_decision_threshold(self, sample_agents): + """Test initialization with invalid decision threshold.""" + with pytest.raises(ValueError, match="Decision threshold must be between 0.0 and 1.0"): + BoardOfDirectorsSwarm(agents=sample_agents, decision_threshold=1.5) + + +class TestBoardOfDirectorsSwarmMethods: + """Test BoardOfDirectorsSwarm methods.""" + + def test_setup_default_board(self, sample_agents): + """Test default board setup.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + + assert len(swarm.board_members) == 3 + assert all(hasattr(member.agent, 'agent_name') for member in swarm.board_members) + assert all(hasattr(member.agent, 'run') for member in swarm.board_members) + + def test_get_chairman_prompt(self, sample_agents): + """Test chairman prompt generation.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + prompt = swarm._get_chairman_prompt() + + assert "Chairman" in prompt + assert "board meetings" in prompt + assert "consensus" in prompt + + def test_get_vice_chairman_prompt(self, sample_agents): + """Test vice chairman prompt generation.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + prompt = swarm._get_vice_chairman_prompt() + + assert "Vice Chairman" in prompt + assert "supporting" in prompt + assert "operational" in prompt + + def test_get_secretary_prompt(self, sample_agents): + """Test secretary prompt generation.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + prompt = swarm._get_secretary_prompt() + + assert "Secretary" in prompt + assert "documenting" in prompt + assert "records" in prompt + + def test_format_board_members_info(self, configured_board_swarm): + """Test board members info formatting.""" + info = configured_board_swarm._format_board_members_info() + + assert "Chairman" in info + assert "Vice-Chairman" in info + assert "Secretary" in info + assert "expertise" in info + + def test_add_board_member(self, basic_board_swarm, mock_board_member): + """Test adding a board member.""" + initial_count = len(basic_board_swarm.board_members) + basic_board_swarm.add_board_member(mock_board_member) + + assert len(basic_board_swarm.board_members) == initial_count + 1 + assert mock_board_member in basic_board_swarm.board_members + + def test_remove_board_member(self, configured_board_swarm): + """Test removing a board member.""" + member_to_remove = configured_board_swarm.board_members[0] + member_name = member_to_remove.agent.agent_name + + initial_count = len(configured_board_swarm.board_members) + configured_board_swarm.remove_board_member(member_name) + + assert len(configured_board_swarm.board_members) == initial_count - 1 + assert member_to_remove not in configured_board_swarm.board_members + + def test_get_board_member(self, configured_board_swarm): + """Test getting a board member by name.""" + member = configured_board_swarm.board_members[0] + member_name = member.agent.agent_name + + found_member = configured_board_swarm.get_board_member(member_name) + assert found_member == member + + # Test with non-existent member + not_found = configured_board_swarm.get_board_member("NonExistent") + assert not_found is None + + def test_get_board_summary(self, configured_board_swarm): + """Test getting board summary.""" + summary = configured_board_swarm.get_board_summary() + + assert "board_name" in summary + assert "total_members" in summary + assert "total_agents" in summary + assert "max_loops" in summary + assert "decision_threshold" in summary + assert "members" in summary + + assert summary["board_name"] == "ConfiguredBoard" + assert summary["total_members"] == 3 + assert summary["total_agents"] == 3 + + +class TestBoardMeetingOperations: + """Test board meeting operations.""" + + def test_create_board_meeting_prompt(self, configured_board_swarm): + """Test board meeting prompt creation.""" + task = "Test task for board meeting" + prompt = configured_board_swarm._create_board_meeting_prompt(task) + + assert task in prompt + assert "BOARD OF DIRECTORS MEETING" in prompt + assert "INSTRUCTIONS" in prompt + assert "plan" in prompt + assert "orders" in prompt + + def test_conduct_board_discussion(self, configured_board_swarm): + """Test board discussion conduction.""" + prompt = "Test board meeting prompt" + + with patch.object(configured_board_swarm.board_members[0].agent, 'run') as mock_run: + mock_run.return_value = "Board discussion result" + result = configured_board_swarm._conduct_board_discussion(prompt) + + assert result == "Board discussion result" + mock_run.assert_called_once_with(task=prompt, img=None) + + def test_conduct_board_discussion_no_chairman(self, sample_agents): + """Test board discussion when no chairman is found.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + # Remove all board members + swarm.board_members = [] + + with pytest.raises(ValueError, match="No chairman found in board members"): + swarm._conduct_board_discussion("Test prompt") + + def test_parse_board_decisions_valid_json(self, configured_board_swarm): + """Test parsing valid JSON board decisions.""" + valid_json = """ + { + "plan": "Test plan", + "orders": [ + { + "agent_name": "Agent1", + "task": "Task 1", + "priority": 1, + "assigned_by": "Chairman" + } + ], + "decisions": [ + { + "decision_type": "majority", + "decision": "Test decision", + "votes_for": 2, + "votes_against": 1, + "abstentions": 0, + "reasoning": "Test reasoning" + } + ], + "meeting_summary": "Test summary" + } + """ + + result = configured_board_swarm._parse_board_decisions(valid_json) + + assert isinstance(result, BoardSpec) + assert result.plan == "Test plan" + assert len(result.orders) == 1 + assert len(result.decisions) == 1 + assert result.meeting_summary == "Test summary" + + def test_parse_board_decisions_invalid_json(self, configured_board_swarm): + """Test parsing invalid JSON board decisions.""" + invalid_json = "Invalid JSON content" + + result = configured_board_swarm._parse_board_decisions(invalid_json) + + assert isinstance(result, BoardSpec) + assert result.plan == invalid_json + assert len(result.orders) == 0 + assert len(result.decisions) == 0 + assert result.meeting_summary == "Parsing failed, using raw output" + + def test_run_board_meeting(self, configured_board_swarm): + """Test running a complete board meeting.""" + task = "Test board meeting task" + + with patch.object(configured_board_swarm, '_conduct_board_discussion') as mock_discuss: + with patch.object(configured_board_swarm, '_parse_board_decisions') as mock_parse: + mock_discuss.return_value = "Board discussion" + mock_parse.return_value = BoardSpec( + plan="Test plan", + orders=[], + decisions=[], + meeting_summary="Test summary" + ) + + result = configured_board_swarm.run_board_meeting(task) + + assert isinstance(result, BoardSpec) + mock_discuss.assert_called_once() + mock_parse.assert_called_once_with("Board discussion") + + +class TestTaskExecution: + """Test task execution methods.""" + + def test_call_single_agent(self, configured_board_swarm): + """Test calling a single agent.""" + agent_name = "Agent1" + task = "Test task" + + with patch.object(configured_board_swarm.agents[0], 'run') as mock_run: + mock_run.return_value = "Agent response" + result = configured_board_swarm._call_single_agent(agent_name, task) + + assert result == "Agent response" + mock_run.assert_called_once() + + def test_call_single_agent_not_found(self, configured_board_swarm): + """Test calling a non-existent agent.""" + with pytest.raises(ValueError, match="Agent 'NonExistent' not found"): + configured_board_swarm._call_single_agent("NonExistent", "Test task") + + def test_execute_single_order(self, configured_board_swarm): + """Test executing a single order.""" + order = BoardOrder( + agent_name="Agent1", + task="Test order task", + priority=1, + assigned_by="Chairman" + ) + + with patch.object(configured_board_swarm, '_call_single_agent') as mock_call: + mock_call.return_value = "Order execution result" + result = configured_board_swarm._execute_single_order(order) + + assert result == "Order execution result" + mock_call.assert_called_once_with( + agent_name="Agent1", + task="Test order task" + ) + + def test_execute_orders(self, configured_board_swarm): + """Test executing multiple orders.""" + orders = [ + BoardOrder(agent_name="Agent1", task="Task 1", priority=1), + BoardOrder(agent_name="Agent2", task="Task 2", priority=2), + ] + + with patch.object(configured_board_swarm, '_execute_single_order') as mock_execute: + mock_execute.side_effect = ["Result 1", "Result 2"] + results = configured_board_swarm._execute_orders(orders) + + assert len(results) == 2 + assert results[0]["agent_name"] == "Agent1" + assert results[0]["output"] == "Result 1" + assert results[1]["agent_name"] == "Agent2" + assert results[1]["output"] == "Result 2" + + def test_generate_board_feedback(self, configured_board_swarm): + """Test generating board feedback.""" + outputs = [ + {"agent_name": "Agent1", "output": "Output 1"}, + {"agent_name": "Agent2", "output": "Output 2"} + ] + + with patch.object(configured_board_swarm.board_members[0].agent, 'run') as mock_run: + mock_run.return_value = "Board feedback" + result = configured_board_swarm._generate_board_feedback(outputs) + + assert result == "Board feedback" + mock_run.assert_called_once() + + def test_generate_board_feedback_no_chairman(self, sample_agents): + """Test generating feedback when no chairman is found.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + swarm.board_members = [] # Remove all board members + + with pytest.raises(ValueError, match="No chairman found for feedback"): + swarm._generate_board_feedback([]) + + +class TestStepAndRunMethods: + """Test step and run methods.""" + + def test_step_method(self, configured_board_swarm): + """Test the step method.""" + task = "Test step task" + + with patch.object(configured_board_swarm, 'run_board_meeting') as mock_meeting: + with patch.object(configured_board_swarm, '_execute_orders') as mock_execute: + with patch.object(configured_board_swarm, '_generate_board_feedback') as mock_feedback: + mock_meeting.return_value = BoardSpec( + plan="Test plan", + orders=[BoardOrder(agent_name="Agent1", task="Task 1")], + decisions=[], + meeting_summary="Test summary" + ) + mock_execute.return_value = [{"agent_name": "Agent1", "output": "Result"}] + mock_feedback.return_value = "Board feedback" + + result = configured_board_swarm.step(task) + + assert result == "Board feedback" + mock_meeting.assert_called_once_with(task=task, img=None) + mock_execute.assert_called_once() + mock_feedback.assert_called_once() + + def test_step_method_no_feedback(self, configured_board_swarm): + """Test the step method with feedback disabled.""" + configured_board_swarm.board_feedback_on = False + task = "Test step task" + + with patch.object(configured_board_swarm, 'run_board_meeting') as mock_meeting: + with patch.object(configured_board_swarm, '_execute_orders') as mock_execute: + mock_meeting.return_value = BoardSpec( + plan="Test plan", + orders=[BoardOrder(agent_name="Agent1", task="Task 1")], + decisions=[], + meeting_summary="Test summary" + ) + mock_execute.return_value = [{"agent_name": "Agent1", "output": "Result"}] + + result = configured_board_swarm.step(task) + + assert result == [{"agent_name": "Agent1", "output": "Result"}] + + def test_run_method(self, configured_board_swarm): + """Test the run method.""" + task = "Test run task" + + with patch.object(configured_board_swarm, 'step') as mock_step: + with patch.object(configured_board_swarm, 'conversation') as mock_conversation: + mock_step.return_value = "Step result" + mock_conversation.add = Mock() + + result = configured_board_swarm.run(task) + + assert mock_step.call_count == 2 # max_loops = 2 + assert mock_conversation.add.call_count == 2 + + def test_arun_method(self, configured_board_swarm): + """Test the async run method.""" + task = "Test async run task" + + with patch.object(configured_board_swarm, 'run') as mock_run: + mock_run.return_value = "Async result" + + async def test_async(): + result = await configured_board_swarm.arun(task) + return result + + result = asyncio.run(test_async()) + assert result == "Async result" + mock_run.assert_called_once_with(task=task, img=None) + + +# Integration tests +class TestBoardOfDirectorsSwarmIntegration: + """Integration tests for BoardOfDirectorsSwarm.""" + + def test_full_workflow_integration(self, sample_agents): + """Test full workflow integration.""" + swarm = BoardOfDirectorsSwarm( + agents=sample_agents, + verbose=False, + max_loops=1 + ) + + task = "Create a simple report" + + # Mock the board discussion to return structured output + mock_board_output = """ + { + "plan": "Create a comprehensive report", + "orders": [ + { + "agent_name": "Agent1", + "task": "Research the topic", + "priority": 1, + "assigned_by": "Chairman" + }, + { + "agent_name": "Agent2", + "task": "Write the report", + "priority": 2, + "assigned_by": "Chairman" + } + ], + "decisions": [ + { + "decision_type": "consensus", + "decision": "Proceed with report creation", + "votes_for": 3, + "votes_against": 0, + "abstentions": 0, + "reasoning": "Report is needed for decision making" + } + ], + "meeting_summary": "Board agreed to create a comprehensive report" + } + """ + + with patch.object(swarm.board_members[0].agent, 'run') as mock_run: + mock_run.return_value = mock_board_output + result = swarm.run(task) + + assert result is not None + assert isinstance(result, dict) + + def test_board_member_management_integration(self, sample_agents): + """Test board member management integration.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents) + + # Test adding a new board member + new_member = BoardMember( + agent=sample_agents[0], + role=BoardMemberRole.MEMBER, + voting_weight=1.0, + expertise_areas=["testing"] + ) + + initial_count = len(swarm.board_members) + swarm.add_board_member(new_member) + assert len(swarm.board_members) == initial_count + 1 + + # Test removing a board member + member_name = swarm.board_members[0].agent.agent_name + swarm.remove_board_member(member_name) + assert len(swarm.board_members) == initial_count + + # Test getting board member + member = swarm.get_board_member(swarm.board_members[0].agent.agent_name) + assert member is not None + + +# Parameterized tests +@pytest.mark.parametrize("max_loops", [1, 2, 3]) +def test_max_loops_parameterization(sample_agents, max_loops): + """Test swarm with different max_loops values.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, max_loops=max_loops) + assert swarm.max_loops == max_loops + + +@pytest.mark.parametrize("decision_threshold", [0.5, 0.6, 0.7, 0.8, 0.9]) +def test_decision_threshold_parameterization(sample_agents, decision_threshold): + """Test swarm with different decision threshold values.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, decision_threshold=decision_threshold) + assert swarm.decision_threshold == decision_threshold + + +@pytest.mark.parametrize("board_model", ["gpt-4o-mini", "gpt-4", "claude-3-sonnet"]) +def test_board_model_parameterization(sample_agents, board_model): + """Test swarm with different board models.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, board_model_name=board_model) + assert swarm.board_model_name == board_model + + +# Error handling tests +class TestBoardOfDirectorsSwarmErrorHandling: + """Test error handling in BoardOfDirectorsSwarm.""" + + def test_initialization_error_handling(self): + """Test error handling during initialization.""" + with pytest.raises(ValueError): + BoardOfDirectorsSwarm(agents=[]) + + def test_board_meeting_error_handling(self, configured_board_swarm): + """Test error handling during board meeting.""" + with patch.object(configured_board_swarm, '_conduct_board_discussion') as mock_discuss: + mock_discuss.side_effect = Exception("Board meeting failed") + + with pytest.raises(Exception, match="Board meeting failed"): + configured_board_swarm.run_board_meeting("Test task") + + def test_task_execution_error_handling(self, configured_board_swarm): + """Test error handling during task execution.""" + with patch.object(configured_board_swarm, '_call_single_agent') as mock_call: + mock_call.side_effect = Exception("Task execution failed") + + with pytest.raises(Exception, match="Task execution failed"): + configured_board_swarm._call_single_agent("Agent1", "Test task") + + def test_order_execution_error_handling(self, configured_board_swarm): + """Test error handling during order execution.""" + orders = [BoardOrder(agent_name="Agent1", task="Task 1")] + + with patch.object(configured_board_swarm, '_execute_single_order') as mock_execute: + mock_execute.side_effect = Exception("Order execution failed") + + # Should not raise exception, but log error + results = configured_board_swarm._execute_orders(orders) + assert len(results) == 1 + assert "Error" in results[0]["output"] + + +# Performance tests +class TestBoardOfDirectorsSwarmPerformance: + """Test performance characteristics of BoardOfDirectorsSwarm.""" + + def test_parallel_execution_performance(self, sample_agents): + """Test parallel execution performance.""" + import time + + swarm = BoardOfDirectorsSwarm( + agents=sample_agents, + max_workers=3, + verbose=False + ) + + # Create multiple orders + orders = [ + BoardOrder(agent_name=f"Agent{i+1}", task=f"Task {i+1}") + for i in range(3) + ] + + start_time = time.time() + + with patch.object(swarm, '_execute_single_order') as mock_execute: + mock_execute.side_effect = lambda order: f"Result for {order.task}" + results = swarm._execute_orders(orders) + + end_time = time.time() + execution_time = end_time - start_time + + assert len(results) == 3 + assert execution_time < 1.0 # Should complete quickly with parallel execution + + def test_memory_usage(self, sample_agents): + """Test memory usage characteristics.""" + import psutil + import os + + process = psutil.Process(os.getpid()) + initial_memory = process.memory_info().rss + + # Create multiple swarms + swarms = [] + for i in range(5): + swarm = BoardOfDirectorsSwarm( + agents=sample_agents, + name=f"Swarm{i}", + verbose=False + ) + swarms.append(swarm) + + final_memory = process.memory_info().rss + memory_increase = final_memory - initial_memory + + # Memory increase should be reasonable (less than 100MB) + assert memory_increase < 100 * 1024 * 1024 + + +# Configuration tests +class TestBoardOfDirectorsSwarmConfiguration: + """Test configuration options for BoardOfDirectorsSwarm.""" + + def test_verbose_configuration(self, sample_agents): + """Test verbose configuration.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, verbose=True) + assert swarm.verbose is True + + swarm = BoardOfDirectorsSwarm(agents=sample_agents, verbose=False) + assert swarm.verbose is False + + def test_collaboration_prompt_configuration(self, sample_agents): + """Test collaboration prompt configuration.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, add_collaboration_prompt=True) + assert swarm.add_collaboration_prompt is True + + swarm = BoardOfDirectorsSwarm(agents=sample_agents, add_collaboration_prompt=False) + assert swarm.add_collaboration_prompt is False + + def test_board_feedback_configuration(self, sample_agents): + """Test board feedback configuration.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, board_feedback_on=True) + assert swarm.board_feedback_on is True + + swarm = BoardOfDirectorsSwarm(agents=sample_agents, board_feedback_on=False) + assert swarm.board_feedback_on is False + + def test_voting_configuration(self, sample_agents): + """Test voting configuration.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, enable_voting=True) + assert swarm.enable_voting is True + + swarm = BoardOfDirectorsSwarm(agents=sample_agents, enable_voting=False) + assert swarm.enable_voting is False + + def test_consensus_configuration(self, sample_agents): + """Test consensus configuration.""" + swarm = BoardOfDirectorsSwarm(agents=sample_agents, enable_consensus=True) + assert swarm.enable_consensus is True + + swarm = BoardOfDirectorsSwarm(agents=sample_agents, enable_consensus=False) + assert swarm.enable_consensus is False + + +# Real integration tests (skipped if no API key) +@pytest.mark.skipif( + not os.getenv("OPENAI_API_KEY"), + reason="OpenAI API key not available" +) +class TestBoardOfDirectorsSwarmRealIntegration: + """Real integration tests for BoardOfDirectorsSwarm.""" + + def test_real_board_meeting(self): + """Test real board meeting with actual API calls.""" + # Create real agents + agents = [ + Agent( + agent_name="Researcher", + agent_description="Research analyst", + model_name="gpt-4o-mini", + max_loops=1 + ), + Agent( + agent_name="Writer", + agent_description="Content writer", + model_name="gpt-4o-mini", + max_loops=1 + ) + ] + + swarm = BoardOfDirectorsSwarm( + agents=agents, + verbose=False, + max_loops=1 + ) + + task = "Create a brief market analysis report" + + result = swarm.run(task) + + assert result is not None + assert isinstance(result, dict) + assert "conversation_history" in result + + def test_real_board_member_management(self): + """Test real board member management.""" + agents = [ + Agent( + agent_name="TestAgent", + agent_description="Test agent", + model_name="gpt-4o-mini", + max_loops=1 + ) + ] + + swarm = BoardOfDirectorsSwarm(agents=agents, verbose=False) + + # Test board summary + summary = swarm.get_board_summary() + assert summary["total_members"] == 3 # Default board + assert summary["total_agents"] == 1 + + +# Test runner +if __name__ == "__main__": + pytest.main([__file__, "-v", "--tb=short"]) \ No newline at end of file From cf510a7198d5c63874ccffedca581bc7db81a57d Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sun, 27 Jul 2025 12:10:27 +0300 Subject: [PATCH 09/18] Add files via upload --- .../board_of_directors_example.py | 437 ++++++++++++++++++ .../trading_showcase/test_results.log | 7 + 2 files changed, 444 insertions(+) create mode 100644 examples/multi_agent/board_of_directors/board_of_directors_example.py create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/test_results.log diff --git a/examples/multi_agent/board_of_directors/board_of_directors_example.py b/examples/multi_agent/board_of_directors/board_of_directors_example.py new file mode 100644 index 00000000..425d460b --- /dev/null +++ b/examples/multi_agent/board_of_directors/board_of_directors_example.py @@ -0,0 +1,437 @@ +""" +Board of Directors Example + +This example demonstrates how to use the Board of Directors swarm feature +in the Swarms Framework. It shows how to create a board, configure it, +and use it to orchestrate tasks across multiple agents. + +The example includes: +1. Basic Board of Directors setup and usage +2. Custom board member configuration +3. Task execution and feedback +4. Configuration management +""" + +import os +import sys +from typing import List, Optional + +# Add the parent directory to the path to import swarms +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))) + +from swarms.structs.board_of_directors_swarm import ( + BoardOfDirectorsSwarm, + BoardMember, + BoardMemberRole, +) +from swarms.structs.agent import Agent +from swarms.config.board_config import ( + enable_board_feature, + disable_board_feature, + is_board_feature_enabled, + create_default_config_file, + set_board_size, + set_decision_threshold, + set_board_model, + enable_verbose_logging, + disable_verbose_logging, +) + + +def enable_board_directors_feature() -> None: + """ + Enable the Board of Directors feature. + + This function demonstrates how to enable the Board of Directors feature + globally and create a default configuration file. + """ + print("šŸ”§ Enabling Board of Directors feature...") + + try: + # Create a default configuration file + create_default_config_file("swarms_board_config.yaml") + + # Enable the feature + enable_board_feature("swarms_board_config.yaml") + + # Configure some default settings + set_board_size(3) + set_decision_threshold(0.6) + set_board_model("gpt-4o-mini") + enable_verbose_logging("swarms_board_config.yaml") + + print("āœ… Board of Directors feature enabled successfully!") + print("šŸ“ Configuration file created: swarms_board_config.yaml") + + except Exception as e: + print(f"āŒ Failed to enable Board of Directors feature: {e}") + raise + + +def create_custom_board_members() -> List[BoardMember]: + """ + Create custom board members with specific roles and expertise. + + This function demonstrates how to create a custom board with + specialized roles and expertise areas. + + Returns: + List[BoardMember]: List of custom board members + """ + print("šŸ‘„ Creating custom board members...") + + # Create specialized board members + chairman = Agent( + agent_name="Executive_Chairman", + agent_description="Executive Chairman with strategic vision and leadership expertise", + model_name="gpt-4o-mini", + max_loops=1, + system_prompt="""You are the Executive Chairman of the Board. Your role is to: +1. Provide strategic leadership and vision +2. Facilitate high-level decision-making +3. Ensure board effectiveness and governance +4. Represent the organization's interests +5. Guide long-term strategic planning + +You should be visionary, strategic, and focused on organizational success.""", + ) + + cto = Agent( + agent_name="CTO", + agent_description="Chief Technology Officer with deep technical expertise", + model_name="gpt-4o-mini", + max_loops=1, + system_prompt="""You are the Chief Technology Officer. Your role is to: +1. Provide technical leadership and strategy +2. Evaluate technology solutions and architectures +3. Ensure technical feasibility of proposed solutions +4. Guide technology-related decisions +5. Maintain technical standards and best practices + +You should be technically proficient, innovative, and focused on technical excellence.""", + ) + + cfo = Agent( + agent_name="CFO", + agent_description="Chief Financial Officer with financial and risk management expertise", + model_name="gpt-4o-mini", + max_loops=1, + system_prompt="""You are the Chief Financial Officer. Your role is to: +1. Provide financial analysis and insights +2. Evaluate financial implications of decisions +3. Ensure financial sustainability and risk management +4. Guide resource allocation and budgeting +5. Maintain financial controls and compliance + +You should be financially astute, risk-aware, and focused on financial health.""", + ) + + # Create BoardMember objects with roles and expertise + board_members = [ + BoardMember( + agent=chairman, + role=BoardMemberRole.CHAIRMAN, + voting_weight=2.0, + expertise_areas=["strategic_planning", "leadership", "governance", "business_strategy"] + ), + BoardMember( + agent=cto, + role=BoardMemberRole.EXECUTIVE_DIRECTOR, + voting_weight=1.5, + expertise_areas=["technology", "architecture", "innovation", "technical_strategy"] + ), + BoardMember( + agent=cfo, + role=BoardMemberRole.EXECUTIVE_DIRECTOR, + voting_weight=1.5, + expertise_areas=["finance", "risk_management", "budgeting", "financial_analysis"] + ), + ] + + print(f"āœ… Created {len(board_members)} custom board members") + for member in board_members: + print(f" - {member.agent.agent_name} ({member.role.value})") + + return board_members + + +def create_worker_agents() -> List[Agent]: + """ + Create worker agents for the swarm. + + This function creates specialized worker agents that will be + managed by the Board of Directors. + + Returns: + List[Agent]: List of worker agents + """ + print("šŸ› ļø Creating worker agents...") + + # Create specialized worker agents + researcher = Agent( + agent_name="Research_Analyst", + agent_description="Research analyst specializing in market research and data analysis", + model_name="gpt-4o-mini", + max_loops=1, + system_prompt="""You are a Research Analyst. Your responsibilities include: +1. Conducting thorough research on assigned topics +2. Analyzing data and market trends +3. Preparing comprehensive research reports +4. Providing data-driven insights and recommendations +5. Maintaining high standards of research quality + +You should be analytical, thorough, and evidence-based in your work.""", + ) + + developer = Agent( + agent_name="Software_Developer", + agent_description="Software developer with expertise in system design and implementation", + model_name="gpt-4o-mini", + max_loops=1, + system_prompt="""You are a Software Developer. Your responsibilities include: +1. Designing and implementing software solutions +2. Writing clean, maintainable code +3. Conducting code reviews and testing +4. Collaborating with team members +5. Following best practices and coding standards + +You should be technically skilled, detail-oriented, and focused on quality.""", + ) + + marketer = Agent( + agent_name="Marketing_Specialist", + agent_description="Marketing specialist with expertise in digital marketing and brand strategy", + model_name="gpt-4o-mini", + max_loops=1, + system_prompt="""You are a Marketing Specialist. Your responsibilities include: +1. Developing marketing strategies and campaigns +2. Creating compelling content and messaging +3. Analyzing market trends and customer behavior +4. Managing brand presence and reputation +5. Measuring and optimizing marketing performance + +You should be creative, strategic, and customer-focused in your approach.""", + ) + + agents = [researcher, developer, marketer] + + print(f"āœ… Created {len(agents)} worker agents") + for agent in agents: + print(f" - {agent.agent_name}: {agent.agent_description}") + + return agents + + +def run_board_of_directors_example() -> None: + """ + Run a comprehensive Board of Directors example. + + This function demonstrates the complete workflow of using + the Board of Directors swarm to orchestrate tasks. + """ + print("\n" + "="*60) + print("šŸ›ļø BOARD OF DIRECTORS SWARM EXAMPLE") + print("="*60) + + try: + # Check if Board of Directors feature is enabled + if not is_board_feature_enabled(): + print("āš ļø Board of Directors feature is not enabled. Enabling now...") + enable_board_directors_feature() + + # Create custom board members + board_members = create_custom_board_members() + + # Create worker agents + worker_agents = create_worker_agents() + + # Create the Board of Directors swarm + print("\nšŸ›ļø Creating Board of Directors swarm...") + board_swarm = BoardOfDirectorsSwarm( + name="Executive_Board_Swarm", + description="Executive board with specialized roles for strategic decision-making", + board_members=board_members, + agents=worker_agents, + max_loops=2, + verbose=True, + decision_threshold=0.6, + enable_voting=True, + enable_consensus=True, + ) + + print("āœ… Board of Directors swarm created successfully!") + + # Display board summary + summary = board_swarm.get_board_summary() + print(f"\nšŸ“Š Board Summary:") + print(f" Board Name: {summary['board_name']}") + print(f" Total Members: {summary['total_members']}") + print(f" Total Agents: {summary['total_agents']}") + print(f" Max Loops: {summary['max_loops']}") + print(f" Decision Threshold: {summary['decision_threshold']}") + + print(f"\nšŸ‘„ Board Members:") + for member in summary['members']: + print(f" - {member['name']} ({member['role']}) - Weight: {member['voting_weight']}") + print(f" Expertise: {', '.join(member['expertise_areas'])}") + + # Define a complex task for the board to handle + task = """ + Develop a comprehensive strategy for launching a new AI-powered product in the market. + + The task involves: + 1. Market research and competitive analysis + 2. Technical architecture and development planning + 3. Marketing strategy and go-to-market plan + 4. Financial projections and risk assessment + + Please coordinate the efforts of all team members to create a cohesive strategy. + """ + + print(f"\nšŸ“‹ Executing task: {task.strip()[:100]}...") + + # Execute the task using the Board of Directors swarm + result = board_swarm.run(task=task) + + print("\nāœ… Task completed successfully!") + print(f"šŸ“„ Result type: {type(result)}") + + # Display conversation history + if hasattr(result, 'get') and callable(result.get): + conversation_history = result.get('conversation_history', []) + print(f"\nšŸ’¬ Conversation History ({len(conversation_history)} messages):") + for i, message in enumerate(conversation_history[-5:], 1): # Show last 5 messages + role = message.get('role', 'Unknown') + content = message.get('content', '')[:100] + "..." if len(message.get('content', '')) > 100 else message.get('content', '') + print(f" {i}. {role}: {content}") + else: + print(f"\nšŸ“ Result: {str(result)[:200]}...") + + print("\nšŸŽ‰ Board of Directors example completed successfully!") + + except Exception as e: + print(f"āŒ Error in Board of Directors example: {e}") + import traceback + traceback.print_exc() + + +def run_simple_board_example() -> None: + """ + Run a simple Board of Directors example with default settings. + + This function demonstrates a basic usage of the Board of Directors + swarm with minimal configuration. + """ + print("\n" + "="*60) + print("šŸ›ļø SIMPLE BOARD OF DIRECTORS EXAMPLE") + print("="*60) + + try: + # Create simple worker agents + print("šŸ› ļø Creating simple worker agents...") + + analyst = Agent( + agent_name="Data_Analyst", + agent_description="Data analyst for processing and analyzing information", + model_name="gpt-4o-mini", + max_loops=1, + ) + + writer = Agent( + agent_name="Content_Writer", + agent_description="Content writer for creating reports and documentation", + model_name="gpt-4o-mini", + max_loops=1, + ) + + agents = [analyst, writer] + + # Create Board of Directors swarm with default settings + print("šŸ›ļø Creating Board of Directors swarm with default settings...") + board_swarm = BoardOfDirectorsSwarm( + name="Simple_Board_Swarm", + agents=agents, + verbose=True, + ) + + print("āœ… Simple Board of Directors swarm created!") + + # Simple task + task = "Analyze the current market trends and create a summary report with recommendations." + + print(f"\nšŸ“‹ Executing simple task: {task}") + + # Execute the task + result = board_swarm.run(task=task) + + print("\nāœ… Simple task completed successfully!") + print(f"šŸ“„ Result type: {type(result)}") + + if hasattr(result, 'get') and callable(result.get): + conversation_history = result.get('conversation_history', []) + print(f"\nšŸ’¬ Conversation History ({len(conversation_history)} messages):") + for i, message in enumerate(conversation_history[-3:], 1): # Show last 3 messages + role = message.get('role', 'Unknown') + content = message.get('content', '')[:80] + "..." if len(message.get('content', '')) > 80 else message.get('content', '') + print(f" {i}. {role}: {content}") + else: + print(f"\nšŸ“ Result: {str(result)[:150]}...") + + print("\nšŸŽ‰ Simple Board of Directors example completed!") + + except Exception as e: + print(f"āŒ Error in simple Board of Directors example: {e}") + import traceback + traceback.print_exc() + + +def check_environment() -> bool: + """ + Check if the environment is properly set up for the example. + + Returns: + bool: True if environment is ready, False otherwise + """ + # Check for OpenAI API key + if not os.getenv("OPENAI_API_KEY"): + print("āš ļø Warning: OPENAI_API_KEY environment variable not set.") + print(" The example may not work without a valid API key.") + print(" Please set your OpenAI API key: export OPENAI_API_KEY='your-key-here'") + return False + + return True + + +def main() -> None: + """ + Main function to run the Board of Directors examples. + """ + print("šŸš€ Board of Directors Swarm Examples") + print("="*50) + + # Check environment + if not check_environment(): + print("\nāš ļø Environment check failed. Please set up your environment properly.") + return + + try: + # Run simple example first + run_simple_board_example() + + # Run comprehensive example + run_board_of_directors_example() + + print("\n" + "="*60) + print("šŸŽ‰ All Board of Directors examples completed successfully!") + print("="*60) + + except KeyboardInterrupt: + print("\nāš ļø Examples interrupted by user.") + except Exception as e: + print(f"\nāŒ Unexpected error: {e}") + import traceback + traceback.print_exc() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/multi_agent/board_of_directors/trading_showcase/test_results.log b/examples/multi_agent/board_of_directors/trading_showcase/test_results.log new file mode 100644 index 00000000..69749700 --- /dev/null +++ b/examples/multi_agent/board_of_directors/trading_showcase/test_results.log @@ -0,0 +1,7 @@ +2025-07-25 16:33:37 | INFO | __main__:run_all_tests:380 - šŸš€ Starting Comprehensive Test Suite +2025-07-25 16:33:37 | INFO | __main__:test_ollama_installation:67 - šŸ” Testing Ollama Installation +2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: ollama --version +2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: ollama list +2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: ollama list +2025-07-25 16:33:37 | INFO | __main__:test_python_dependencies:86 - šŸ Testing Python Dependencies +2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: C:\Users\arona\scoop\apps\python\current\python.exe -m pip list From eec69739675c6e6901f57602313bda1da5efb9ad Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Sun, 27 Jul 2025 12:11:15 +0300 Subject: [PATCH 10/18] Add files via upload --- .../trading_showcase/agent_workspace/error.txt | 0 .../__pycache__/litellm_config.cpython-313.pyc | Bin 0 -> 8218 bytes .../src/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 223 bytes .../src/__pycache__/board_setup.cpython-313.pyc | Bin 0 -> 15640 bytes .../src/__pycache__/main.cpython-313.pyc | Bin 0 -> 17456 bytes .../src/__pycache__/market_data.cpython-313.pyc | Bin 0 -> 21895 bytes .../__pycache__/trading_agents.cpython-313.pyc | Bin 0 -> 20355 bytes .../trading_analysis.cpython-313.pyc | Bin 0 -> 25034 bytes .../tests/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 301 bytes ...est_market_data.cpython-313-pytest-8.3.5.pyc | Bin 0 -> 42872 bytes ...t_ollama_models.cpython-313-pytest-8.3.5.pyc | Bin 0 -> 29543 bytes ...rading_analysis.cpython-313-pytest-8.3.5.pyc | Bin 0 -> 64869 bytes 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/agent_workspace/error.txt create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__/litellm_config.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/__init__.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/board_setup.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/main.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/market_data.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_agents.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_analysis.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/__init__.cpython-313.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_market_data.cpython-313-pytest-8.3.5.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_ollama_models.cpython-313-pytest-8.3.5.pyc create mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_trading_analysis.cpython-313-pytest-8.3.5.pyc diff --git a/examples/multi_agent/board_of_directors/trading_showcase/agent_workspace/error.txt b/examples/multi_agent/board_of_directors/trading_showcase/agent_workspace/error.txt new file mode 100644 index 00000000..e69de29b diff --git a/examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__/litellm_config.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__/litellm_config.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf77d0ec70679fb6ca15baa950e97ec37c015727 GIT binary patch literal 8218 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 literal 0 HcmV?d00001 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/board_setup.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/board_setup.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..725e1b6948ff3c114f456620d2eda5a1f8864c63 GIT binary patch literal 15640 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 literal 0 HcmV?d00001 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/main.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b43bb05fd0e8192518af3d388a7f3f124562cf0c GIT binary patch literal 17456 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 literal 0 HcmV?d00001 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/market_data.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/market_data.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c2209c2fdd87924b5f032217d0d29b06f7c81e2 GIT binary patch literal 21895 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 LjS(d-k~sb!%Zo6y literal 0 HcmV?d00001 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_analysis.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_analysis.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab50fe302e046b50b5b1a02218aae802ca096b6c GIT binary patch literal 25034 zcmc(H3vgT4b>PDv#D^dN5+FbTe56Q;r1%j(q9j@rP3kX^l*}hcj0qbHk{}5S1eo_g zeOSkFnr#CmJ8R0WD>BWlskT#5Nv5WoorIa$*(gnBtDWiY;2E}ozIwOHG+nQ@yDb$t zn@PJn*>moD4oDo9a(jRE;HOP+@( z)D-n5#ZWB8C>Z5w1*;^#Dpn1@s?(ZNT2^~X$Ldb$S^cRJw&aw7HJmcCMjG?0Pn%Ae zSu^o#PM4l4WlK+4SPKa&PnWS}kVkvkddkMyXewZ?q-rTf=cX9_UZq(7Ua1+ZT}my1 zRKp{wbN5GClnQM)Ka;+Dg)|~4tXH*ztFZa z#>&_j`vDc}4k$;u^J%hgKb`W=18ZGF7db zfSd6gP_ngw%8}#wGO{mFE6*ES2RTm5@%i6CT`tGYz%IZeFR5#%99v2;zD|`K0{q*_ zD4A+CWv5PbQ54%i%Fuy^k&!%1*#~87AmyAK&i_J6Eu@^!$H+crhlOJ5I(7LPhhUW$ zDVmyAPAePh7rt#c$A%^&v1z(L7K&cwA{;#wpPY||>8UtNKQ|wWB_fGXB62BA%Nd!O z_~nTZ7d9Bq%|P~9G5Z`FzZ97abM$97mkG&0r{-f5iAX%g5x5DdP7XYY@N^{1H5=Fn zcaffj0@LBya4gYGhhmfTT%1iz#iNlp9iK}?W+MyGlz6Pwa34E3+^7}QMDnPLcAiqF%Syes7C|Pwt6VNiMU64wAYU0yDoCbZ2 zmemJJ0ytxG~=muHn_e#fGK5*W1#NTvPw*$>fzK&9%>`)%Dp5Cxp1P+PTSB?s)Y?a^eHE zgWVxlQ5=(Fko*)(M*JikJ*y24J#5!tN4+p9Tq&Mcg&9rfGenS+Jj# z7ju6!8lNDOd%qf>E!5>w=uj@H5Odiw$SRcPGX&>g<(ntwSr#TFcqtT}59e@K3~57z z<_rsZi6~uVD*%XyIEWXGX4Z`nRp@xo@uK5H2V2I{=+vOoj1J|l8g#Sfg^R&jF6U1_x|Yp+bJE3-ByP9B+aUoFhr%p!MfHm$Ce=JNx!Q-q2D zi_hZgkn)sSM9L)2BKinDB6C+TizJRvp@41#$GPBxvSem)rURNTr8L`wQjxOqOdF@o zK$naoK+A{1um~r(`?~?wf(K*hSuv_`W`*(`nGaryM*%USk;GNO#La}*xp0us9Kkdj zx)PjZLzgGxmt%tVQiu&6*emEJB#(MLoCpcFi8x>bLWswLvp_K-R|E@3)@Lw$WiHME z3B*i5=U@)SY{+-WBn~&49*+$K2WaSupq!f&N{#?kJ;nl=W05`a32@$Mc9Lkz)UmVUFkPKA1-!d(m((1Zwg==ZY()>~rUr~?izS8@F z+ACrP!rg)yMu@=gVHCvmt(bv)icz^KR>PUuys-TMxR!0@HIck!Obt^C z=yy3&%UFw#Cu0j#Fn0LU1RSuQD#X>)rDw{evQB2l zV_RGyk1^xOL8#0@a7qwdKFSATA5%$cC_bxX4Kpr);wE#4ZOKEbk|2RNOkhYUAkM-( zGiKWTj<#$K}sAFBs)peL=jIG9_R>iS!BaxUA9h0 zn=~>FfX_q@dq{)lO==J2r=lbQ9TLjro>nv}7j~VDMG}!vG_nw;6EpB937ol_MZu(X z7(_vX)B=z~1tU@elv=`34#Yt<7miMG2%2V*x}$It0mvYdR2KBNRZhWOBWDHYRqCGG zlT`mJOSa0JRKKsUB&$|XqeLcX*)Ygsu?g&${OQ1hZZ?{A~dZ4*1KYv@$Y(#oB4zMh&*jPyniJQw{bleb5yQ0|aF} zh$;Qbk&;K#{Ys|1=U)OQmCHJqqIg#Ev{{L%o&X=PI}g99I3_>62K8uH3$V7BhH=0@ zr(c6w6O55YyK>7|6k9FZ!E@I(p~y^j(~#!IS_`w}!ddcb88_-fu%!@JCBfdBCgO@m zN~La1Q}LSgDgzaZ9Cw5EEgCej}$L&gPj z#!AL=V($oU%L=|)oB_F%NR=xJvOrMoGeVR#E-}M4Ad_~;qcpNz$i_{OaW7o(L7O-C zs%VbUZ^)}({*9UZrYB&^lR3^#X?%A*b|$y85*s!{fl+BdXc9&@V%nyD{m|I1wM9{O(_;yr?$@ zD9s|2I;yc{;cJIO(TRE3?}X`z`0N}To(ab|)YT=z6Em^ML?}u}Vw3QT3W`>Pp`V@R zdJHstD1`LTXHmr?ZpSW15;OFf6N87(1E}cyY>XrM3?oENkxI=?w&r#|Jv4f0Qm$Ba z20?Qe)JEa^(0K|~YnP!Z@ymji8R`$V@41gE95K+b=YB^nuy@b>yBN@6wvIh}?wiEo zYHltB`@W-CxZ^(V+QmRex1b*CKYZjq@;JeW-k_)t6G}ZL z=pdsIR3pqup=4knI24(jjE3)H9zhRb|J+=dCBDJ zZHnknn6UFlwqW_+!@uXU|IFkf>xsZN=_yxs>;trd$GuA4JuwR~A^x~wj#0hQzp<8|ZG(Utz?lPjN1mo;WA z9lWJuy*6d(NLhL_mI2-}khUC2soA)%YCe}{zZGF6_?@rfUBY*fDUv*9{TD@cC z`10rE9Myeyj@)(gN6w`#jHLoo{Do=$$TaVpf!sLM&=0$FasK-5jIExx)vu1EZ1pMI zo{X)Fw{@j$-AP^6?p)GdKbW!a;_bUu*_3@(%HEN&ck}k{w0(b4pLKgz%2%dude@wM z&3@i}V11PDJ;S@tLJfdYSwOq1%WWBVJMV5^x2D|fMbQq>Vs!1oJ7&JVm-imJ)4&g$ zXMHe#i2W&Y-F-rkbbe^}wXasKu5OGj25%Y&<3Yr5OLncau@-G|b< zpXEKzrYriBh7ZdfH;%o2Y^iHSv;53z`Rep-Z>I4e-*_V~ zZs)7p)7716XV+R{{lq)3@Xn(d#}MxrN;}Tv>VwJGE%$Ej>^hs?J-}BD+4)M-IcdWc~;LZf^I4Q!sXR#-ZqRtNGm5I$l z6v{Rje)tmbqc^EG3O7`Y0*}HcLEQ{~CHg}&_*KOOGe1>K4d7SEB8dD;BdpDERZoSB zZ7cY;0ayK0xJAUWZNSw$6>hO@Zn1Gtf$*eV;E#u6VNe3+wL{{O7)Ou8>E{b2^>WTn@N1g*_GpfJ!)5 zBhwLtn(;(BDCH9x3R(Z-a()p2a<{-COy6FS)ZH`M7Z=jT8lZaabp10~ll`^fYr{)j znW_%Hs$;DyUA6x`(}8@hRC|BAzJF7;{e0E__40Jpq4!LE`E1(*wpN+0Kd=eb9=>YN z8o=s)&$REJ#gQx}Bw>pR5S0sr8sM5H)Id3wQ)uMZ2&`k+q=rCP^(*UOYcYaiYr)45 z4R1^}mRrTJc~CLxy$Bz^nA)#mG?>U}3A8h?vC6GXznal8ddN{iau{%XlnWU##F)lF zO(}jODB~A=c>|u2C#V+~GgEp%AJc#msfZH6ugO!dGZ%90we#6XW=z@N7W)yd5PHMjv;;>0>2H?E!R%V zG@FHCqwd2V@fU&`ts?}TfB5w9nG3`0iD6zm2|+ z#OS~4TX4WmmX0Hpk4GnA4-Z=>vO_iHNIKB}+j?@0&f@t53zJ5PHWfw8DefP`n$^tF z!NG+}8T5F3etIU62hIW(P%I!d#XgS?lA(_}$@kZNAN@x8A0PkG!bab;A@c`wy@tPs zHsX$)9-oITEH^_>uwYe!Ef&nVHqM47Cgp755S+$r%63~XsG?!mlSaUNK+u7W3L1Kd z<`hVP1XT>Spd}G54z^2h`YUKdu!)aN-qvnnK}(oXiz*Y~aKxlQD@_GRTZA1+42cCA zLkYEoyysC4`EMW}cMqsEa2*?kT<6Ee(q!T*2Nv0{9Ln0=$>Dp}iW{!$uBDFa-lXx=rdqM>JFgvDI=0dayR)>heQhe$JH&Snr=A;0caO+5{tDe` zc(glMqlYSUCQCP}sM7MqW7l3>np$~*_jRVto$K0E-x+@Y*%Wgwz5kqC@sqn+bR3IU z{4{p`5@7zP%&rF?VH`Pj4TP2$`I9+RM=)6oI6RmX~;mskC>gk+RpWg}q zKSQzopPG$rt$hnKW4{IjkwvP={#$e=!TIQ`%lLh_k6nS#w8*`F+{Xqn!#HLLy!NL* zZ3qC5a1MwX&M-?4pnZVM(gbV4K4g5H{lh%4|JBF-5dsTg)X2K;xBm9IjlKm}5nv({ zBW#ofnU`XJ9~`NHKLQ>lD#gdcpuVK{?rE6}U8PYwYb&Upn+>sF$KvmR!xb`*HzD%T zjmzV#d!l;TPZ zWQaG{t}tnHgA5wT>f=D~-6rT9``C4@Z|VHX3EtbXrslm}X=9gMi`)TB+Xe${d9?jd z$6SXaknLs%@QPrkXs_+p9q05G3M>AOK9LNf*iNVuA%QHaDcGCnAPszk z>dBfF!6^HJ61^kjQlxcAxE3l4NF2$JMv_mUPQMEUi-@+ls$}I)HLMPf`nBkixV}&E z-nO){ZPU_zM82)!-LTAylBS(Sm-ZH6@c6YL$kZ>Pde_`8S5r*<6RRmI8fSsKe0z9JrT z{`2g=#k%vmZ;+y?LV+a)antaJ-?Kzc5Y%U2BPlN2??NoQiq3bySt!S|Us_ap(((cl zERq&fjv$iC6BgtR042z3VcCSTwNRHjh|3YH{?&Jytvo1052ua0R*$XiyM1PT>dyJ^ z#?sA$@{*C6Zt0uluL&J4{A7cSF~}o+BWl@~|AnhpIn6)fI-IH~MsnKCd_EZ(qaeA|j1qK_Dn>=t z8RQ>5N{lyDXvlE}^rtbfr}ryb06;OLIvH9_=huxuiNa4#f09NtrXRgR>eOSMu@Zkt zG0mt93CxS~m~9L%c#zMp@@xGDztL~a+ zA>FU&p)nvgijI%J1lJu5_x~^SQBuJDP9M?Bu`fW>eVq4?NdKvgzD8v}MJ9MuV+q?1 z8Q2bVI??Gu2PcE=MrR*7`_VxY??wxI8T||3fKkb3*#yg>R|l3Qa3>J%O2EYn*vG+v z4to_dUcpoY7}ww(j7T)hegh*^6Y)!e3NCZ7J(%ekblSjaw2QjCA7I1}!4V8VTEReu zToEx!domnpp%iB)IK_s^m60&%09^K%hihAq{}RMXRLIEA$6|QEL~K{&J0->XiWlRc zO_2~>7!hpw>67CM#)89zf+t!9pLoFK$Xl$CmP)r_gq?*d#^U*Ak@%kh2Z+Cea(Hiy zT_1bng+Cm*b>a6ftTKNP;49kkG~Ih6dOi9^Y=z?;O-Zz$aQl*_*<+{}`$25U$X9l) z8{Tyeq@Ev3njp2BUfH#LG2`vvy&Y+9S4!{BIvO&L4&Kp`c68;>;*HtzoqT!Mx{84Nz=z#%2s~E`?`1OGBNcaDowk4QG z9qc`f9^TmSO(xYokZw8rL+eYJsQ{eY9RPyi#uDh zJL{^)|8`flyb7#DveoTb&u(xZ*bQZd4a!hr5Uuh}5^@BIb-r1;0x3qa@4~cBY-TdJ z+b4_)F%m8HpTwwS)&jYtqc~<>?`_+>`v*CNRbDu+NzZlq``rUwS4uY)`^{Ka%rRHG`i15gX^&cY?z@TPmW`TKTo zLJfP>lyM%aOIUJgp5!+*6|07HY`=7vplWnAQ?0-Rr5HX$9d?29%7%8Chm*^k{31vVD zfjEaJbCk%MCol4KHGM27c3jYqUqL4|ghT6w9AObjiVc|rPFOH^gYMC7-J^MKAt^yA z7f4AZ{c`dbj&j+IAY;RsYhC75#GSyY>dY`&3ewvYp;A5Pkj6e`2KUg9@S~`@X@_?^Uzp z7{-EkY2cPla3VAZx6Gqk))=1XkTv!JxUj}lcwimV03+9ek&JHBu{fBuz*`c^1Ay_z z6(@cRgeJXTU-U>^G>Qb0&8 zcIaNTmyfAS1tL^YI`rhR@*5dlt5zN@ni~3V6g6}YT2y@A^e9?RLa&B?Lh=;pwO@-e z!zAF!am5gfUGZL{_!Bey%JX3w4YZhXK8iyx`6NbE|0|BDY3qo>C?rK{@7I7JuN}c7 z--1u(J-{j8^7A~5@7(_!6<|JX1sNeI8G;Z6CaxAT4(1^^pGJ-{n$B;NVwSNAxx7F3 z@^|W3x&aPX?$`9Rjmi{@_dv#1Rk*vkK`N))2q~4|94LR$!Q|e zfXTh;V)!b%0tup+|84Z00H;waKAV91MRqqh@G1n{wTAnT8u8Hw4Y@xrDjD%K2MYWR zW;0GjU`LX>YY#6pL?vD(7-I9Y#BvLuXyFhFo&pg{;KnsELf{&WPz7v_!jq!u0n#Nn z%#Tlyh6pM+%NGq3)-XX6NrY!P_M6}*jJ45PaDXqi#*$-tQj63RA#R5KDHi(}oo^wq zQn?XgCid?zQaure2SfC*L751LCpq>3W+%e|1cqWCf7b5&5q5ky#OHo;q>g z!)f||;1I4`)s(bkEk2Nk%N@y*tks^>0*7^amoD&4eeXM-O&-fyDl(QD-cqyTPg|P6 z&^YvsEB9*ZS5-INi=`jBJWDUWJ#%|z?NVmnaem+NyUx_UvwZ7wy!W}ZYh+P-&+c04 zf1@W`Rdega%@eEVGcCP*OYi#SRLe2G?l@m{eDO%Oyz=@W{Iury-Wc<-}WFE*{(_A^RnwLjQPIr|kGClr*k zDrwC6cD)r}j(^~5yEY6HU~;Y;xpng9$<^_jLu(46w^TFirL%d3BDe3fJjvM`Smi}2i=yYm?q3$BIf|X z0Mr4E`4Tpu;O=%tWLHk$^G#ONsWN31YO4Zx(a2FA{mGZlE1 zxK$1L$n{~y)kZPy=U_!JRnNiY+Ex{$h*xgaxs9>`Hp;$*f6Up9hYD`pb+ud$hcD*j zn7L>Oo~qik6W+AwVIvGXPgL-+SJ9MPOcJl+;mccir3J*a*cYyB%5JR z!h=hMh_OlqP%;xfs1=-vvylZbH@Cp^Nby-PDhE;r-Q_kv_LA2v2&OG6u~KQIz)C$D zk6$E*rN4^E#r_XK1rWM$3A6XX*(7wae+yw@Um@F;JC(CSC$sp7%(V-IWm)EG|IWcb zIY?x#bD&ZE-v|~?JkSy|Jj|Yi;57WfSN?3HWPXV@2^O^Ks)dS^u>>qJ*m{slAQLm>dg4OG@o;<&o}7b+#6SxK*CO!N z1h-&68e&mt%;8y|q<;n=W&I~X!;cSu(bH`Fa$;to^gO;qMYGcLWeZ+XO^jea0GtF( zG#KJe;iX&v+^7<)XyF7)A;_UZ9IsypB_Oy5aYb-~IX;K0ejYU?VU9IGCqO5T$`SUD z(Rmx4pQG~?be7S110BS9P{>1BQLx4RU!k=xLANWIK;&)}Tm>ac`bL{5a4T?jP&|=W zwsbQC*MwjsZ6>eGabgumvC49kX@Ynyc+>SwQQxEB1gCgGH22(`e91$S)wdE0p)5hR z7@O$?2eT3mPQlAwaaK@4e!+rLe=whi!=B6Xdj40G+$)N%Z=rr$c&|kyF9qjS>SGV( zt$%CqtAoEcobhylhAi#r&Q`Z(ea%@aJ13@s`g6C=>h@Mvn%6i z;XN%Mc-pQFf{3|eS7ygCe#fypiS&-al!?wd+!;qF@90c*ok+v|vEv|wW=uZb1h+~* zFztGvqr7__n5ed%bnV%%UtG0*FYw*K-NSGb@K*cniz$6|s`hMFU!Bp{@$kQ~?{0Yt zy~7}rI$KvKR@tJ;7np1mV^I6H7Ob?iJpa3MLEa<%cMJ!|&0(RaLQQy)Mp?*tuXT|>6M zA?v}xe^8=nfazLUsUn4HH%7N$IP8{*$1B+VPx% zLv_^m`|QVh)PL&Gg3Ef4)aa++bPG-Tx14d~J{?KSdB_@RL z5=iebApyZlZ#YC-L?kIg5HsZO$&u`E67{9nsfwZbHOPip$%>E1L3vf#<+(1WyteXr^g+TMO;E)If z5r=3F`ZS6C0C7ke=it^|=wcXNgyaNu91KPT^-COxKs?exZuws2%1d~VA4v%EHfJAE&s(O`rSW1=HvUy^|4*S>WN5qGCJNEg{NPJ}Fw-pd||JeZxi~zpAg&euj`}pVh4kIAg8cHX{g!PdD zMmdAUy^zQWe+PYUqVv1x+yDpOoFFIiEUp%E#>{5XSA!0&O!lwQ!A%7F3v_m3L%Y$b z#h?qF9q81d(HkY*`H$MM%Ph=#<{}Ydimzd8x;E2)$1?t z`%iyN0vp5119>3eU7x(u%O85~V+#BmmlV76Wx<;(3jU4f71fY9aw~8Xst51dryqVm=k~HP&2}7opgE(^c-G3-Ce}N? zcksIhQ{Bh;_7fXm#G~pyyD;%?`ineY34N+LGKm8F^ktCMS; z>#DW=w__U=1n;WIPwMQspJ7nM0z?3O7j71w%LoP+3>|wqx?1+M!+*)&-qF(8E+~$G zsHcGkYFT)w81LGu;aKvs_feQ9GO@HrxYtKEJJX`Q{9p93`vIdOum0{5)u>_bVCE@w z!swhpCkhVGGz}7}D+`9>(k0qSdZ8>wZ6!51I|F$alr8jvvWH$MrQx(ye)Si^s@9Gv zLDAUQOrAd#G@#Fgw`v!lh@eFSju1x{94L3M&Y>{}St?|?k)=XblMY*?$0A0gtmLs} z5L!`BB#Nv^9@uv15_xHPo}DKYQCzS)F%4}##5IMA5J4~ByA})pPFa^b@jO~mCTQV7!FP0(*){blG7 zd6{e+x2||We^7ip@DTePfPnvC{SP#DL#0qC9w;>mHIP|_{Vyr|Ur{|7s^`B_HGf4l z{3T`l8_ES@n9}$&Wr@PML4os71;GsxtRx9~Mdbzsj+B5w2T3p}d|<4g@JR{a`M~X2p@yDx)o@B(30<@}Go@{OXb%7 literal 0 HcmV?d00001 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/__init__.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..589fde012ef6b421397518b9b87da5fc551498cb GIT binary patch literal 301 zcmXw#F;2rk5JkNqg2++|Zm?~d8~_kSa1Dh+H_~YFj_nopuC=o!Kn2`^LvSUxTmaz< zuqMfG=KpEt{TY|bG>JNY|ERM#zo&4NIGAw}&1aG)KB>fN_IjCaiG%D^@u(`2rSme> zBsWfZEnO)y6jjd!}yIrA}*6Hm^3}=Yi6^LKSI9(XtZZ6=S$ulVLtb#jB znKw@anJfC1Y+%TD%D236Io^2qAuFGcot`823iu3c-U;@aYRw<=0GN%!x&ww|;pd6IC_E;}Sz;*_1FM3hBx&X@DyY(3>VSs)jj zbjxlHu23$7eA}s_lOEY~(kpvOzWr43$r8Cl63&ag+t?uVbFW{Iv)Fm3Dda9zuAd(Q z*{DOX*!l7fxL!Phj-a!{O5-e#j8r^Tak5gbJXs}IovfCtC80vtEClnbgrKV_3tk&*cLWtZ#ha9oi_lhKKhm^2QsiZnhPlSXNU zC{~Ck#$!Wr1nWqVL{#cJb3z(4HWF~XhlAiGrGCnZu zx2TShGuJT6C~@x)MgA`!nBla-k2 z!CWOaFrJjdvGGA=z3_< zC{aE&^&w&j9lWiCURI|wTWSn7tbCcgW-Sszo^I`lY=G z>n5c9WF-bhB8nmnCgq$d&YjKy4ZFxN91!C5z5nkZcthwXnHcnHc*HX>&u&c7_$oEn zJ#47hFR}!m6}YQ|)(#uZ4+$f@pC%z_d)5LuI8Jg5+5L`GbuczQF(!@1#)p$pa=Ed{ zz%W6ufQ-$nj)7!iFh2Ca9T|&n9=}t~ zODd`j5NTMoeKr|SsLp6yPDDmysu&Ir#z$h|uv*9(A{nY1kvXhf9=(tpQEpjOn-Uut zRB&b`b@K4O^C1QB>U>0o8{zyjiCDJ`h<3g^IWRFAON=Y$gO?)msB$P7g{<=mNt}

(|J;>bMYo%EUbW$D{T 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 literal 0 HcmV?d00001 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_ollama_models.cpython-313-pytest-8.3.5.pyc b/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_ollama_models.cpython-313-pytest-8.3.5.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62f6bfdf1156772005a0228bdd97292968c27a77 GIT binary patch literal 29543 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 Date: Mon, 28 Jul 2025 12:10:22 +0300 Subject: [PATCH 11/18] Delete examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__ directory --- .../__pycache__/litellm_config.cpython-313.pyc | Bin 8218 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__/litellm_config.cpython-313.pyc diff --git a/examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__/litellm_config.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/config/__pycache__/litellm_config.cpython-313.pyc deleted file mode 100644 index bf77d0ec70679fb6ca15baa950e97ec37c015727..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8218 zcmbVRYit`=cD_S$$kC7@C6SUvQ5MIt<3x@g*2{@$Ted9Aaw1!HJl4jES+FB&NHL~{ z+!@jj{xZ@Qt2K5JZ_!}gc8hg^0(Jfr{#O?*P&=CdMqeOfC1R&3s@)A1Fi@a$Y%Egc zPtUnCLsAO033>_Md*{x%=f2K8=X__LH8=AF(r@4UgQXh-g!~#GtVG|y!?Uj-d!L9z zB_bo*W*L>CrA@U#X`i*f?ob`Cvnu<#Q*{bR1qxMcZC7szhpncm7@?wvIDKlR%O-+R|3vlC<>&3Xk~HshoWJ z^ci6)qa;$vyej2V8AV8BRN-7k%_TDFR7N8w>?Lc0 z#VD5%vT7zPtLf{4D#tTPB~_3GNm&%~8kFg@AYGACX=x!X^Jmj(X<0&Ma$2K<=9Xk3 zTOBx4H?Xjfk<>*YlMohDz&DpsH9=d-T#ZYbJjg%6rOx%)b;pTRJg3_ymFv3WbV|$h zF}gFINhW1gcdBwOuPSkKqiE3#xgGw`DmE$z^!P=)=oqxa;WUo~CYPAwX zuxp<2l2Kbt?9R*(;wA#=A!1K$CTW+|>r#tV8)E9-gGd|cTSpAn#u9hcaj-5t5!t#{ z_jl&oTjQJDxrkIaK?^K}A3-ujR9-2)<1#)KtL63mK|T zhEhsg&gRC4=+o%n@IX8*qD9c$*mM;%n8Ho%Z zSQx-D2jWXoZs7Z)vDw&}jU8JF)#1qS;P}E50{1FKjuEoaRX@T=%QXtlExQ2WC4k z3u4xVSqQUk%<#UeZJ7Bn3qaOq-`c=fTa9v)M~1)p*&hk#%Qz9K?iz*m2E z=YQ_MC!7Qu18=|@sV1E%g#}wgm^+!r(UHqky(re~*MMeSIFCg~J5FahZaod#!oLsF1!zA zV5oK1RY_Igy6A4WYq2Y`x{v{R?ZAzSSr?2--U3`Uy+zB% zUIfE!N^qY;Z#K@>7+<4Dr8|u!>5QzQ`4AxKKbVR{=QUZ?qLP|Xr07{iKB16oz$bwAA42Y+o0OyCVt=^&xw%zE%xxqGY}+Wpk! z2zx6$**943>M8f^e(L8(_(~@U4X+1>wk6p`NlpNp%sAD zNnWHRhu4FVZAtnm$-sK>4u;VU*@(;Lhe9{-xB_Y+U=dZ6p};ZoqG^7x_R;Wta;7t4G5??y{|BjtVj zi^G$peaB&AU+$>bo!xC;+PP-$^8jh~zc+hxw%E1*Ue`TOvGd4ho{6U+5+1AUW!cvl z*!v&3R=LpUdm_c%hp;Mq&UxQ+-*guPBdgpfoKdLz4`)^#JK&&b`Gtf3!R))U#g>^* z9jCr}9wsfpXM}-Se(q^|Z|>$?ap#fy@7#|*YI`*KXtWqQyXHCfiRawc6+6;={k(;E z+JPR1#&Ntiy~W_vgUJV@#T_$i+^G_G3Mt|3hK3UKaOCKTfbGKr!_yr3D8Ns%>_A=9nZoa6hUJ9=JK^emHB+(>5Gk^UlpKAGjZ!;+%9QIisw(H+@ZoulXr3_o$l$ z%T5{w-}DVkot@V}J5V{Uf5NZM}e2 znD(o+Rgc49VjYfJeHu}z z=qKu~ymDE|TvZCLGl+sBLc!B7oG@`1JlO|F5;~(5c1^1)SdEmj+49i!;QoP81C?!0 zf-0w$f?bps@=5gt7^Ban4nv`iU^a@`7-ndCb#BodN*#np4W$h?6_PrHM2ISB_CCIj zLk60&$Hh*R+e1Hn`zLSTaor6*ZXaFY%l=Tw|I!Ng1>7OeP0y{Xw+pw^cl+;Mdtkq( zJeVxDpZt`Y`RWUI0I%8v-ZY>p?s)Zn>wSB%{qP!hq{JPeH*I1=L&xFWu~*37@{@b) z51HU(*#0ogLY+=JUJrJv0Pbhd2ar760|aUa-T)podUDmh;{f2*D7j7je%Dh|m68Vl z#>_K~0N6a)Ppmt+hxEA%f6ULwxvGy*L)wy{W#xD(k%}9lwn@HgPNpHA=x$m9R})PB zJjJ%=oj?o>dPY*O<7hc4g)V}5mn<7;pm`O6jEXo&McbH6(Da+5$$$M9O#gip{9F!w z;8Y6|HN1_O@mf6wZ~q4VS`jjkyiO7vF7F7Vi4OIY+dH4SonWO~zS#AT^{{7~%=8xw}j5?%QwQZF}tQFFN|4!I}tO zscJ%iO_hBMY>OexvqT}HeTWPZ5NyYwLt&^1K&mYX1zB_*v?;cETO;Kxax`>w6>w(L zJR|Y|TLI;t$1A@jp&N@yvCrGjHyX)3R26JL`JO|w4H3--aR%U(IU#y*8Ru+g00X!I zFDb0zfY~>{!6?poCs2VN0uwcT2&g1*=3y>g>~X$|^5MZu^L0r13u+aQ!219(#h1M~X&pmkr&ll7w$aSYN zi0(jj*T)rlemAHuG;c!81>xJEa-pS4VPfQhpR(8ti3^?EVc|kk6$BSJ3;n7mVD9QP zWQASku}q$O4R#gdj^K`f`;g0PaDEVt5Y&@McWO#fluY$ZYX>?goRKcef(8oKI%0^s zs(FR#aya@e@e9jCz;i@xZ;oG+m59*Sq;sZ^qEVd;sFBVH)a|0IJKoU%Q92W8uF3>*Xd6uNS0NToehYtX8hnBq@DvMmxG~l zYx~nC*5|x2Q}OO*PciHM&`%HluNLRuTs?I0armuI4qd$W!kxrlHJ1)u zEPA?&;kUkYHif+_XPaugu(<`NY#*@luNa z{qi6Y-e$h43=&UZ&D~RS_pG@GOYT8*trAQ*B(Jz`xjx}KD;%YN?lKY1DW<%0;vcjJ z!+(F}{!%eCgJhp_o$Kzl8*^V*Tny~chIRn9^T(4-$0x|c4)5`Uj)!|Dp#I^WHp~yQ zm`{XHu=ZaFO_=w!o*?#*2n+Q%^sFY-(r7xK-G`Gw+;XY<>b!|lstr(q04ZZBLLag)GBspEzcxFrEM zm(^=Cx4M3fSH?lVrf<&TQZ@W+trAvV9d(;s;%mE)#O}I^Rkdi0EjU;8ZPiv z3BKeQfvH43-4CI=G<+$_zyRvilqU0ege#Sw|H)qq)v2I@tDj8cZ&lQk zr4UisR`rmng-=qQo$p0TBYY@kz{@rin6RZsH2^tjnM9Kin4$j9BiO2s0&ZDuEeu#& zbo%-QV|18jEpl1ySlxL zT3GeO@s$}X3Ku6Yl!oVv`@dK0d~?-v5k_lzVU^p9fRhG?W>&dVWuM=`m^Nc>6k{H| zzw5rg*nVV{oA}%p_`1Tv%MC3It9Wy3WO7 z%K)BYvHS}_U4N#qxpkjQsqbWj91Kc0MoT;!P#SI$03!6g=lTM=D;8VK#A7ktmeEv{ zLfx6Wj^9dDRH3Q^Gt?jSQ)XVx8xlZI`#d(YiF8KF8DRYw5~E$z9SfOEnjRZ21RW_D z!DR}a&Suq=lKX(Dlh^^lzRn#6iHFa+6KWD3;i!rB&yYd*i(#HRSjGYNmEr$`c>jy^ zmPqe^lHhaal#O|fshoCnFcW1@%Ps${_^r+#&Q Date: Mon, 28 Jul 2025 12:10:30 +0300 Subject: [PATCH 12/18] Delete examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__ directory --- .../src/__pycache__/__init__.cpython-313.pyc | Bin 223 -> 0 bytes .../src/__pycache__/board_setup.cpython-313.pyc | Bin 15640 -> 0 bytes .../src/__pycache__/main.cpython-313.pyc | Bin 17456 -> 0 bytes .../src/__pycache__/market_data.cpython-313.pyc | Bin 21895 -> 0 bytes .../__pycache__/trading_agents.cpython-313.pyc | Bin 20355 -> 0 bytes .../trading_analysis.cpython-313.pyc | Bin 25034 -> 0 bytes 6 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/__init__.cpython-313.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/board_setup.cpython-313.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/main.cpython-313.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/market_data.cpython-313.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_agents.cpython-313.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_analysis.cpython-313.pyc diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/__init__.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/__init__.cpython-313.pyc deleted file mode 100644 index 78bfa93e46b4f13813c27816e3a3eb45361276aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 223 zcmXwzJ&FQB5QV2#7Z$-wn3;HhMGVwf12HRTdZ%k=8m7CYs>h#1@DOHRz$=-0f@LBz zYh-;%eXpu`yr$ppWunXDR1Rd`Tl1Fsho&oV&WdcP7T1hE#5L{dcAR~~nvoa`#b96= za87QEFpqidF(ii7&XDJ6w6X$z8Nj{qn+h3xT_vYYA)oLQ4Otz3wRMDfiV~X0SQiS- oW!&Y45twq&+69-i9&HY{ud$D|u5d!1Qm3uUE&O$qQq&Q80)@~+MgRZ+ diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/board_setup.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/board_setup.cpython-313.pyc deleted file mode 100644 index 725e1b6948ff3c114f456620d2eda5a1f8864c63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15640 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 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/main.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/main.cpython-313.pyc deleted file mode 100644 index b43bb05fd0e8192518af3d388a7f3f124562cf0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17456 zcmcJ1Yfu|mmS*Y&i4YPG3B)_W1|uHAHpUNZZ1c1+25cqx1!c7?C7`m9s7$GB)YBbR zGt=92ZO^uAHYy5N&#tN7AFbL)3>!PU!R*sj6S3hR8?l)sYQ$uFq9%H3epGC1EFM=+ z&DQ+cb8bE)u&}#2decEF^S<-uz2|)AJ170Tq{K?W@%cAzFaFPy6!q75qaB6n#q%2m zih7S?DV|~tta04H8_2JbHw76!|i#|thM@`aaZp1xGX7ctbF z$>-FX&i?wUve(+xoFQ+?YArweyHCm5YzggZ&fW`8fd^}03wlk;wU$OkTsZEyRLYl< zYkIuwQaN8vu8YPiE;)JUB^U1^_tx>sOI3Uoxh@`eU#jM-8OlvHQ>?9qVoQ3BO51!5 zYpw zCcelq!PwGrgo|_enquz-_$5YI5#rnuc4vJf5s1da@jyKMCdWV{q@xfQ3=1$Wfk_D1 zG0z1e%u;~A%f*>cARh2qzr;tH^cZCt?zwn)iIa=)9O5GJfX5`8hr_|RY`z>8;<9NV zx{@?{y|PK*gC2wIzM9jg`fTK>A+I`5-oOGEjSJ9M`2-olFpS^|AA2(#;&|D)z{UOQ zxc!MJJOwXs(2zrIcpw^xtO#KNk_sZRg$0fes&9k*=qvspS@CletaJ)jIjnFaZ)RPr zY0h%Y$eL@Y*UhgR_yX24S2$;xqmLOa&;aBVU=CmOLV6)dx3ZON5xFX6t61xtZO(%A z_LMfW#cKN{tSz_w7s{28w(KvIvK%wx+JliepdZJsHcIC#umk901#FqxOX;2xm}_Rs zN&T`teHz&cl3va_`HBVFmvJAwT7$02Zau;fz zrLL?@uUs6AMd!l{{^dY?F{o}Y^1^T%avj!N2-g-BTIAYVv&(>&H zzB=tH`wODRm=#?M29GH@Hx>=Y!+}UR2^$x-{obkfTCD^8g3xDW;K-TIKIRHcDie?C zHI&Q*ND!1o^Wg|*olMrL8;H?gWmxYo|!G z7X-)-=JCnpVnvSlQI7B>m_i5CJt`NIN`3)_lw5Kz1_FootCj6o)Eth^$3PO81uimA zh9KZeWf(a*)HgRHz~-L|@UduMZYs(R^B@i8hGW6R5(Nz=B5SIfay zDum$l7PVue>JDwu?(NE&Ol7N7*_y6wTQ&c<_^Se{(wla5!?pEkWp}#r2&O)*?Ml}| z8dP}dK9qKQAhBepfU09i+ID>-{?>d!+kaC0PO<1b`WfBx9QuJ-=ec--j|NpGh-nnA zVzPVg5OLQ)&FZt{%L$+))HDl1$Xw=A(e_CyZn$`D+ zPu~x@by-vX5!k7ooRxpwc#vwMI;l3bY6!+ZZ)B)Oih+NVJ^iLeYTnR9&FcHAkP4iD z6_VROE~PyO>@V|v{j-)HllEK;N|~}fmEl&~?Siq9I!Mh^$~Zg)N%k`Ako-FhHmHxh zB6W|V%A5uH*vWvxe65ceA|g=RmLbT6?HS-#tg?ZhOg3Y~+&)b+^L%WHNmlG`0(Ul( ztYM-tgc^xxs8iMNA#OeZ>tFB`$>!KH7gaX5`E?-{mCd-td7LsH7qMJ63aw1W;-lEW z2+zlOxe)ei6mWuEj>=eVOqB{A6JL+j4D-ATeg#~8AdmP4_~j8D%C&pqvy z6K0e`j2*IkP#P z>7S7LC&V+8qI+t~c4fPwdUfLKLMZfES?51|MN_3s&nY7`3solHnH1{}Z#XkY2Baec z;^9GYa89g!ZOe9hyP_&n(JocArz<)?wRP@TpvE`CAsE%~Rt|JgYgGevra$h4tB>of z1MP($w-(}c*V#d@>60!4oOf+ORR3fP9)t_P*nqED6KiHIUNc+37P7S0$QH3ywiteG zUeiI!Qe(=ApZvNME3q9oc zvvVG^>`=wNKNwgBoEVYqd|0^akH;cVCmQ5rC&+Pp?}2DE5s3H|sUzE#0{8tPK5#D- zyBC!$p+GpY5-x>h1k$@Sv5ctEKhJY-B)DjBMYab6fDQa1bzo}$e|_#t6ctdTRtPVE zl2F!E2&!=Y_#)4NG>(Mi66|U@CV(~s$O_=IXgS8m=VOs@jCVtQ9`VUXl*d3;q5u+u zQrBNQT*}RR*WZha_&k&oPQeM5VJUU6W4pO?yRCDZIryx|Qe)q-Q!Sm_&8^QYraJqM zl{(zB-E;tMs_oCJ9HrJB%28zHo1pgOu7#k>;!j{i?@_Z*KsoZsVUSO{Y$Y;Cm&95v zit_2GCYz?oC6L{E;y&#gXHjvJBP+-46l>Ze{qjg}AL{Wvht@M-9DQ8hY7CSwkDS)z zFpSH*XI%MaB#)#9`Tdf1VYK=zymGV_Z8Tum6?h7hhgsOBiDiPu@?hIQG{h*FhEXt$ zH+d9l#L>cnTEA8euQy2#fjJfj$)B_{1gS7f+|nIDK5)OQ`D9m~CJF9gf@%{&A{gWZ zVLlOwtW0{WSuxL7!t0bhN;!Y7k*FJ6q;J34w`_`l+Ca-*cBz##$fV-8TFfg~^OU+| zEIi^~k5SPQCA%6`u^rJBa-{&ea@nsGfT>h*q1?K6`{plq9eNRd2B)_u9V=bjqQ?MA zfd;WYv}W9wCHLjDdvdkpsRE`REdG(O-k)wfA~qb|@QTiXEqV}&H#9$*eK?z`KP%Or zP1m0%@GG~*vCM&9=|FF~@wnJqnOvZxNX>V+g{|%VIcf&!JK=BVN-HoiESs0GVRS zT0*<_{I0!qn2H)_3>DNx09{c;X*!aF=~NG&Zq;ZhV2_zti-!NA<{2|S$;3g5x-mFo zLhU&L;-@r5v# zh#~iK$fyt`grk8*LrTNIepn~JM68vp9_8Y}MHDzW!z8p*vRE6C7nz!#r5Nabs}PR` z?-El@cBpn+3>cO-!`wZ&Tp;w6f0^TfNLnITpjIot8}|y9Jp~r9ng0SO00rfgt>Q=Lo>sP}D?3wc>W&D;+XYR|RCfP~ zY2(7bv!%YjIV(EHw&+VB4XUbFi+@pBzdB0LyKP=S`r|U;W zx(1SKTelm%+s((GHn;!0^Jks^!kcOClbZX|&1V3&ATY70z=XVwU4jOcAVH~*e-m(m z7wrb(tXsYrwi zNtJEHPFmvPd^jk0%t`lHG|qv|5@*oXV&05JfNzV0<10zm1unJ>=1M#q1fD&PiUbUq zWX*_TRs++|1;7-~t>R>fKxFtBQumODox#IZW*;uMd$~e=VI*-rK>P|x*Ccm8&K&7F zs!wewup%U@CIa`vONk|>w}k=W&S<7p(!<7M%UzKe5V`@V2ifSb2uDL<;Nrpd(@P4; zmg^jMH?jhr1Jo5n7lD@|zDSbp1YoTN;gy1lsRJiRYzYWD;4=K2<`6;k0r|2^>)S7c zlaS!&6F}C<4&~WE*(`9#?a3~l(;Lm2l^%=s;+8n@Q9ye(bq)D(wd*QPQ(9`fKv)AN zCheAIN3@U#hfv3PO0ud;T zlzGSZBPc4^LH55zeN|2sITUhH)m^2|jH6X@w61?Q?dVxGgQjuUWvUKIRfjTF9a2@t zhEuHS5UY-_+DO*>-+T9anW{dis&Cs?wPurSE!%a>qw$C1sbZ<_nAkfi)m_-GZG3e4 z;pz47O0_-Wv0Y_e%A>>G~7f2fDYLT7F*h zVNIr~Uux=4H=TP{Xl_6Qyx#Lyb%(^ZQ&L^ucIy%G=&00sLBD`Pj2$#-2Virlee`dQ zmbUU|78=r=)RBvZZO`ELfyr&p6;P1}?9V!C8?2~I`>4`pk!~W;e3zm`3`rE_GN9Y{ zfB|ISW9Mc&d9;)ZdxBs+@52`^fFeXg1TnDW)V!?lwbt=1kis1-oo+->zFaa zjFiq;*fIyjmiJh$7$<-WKx;!VMJ-XYX1PPDiu|?&>m+K{Mb4F7@B?M5URu_TWua8{ zOH0-4YO(gEW$Q@UdU%G0o-(jt3J$`PYR@oFc^Z@N4G~lRMYRqJkcj91Z^|5)>OK`F zpxgtktvIAX8(Fg&GWiSZfZ~>ZQCE}k#S%P|%P;7X=BRaZAeZ3_AnMNt(VWA1_45&-E8&G>vHlhe$^fNy+c zni-m!93Gnhbj$58fYuJ)DrV+`hnG8Imo_pz^tIOq1OM zNf(q?@sR-I1*<3;hl-`DKGxIZ(s?ex`xkf)^dPjy-A~d`_1f5tJ|=0t4ZlgoYGp@; zrl)+&l@Z_Qly72Sa%hBUJJLlotEbP(ABXjqG%Vt5}0F%yNJa0B8h0Pg%(-ugxd` zh(Q>_Mc|19Yp<74!yt0jxdv16E^MS7R0ITzLfKU6Rw3&e^1urKPo=C*Mt$;K0|6KX zD@Da@$|i#M%0U%85X@R0C%z}xX8=q*JEMui@-E2 z2?Pvk)CEC#x`81VC<|6Ln9gvGs&hb8^+O zUEd~p`hm_wq+>QaZ96noQkStcO18#z$3}VDb}VB%DcMeLRy}S`+eR|BG08Ueqxz?K+rowMi~$?DVED?K+=v4NI^vh?^o!+ZA?qAGU-kR5@6N8*O0KR{RC4ui1|`>k=p2OHA$6P-gl zRN1h>u+zwtngJ>g8>mv}YVrSl-a|QV83;oE`#>VFLtpd<5?d*-^ZI z{wcgWz?jA$FsHBbPG~ejK2(*BB_Zh41egUF->7j`_v+{4c!4j5KsvVY6d({po9LMb zdPHY_fsQEB@F+wJSh7C&d>)r(>V}K8X2}({_>>vi#Xv(n<^a6*I!Bu?KoCY`L!_4* zA;6aWc4kJMlLEkJXqW9d@)0+H`0a?-W(u@f0KbsoCD95oHA=vd{9QJX6Mjdi7^26B zfd}v@Mxt^Mm}EnGa!uJjJw}k!-9y4?i>i;AO2n5F;QUut8PkSp5tWh$B7RC*ZniA7 zg#0ZRTP9jqxg@s(f70T`aDb!}DW7gFi|0`F3e!Nj&>+}_xIcC`>B?86TQ=PL5;Q(C zFa?Njz-lj4>F#9Zv>JFwMlZlzKwLwNK_@cC91;Q=9Lrd{Bx^LwG|1+8gjBLICV(3| zaF>IK9f5Cwf_y8Sfb~r*EkoR4oX;BV3iVuyy=YuB4p@`F2zmIo@pJ=QAUhJH(D)9# z)o>fu@Z&VTAdO`kX<4z&1z8KD(#`GM+-K0F@IT-L6tbPNIi=#-r*7tv?E~9S?HPBs zZq}}IN$F{3m*H_l>Zn(s%6RQ_N7#0;P7J2)|^rv*+wyQmLGSx0t^sdrhl$1Sa zTN~OcVb%wp+Dd;i_RiRYNGkB3D?YXLLwtn232Q6%JaE-FQkO*Mi7omh2*!r?f8F-S zo&U1)UwJd_15*3Io}XYEJA=PHJvE z4g? zuI!p=pDD__W;(L(4(B9S59PGkxliq`oZ8-fYj^Kc`*2R}{rf($Pwk`o*Vflv51Acn z&XXL=J3GBI*1WTGJln^!y8<>toCz>0{Y#9tocLbUk-q^DNM5z}|CSF3Fd^3a z)F?AN<|EVu%S`(QhQ}r^Fzm&t>q7(V2m{92%mnZ#H%l-G0SbqK%$d&|}P1c=9 z|MVS38Pm|z#FZ(Qa5jAq^2oq2romSdQ5mZVC1eIEoH!eyHH$%Dz9nwS`w93CK~ z6VsNoWl053-{hCLGrvUnlr+Hz;Oh#8zY2GJ0!|QbO+rN>9;l53fRcbY7?G7k|B<_- z$$O+FX@^i#od|&f_N+baUk=8x(0tO^;*p&?8RyRyNnl71%=sT~Fj<0W;PU0EAu{T| zUD0j`{V+EEIidrwVF2mlGk|l_ILUtiS9~9w07n|`=S1kq^qELt=}stcR_<0Yq7I~h zWQ#)dfZ~$#onS8OEbui+7#WW-Cvp)N zg--#H;{sX*>=rJ>e-AT%2Tl;Cf^o`ZhZ2dxuVEEK7+iT=P_|~5y=*}TA<#ImL&%EZ zQ&3VsGZ-FUJCvZ3l3j~bu7BwoF2WW2Icya0x!I^9`|8pbUH6nO5$*k3^jWxAohPCH z)h+9O$=$mVliZ^itX3kHdba2ea?zgZ&vcxTI?inRfk5e)7Tae;`?W3l`kvg|PiE2` ztk^y++Gn=tYf2-ju1x!Bsr|Hg=8EXMo^HP(dTxsLTU+!jSO>L-*1s>+97o7sGq&m= zH4gtt#fCq9WJEkX`Zyxm*)4kdX(dud#*H$O>DjpY=anaZG`b3QNZEs-HNyj8t$B@I zcRzd$h@YdW;6~d=ODR9FC;iRa%`NK@skvukNNhR@DW{sYn+}RCy;9Th4MAj1ZytrP z>xy%KM;S}b8=je{s*~Wtt88BPN-o0UxW-nkWJsM`wD)NZvkqRtBU00mbW_itHi%be zq?&8u^_$|2o9UWcKf1I!f+HGPYgwyWH?H@r3+tZL5wX1M&uw04yLQ$91ep8a`lM9V zvjL}}RU2s=zS{7Ri}uu+Ovh=d17_+fl3*P-#apk5?YBj{e~bQ(GLF<-rmJ7->KD(> zh}Y-RU9X9^17hbL(H`8QLrQZgTc+)#)OK>S;fX8VHYHwR#Y4F-gjugso?@eIb0pm~ z__#-8E{JwDY_XIw z%`N&C$!FG`Kd=6JSpW%b&g1vf zG=Q$lA*}h3mZ%Lv|BiLHYDm_Sk4_-$L~~{6U#Rsllb)g+qGu51hG+4Fkq`VI;_2VR zNiG_>ALI!0C0jWBgvDdd39NH%bS8GccmE27*65gq#HUoX-+xw&UhkpFY2tq5{8 zcw%IW9^Em!ipu}WR+_OLl5B^zY#tP>5Yp$BYP{*1!>i+PU&mx>d!^dmjl1dE!PU!< zQc{+&)l0VewaAvOL%na1Yz=F_vt{elK6h~sY}p34D;h;x6Cehp^ zhJ^&CkT`86Yy~-4<;x00fF47#h5*Y2ofcGX31JA4-OW&F(qowPIPpt4WVhi)7-1e!a~ysk)_5U~9-L?lvJ3tGP%P;8^Zx|MxY9##sT93d=-tqIkK@J=_X$>XMKkAi72t9yooj#^3J0V-pUghsgv)TJWC$^ z_Lgp<1v;?)@{fL?f9AiB0BlMiP__Q@pZ%CoBq4|%#Z#$DZxn-O{@*|$WfkM9=QrVm zfr^@RMFR+<#{~XALe8$w@?2oN_z5^HV)r7f7v>w|s_dYcjt+xIC6wt_} zjcEt-*2SHI0*iCIye3nANGd;+F88b!5|w{^i$1aKs9d%G{nKJ6$RmrBKo4)~jZ{#y zAKjvRo;oT}7FnF%2rlU4XLaYO|7IO%GJRZRhi~dWuCu^3$_yNj-|wmCKZa8LKgJWG z_f7D*xZ)2$SuGdDSC+vct4IeT2~b3U>lEmFFp8Jq%f=7^``~#9^C)hxab)p9%4pvn z<5woiC(L$LEoxsNTd`l1ndC!e64fr3>SZu)0V3^{Pnz++8c6U7MHdlKg0snEwD=xD z0~W3#2hZ}KLN2ay;rHOQV=@>F&x{s>`MI4kSbsqk|AMl9PPKhbHA_@8C;@}{hxFU@ z4;^ni9vI&*e7Ep@+qyK}mH@S4_@D?@lH`L+3q>g<~o&QU! u^KYo?uM5sw4CT)#Jpb*e)nRb%9Hh*))nwXK{TF8X2ctVC%3MRX{{I8)^u0X* diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/market_data.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/market_data.cpython-313.pyc deleted file mode 100644 index 8c2209c2fdd87924b5f032217d0d29b06f7c81e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21895 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 LjS(d-k~sb!%Zo6y diff --git a/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_analysis.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/src/__pycache__/trading_analysis.cpython-313.pyc deleted file mode 100644 index ab50fe302e046b50b5b1a02218aae802ca096b6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25034 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 From e3a09e2e59acaff1cf57fa1499ffddbae46fc764 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:10:39 +0300 Subject: [PATCH 13/18] Delete examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__ directory --- .../tests/__pycache__/__init__.cpython-313.pyc | Bin 301 -> 0 bytes ...est_market_data.cpython-313-pytest-8.3.5.pyc | Bin 42872 -> 0 bytes ...t_ollama_models.cpython-313-pytest-8.3.5.pyc | Bin 29543 -> 0 bytes ...rading_analysis.cpython-313-pytest-8.3.5.pyc | Bin 64869 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/__init__.cpython-313.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_market_data.cpython-313-pytest-8.3.5.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_ollama_models.cpython-313-pytest-8.3.5.pyc delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_trading_analysis.cpython-313-pytest-8.3.5.pyc diff --git a/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/__init__.cpython-313.pyc b/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/__init__.cpython-313.pyc deleted file mode 100644 index 589fde012ef6b421397518b9b87da5fc551498cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 301 zcmXw#F;2rk5JkNqg2++|Zm?~d8~_kSa1Dh+H_~YFj_nopuC=o!Kn2`^LvSUxTmaz< zuqMfG=KpEt{TY|bG>JNY|ERM#zo&4NIGAw}&1aG)KB>fN_IjCaiG%D^@u(`2rSme> zBsWfZEnO)y6jjd!}yIrA}*6Hm^3}=Yi6^LKSI9(XtZZ6=S$ulVLtb#jB znKw@anJfC1Y+%TD%D236Io^2qAuFGcot`823iu3c-U;@aYRw<=0GN%!x&ww|;pd6IC_E;}Sz;*_1FM3hBx&X@DyY(3>VSs)jj zbjxlHu23$7eA}s_lOEY~(kpvOzWr43$r8Cl63&ag+t?uVbFW{Iv)Fm3Dda9zuAd(Q z*{DOX*!l7fxL!Phj-a!{O5-e#j8r^Tak5gbJXs}IovfCtC80vtEClnbgrKV_3tk&*cLWtZ#ha9oi_lhKKhm^2QsiZnhPlSXNU zC{~Ck#$!Wr1nWqVL{#cJb3z(4HWF~XhlAiGrGCnZu zx2TShGuJT6C~@x)MgA`!nBla-k2 z!CWOaFrJjdvGGA=z3_< zC{aE&^&w&j9lWiCURI|wTWSn7tbCcgW-Sszo^I`lY=G z>n5c9WF-bhB8nmnCgq$d&YjKy4ZFxN91!C5z5nkZcthwXnHcnHc*HX>&u&c7_$oEn zJ#47hFR}!m6}YQ|)(#uZ4+$f@pC%z_d)5LuI8Jg5+5L`GbuczQF(!@1#)p$pa=Ed{ zz%W6ufQ-$nj)7!iFh2Ca9T|&n9=}t~ zODd`j5NTMoeKr|SsLp6yPDDmysu&Ir#z$h|uv*9(A{nY1kvXhf9=(tpQEpjOn-Uut zRB&b`b@K4O^C1QB>U>0o8{zyjiCDJ`h<3g^IWRFAON=Y$gO?)msB$P7g{<=mNt}

(|J;>bMYo%EUbW$D{T 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 diff --git a/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_ollama_models.cpython-313-pytest-8.3.5.pyc b/examples/multi_agent/board_of_directors/trading_showcase/tests/__pycache__/test_ollama_models.cpython-313-pytest-8.3.5.pyc deleted file mode 100644 index 62f6bfdf1156772005a0228bdd97292968c27a77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29543 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 Date: Tue, 29 Jul 2025 00:49:28 +0300 Subject: [PATCH 14/18] Update board_of_directors_swarm.py --- swarms/structs/board_of_directors_swarm.py | 594 ++++++++++++++++++++- 1 file changed, 593 insertions(+), 1 deletion(-) diff --git a/swarms/structs/board_of_directors_swarm.py b/swarms/structs/board_of_directors_swarm.py index a6d24794..f80fb4a4 100644 --- a/swarms/structs/board_of_directors_swarm.py +++ b/swarms/structs/board_of_directors_swarm.py @@ -27,6 +27,8 @@ import traceback from concurrent.futures import ThreadPoolExecutor, as_completed from dataclasses import dataclass, field from enum import Enum +from functools import lru_cache +from pathlib import Path from typing import Any, Callable, Dict, List, Optional, Union, Tuple from loguru import logger @@ -44,6 +46,588 @@ from swarms.utils.output_types import OutputType board_logger = initialize_logger(log_folder="board_of_directors_swarm") +# ============================================================================ +# BOARD OF DIRECTORS CONFIGURATION +# ============================================================================ + +class BoardFeatureStatus(str, Enum): + """Enumeration of Board of Directors feature status. + + This enum defines the possible states of the Board of Directors feature + within the Swarms Framework. + + Attributes: + ENABLED: Feature is explicitly enabled + DISABLED: Feature is explicitly disabled + AUTO: Feature state is determined automatically + """ + + ENABLED = "enabled" + DISABLED = "disabled" + AUTO = "auto" + + +class BoardConfigModel(BaseModel): + """ + Configuration model for Board of Directors feature. + + This model defines all configurable parameters for the Board of Directors + feature, including feature status, board composition, and operational settings. + + Attributes: + board_feature_enabled: Whether the Board of Directors feature is enabled globally + default_board_size: Default number of board members when creating a new board + decision_threshold: Threshold for majority decisions (0.0-1.0) + enable_voting: Enable voting mechanisms for board decisions + enable_consensus: Enable consensus-building mechanisms + default_board_model: Default model for board member agents + verbose_logging: Enable verbose logging for board operations + max_board_meeting_duration: Maximum duration for board meetings in seconds + auto_fallback_to_director: Automatically fall back to Director mode if Board fails + custom_board_templates: Custom board templates for different use cases + """ + + # Feature control + board_feature_enabled: bool = Field( + default=False, + description="Whether the Board of Directors feature is enabled globally." + ) + + # Board composition + default_board_size: int = Field( + default=3, + ge=1, + le=10, + description="Default number of board members when creating a new board." + ) + + # Operational settings + decision_threshold: float = Field( + default=0.6, + ge=0.0, + le=1.0, + description="Threshold for majority decisions (0.0-1.0)." + ) + + enable_voting: bool = Field( + default=True, + description="Enable voting mechanisms for board decisions." + ) + + enable_consensus: bool = Field( + default=True, + description="Enable consensus-building mechanisms." + ) + + # Model settings + default_board_model: str = Field( + default="gpt-4o-mini", + description="Default model for board member agents." + ) + + # Logging and monitoring + verbose_logging: bool = Field( + default=False, + description="Enable verbose logging for board operations." + ) + + # Performance settings + max_board_meeting_duration: int = Field( + default=300, + ge=60, + le=3600, + description="Maximum duration for board meetings in seconds." + ) + + # Integration settings + auto_fallback_to_director: bool = Field( + default=True, + description="Automatically fall back to Director mode if Board fails." + ) + + # Custom board templates + custom_board_templates: Dict[str, Dict[str, Any]] = Field( + default_factory=dict, + description="Custom board templates for different use cases." + ) + + +@dataclass +class BoardConfig: + """ + Board of Directors configuration manager. + + This class manages the configuration for the Board of Directors feature, + including loading from environment variables, configuration files, and + providing default values. + + Attributes: + config_file_path: Optional path to configuration file + config_data: Optional configuration data dictionary + config: The current configuration model instance + """ + + config_file_path: Optional[str] = None + config_data: Optional[Dict[str, Any]] = None + config: BoardConfigModel = field(init=False) + + def __post_init__(self) -> None: + """Initialize the configuration after object creation.""" + self._load_config() + + def _load_config(self) -> None: + """ + Load configuration from various sources. + + Priority order: + 1. Environment variables + 2. Configuration file + 3. Default values + + Raises: + Exception: If configuration loading fails + """ + try: + # Start with default configuration + self.config = BoardConfigModel() + + # Load from configuration file if specified + if self.config_file_path and os.path.exists(self.config_file_path): + self._load_from_file() + + # Override with environment variables + self._load_from_environment() + + # Override with explicit config data + if self.config_data: + self._load_from_dict(self.config_data) + + except Exception as e: + logger.error(f"Failed to load Board of Directors configuration: {str(e)}") + raise + + def _load_from_file(self) -> None: + """ + Load configuration from file. + + Raises: + Exception: If file loading fails + """ + try: + import yaml + with open(self.config_file_path, 'r') as f: + file_config = yaml.safe_load(f) + self._load_from_dict(file_config) + logger.info(f"Loaded Board of Directors config from: {self.config_file_path}") + except Exception as e: + logger.warning(f"Failed to load config file {self.config_file_path}: {e}") + raise + + def _load_from_environment(self) -> None: + """ + Load configuration from environment variables. + + This method maps environment variables to configuration parameters + and handles type conversion appropriately. + """ + env_mappings = { + 'SWARMS_BOARD_FEATURE_ENABLED': 'board_feature_enabled', + 'SWARMS_BOARD_DEFAULT_SIZE': 'default_board_size', + 'SWARMS_BOARD_DECISION_THRESHOLD': 'decision_threshold', + 'SWARMS_BOARD_ENABLE_VOTING': 'enable_voting', + 'SWARMS_BOARD_ENABLE_CONSENSUS': 'enable_consensus', + 'SWARMS_BOARD_DEFAULT_MODEL': 'default_board_model', + 'SWARMS_BOARD_VERBOSE_LOGGING': 'verbose_logging', + 'SWARMS_BOARD_MAX_MEETING_DURATION': 'max_board_meeting_duration', + 'SWARMS_BOARD_AUTO_FALLBACK': 'auto_fallback_to_director', + } + + for env_var, config_key in env_mappings.items(): + value = os.getenv(env_var) + if value is not None: + try: + # Convert string values to appropriate types + if config_key in ['board_feature_enabled', 'enable_voting', 'enable_consensus', 'verbose_logging', 'auto_fallback_to_director']: + converted_value = value.lower() in ['true', '1', 'yes', 'on'] + elif config_key in ['default_board_size', 'max_board_meeting_duration']: + converted_value = int(value) + elif config_key in ['decision_threshold']: + converted_value = float(value) + else: + converted_value = value + + setattr(self.config, config_key, converted_value) + logger.debug(f"Loaded {config_key} from environment: {converted_value}") + except (ValueError, TypeError) as e: + logger.warning(f"Failed to parse environment variable {env_var}: {e}") + + def _load_from_dict(self, config_dict: Dict[str, Any]) -> None: + """ + Load configuration from dictionary. + + Args: + config_dict: Dictionary containing configuration values + + Raises: + ValueError: If configuration values are invalid + """ + for key, value in config_dict.items(): + if hasattr(self.config, key): + try: + setattr(self.config, key, value) + except (ValueError, TypeError) as e: + logger.warning(f"Failed to set config {key}: {e}") + raise ValueError(f"Invalid configuration value for {key}: {e}") + + def is_enabled(self) -> bool: + """ + Check if the Board of Directors feature is enabled. + + Returns: + bool: True if the feature is enabled, False otherwise + """ + return self.config.board_feature_enabled + + def get_config(self) -> BoardConfigModel: + """ + Get the current configuration. + + Returns: + BoardConfigModel: The current configuration + """ + return self.config + + def update_config(self, updates: Dict[str, Any]) -> None: + """ + Update the configuration with new values. + + Args: + updates: Dictionary of configuration updates + + Raises: + ValueError: If any update values are invalid + """ + try: + self._load_from_dict(updates) + except ValueError as e: + logger.error(f"Failed to update configuration: {e}") + raise + + def save_config(self, file_path: Optional[str] = None) -> None: + """ + Save the current configuration to a file. + + Args: + file_path: Optional file path to save to (uses config_file_path if not provided) + + Raises: + Exception: If saving fails + """ + save_path = file_path or self.config_file_path + if not save_path: + logger.warning("No file path specified for saving configuration") + return + + try: + import yaml + # Convert config to dictionary + config_dict = self.config.model_dump() + + # Ensure directory exists + os.makedirs(os.path.dirname(save_path), exist_ok=True) + + with open(save_path, 'w') as f: + yaml.dump(config_dict, f, default_flow_style=False, indent=2) + + logger.info(f"Saved Board of Directors config to: {save_path}") + except Exception as e: + logger.error(f"Failed to save config to {save_path}: {e}") + raise + + @lru_cache(maxsize=128) + def get_default_board_template(self, template_name: str = "standard") -> Dict[str, Any]: + """ + Get a default board template. + + This method provides predefined board templates for common use cases. + Templates are cached for improved performance. + + Args: + template_name: Name of the template to retrieve + + Returns: + Dict[str, Any]: Board template configuration + """ + templates = { + "standard": { + "roles": [ + {"name": "Chairman", "weight": 1.5, "expertise": ["leadership", "strategy"]}, + {"name": "Vice-Chairman", "weight": 1.2, "expertise": ["operations", "coordination"]}, + {"name": "Secretary", "weight": 1.0, "expertise": ["documentation", "communication"]}, + ] + }, + "executive": { + "roles": [ + {"name": "CEO", "weight": 2.0, "expertise": ["executive_leadership", "strategy"]}, + {"name": "CFO", "weight": 1.5, "expertise": ["finance", "risk_management"]}, + {"name": "CTO", "weight": 1.5, "expertise": ["technology", "innovation"]}, + {"name": "COO", "weight": 1.3, "expertise": ["operations", "efficiency"]}, + ] + }, + "advisory": { + "roles": [ + {"name": "Lead_Advisor", "weight": 1.3, "expertise": ["strategy", "consulting"]}, + {"name": "Technical_Advisor", "weight": 1.2, "expertise": ["technology", "architecture"]}, + {"name": "Business_Advisor", "weight": 1.2, "expertise": ["business", "market_analysis"]}, + {"name": "Legal_Advisor", "weight": 1.1, "expertise": ["legal", "compliance"]}, + ] + }, + "minimal": { + "roles": [ + {"name": "Chairman", "weight": 1.0, "expertise": ["leadership"]}, + {"name": "Member", "weight": 1.0, "expertise": ["general"]}, + ] + } + } + + # Check custom templates first + if template_name in self.config.custom_board_templates: + return self.config.custom_board_templates[template_name] + + # Return standard template if requested template not found + return templates.get(template_name, templates["standard"]) + + def validate_config(self) -> List[str]: + """ + Validate the current configuration. + + This method performs comprehensive validation of the configuration + to ensure all values are within acceptable ranges and constraints. + + Returns: + List[str]: List of validation errors (empty if valid) + """ + errors = [] + + try: + # Validate the configuration model + self.config.model_validate(self.config.model_dump()) + except Exception as e: + errors.append(f"Configuration validation failed: {e}") + + # Additional custom validations + if self.config.decision_threshold < 0.5: + errors.append("Decision threshold should be at least 0.5 for meaningful majority decisions") + + if self.config.default_board_size < 2: + errors.append("Board size should be at least 2 for meaningful discussions") + + if self.config.max_board_meeting_duration < 60: + errors.append("Board meeting duration should be at least 60 seconds") + + return errors + + +# Global configuration instance +_board_config: Optional[BoardConfig] = None + + +@lru_cache(maxsize=1) +def get_board_config(config_file_path: Optional[str] = None) -> BoardConfig: + """ + Get the global Board of Directors configuration instance. + + This function provides a singleton pattern for accessing the Board of Directors + configuration. The configuration is cached for improved performance. + + Args: + config_file_path: Optional path to configuration file + + Returns: + BoardConfig: The global configuration instance + """ + global _board_config + + if _board_config is None: + _board_config = BoardConfig(config_file_path=config_file_path) + + return _board_config + + +def enable_board_feature(config_file_path: Optional[str] = None) -> None: + """ + Enable the Board of Directors feature globally. + + This function enables the Board of Directors feature and saves the configuration + to the specified file path. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"board_feature_enabled": True}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Board of Directors feature enabled") + + +def disable_board_feature(config_file_path: Optional[str] = None) -> None: + """ + Disable the Board of Directors feature globally. + + This function disables the Board of Directors feature and saves the configuration + to the specified file path. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"board_feature_enabled": False}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Board of Directors feature disabled") + + +def is_board_feature_enabled(config_file_path: Optional[str] = None) -> bool: + """ + Check if the Board of Directors feature is enabled. + + Args: + config_file_path: Optional path to configuration file + + Returns: + bool: True if the feature is enabled, False otherwise + """ + config = get_board_config(config_file_path) + return config.is_enabled() + + +def create_default_config_file(file_path: str = "swarms_board_config.yaml") -> None: + """ + Create a default configuration file. + + This function creates a default Board of Directors configuration file + with recommended settings. + + Args: + file_path: Path where to create the configuration file + """ + default_config = { + "board_feature_enabled": False, + "default_board_size": 3, + "decision_threshold": 0.6, + "enable_voting": True, + "enable_consensus": True, + "default_board_model": "gpt-4o-mini", + "verbose_logging": False, + "max_board_meeting_duration": 300, + "auto_fallback_to_director": True, + "custom_board_templates": {} + } + + config = BoardConfig(config_file_path=file_path, config_data=default_config) + config.save_config(file_path) + + logger.info(f"Created default Board of Directors config file: {file_path}") + + +def set_board_size(size: int, config_file_path: Optional[str] = None) -> None: + """ + Set the default board size. + + Args: + size: The default board size (1-10) + config_file_path: Optional path to save the configuration + """ + if not 1 <= size <= 10: + raise ValueError("Board size must be between 1 and 10") + + config = get_board_config(config_file_path) + config.update_config({"default_board_size": size}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info(f"Default board size set to: {size}") + + +def set_decision_threshold(threshold: float, config_file_path: Optional[str] = None) -> None: + """ + Set the decision threshold for majority decisions. + + Args: + threshold: The decision threshold (0.0-1.0) + config_file_path: Optional path to save the configuration + """ + if not 0.0 <= threshold <= 1.0: + raise ValueError("Decision threshold must be between 0.0 and 1.0") + + config = get_board_config(config_file_path) + config.update_config({"decision_threshold": threshold}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info(f"Decision threshold set to: {threshold}") + + +def set_board_model(model: str, config_file_path: Optional[str] = None) -> None: + """ + Set the default board model. + + Args: + model: The default model name for board members + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"default_board_model": model}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info(f"Default board model set to: {model}") + + +def enable_verbose_logging(config_file_path: Optional[str] = None) -> None: + """ + Enable verbose logging for board operations. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"verbose_logging": True}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Verbose logging enabled for Board of Directors") + + +def disable_verbose_logging(config_file_path: Optional[str] = None) -> None: + """ + Disable verbose logging for board operations. + + Args: + config_file_path: Optional path to save the configuration + """ + config = get_board_config(config_file_path) + config.update_config({"verbose_logging": False}) + + if config_file_path: + config.save_config(config_file_path) + + logger.info("Verbose logging disabled for Board of Directors") + + +# ============================================================================ +# BOARD OF DIRECTORS IMPLEMENTATION +# ============================================================================ + class BoardMemberRole(str, Enum): """Enumeration of possible board member roles. @@ -504,6 +1088,14 @@ You should be thorough, organized, and detail-oriented in your documentation.""" if self.verbose: board_logger.info(f"šŸ” Running reliability checks for swarm: {self.name}") + # Check if Board of Directors feature is enabled + board_config = get_board_config() + if not board_config.is_enabled(): + raise ValueError( + "Board of Directors feature is not enabled. Please enable it using " + "enable_board_feature() or set SWARMS_BOARD_FEATURE_ENABLED=true environment variable." + ) + if not self.agents or len(self.agents) == 0: raise ValueError( "No agents found in the swarm. At least one agent must be provided to create a Board of Directors swarm." @@ -1141,4 +1733,4 @@ Please provide your response in the following format: "total_agents": len(self.agents), "max_loops": self.max_loops, "decision_threshold": self.decision_threshold, - } \ No newline at end of file + } From 0e1f70e68e17211b3968fbd3a47c12f871d6b3cb Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Tue, 29 Jul 2025 00:49:43 +0300 Subject: [PATCH 15/18] Delete swarms/config/board_config.py --- swarms/config/board_config.py | 596 ---------------------------------- 1 file changed, 596 deletions(-) delete mode 100644 swarms/config/board_config.py diff --git a/swarms/config/board_config.py b/swarms/config/board_config.py deleted file mode 100644 index 8b29c0ae..00000000 --- a/swarms/config/board_config.py +++ /dev/null @@ -1,596 +0,0 @@ -""" -Board of Directors Configuration Module - -This module provides configuration management for the Board of Directors feature -in the Swarms Framework. It allows users to enable and configure the Board of -Directors feature manually through environment variables or configuration files. - -The implementation follows the Swarms philosophy of: -- Readable code with comprehensive type annotations and documentation -- Performance optimization through caching and efficient loading -- Simplified abstractions for configuration management -""" - -import os -from typing import Dict, Any, Optional, List, Union -from dataclasses import dataclass, field -from enum import Enum -from pathlib import Path -from functools import lru_cache - -from pydantic import BaseModel, Field -from loguru import logger - - -class BoardFeatureStatus(str, Enum): - """Enumeration of Board of Directors feature status. - - This enum defines the possible states of the Board of Directors feature - within the Swarms Framework. - - Attributes: - ENABLED: Feature is explicitly enabled - DISABLED: Feature is explicitly disabled - AUTO: Feature state is determined automatically - """ - - ENABLED = "enabled" - DISABLED = "disabled" - AUTO = "auto" - - -class BoardConfigModel(BaseModel): - """ - Configuration model for Board of Directors feature. - - This model defines all configurable parameters for the Board of Directors - feature, including feature status, board composition, and operational settings. - - Attributes: - board_feature_enabled: Whether the Board of Directors feature is enabled globally - default_board_size: Default number of board members when creating a new board - decision_threshold: Threshold for majority decisions (0.0-1.0) - enable_voting: Enable voting mechanisms for board decisions - enable_consensus: Enable consensus-building mechanisms - default_board_model: Default model for board member agents - verbose_logging: Enable verbose logging for board operations - max_board_meeting_duration: Maximum duration for board meetings in seconds - auto_fallback_to_director: Automatically fall back to Director mode if Board fails - custom_board_templates: Custom board templates for different use cases - """ - - # Feature control - board_feature_enabled: bool = Field( - default=False, - description="Whether the Board of Directors feature is enabled globally." - ) - - # Board composition - default_board_size: int = Field( - default=3, - ge=1, - le=10, - description="Default number of board members when creating a new board." - ) - - # Operational settings - decision_threshold: float = Field( - default=0.6, - ge=0.0, - le=1.0, - description="Threshold for majority decisions (0.0-1.0)." - ) - - enable_voting: bool = Field( - default=True, - description="Enable voting mechanisms for board decisions." - ) - - enable_consensus: bool = Field( - default=True, - description="Enable consensus-building mechanisms." - ) - - # Model settings - default_board_model: str = Field( - default="gpt-4o-mini", - description="Default model for board member agents." - ) - - # Logging and monitoring - verbose_logging: bool = Field( - default=False, - description="Enable verbose logging for board operations." - ) - - # Performance settings - max_board_meeting_duration: int = Field( - default=300, - ge=60, - le=3600, - description="Maximum duration for board meetings in seconds." - ) - - # Integration settings - auto_fallback_to_director: bool = Field( - default=True, - description="Automatically fall back to Director mode if Board fails." - ) - - # Custom board templates - custom_board_templates: Dict[str, Dict[str, Any]] = Field( - default_factory=dict, - description="Custom board templates for different use cases." - ) - - -@dataclass -class BoardConfig: - """ - Board of Directors configuration manager. - - This class manages the configuration for the Board of Directors feature, - including loading from environment variables, configuration files, and - providing default values. - - Attributes: - config_file_path: Optional path to configuration file - config_data: Optional configuration data dictionary - config: The current configuration model instance - """ - - config_file_path: Optional[str] = None - config_data: Optional[Dict[str, Any]] = None - config: BoardConfigModel = field(init=False) - - def __post_init__(self) -> None: - """Initialize the configuration after object creation.""" - self._load_config() - - def _load_config(self) -> None: - """ - Load configuration from various sources. - - Priority order: - 1. Environment variables - 2. Configuration file - 3. Default values - - Raises: - Exception: If configuration loading fails - """ - try: - # Start with default configuration - self.config = BoardConfigModel() - - # Load from configuration file if specified - if self.config_file_path and os.path.exists(self.config_file_path): - self._load_from_file() - - # Override with environment variables - self._load_from_environment() - - # Override with explicit config data - if self.config_data: - self._load_from_dict(self.config_data) - - except Exception as e: - logger.error(f"Failed to load Board of Directors configuration: {str(e)}") - raise - - def _load_from_file(self) -> None: - """ - Load configuration from file. - - Raises: - Exception: If file loading fails - """ - try: - import yaml - with open(self.config_file_path, 'r') as f: - file_config = yaml.safe_load(f) - self._load_from_dict(file_config) - logger.info(f"Loaded Board of Directors config from: {self.config_file_path}") - except Exception as e: - logger.warning(f"Failed to load config file {self.config_file_path}: {e}") - raise - - def _load_from_environment(self) -> None: - """ - Load configuration from environment variables. - - This method maps environment variables to configuration parameters - and handles type conversion appropriately. - """ - env_mappings = { - 'SWARMS_BOARD_FEATURE_ENABLED': 'board_feature_enabled', - 'SWARMS_BOARD_DEFAULT_SIZE': 'default_board_size', - 'SWARMS_BOARD_DECISION_THRESHOLD': 'decision_threshold', - 'SWARMS_BOARD_ENABLE_VOTING': 'enable_voting', - 'SWARMS_BOARD_ENABLE_CONSENSUS': 'enable_consensus', - 'SWARMS_BOARD_DEFAULT_MODEL': 'default_board_model', - 'SWARMS_BOARD_VERBOSE_LOGGING': 'verbose_logging', - 'SWARMS_BOARD_MAX_MEETING_DURATION': 'max_board_meeting_duration', - 'SWARMS_BOARD_AUTO_FALLBACK': 'auto_fallback_to_director', - } - - for env_var, config_key in env_mappings.items(): - value = os.getenv(env_var) - if value is not None: - try: - # Convert string values to appropriate types - if config_key in ['board_feature_enabled', 'enable_voting', 'enable_consensus', 'verbose_logging', 'auto_fallback_to_director']: - converted_value = value.lower() in ['true', '1', 'yes', 'on'] - elif config_key in ['default_board_size', 'max_board_meeting_duration']: - converted_value = int(value) - elif config_key in ['decision_threshold']: - converted_value = float(value) - else: - converted_value = value - - setattr(self.config, config_key, converted_value) - logger.debug(f"Loaded {config_key} from environment: {converted_value}") - except (ValueError, TypeError) as e: - logger.warning(f"Failed to parse environment variable {env_var}: {e}") - - def _load_from_dict(self, config_dict: Dict[str, Any]) -> None: - """ - Load configuration from dictionary. - - Args: - config_dict: Dictionary containing configuration values - - Raises: - ValueError: If configuration values are invalid - """ - for key, value in config_dict.items(): - if hasattr(self.config, key): - try: - setattr(self.config, key, value) - except (ValueError, TypeError) as e: - logger.warning(f"Failed to set config {key}: {e}") - raise ValueError(f"Invalid configuration value for {key}: {e}") - - def is_enabled(self) -> bool: - """ - Check if the Board of Directors feature is enabled. - - Returns: - bool: True if the feature is enabled, False otherwise - """ - return self.config.board_feature_enabled - - def get_config(self) -> BoardConfigModel: - """ - Get the current configuration. - - Returns: - BoardConfigModel: The current configuration - """ - return self.config - - def update_config(self, updates: Dict[str, Any]) -> None: - """ - Update the configuration with new values. - - Args: - updates: Dictionary of configuration updates - - Raises: - ValueError: If any update values are invalid - """ - try: - self._load_from_dict(updates) - except ValueError as e: - logger.error(f"Failed to update configuration: {e}") - raise - - def save_config(self, file_path: Optional[str] = None) -> None: - """ - Save the current configuration to a file. - - Args: - file_path: Optional file path to save to (uses config_file_path if not provided) - - Raises: - Exception: If saving fails - """ - save_path = file_path or self.config_file_path - if not save_path: - logger.warning("No file path specified for saving configuration") - return - - try: - import yaml - # Convert config to dictionary - config_dict = self.config.model_dump() - - # Ensure directory exists - os.makedirs(os.path.dirname(save_path), exist_ok=True) - - with open(save_path, 'w') as f: - yaml.dump(config_dict, f, default_flow_style=False, indent=2) - - logger.info(f"Saved Board of Directors config to: {save_path}") - except Exception as e: - logger.error(f"Failed to save config to {save_path}: {e}") - raise - - @lru_cache(maxsize=128) - def get_default_board_template(self, template_name: str = "standard") -> Dict[str, Any]: - """ - Get a default board template. - - This method provides predefined board templates for common use cases. - Templates are cached for improved performance. - - Args: - template_name: Name of the template to retrieve - - Returns: - Dict[str, Any]: Board template configuration - """ - templates = { - "standard": { - "roles": [ - {"name": "Chairman", "weight": 1.5, "expertise": ["leadership", "strategy"]}, - {"name": "Vice-Chairman", "weight": 1.2, "expertise": ["operations", "coordination"]}, - {"name": "Secretary", "weight": 1.0, "expertise": ["documentation", "communication"]}, - ] - }, - "executive": { - "roles": [ - {"name": "CEO", "weight": 2.0, "expertise": ["executive_leadership", "strategy"]}, - {"name": "CFO", "weight": 1.5, "expertise": ["finance", "risk_management"]}, - {"name": "CTO", "weight": 1.5, "expertise": ["technology", "innovation"]}, - {"name": "COO", "weight": 1.3, "expertise": ["operations", "efficiency"]}, - ] - }, - "advisory": { - "roles": [ - {"name": "Lead_Advisor", "weight": 1.3, "expertise": ["strategy", "consulting"]}, - {"name": "Technical_Advisor", "weight": 1.2, "expertise": ["technology", "architecture"]}, - {"name": "Business_Advisor", "weight": 1.2, "expertise": ["business", "market_analysis"]}, - {"name": "Legal_Advisor", "weight": 1.1, "expertise": ["legal", "compliance"]}, - ] - }, - "minimal": { - "roles": [ - {"name": "Chairman", "weight": 1.0, "expertise": ["leadership"]}, - {"name": "Member", "weight": 1.0, "expertise": ["general"]}, - ] - } - } - - # Check custom templates first - if template_name in self.config.custom_board_templates: - return self.config.custom_board_templates[template_name] - - # Return standard template if requested template not found - return templates.get(template_name, templates["standard"]) - - def validate_config(self) -> List[str]: - """ - Validate the current configuration. - - This method performs comprehensive validation of the configuration - to ensure all values are within acceptable ranges and constraints. - - Returns: - List[str]: List of validation errors (empty if valid) - """ - errors = [] - - try: - # Validate the configuration model - self.config.model_validate(self.config.model_dump()) - except Exception as e: - errors.append(f"Configuration validation failed: {e}") - - # Additional custom validations - if self.config.decision_threshold < 0.5: - errors.append("Decision threshold should be at least 0.5 for meaningful majority decisions") - - if self.config.default_board_size < 2: - errors.append("Board size should be at least 2 for meaningful discussions") - - if self.config.max_board_meeting_duration < 60: - errors.append("Board meeting duration should be at least 60 seconds") - - return errors - - -# Global configuration instance -_board_config: Optional[BoardConfig] = None - - -@lru_cache(maxsize=1) -def get_board_config(config_file_path: Optional[str] = None) -> BoardConfig: - """ - Get the global Board of Directors configuration instance. - - This function provides a singleton pattern for accessing the Board of Directors - configuration. The configuration is cached for improved performance. - - Args: - config_file_path: Optional path to configuration file - - Returns: - BoardConfig: The global configuration instance - """ - global _board_config - - if _board_config is None: - _board_config = BoardConfig(config_file_path=config_file_path) - - return _board_config - - -def enable_board_feature(config_file_path: Optional[str] = None) -> None: - """ - Enable the Board of Directors feature globally. - - This function enables the Board of Directors feature and saves the configuration - to the specified file path. - - Args: - config_file_path: Optional path to save the configuration - """ - config = get_board_config(config_file_path) - config.update_config({"board_feature_enabled": True}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info("Board of Directors feature enabled") - - -def disable_board_feature(config_file_path: Optional[str] = None) -> None: - """ - Disable the Board of Directors feature globally. - - This function disables the Board of Directors feature and saves the configuration - to the specified file path. - - Args: - config_file_path: Optional path to save the configuration - """ - config = get_board_config(config_file_path) - config.update_config({"board_feature_enabled": False}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info("Board of Directors feature disabled") - - -def is_board_feature_enabled(config_file_path: Optional[str] = None) -> bool: - """ - Check if the Board of Directors feature is enabled. - - Args: - config_file_path: Optional path to configuration file - - Returns: - bool: True if the feature is enabled, False otherwise - """ - config = get_board_config(config_file_path) - return config.is_enabled() - - -def create_default_config_file(file_path: str = "swarms_board_config.yaml") -> None: - """ - Create a default configuration file. - - This function creates a default Board of Directors configuration file - with recommended settings. - - Args: - file_path: Path where to create the configuration file - """ - default_config = { - "board_feature_enabled": False, - "default_board_size": 3, - "decision_threshold": 0.6, - "enable_voting": True, - "enable_consensus": True, - "default_board_model": "gpt-4o-mini", - "verbose_logging": False, - "max_board_meeting_duration": 300, - "auto_fallback_to_director": True, - "custom_board_templates": {} - } - - config = BoardConfig(config_file_path=file_path, config_data=default_config) - config.save_config(file_path) - - logger.info(f"Created default Board of Directors config file: {file_path}") - - -def set_board_size(size: int, config_file_path: Optional[str] = None) -> None: - """ - Set the default board size. - - Args: - size: The default board size (1-10) - config_file_path: Optional path to save the configuration - """ - if not 1 <= size <= 10: - raise ValueError("Board size must be between 1 and 10") - - config = get_board_config(config_file_path) - config.update_config({"default_board_size": size}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info(f"Default board size set to: {size}") - - -def set_decision_threshold(threshold: float, config_file_path: Optional[str] = None) -> None: - """ - Set the decision threshold for majority decisions. - - Args: - threshold: The decision threshold (0.0-1.0) - config_file_path: Optional path to save the configuration - """ - if not 0.0 <= threshold <= 1.0: - raise ValueError("Decision threshold must be between 0.0 and 1.0") - - config = get_board_config(config_file_path) - config.update_config({"decision_threshold": threshold}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info(f"Decision threshold set to: {threshold}") - - -def set_board_model(model: str, config_file_path: Optional[str] = None) -> None: - """ - Set the default board model. - - Args: - model: The default model name for board members - config_file_path: Optional path to save the configuration - """ - config = get_board_config(config_file_path) - config.update_config({"default_board_model": model}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info(f"Default board model set to: {model}") - - -def enable_verbose_logging(config_file_path: Optional[str] = None) -> None: - """ - Enable verbose logging for board operations. - - Args: - config_file_path: Optional path to save the configuration - """ - config = get_board_config(config_file_path) - config.update_config({"verbose_logging": True}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info("Verbose logging enabled for Board of Directors") - - -def disable_verbose_logging(config_file_path: Optional[str] = None) -> None: - """ - Disable verbose logging for board operations. - - Args: - config_file_path: Optional path to save the configuration - """ - config = get_board_config(config_file_path) - config.update_config({"verbose_logging": False}) - - if config_file_path: - config.save_config(config_file_path) - - logger.info("Verbose logging disabled for Board of Directors") \ No newline at end of file From 1ae94fd04240722b7abc0a4090ce4e976dfce194 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Tue, 29 Jul 2025 00:50:15 +0300 Subject: [PATCH 16/18] Delete examples/multi_agent/board_of_directors/trading_showcase/agent_workspace directory --- .../board_of_directors/trading_showcase/agent_workspace/error.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/agent_workspace/error.txt diff --git a/examples/multi_agent/board_of_directors/trading_showcase/agent_workspace/error.txt b/examples/multi_agent/board_of_directors/trading_showcase/agent_workspace/error.txt deleted file mode 100644 index e69de29b..00000000 From 4e6eced828e9ed131f1e8647d9ad14a2fc5e922a Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Tue, 29 Jul 2025 19:45:02 +0300 Subject: [PATCH 17/18] Delete examples/multi_agent/board_of_directors/trading_showcase/test_results.log --- .../board_of_directors/trading_showcase/test_results.log | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 examples/multi_agent/board_of_directors/trading_showcase/test_results.log diff --git a/examples/multi_agent/board_of_directors/trading_showcase/test_results.log b/examples/multi_agent/board_of_directors/trading_showcase/test_results.log deleted file mode 100644 index 69749700..00000000 --- a/examples/multi_agent/board_of_directors/trading_showcase/test_results.log +++ /dev/null @@ -1,7 +0,0 @@ -2025-07-25 16:33:37 | INFO | __main__:run_all_tests:380 - šŸš€ Starting Comprehensive Test Suite -2025-07-25 16:33:37 | INFO | __main__:test_ollama_installation:67 - šŸ” Testing Ollama Installation -2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: ollama --version -2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: ollama list -2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: ollama list -2025-07-25 16:33:37 | INFO | __main__:test_python_dependencies:86 - šŸ Testing Python Dependencies -2025-07-25 16:33:37 | INFO | __main__:run_command:35 - Running command: C:\Users\arona\scoop\apps\python\current\python.exe -m pip list From def507cf5ca8a6f024e7c08db33c3e96ccbc0b01 Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Fri, 1 Aug 2025 23:25:52 +0300 Subject: [PATCH 18/18] Update board_of_directors_example.py --- .../board_of_directors_example.py | 440 ++++-------------- 1 file changed, 100 insertions(+), 340 deletions(-) diff --git a/examples/multi_agent/board_of_directors/board_of_directors_example.py b/examples/multi_agent/board_of_directors/board_of_directors_example.py index 425d460b..bc043733 100644 --- a/examples/multi_agent/board_of_directors/board_of_directors_example.py +++ b/examples/multi_agent/board_of_directors/board_of_directors_example.py @@ -5,19 +5,25 @@ This example demonstrates how to use the Board of Directors swarm feature in the Swarms Framework. It shows how to create a board, configure it, and use it to orchestrate tasks across multiple agents. -The example includes: -1. Basic Board of Directors setup and usage -2. Custom board member configuration -3. Task execution and feedback -4. Configuration management +To run this example: +1. Make sure you're in the root directory of the swarms project +2. Run: python examples/multi_agent/board_of_directors/board_of_directors_example.py """ import os import sys -from typing import List, Optional - -# Add the parent directory to the path to import swarms -sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))) +from typing import List + +# Add the root directory to the Python path if running from examples directory +current_dir = os.path.dirname(os.path.abspath(__file__)) +if 'examples' in current_dir: + root_dir = current_dir + while os.path.basename(root_dir) != 'examples' and root_dir != os.path.dirname(root_dir): + root_dir = os.path.dirname(root_dir) + if os.path.basename(root_dir) == 'examples': + root_dir = os.path.dirname(root_dir) + if root_dir not in sys.path: + sys.path.insert(0, root_dir) from swarms.structs.board_of_directors_swarm import ( BoardOfDirectorsSwarm, @@ -25,413 +31,167 @@ from swarms.structs.board_of_directors_swarm import ( BoardMemberRole, ) from swarms.structs.agent import Agent -from swarms.config.board_config import ( - enable_board_feature, - disable_board_feature, - is_board_feature_enabled, - create_default_config_file, - set_board_size, - set_decision_threshold, - set_board_model, - enable_verbose_logging, - disable_verbose_logging, -) - - -def enable_board_directors_feature() -> None: - """ - Enable the Board of Directors feature. - - This function demonstrates how to enable the Board of Directors feature - globally and create a default configuration file. - """ - print("šŸ”§ Enabling Board of Directors feature...") - - try: - # Create a default configuration file - create_default_config_file("swarms_board_config.yaml") - - # Enable the feature - enable_board_feature("swarms_board_config.yaml") - - # Configure some default settings - set_board_size(3) - set_decision_threshold(0.6) - set_board_model("gpt-4o-mini") - enable_verbose_logging("swarms_board_config.yaml") - - print("āœ… Board of Directors feature enabled successfully!") - print("šŸ“ Configuration file created: swarms_board_config.yaml") - - except Exception as e: - print(f"āŒ Failed to enable Board of Directors feature: {e}") - raise -def create_custom_board_members() -> List[BoardMember]: - """ - Create custom board members with specific roles and expertise. - - This function demonstrates how to create a custom board with - specialized roles and expertise areas. +def create_board_members() -> List[BoardMember]: + """Create board members with specific roles.""" - Returns: - List[BoardMember]: List of custom board members - """ - print("šŸ‘„ Creating custom board members...") - - # Create specialized board members chairman = Agent( - agent_name="Executive_Chairman", - agent_description="Executive Chairman with strategic vision and leadership expertise", + agent_name="Chairman", + agent_description="Executive Chairman with strategic vision", model_name="gpt-4o-mini", max_loops=1, - system_prompt="""You are the Executive Chairman of the Board. Your role is to: -1. Provide strategic leadership and vision -2. Facilitate high-level decision-making -3. Ensure board effectiveness and governance -4. Represent the organization's interests -5. Guide long-term strategic planning - -You should be visionary, strategic, and focused on organizational success.""", + system_prompt="You are the Executive Chairman. Provide strategic leadership and facilitate decision-making.", ) cto = Agent( agent_name="CTO", - agent_description="Chief Technology Officer with deep technical expertise", + agent_description="Chief Technology Officer with technical expertise", model_name="gpt-4o-mini", max_loops=1, - system_prompt="""You are the Chief Technology Officer. Your role is to: -1. Provide technical leadership and strategy -2. Evaluate technology solutions and architectures -3. Ensure technical feasibility of proposed solutions -4. Guide technology-related decisions -5. Maintain technical standards and best practices - -You should be technically proficient, innovative, and focused on technical excellence.""", + system_prompt="You are the CTO. Provide technical leadership and evaluate technology solutions.", ) cfo = Agent( agent_name="CFO", - agent_description="Chief Financial Officer with financial and risk management expertise", + agent_description="Chief Financial Officer with financial expertise", model_name="gpt-4o-mini", max_loops=1, - system_prompt="""You are the Chief Financial Officer. Your role is to: -1. Provide financial analysis and insights -2. Evaluate financial implications of decisions -3. Ensure financial sustainability and risk management -4. Guide resource allocation and budgeting -5. Maintain financial controls and compliance - -You should be financially astute, risk-aware, and focused on financial health.""", + system_prompt="You are the CFO. Provide financial analysis and ensure fiscal responsibility.", ) - # Create BoardMember objects with roles and expertise - board_members = [ + return [ BoardMember( agent=chairman, role=BoardMemberRole.CHAIRMAN, voting_weight=2.0, - expertise_areas=["strategic_planning", "leadership", "governance", "business_strategy"] + expertise_areas=["leadership", "strategy"] ), BoardMember( agent=cto, role=BoardMemberRole.EXECUTIVE_DIRECTOR, voting_weight=1.5, - expertise_areas=["technology", "architecture", "innovation", "technical_strategy"] + expertise_areas=["technology", "innovation"] ), BoardMember( agent=cfo, role=BoardMemberRole.EXECUTIVE_DIRECTOR, voting_weight=1.5, - expertise_areas=["finance", "risk_management", "budgeting", "financial_analysis"] + expertise_areas=["finance", "risk_management"] ), ] - - print(f"āœ… Created {len(board_members)} custom board members") - for member in board_members: - print(f" - {member.agent.agent_name} ({member.role.value})") - - return board_members def create_worker_agents() -> List[Agent]: - """ - Create worker agents for the swarm. - - This function creates specialized worker agents that will be - managed by the Board of Directors. + """Create worker agents for the swarm.""" - Returns: - List[Agent]: List of worker agents - """ - print("šŸ› ļø Creating worker agents...") - - # Create specialized worker agents researcher = Agent( - agent_name="Research_Analyst", - agent_description="Research analyst specializing in market research and data analysis", + agent_name="Researcher", + agent_description="Research analyst for data analysis", model_name="gpt-4o-mini", max_loops=1, - system_prompt="""You are a Research Analyst. Your responsibilities include: -1. Conducting thorough research on assigned topics -2. Analyzing data and market trends -3. Preparing comprehensive research reports -4. Providing data-driven insights and recommendations -5. Maintaining high standards of research quality - -You should be analytical, thorough, and evidence-based in your work.""", + system_prompt="You are a Research Analyst. Conduct thorough research and provide data-driven insights.", ) developer = Agent( - agent_name="Software_Developer", - agent_description="Software developer with expertise in system design and implementation", + agent_name="Developer", + agent_description="Software developer for implementation", model_name="gpt-4o-mini", max_loops=1, - system_prompt="""You are a Software Developer. Your responsibilities include: -1. Designing and implementing software solutions -2. Writing clean, maintainable code -3. Conducting code reviews and testing -4. Collaborating with team members -5. Following best practices and coding standards - -You should be technically skilled, detail-oriented, and focused on quality.""", + system_prompt="You are a Software Developer. Design and implement software solutions.", ) marketer = Agent( - agent_name="Marketing_Specialist", - agent_description="Marketing specialist with expertise in digital marketing and brand strategy", + agent_name="Marketer", + agent_description="Marketing specialist for strategy", model_name="gpt-4o-mini", max_loops=1, - system_prompt="""You are a Marketing Specialist. Your responsibilities include: -1. Developing marketing strategies and campaigns -2. Creating compelling content and messaging -3. Analyzing market trends and customer behavior -4. Managing brand presence and reputation -5. Measuring and optimizing marketing performance - -You should be creative, strategic, and customer-focused in your approach.""", + system_prompt="You are a Marketing Specialist. Develop marketing strategies and campaigns.", ) - agents = [researcher, developer, marketer] - - print(f"āœ… Created {len(agents)} worker agents") - for agent in agents: - print(f" - {agent.agent_name}: {agent.agent_description}") - - return agents + return [researcher, developer, marketer] -def run_board_of_directors_example() -> None: - """ - Run a comprehensive Board of Directors example. +def run_board_example() -> None: + """Run a Board of Directors example.""" - This function demonstrates the complete workflow of using - the Board of Directors swarm to orchestrate tasks. - """ - print("\n" + "="*60) - print("šŸ›ļø BOARD OF DIRECTORS SWARM EXAMPLE") - print("="*60) + # Create board members and worker agents + board_members = create_board_members() + worker_agents = create_worker_agents() - try: - # Check if Board of Directors feature is enabled - if not is_board_feature_enabled(): - print("āš ļø Board of Directors feature is not enabled. Enabling now...") - enable_board_directors_feature() - - # Create custom board members - board_members = create_custom_board_members() - - # Create worker agents - worker_agents = create_worker_agents() - - # Create the Board of Directors swarm - print("\nšŸ›ļø Creating Board of Directors swarm...") - board_swarm = BoardOfDirectorsSwarm( - name="Executive_Board_Swarm", - description="Executive board with specialized roles for strategic decision-making", - board_members=board_members, - agents=worker_agents, - max_loops=2, - verbose=True, - decision_threshold=0.6, - enable_voting=True, - enable_consensus=True, - ) - - print("āœ… Board of Directors swarm created successfully!") - - # Display board summary - summary = board_swarm.get_board_summary() - print(f"\nšŸ“Š Board Summary:") - print(f" Board Name: {summary['board_name']}") - print(f" Total Members: {summary['total_members']}") - print(f" Total Agents: {summary['total_agents']}") - print(f" Max Loops: {summary['max_loops']}") - print(f" Decision Threshold: {summary['decision_threshold']}") - - print(f"\nšŸ‘„ Board Members:") - for member in summary['members']: - print(f" - {member['name']} ({member['role']}) - Weight: {member['voting_weight']}") - print(f" Expertise: {', '.join(member['expertise_areas'])}") - - # Define a complex task for the board to handle - task = """ - Develop a comprehensive strategy for launching a new AI-powered product in the market. - - The task involves: - 1. Market research and competitive analysis - 2. Technical architecture and development planning - 3. Marketing strategy and go-to-market plan - 4. Financial projections and risk assessment - - Please coordinate the efforts of all team members to create a cohesive strategy. - """ - - print(f"\nšŸ“‹ Executing task: {task.strip()[:100]}...") - - # Execute the task using the Board of Directors swarm - result = board_swarm.run(task=task) - - print("\nāœ… Task completed successfully!") - print(f"šŸ“„ Result type: {type(result)}") - - # Display conversation history - if hasattr(result, 'get') and callable(result.get): - conversation_history = result.get('conversation_history', []) - print(f"\nšŸ’¬ Conversation History ({len(conversation_history)} messages):") - for i, message in enumerate(conversation_history[-5:], 1): # Show last 5 messages - role = message.get('role', 'Unknown') - content = message.get('content', '')[:100] + "..." if len(message.get('content', '')) > 100 else message.get('content', '') - print(f" {i}. {role}: {content}") - else: - print(f"\nšŸ“ Result: {str(result)[:200]}...") - - print("\nšŸŽ‰ Board of Directors example completed successfully!") - - except Exception as e: - print(f"āŒ Error in Board of Directors example: {e}") - import traceback - traceback.print_exc() - - -def run_simple_board_example() -> None: - """ - Run a simple Board of Directors example with default settings. + # Create the Board of Directors swarm + board_swarm = BoardOfDirectorsSwarm( + name="Executive_Board", + board_members=board_members, + agents=worker_agents, + max_loops=2, + verbose=True, + decision_threshold=0.6, + ) - This function demonstrates a basic usage of the Board of Directors - swarm with minimal configuration. + # Define task + task = """ + Develop a strategy for launching a new AI-powered product in the market. + Include market research, technical planning, marketing strategy, and financial projections. """ - print("\n" + "="*60) - print("šŸ›ļø SIMPLE BOARD OF DIRECTORS EXAMPLE") - print("="*60) - try: - # Create simple worker agents - print("šŸ› ļø Creating simple worker agents...") - - analyst = Agent( - agent_name="Data_Analyst", - agent_description="Data analyst for processing and analyzing information", - model_name="gpt-4o-mini", - max_loops=1, - ) - - writer = Agent( - agent_name="Content_Writer", - agent_description="Content writer for creating reports and documentation", - model_name="gpt-4o-mini", - max_loops=1, - ) - - agents = [analyst, writer] - - # Create Board of Directors swarm with default settings - print("šŸ›ļø Creating Board of Directors swarm with default settings...") - board_swarm = BoardOfDirectorsSwarm( - name="Simple_Board_Swarm", - agents=agents, - verbose=True, - ) - - print("āœ… Simple Board of Directors swarm created!") - - # Simple task - task = "Analyze the current market trends and create a summary report with recommendations." - - print(f"\nšŸ“‹ Executing simple task: {task}") - - # Execute the task - result = board_swarm.run(task=task) - - print("\nāœ… Simple task completed successfully!") - print(f"šŸ“„ Result type: {type(result)}") - - if hasattr(result, 'get') and callable(result.get): - conversation_history = result.get('conversation_history', []) - print(f"\nšŸ’¬ Conversation History ({len(conversation_history)} messages):") - for i, message in enumerate(conversation_history[-3:], 1): # Show last 3 messages - role = message.get('role', 'Unknown') - content = message.get('content', '')[:80] + "..." if len(message.get('content', '')) > 80 else message.get('content', '') - print(f" {i}. {role}: {content}") - else: - print(f"\nšŸ“ Result: {str(result)[:150]}...") - - print("\nšŸŽ‰ Simple Board of Directors example completed!") - - except Exception as e: - print(f"āŒ Error in simple Board of Directors example: {e}") - import traceback - traceback.print_exc() + # Execute the task + result = board_swarm.run(task=task) + + print("Task completed successfully!") + print(f"Result: {result}") -def check_environment() -> bool: - """ - Check if the environment is properly set up for the example. +def run_simple_example() -> None: + """Run a simple Board of Directors example.""" - Returns: - bool: True if environment is ready, False otherwise - """ - # Check for OpenAI API key - if not os.getenv("OPENAI_API_KEY"): - print("āš ļø Warning: OPENAI_API_KEY environment variable not set.") - print(" The example may not work without a valid API key.") - print(" Please set your OpenAI API key: export OPENAI_API_KEY='your-key-here'") - return False + # Create simple agents + analyst = Agent( + agent_name="Analyst", + agent_description="Data analyst", + model_name="gpt-4o-mini", + max_loops=1, + ) - return True + writer = Agent( + agent_name="Writer", + agent_description="Content writer", + model_name="gpt-4o-mini", + max_loops=1, + ) + + # Create swarm with default settings + board_swarm = BoardOfDirectorsSwarm( + name="Simple_Board", + agents=[analyst, writer], + verbose=True, + ) + + # Execute simple task + task = "Analyze current market trends and create a summary report." + result = board_swarm.run(task=task) + + print("Simple example completed!") + print(f"Result: {result}") def main() -> None: - """ - Main function to run the Board of Directors examples. - """ - print("šŸš€ Board of Directors Swarm Examples") - print("="*50) + """Main function to run the examples.""" - # Check environment - if not check_environment(): - print("\nāš ļø Environment check failed. Please set up your environment properly.") + if not os.getenv("OPENAI_API_KEY"): + print("Warning: OPENAI_API_KEY not set. Example may not work.") return try: - # Run simple example first - run_simple_board_example() - - # Run comprehensive example - run_board_of_directors_example() + print("Running simple Board of Directors example...") + run_simple_example() - print("\n" + "="*60) - print("šŸŽ‰ All Board of Directors examples completed successfully!") - print("="*60) + print("\nRunning comprehensive Board of Directors example...") + run_board_example() - except KeyboardInterrupt: - print("\nāš ļø Examples interrupted by user.") except Exception as e: - print(f"\nāŒ Unexpected error: {e}") - import traceback - traceback.print_exc() + print(f"Error: {e}") if __name__ == "__main__": - main() \ No newline at end of file + main()