From a7f349cc8db38ec7646fc22b0c543a2557d73045 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:24:25 +0300
Subject: [PATCH 01/56] Update Dockerfile
---
Dockerfile | 34 +++++++++++++++++++++++-----------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index aa312517..44392b09 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,25 +1,37 @@
-# Use a lightweight Python image
+# Multi-stage build for optimized Docker image
+FROM python:3.11-slim-bullseye as builder
+
+# Install system dependencies for building
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ build-essential gcc curl \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install UV for faster package management
+RUN curl -LsSf https://astral.sh/uv/install.sh | sh
+ENV PATH="/root/.cargo/bin:${PATH}"
+
+# Create a virtual environment and install dependencies
+RUN uv venv /opt/venv
+ENV PATH="/opt/venv/bin:$PATH"
+
+# Install the swarms package using UV
+RUN uv pip install --system -U swarms
+
+# Final stage
FROM python:3.11-slim-bullseye
# Environment config for speed and safety
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
- PIP_NO_CACHE_DIR=1 \
- PIP_DISABLE_PIP_VERSION_CHECK=1 \
- PATH="/app:${PATH}" \
+ PATH="/opt/venv/bin:${PATH}" \
PYTHONPATH="/app:${PYTHONPATH}" \
USER=swarms
# Set working directory
WORKDIR /app
-# System dependencies (minimal)
-RUN apt-get update && apt-get install -y --no-install-recommends \
- build-essential gcc \
- && rm -rf /var/lib/apt/lists/*
-
-# Install the swarms package
-RUN pip install --upgrade pip && pip install -U swarms
+# Copy virtual environment from builder stage
+COPY --from=builder /opt/venv /opt/venv
# Add non-root user
RUN useradd -m -s /bin/bash -U $USER && \
From 13e7d5b20b1fe6fdbb447ab5e44678fde7b18b7e Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:26:55 +0300
Subject: [PATCH 02/56] Update docker-publish.yml
---
.github/workflows/docker-publish.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
index 34372b3e..40fac9cb 100644
--- a/.github/workflows/docker-publish.yml
+++ b/.github/workflows/docker-publish.yml
@@ -58,6 +58,7 @@ jobs:
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
+ type=raw,value=latest,enable={{is_default_branch}}
# Build and push Docker image
- name: Build and push Docker image
@@ -71,3 +72,5 @@ jobs:
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
+ build-args: |
+ BUILDKIT_INLINE_CACHE=1
From 6f5496a48db4e450c75fba6fc808fb595c3d27d2 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:30:26 +0300
Subject: [PATCH 03/56] Add files via upload
---
docker-compose.yml | 71 ++++++++++++++++++++++++++++++++++++++++++++++
test_docker.py | 65 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 136 insertions(+)
create mode 100644 docker-compose.yml
create mode 100644 test_docker.py
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..8e4f2360
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,71 @@
+version: '3.8'
+
+services:
+ swarms:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: swarms:latest
+ container_name: swarms-container
+ environment:
+ - PYTHONUNBUFFERED=1
+ - PYTHONPATH=/app
+ # Add your API keys here or use .env file
+ # - OPENAI_API_KEY=${OPENAI_API_KEY}
+ # - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
+ # - GOOGLE_API_KEY=${GOOGLE_API_KEY}
+ volumes:
+ - .:/app
+ - ./data:/app/data
+ - ./models:/app/models
+ working_dir: /app
+ command: python test_docker.py
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD", "python", "-c", "import swarms; print('Health check passed')"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ start_period: 40s
+
+ swarms-dev:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: swarms:dev
+ container_name: swarms-dev-container
+ environment:
+ - PYTHONUNBUFFERED=1
+ - PYTHONPATH=/app
+ volumes:
+ - .:/app
+ - ./data:/app/data
+ - ./models:/app/models
+ working_dir: /app
+ command: bash
+ stdin_open: true
+ tty: true
+ restart: unless-stopped
+
+ swarms-api:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: swarms:api
+ container_name: swarms-api-container
+ environment:
+ - PYTHONUNBUFFERED=1
+ - PYTHONPATH=/app
+ volumes:
+ - .:/app
+ working_dir: /app
+ ports:
+ - "8000:8000"
+ command: python -m uvicorn main:app --host 0.0.0.0 --port 8000 --reload
+ restart: unless-stopped
+ depends_on:
+ - swarms
+
+networks:
+ default:
+ name: swarms-network
\ No newline at end of file
diff --git a/test_docker.py b/test_docker.py
new file mode 100644
index 00000000..4733fc0d
--- /dev/null
+++ b/test_docker.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+"""
+Test script to verify Swarms installation in Docker container.
+"""
+
+import sys
+from typing import Dict, Any
+
+def test_swarms_import() -> Dict[str, Any]:
+ """
+ Test that swarms can be imported and basic functionality works.
+
+ Returns:
+ Dict[str, Any]: Test results
+ """
+ try:
+ import swarms
+ print(f"ā
Swarms imported successfully. Version: {swarms.__version__}")
+
+ # Test basic functionality
+ from swarms import Agent
+ print("ā
Agent class imported successfully")
+
+ return {
+ "status": "success",
+ "version": swarms.__version__,
+ "message": "Swarms package is working correctly"
+ }
+
+ except ImportError as e:
+ print(f"ā Failed to import swarms: {e}")
+ return {
+ "status": "error",
+ "error": str(e),
+ "message": "Swarms package import failed"
+ }
+ except Exception as e:
+ print(f"ā Unexpected error: {e}")
+ return {
+ "status": "error",
+ "error": str(e),
+ "message": "Unexpected error occurred"
+ }
+
+def main() -> None:
+ """Main function to run tests."""
+ print("š Testing Swarms Docker Image...")
+ print("=" * 50)
+
+ # Test Python version
+ print(f"Python version: {sys.version}")
+
+ # Test swarms import
+ result = test_swarms_import()
+
+ print("=" * 50)
+ if result["status"] == "success":
+ print("š All tests passed! Docker image is working correctly.")
+ sys.exit(0)
+ else:
+ print("š„ Tests failed! Please check the Docker image.")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
From 0c410052b026a5d45802baf1db40f3312cdffe1f Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:30:50 +0300
Subject: [PATCH 04/56] Add files via upload
---
DOCKER.md | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 225 insertions(+)
create mode 100644 DOCKER.md
diff --git a/DOCKER.md b/DOCKER.md
new file mode 100644
index 00000000..0b2ec1fb
--- /dev/null
+++ b/DOCKER.md
@@ -0,0 +1,225 @@
+# Swarms Docker Image
+
+This repository includes a Docker image for running Swarms, an AI agent framework. The image is automatically built and published to DockerHub on every push to the main branch and on version tags.
+
+## š³ Quick Start
+
+### Pull and Run
+
+```bash
+# Pull the latest image
+docker pull kyegomez/swarms:latest
+
+# Run a simple test
+docker run --rm kyegomez/swarms:latest python test_docker.py
+
+# Run with interactive shell
+docker run -it --rm kyegomez/swarms:latest bash
+```
+
+### Using Specific Versions
+
+```bash
+# Pull a specific version
+docker pull kyegomez/swarms:v8.0.4
+
+# Run with specific version
+docker run --rm kyegomez/swarms:v8.0.4 python -c "import swarms; print(swarms.__version__)"
+```
+
+## šļø Building Locally
+
+### Prerequisites
+
+- Docker installed on your system
+- Git to clone the repository
+
+### Build Steps
+
+```bash
+# Clone the repository
+git clone https://github.com/kyegomez/swarms.git
+cd swarms
+
+# Build the image
+docker build -t swarms:latest .
+
+# Test the image
+docker run --rm swarms:latest python test_docker.py
+```
+
+## š Usage Examples
+
+### Basic Agent Example
+
+```bash
+# Create a Python script (agent_example.py)
+cat > agent_example.py << 'EOF'
+from swarms import Agent
+
+# Create an agent
+agent = Agent(
+ agent_name="test_agent",
+ system_prompt="You are a helpful AI assistant."
+)
+
+# Run the agent
+result = agent.run("Hello! How are you today?")
+print(result)
+EOF
+
+# Run in Docker
+docker run --rm -v $(pwd):/app swarms:latest python /app/agent_example.py
+```
+
+### Interactive Development
+
+```bash
+# Run with volume mount for development
+docker run -it --rm \
+ -v $(pwd):/app \
+ -w /app \
+ swarms:latest bash
+
+# Inside the container, you can now run Python scripts
+python your_script.py
+```
+
+### Using Environment Variables
+
+```bash
+# Run with environment variables
+docker run --rm \
+ -e OPENAI_API_KEY=your_api_key_here \
+ -e ANTHROPIC_API_KEY=your_anthropic_key_here \
+ swarms:latest python your_script.py
+```
+
+## š§ Configuration
+
+### Environment Variables
+
+The Docker image supports the following environment variables:
+
+- `OPENAI_API_KEY`: Your OpenAI API key
+- `ANTHROPIC_API_KEY`: Your Anthropic API key
+- `GOOGLE_API_KEY`: Your Google API key
+- `PYTHONPATH`: Additional Python path entries
+- `PYTHONUNBUFFERED`: Set to 1 for unbuffered output
+
+### Volume Mounts
+
+Common volume mount patterns:
+
+```bash
+# Mount current directory for development
+-v $(pwd):/app
+
+# Mount specific directories
+-v $(pwd)/data:/app/data
+-v $(pwd)/models:/app/models
+
+# Mount configuration files
+-v $(pwd)/config:/app/config
+```
+
+## š Troubleshooting
+
+### Common Issues
+
+1. **Permission Denied**
+ ```bash
+ # Fix permission issues
+ docker run --rm -v $(pwd):/app:rw swarms:latest python your_script.py
+ ```
+
+2. **Memory Issues**
+ ```bash
+ # Increase memory limit
+ docker run --rm --memory=4g swarms:latest python your_script.py
+ ```
+
+3. **Network Issues**
+ ```bash
+ # Use host network
+ docker run --rm --network=host swarms:latest python your_script.py
+ ```
+
+### Debug Mode
+
+```bash
+# Run with debug output
+docker run --rm -e PYTHONUNBUFFERED=1 swarms:latest python -u your_script.py
+
+# Run with interactive debugging
+docker run -it --rm swarms:latest python -m pdb your_script.py
+```
+
+## š CI/CD Integration
+
+The Docker image is automatically built and published via GitHub Actions:
+
+- **Triggers**: Push to main branch, version tags (v*.*.*)
+- **Platforms**: linux/amd64, linux/arm64
+- **Registry**: DockerHub (kyegomez/swarms)
+
+### GitHub Actions Secrets Required
+
+- `DOCKERHUB_USERNAME`: Your DockerHub username
+- `DOCKERHUB_TOKEN`: Your DockerHub access token
+
+## š Image Details
+
+### Base Image
+- Python 3.11-slim-bullseye
+- Multi-stage build for optimization
+- UV package manager for faster installations
+
+### Image Size
+- Optimized for minimal size
+- Multi-stage build reduces final image size
+- Only necessary dependencies included
+
+### Security
+- Non-root user execution
+- Minimal system dependencies
+- Regular security updates
+
+## š¤ Contributing
+
+To contribute to the Docker setup:
+
+1. Fork the repository
+2. Make your changes to the Dockerfile
+3. Test locally: `docker build -t swarms:test .`
+4. Submit a pull request
+
+### Testing Changes
+
+```bash
+# Build test image
+docker build -t swarms:test .
+
+# Run tests
+docker run --rm swarms:test python test_docker.py
+
+# Test with your code
+docker run --rm -v $(pwd):/app swarms:test python your_test_script.py
+```
+
+## š License
+
+This Docker setup is part of the Swarms project and follows the same MIT license.
+
+## š Support
+
+For issues with the Docker image:
+
+1. Check the troubleshooting section above
+2. Review the GitHub Actions logs for build issues
+3. Open an issue on GitHub with detailed error information
+4. Include your Docker version and system information
+
+---
+
+**Note**: This Docker image is automatically updated with each release. For production use, consider pinning to specific version tags for stability.
\ No newline at end of file
From f88c94ba469bfe2bd88ede0c19915d46f411d951 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:33:08 +0300
Subject: [PATCH 05/56] Add files via upload
---
scripts/docker-utils.ps1 | 139 ++++++++++++++++++++++++
scripts/docker-utils.sh | 167 +++++++++++++++++++++++++++++
scripts/setup-dockerhub-secrets.md | 113 +++++++++++++++++++
3 files changed, 419 insertions(+)
create mode 100644 scripts/docker-utils.ps1
create mode 100644 scripts/docker-utils.sh
create mode 100644 scripts/setup-dockerhub-secrets.md
diff --git a/scripts/docker-utils.ps1 b/scripts/docker-utils.ps1
new file mode 100644
index 00000000..59c94636
--- /dev/null
+++ b/scripts/docker-utils.ps1
@@ -0,0 +1,139 @@
+# Docker utilities for Swarms project (PowerShell version)
+# Usage: .\scripts\docker-utils.ps1 [command]
+
+param(
+ [Parameter(Position=0)]
+ [string]$Command = "help"
+)
+
+# Configuration
+$ImageName = "swarms"
+$Registry = "kyegomez"
+$FullImageName = "$Registry/$ImageName"
+
+# Functions
+function Write-Usage {
+ Write-Host "Docker Utilities for Swarms" -ForegroundColor Blue
+ Write-Host ""
+ Write-Host "Usage: .\scripts\docker-utils.ps1 [command]"
+ Write-Host ""
+ Write-Host "Commands:"
+ Write-Host " build Build the Docker image locally"
+ Write-Host " test Test the Docker image"
+ Write-Host " run Run the Docker image interactively"
+ Write-Host " push Push to DockerHub (requires login)"
+ Write-Host " clean Clean up Docker images and containers"
+ Write-Host " logs Show logs from running containers"
+ Write-Host " shell Open shell in running container"
+ Write-Host " compose-up Start services with docker-compose"
+ Write-Host " compose-down Stop services with docker-compose"
+ Write-Host " help Show this help message"
+ Write-Host ""
+}
+
+function Build-Image {
+ Write-Host "Building Docker image..." -ForegroundColor Green
+ docker build -t "$ImageName`:latest" .
+ Write-Host "ā
Image built successfully!" -ForegroundColor Green
+}
+
+function Test-Image {
+ Write-Host "Testing Docker image..." -ForegroundColor Green
+ docker run --rm "$ImageName`:latest" python test_docker.py
+ Write-Host "ā
Image test completed!" -ForegroundColor Green
+}
+
+function Run-Interactive {
+ Write-Host "Running Docker image interactively..." -ForegroundColor Green
+ docker run -it --rm -v "${PWD}:/app" -w /app "$ImageName`:latest" bash
+}
+
+function Push-ToDockerHub {
+ Write-Host "ā ļø Make sure you're logged into DockerHub first!" -ForegroundColor Yellow
+ Write-Host "Pushing to DockerHub..." -ForegroundColor Green
+
+ # Tag the image
+ docker tag "$ImageName`:latest" "$FullImageName`:latest"
+
+ # Push to DockerHub
+ docker push "$FullImageName`:latest"
+
+ Write-Host "ā
Image pushed to DockerHub!" -ForegroundColor Green
+}
+
+function Clean-Docker {
+ Write-Host "Cleaning up Docker resources..." -ForegroundColor Yellow
+
+ # Stop and remove containers
+ docker ps -aq | ForEach-Object { docker rm -f $_ }
+
+ # Remove images
+ docker images "$ImageName" -q | ForEach-Object { docker rmi -f $_ }
+
+ # Remove dangling images
+ docker image prune -f
+
+ Write-Host "ā
Docker cleanup completed!" -ForegroundColor Green
+}
+
+function Show-Logs {
+ Write-Host "Showing logs from running containers..." -ForegroundColor Green
+ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
+ Write-Host ""
+
+ # Show logs for swarms containers
+ $containers = docker ps --filter "name=swarms" --format "{{.Names}}"
+ foreach ($container in $containers) {
+ Write-Host "Logs for $container:" -ForegroundColor Blue
+ docker logs $container --tail 20
+ Write-Host ""
+ }
+}
+
+function Open-Shell {
+ Write-Host "Opening shell in running container..." -ForegroundColor Green
+
+ # Find running swarms container
+ $container = docker ps --filter "name=swarms" --format "{{.Names}}" | Select-Object -First 1
+
+ if (-not $container) {
+ Write-Host "ā No running swarms container found!" -ForegroundColor Red
+ Write-Host "Start a container first with: .\scripts\docker-utils.ps1 run"
+ exit 1
+ }
+
+ Write-Host "Opening shell in $container..." -ForegroundColor Blue
+ docker exec -it $container bash
+}
+
+function Compose-Up {
+ Write-Host "Starting services with docker-compose..." -ForegroundColor Green
+ docker-compose up -d
+ Write-Host "ā
Services started!" -ForegroundColor Green
+ Write-Host "Use 'docker-compose logs -f' to view logs"
+}
+
+function Compose-Down {
+ Write-Host "Stopping services with docker-compose..." -ForegroundColor Yellow
+ docker-compose down
+ Write-Host "ā
Services stopped!" -ForegroundColor Green
+}
+
+# Main script logic
+switch ($Command.ToLower()) {
+ "build" { Build-Image }
+ "test" { Test-Image }
+ "run" { Run-Interactive }
+ "push" { Push-ToDockerHub }
+ "clean" { Clean-Docker }
+ "logs" { Show-Logs }
+ "shell" { Open-Shell }
+ "compose-up" { Compose-Up }
+ "compose-down" { Compose-Down }
+ "help" { Write-Usage }
+ default {
+ Write-Host "ā Unknown command: $Command" -ForegroundColor Red
+ Write-Usage
+ exit 1
+ }
+}
\ No newline at end of file
diff --git a/scripts/docker-utils.sh b/scripts/docker-utils.sh
new file mode 100644
index 00000000..5b86e7dd
--- /dev/null
+++ b/scripts/docker-utils.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+
+# Docker utilities for Swarms project
+# Usage: ./scripts/docker-utils.sh [command]
+
+set -e
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Configuration
+IMAGE_NAME="swarms"
+REGISTRY="kyegomez"
+FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
+
+# Functions
+print_usage() {
+ echo -e "${BLUE}Docker Utilities for Swarms${NC}"
+ echo ""
+ echo "Usage: $0 [command]"
+ echo ""
+ echo "Commands:"
+ echo " build Build the Docker image locally"
+ echo " test Test the Docker image"
+ echo " run Run the Docker image interactively"
+ echo " push Push to DockerHub (requires login)"
+ echo " clean Clean up Docker images and containers"
+ echo " logs Show logs from running containers"
+ echo " shell Open shell in running container"
+ echo " compose-up Start services with docker-compose"
+ echo " compose-down Stop services with docker-compose"
+ echo " help Show this help message"
+ echo ""
+}
+
+build_image() {
+ echo -e "${GREEN}Building Docker image...${NC}"
+ docker build -t "${IMAGE_NAME}:latest" .
+ echo -e "${GREEN}ā
Image built successfully!${NC}"
+}
+
+test_image() {
+ echo -e "${GREEN}Testing Docker image...${NC}"
+ docker run --rm "${IMAGE_NAME}:latest" python test_docker.py
+ echo -e "${GREEN}ā
Image test completed!${NC}"
+}
+
+run_interactive() {
+ echo -e "${GREEN}Running Docker image interactively...${NC}"
+ docker run -it --rm \
+ -v "$(pwd):/app" \
+ -w /app \
+ "${IMAGE_NAME}:latest" bash
+}
+
+push_to_dockerhub() {
+ echo -e "${YELLOW}ā ļø Make sure you're logged into DockerHub first!${NC}"
+ echo -e "${GREEN}Pushing to DockerHub...${NC}"
+
+ # Tag the image
+ docker tag "${IMAGE_NAME}:latest" "${FULL_IMAGE_NAME}:latest"
+
+ # Push to DockerHub
+ docker push "${FULL_IMAGE_NAME}:latest"
+
+ echo -e "${GREEN}ā
Image pushed to DockerHub!${NC}"
+}
+
+clean_docker() {
+ echo -e "${YELLOW}Cleaning up Docker resources...${NC}"
+
+ # Stop and remove containers
+ docker ps -aq | xargs -r docker rm -f
+
+ # Remove images
+ docker images "${IMAGE_NAME}" -q | xargs -r docker rmi -f
+
+ # Remove dangling images
+ docker image prune -f
+
+ echo -e "${GREEN}ā
Docker cleanup completed!${NC}"
+}
+
+show_logs() {
+ echo -e "${GREEN}Showing logs from running containers...${NC}"
+ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
+ echo ""
+
+ # Show logs for swarms containers
+ for container in $(docker ps --filter "name=swarms" --format "{{.Names}}"); do
+ echo -e "${BLUE}Logs for $container:${NC}"
+ docker logs "$container" --tail 20
+ echo ""
+ done
+}
+
+open_shell() {
+ echo -e "${GREEN}Opening shell in running container...${NC}"
+
+ # Find running swarms container
+ container=$(docker ps --filter "name=swarms" --format "{{.Names}}" | head -1)
+
+ if [ -z "$container" ]; then
+ echo -e "${RED}ā No running swarms container found!${NC}"
+ echo "Start a container first with: $0 run"
+ exit 1
+ fi
+
+ echo -e "${BLUE}Opening shell in $container...${NC}"
+ docker exec -it "$container" bash
+}
+
+compose_up() {
+ echo -e "${GREEN}Starting services with docker-compose...${NC}"
+ docker-compose up -d
+ echo -e "${GREEN}ā
Services started!${NC}"
+ echo "Use 'docker-compose logs -f' to view logs"
+}
+
+compose_down() {
+ echo -e "${YELLOW}Stopping services with docker-compose...${NC}"
+ docker-compose down
+ echo -e "${GREEN}ā
Services stopped!${NC}"
+}
+
+# Main script logic
+case "${1:-help}" in
+ build)
+ build_image
+ ;;
+ test)
+ test_image
+ ;;
+ run)
+ run_interactive
+ ;;
+ push)
+ push_to_dockerhub
+ ;;
+ clean)
+ clean_docker
+ ;;
+ logs)
+ show_logs
+ ;;
+ shell)
+ open_shell
+ ;;
+ compose-up)
+ compose_up
+ ;;
+ compose-down)
+ compose_down
+ ;;
+ help|--help|-h)
+ print_usage
+ ;;
+ *)
+ echo -e "${RED}ā Unknown command: $1${NC}"
+ print_usage
+ exit 1
+ ;;
+esac
\ No newline at end of file
diff --git a/scripts/setup-dockerhub-secrets.md b/scripts/setup-dockerhub-secrets.md
new file mode 100644
index 00000000..ac4dd691
--- /dev/null
+++ b/scripts/setup-dockerhub-secrets.md
@@ -0,0 +1,113 @@
+# Setting up DockerHub Secrets for GitHub Actions
+
+This guide will help you set up the required secrets for the Docker workflow to automatically build and push images to DockerHub.
+
+## Prerequisites
+
+1. A DockerHub account
+2. Admin access to the GitHub repository
+3. DockerHub access token
+
+## Step 1: Create a DockerHub Access Token
+
+1. Log in to [DockerHub](https://hub.docker.com/)
+2. Go to your account settings
+3. Navigate to "Security" ā "Access Tokens"
+4. Click "New Access Token"
+5. Give it a name (e.g., "GitHub Actions")
+6. Set the permissions to "Read & Write"
+7. Copy the generated token (you won't be able to see it again!)
+
+## Step 2: Add Secrets to GitHub Repository
+
+1. Go to your GitHub repository
+2. Navigate to "Settings" ā "Secrets and variables" ā "Actions"
+3. Click "New repository secret"
+4. Add the following secrets:
+
+### Required Secrets
+
+| Secret Name | Value | Description |
+|-------------|-------|-------------|
+| `DOCKERHUB_USERNAME` | Your DockerHub username | Your DockerHub username (e.g., `kyegomez`) |
+| `DOCKERHUB_TOKEN` | Your DockerHub access token | The access token you created in Step 1 |
+
+## Step 3: Verify Setup
+
+1. Push a commit to the `main` branch
+2. Go to the "Actions" tab in your GitHub repository
+3. You should see the "Docker Build and Publish" workflow running
+4. Check that it completes successfully
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Authentication Failed**
+ - Double-check your DockerHub username and token
+ - Ensure the token has "Read & Write" permissions
+ - Make sure the token hasn't expired
+
+2. **Permission Denied**
+ - Verify you have admin access to the repository
+ - Check that the secrets are named exactly as shown above
+
+3. **Workflow Not Triggering**
+ - Ensure you're pushing to the `main` branch
+ - Check that the workflow file is in `.github/workflows/`
+ - Verify the workflow file has the correct triggers
+
+### Testing Locally
+
+You can test the Docker build locally before pushing:
+
+```bash
+# Build the image locally
+docker build -t swarms:test .
+
+# Test the image
+docker run --rm swarms:test python test_docker.py
+
+# If everything works, push to GitHub
+git add .
+git commit -m "Add Docker support"
+git push origin main
+```
+
+## Security Notes
+
+- Never commit secrets directly to your repository
+- Use repository secrets for sensitive information
+- Regularly rotate your DockerHub access tokens
+- Consider using organization-level secrets for team repositories
+
+## Additional Configuration
+
+### Custom Registry
+
+If you want to use a different registry (not DockerHub), update the workflow file:
+
+```yaml
+env:
+ REGISTRY: your-registry.com
+ IMAGE_NAME: your-org/your-repo
+```
+
+### Multiple Tags
+
+The workflow automatically creates tags based on:
+- Git branch name
+- Git commit SHA
+- Version tags (v*.*.*)
+- Latest tag for main branch
+
+You can customize this in the workflow file under the "Extract Docker metadata" step.
+
+## Support
+
+If you encounter issues:
+
+1. Check the GitHub Actions logs for detailed error messages
+2. Verify your DockerHub credentials
+3. Ensure the workflow file is properly configured
+4. Open an issue in the repository with the error details
\ No newline at end of file
From cc37ec218a124949a056c5f742422e771ad51f0d Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:36:19 +0300
Subject: [PATCH 06/56] Update README.md
---
README.md | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/README.md b/README.md
index bfcf4264..e893bfc4 100644
--- a/README.md
+++ b/README.md
@@ -146,6 +146,24 @@ $ cd swarms
$ pip install -e .
```
+### Using Docker
+
+The easiest way to get started with Swarms is using our pre-built Docker image:
+
+```bash
+# Pull and run the latest image
+$ docker pull kyegomez/swarms:latest
+$ docker run --rm kyegomez/swarms:latest python -c "import swarms; print('Swarms is ready!')"
+
+# Run interactively for development
+$ docker run -it --rm -v $(pwd):/app kyegomez/swarms:latest bash
+
+# Using docker-compose (recommended for development)
+$ docker-compose up -d
+```
+
+For more Docker options and advanced usage, see our [Docker documentation](DOCKER.md).
+
---
## Environment Configuration
From 92d0f360f6c62e2bcd10ede69f942f74b1e11359 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:38:43 +0300
Subject: [PATCH 07/56] Add files via upload
---
.github/workflows/docker-test.yml | 58 +++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 .github/workflows/docker-test.yml
diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml
new file mode 100644
index 00000000..05ee8ed3
--- /dev/null
+++ b/.github/workflows/docker-test.yml
@@ -0,0 +1,58 @@
+name: Docker Test Build
+
+on:
+ pull_request:
+ branches: [ "master" ]
+ workflow_dispatch:
+
+env:
+ REGISTRY: docker.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ test-build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Setup QEMU for multi-platform builds
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ # Setup Docker BuildX
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ # Build Docker image (without pushing)
+ - name: Build Docker image
+ id: build
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ push: false
+ tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
+ platforms: linux/amd64
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ build-args: |
+ BUILDKIT_INLINE_CACHE=1
+
+ # Test the built image
+ - name: Test Docker image
+ run: |
+ docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test python test_docker.py
+
+ # Show image size
+ - name: Show image size
+ run: |
+ docker images ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
+
+ # Clean up test image
+ - name: Clean up test image
+ if: always()
+ run: |
+ docker rmi ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test || true
\ No newline at end of file
From 88d690a55d7056fca8abf01bcc98bfba9b3a1f4a Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:53:25 +0300
Subject: [PATCH 08/56] Create docker
---
scripts/docker | 1 +
1 file changed, 1 insertion(+)
create mode 100644 scripts/docker
diff --git a/scripts/docker b/scripts/docker
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/scripts/docker
@@ -0,0 +1 @@
+
From dd76134ed313f65039a5fc376d1bee32dfded01a Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:53:35 +0300
Subject: [PATCH 09/56] Delete scripts/docker
---
scripts/docker | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 scripts/docker
diff --git a/scripts/docker b/scripts/docker
deleted file mode 100644
index 8b137891..00000000
--- a/scripts/docker
+++ /dev/null
@@ -1 +0,0 @@
-
From 2299b48e0dd127c4be92b40dc064b23beea22855 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:53:53 +0300
Subject: [PATCH 10/56] Create file
---
scripts/docker/file | 1 +
1 file changed, 1 insertion(+)
create mode 100644 scripts/docker/file
diff --git a/scripts/docker/file b/scripts/docker/file
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/scripts/docker/file
@@ -0,0 +1 @@
+
From ed1ba6cd741f195afe78b35eb63b4ae28e44e1f3 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:55:02 +0300
Subject: [PATCH 11/56] Update and rename file to test_docker.py
---
scripts/docker/file | 1 -
scripts/docker/test_docker.py | 66 +++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 1 deletion(-)
delete mode 100644 scripts/docker/file
create mode 100644 scripts/docker/test_docker.py
diff --git a/scripts/docker/file b/scripts/docker/file
deleted file mode 100644
index 8b137891..00000000
--- a/scripts/docker/file
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/scripts/docker/test_docker.py b/scripts/docker/test_docker.py
new file mode 100644
index 00000000..70e9060b
--- /dev/null
+++ b/scripts/docker/test_docker.py
@@ -0,0 +1,66 @@
+
+#!/usr/bin/env python3
+"""
+Test script to verify Swarms installation in Docker container.
+"""
+
+import sys
+from typing import Dict, Any
+
+def test_swarms_import() -> Dict[str, Any]:
+ """
+ Test that swarms can be imported and basic functionality works.
+
+ Returns:
+ Dict[str, Any]: Test results
+ """
+ try:
+ import swarms
+ print(f" Swarms imported successfully. Version: {swarms.__version__}")
+
+ # Test basic functionality
+ from swarms import Agent
+ print(" Agent class imported successfully")
+
+ return {
+ "status": "success",
+ "version": swarms.__version__,
+ "message": "Swarms package is working correctly"
+ }
+
+ except ImportError as e:
+ print(f" Failed to import swarms: {e}")
+ return {
+ "status": "error",
+ "error": str(e),
+ "message": "Swarms package import failed"
+ }
+ except Exception as e:
+ print(f" Unexpected error: {e}")
+ return {
+ "status": "error",
+ "error": str(e),
+ "message": "Unexpected error occurred"
+ }
+
+def main() -> None:
+ """Main function to run tests."""
+ print(" Testing Swarms Docker Image...")
+ print("=" * 50)
+
+ # Test Python version
+ print(f"Python version: {sys.version}")
+
+ # Test swarms import
+ result = test_swarms_import()
+
+ print("=" * 50)
+ if result["status"] == "success":
+ print(" All tests passed! Docker image is working correctly.")
+ sys.exit(0)
+ else:
+ print(" Tests failed! Please check the Docker image.")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
From 5fd6eb8ff043c3a63bae9c0db495c61b4c09ca04 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:55:58 +0300
Subject: [PATCH 12/56] Create docker-compose.yml
---
scripts/docker/docker-compose.yml | 71 +++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 scripts/docker/docker-compose.yml
diff --git a/scripts/docker/docker-compose.yml b/scripts/docker/docker-compose.yml
new file mode 100644
index 00000000..a0ef3a35
--- /dev/null
+++ b/scripts/docker/docker-compose.yml
@@ -0,0 +1,71 @@
+version: '3.8'
+
+services:
+ swarms:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: swarms:latest
+ container_name: swarms-container
+ environment:
+ - PYTHONUNBUFFERED=1
+ - PYTHONPATH=/app
+ # Add your API keys here or use .env file
+ # - OPENAI_API_KEY=${OPENAI_API_KEY}
+ # - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
+ # - GOOGLE_API_KEY=${GOOGLE_API_KEY}
+ volumes:
+ - .:/app
+ - ./data:/app/data
+ - ./models:/app/models
+ working_dir: /app
+ command: python test_docker.py
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD", "python", "-c", "import swarms; print('Health check passed')"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ start_period: 40s
+
+ swarms-dev:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: swarms:dev
+ container_name: swarms-dev-container
+ environment:
+ - PYTHONUNBUFFERED=1
+ - PYTHONPATH=/app
+ volumes:
+ - .:/app
+ - ./data:/app/data
+ - ./models:/app/models
+ working_dir: /app
+ command: bash
+ stdin_open: true
+ tty: true
+ restart: unless-stopped
+
+ swarms-api:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: swarms:api
+ container_name: swarms-api-container
+ environment:
+ - PYTHONUNBUFFERED=1
+ - PYTHONPATH=/app
+ volumes:
+ - .:/app
+ working_dir: /app
+ ports:
+ - "8000:8000"
+ command: python -m uvicorn main:app --host 0.0.0.0 --port 8000 --reload
+ restart: unless-stopped
+ depends_on:
+ - swarms
+
+networks:
+ default:
+ name: swarms-network
From 62f02e133cb4fd69a012c9946d24db72c87ebca4 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:57:03 +0300
Subject: [PATCH 13/56] Create .dockerignore
---
scripts/docker/.dockerignore | 296 +++++++++++++++++++++++++++++++++++
1 file changed, 296 insertions(+)
create mode 100644 scripts/docker/.dockerignore
diff --git a/scripts/docker/.dockerignore b/scripts/docker/.dockerignore
new file mode 100644
index 00000000..241d24cb
--- /dev/null
+++ b/scripts/docker/.dockerignore
@@ -0,0 +1,296 @@
+.git
+.gitignore
+.env
+__pycache__
+*.pyc
+*.pyo
+*.pyd
+.Python
+env/
+venv/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.log
+.pytest_cache/
+.mypy_cache/
+
+__pycache__/
+.venv/
+
+.env
+
+image/
+audio/
+video/
+artifacts_three
+dataframe/
+.ruff_cache
+.pytest_cache
+static/generated
+runs
+Financial-Analysis-Agent_state.json
+experimental
+artifacts_five
+encryption
+errors
+chroma
+agent_workspace
+.pt
+Accounting Assistant_state.json
+Unit Testing Agent_state.json
+sec_agent
+Devin_state.json
+poetry.lock
+hire_researchers
+agent_workspace
+json_logs
+Medical Image Diagnostic Agent_state.json
+flight agent_state.json
+D_state.json
+artifacts_six
+artifacts_seven
+swarms/__pycache__
+artifacts_once
+transcript_generator.json
+venv
+.DS_Store
+Cargo.lock
+.DS_STORE
+artifacts_logs
+Cargo.lock
+Medical Treatment Recommendation Agent_state.json
+swarms/agents/.DS_Store
+artifacts_two
+logs
+T_state.json
+_build
+conversation.txt
+t1_state.json
+stderr_log.txt
+t2_state.json
+.vscode
+.DS_STORE
+# Byte-compiled / optimized / DLL files
+Transcript Generator_state.json
+__pycache__/
+*.py[cod]
+*$py.class
+.grit
+swarm-worker-01_state.json
+error.txt
+Devin Worker 2_state.json
+# C extensions
+*.so
+.ruff_cache
+
+
+errors.txt
+
+Autonomous-Agent-XYZ1B_state.json
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+.DS_Store
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+.vscode/settings.json
+# -*- mode: gitignore; -*-
+*~
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+*.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+
+# flymake-mode
+*_flymake.*
+
+# eshell files
+/eshell/history
+/eshell/lastdir
+
+# elpa packages
+/elpa/
+
+# reftex files
+*.rel
+
+# AUCTeX auto folder
+/auto/
+
+# cask packages
+.cask/
+dist/
+
+# Flycheck
+flycheck_*.el
+
+# server auth directory
+/server/
+
+# projectiles files
+.projectile
+
+# directory configuration
+.dir-locals.el
+
+# network security
+/network-security.data
From 6a7071afd17721d64ebba32ceb16f4adf17e922a Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:57:52 +0300
Subject: [PATCH 14/56] Create Dockerfile
---
scripts/docker/Dockerfile | 48 +++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 scripts/docker/Dockerfile
diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile
new file mode 100644
index 00000000..44392b09
--- /dev/null
+++ b/scripts/docker/Dockerfile
@@ -0,0 +1,48 @@
+# Multi-stage build for optimized Docker image
+FROM python:3.11-slim-bullseye as builder
+
+# Install system dependencies for building
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ build-essential gcc curl \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install UV for faster package management
+RUN curl -LsSf https://astral.sh/uv/install.sh | sh
+ENV PATH="/root/.cargo/bin:${PATH}"
+
+# Create a virtual environment and install dependencies
+RUN uv venv /opt/venv
+ENV PATH="/opt/venv/bin:$PATH"
+
+# Install the swarms package using UV
+RUN uv pip install --system -U swarms
+
+# Final stage
+FROM python:3.11-slim-bullseye
+
+# Environment config for speed and safety
+ENV PYTHONDONTWRITEBYTECODE=1 \
+ PYTHONUNBUFFERED=1 \
+ PATH="/opt/venv/bin:${PATH}" \
+ PYTHONPATH="/app:${PYTHONPATH}" \
+ USER=swarms
+
+# Set working directory
+WORKDIR /app
+
+# Copy virtual environment from builder stage
+COPY --from=builder /opt/venv /opt/venv
+
+# Add non-root user
+RUN useradd -m -s /bin/bash -U $USER && \
+ chown -R $USER:$USER /app
+
+# Copy application code
+COPY --chown=$USER:$USER . .
+
+# Switch to non-root
+USER $USER
+
+# Optional health check
+HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
+ CMD python -c "import swarms; print('Health check passed')" || exit 1
From d6f6d05c90c173caccfe6bcb0f3f4fa24001e092 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:58:23 +0300
Subject: [PATCH 15/56] Create DOCKER.md
---
scripts/docker/DOCKER.md | 225 +++++++++++++++++++++++++++++++++++++++
1 file changed, 225 insertions(+)
create mode 100644 scripts/docker/DOCKER.md
diff --git a/scripts/docker/DOCKER.md b/scripts/docker/DOCKER.md
new file mode 100644
index 00000000..5eeee366
--- /dev/null
+++ b/scripts/docker/DOCKER.md
@@ -0,0 +1,225 @@
+# Swarms Docker Image
+
+This repository includes a Docker image for running Swarms, an AI agent framework. The image is automatically built and published to DockerHub on every push to the main branch and on version tags.
+
+## š³ Quick Start
+
+### Pull and Run
+
+```bash
+# Pull the latest image
+docker pull kyegomez/swarms:latest
+
+# Run a simple test
+docker run --rm kyegomez/swarms:latest python test_docker.py
+
+# Run with interactive shell
+docker run -it --rm kyegomez/swarms:latest bash
+```
+
+### Using Specific Versions
+
+```bash
+# Pull a specific version
+docker pull kyegomez/swarms:v8.0.4
+
+# Run with specific version
+docker run --rm kyegomez/swarms:v8.0.4 python -c "import swarms; print(swarms.__version__)"
+```
+
+## šļø Building Locally
+
+### Prerequisites
+
+- Docker installed on your system
+- Git to clone the repository
+
+### Build Steps
+
+```bash
+# Clone the repository
+git clone https://github.com/kyegomez/swarms.git
+cd swarms
+
+# Build the image
+docker build -t swarms:latest .
+
+# Test the image
+docker run --rm swarms:latest python test_docker.py
+```
+
+## š Usage Examples
+
+### Basic Agent Example
+
+```bash
+# Create a Python script (agent_example.py)
+cat > agent_example.py << 'EOF'
+from swarms import Agent
+
+# Create an agent
+agent = Agent(
+ agent_name="test_agent",
+ system_prompt="You are a helpful AI assistant."
+)
+
+# Run the agent
+result = agent.run("Hello! How are you today?")
+print(result)
+EOF
+
+# Run in Docker
+docker run --rm -v $(pwd):/app swarms:latest python /app/agent_example.py
+```
+
+### Interactive Development
+
+```bash
+# Run with volume mount for development
+docker run -it --rm \
+ -v $(pwd):/app \
+ -w /app \
+ swarms:latest bash
+
+# Inside the container, you can now run Python scripts
+python your_script.py
+```
+
+### Using Environment Variables
+
+```bash
+# Run with environment variables
+docker run --rm \
+ -e OPENAI_API_KEY=your_api_key_here \
+ -e ANTHROPIC_API_KEY=your_anthropic_key_here \
+ swarms:latest python your_script.py
+```
+
+## š§ Configuration
+
+### Environment Variables
+
+The Docker image supports the following environment variables:
+
+- `OPENAI_API_KEY`: Your OpenAI API key
+- `ANTHROPIC_API_KEY`: Your Anthropic API key
+- `GOOGLE_API_KEY`: Your Google API key
+- `PYTHONPATH`: Additional Python path entries
+- `PYTHONUNBUFFERED`: Set to 1 for unbuffered output
+
+### Volume Mounts
+
+Common volume mount patterns:
+
+```bash
+# Mount current directory for development
+-v $(pwd):/app
+
+# Mount specific directories
+-v $(pwd)/data:/app/data
+-v $(pwd)/models:/app/models
+
+# Mount configuration files
+-v $(pwd)/config:/app/config
+```
+
+## š Troubleshooting
+
+### Common Issues
+
+1. **Permission Denied**
+ ```bash
+ # Fix permission issues
+ docker run --rm -v $(pwd):/app:rw swarms:latest python your_script.py
+ ```
+
+2. **Memory Issues**
+ ```bash
+ # Increase memory limit
+ docker run --rm --memory=4g swarms:latest python your_script.py
+ ```
+
+3. **Network Issues**
+ ```bash
+ # Use host network
+ docker run --rm --network=host swarms:latest python your_script.py
+ ```
+
+### Debug Mode
+
+```bash
+# Run with debug output
+docker run --rm -e PYTHONUNBUFFERED=1 swarms:latest python -u your_script.py
+
+# Run with interactive debugging
+docker run -it --rm swarms:latest python -m pdb your_script.py
+```
+
+## š CI/CD Integration
+
+The Docker image is automatically built and published via GitHub Actions:
+
+- **Triggers**: Push to main branch, version tags (v*.*.*)
+- **Platforms**: linux/amd64, linux/arm64
+- **Registry**: DockerHub (kyegomez/swarms)
+
+### GitHub Actions Secrets Required
+
+- `DOCKERHUB_USERNAME`: Your DockerHub username
+- `DOCKERHUB_TOKEN`: Your DockerHub access token
+
+## š Image Details
+
+### Base Image
+- Python 3.11-slim-bullseye
+- Multi-stage build for optimization
+- UV package manager for faster installations
+
+### Image Size
+- Optimized for minimal size
+- Multi-stage build reduces final image size
+- Only necessary dependencies included
+
+### Security
+- Non-root user execution
+- Minimal system dependencies
+- Regular security updates
+
+## š¤ Contributing
+
+To contribute to the Docker setup:
+
+1. Fork the repository
+2. Make your changes to the Dockerfile
+3. Test locally: `docker build -t swarms:test .`
+4. Submit a pull request
+
+### Testing Changes
+
+```bash
+# Build test image
+docker build -t swarms:test .
+
+# Run tests
+docker run --rm swarms:test python test_docker.py
+
+# Test with your code
+docker run --rm -v $(pwd):/app swarms:test python your_test_script.py
+```
+
+## š License
+
+This Docker setup is part of the Swarms project and follows the same MIT license.
+
+## š Support
+
+For issues with the Docker image:
+
+1. Check the troubleshooting section above
+2. Review the GitHub Actions logs for build issues
+3. Open an issue on GitHub with detailed error information
+4. Include your Docker version and system information
+
+---
+
+**Note**: This Docker image is automatically updated with each release. For production use, consider pinning to specific version tags for stability.
From b1a438de6bfd29fbc38a698cadecff2495ae84ed Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 20:59:25 +0300
Subject: [PATCH 16/56] Create docker-utils.sh
---
scripts/docker/docker-utils.sh | 167 +++++++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
create mode 100644 scripts/docker/docker-utils.sh
diff --git a/scripts/docker/docker-utils.sh b/scripts/docker/docker-utils.sh
new file mode 100644
index 00000000..ca24332f
--- /dev/null
+++ b/scripts/docker/docker-utils.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+
+# Docker utilities for Swarms project
+# Usage: ./scripts/docker-utils.sh [command]
+
+set -e
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Configuration
+IMAGE_NAME="swarms"
+REGISTRY="kyegomez"
+FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
+
+# Functions
+print_usage() {
+ echo -e "${BLUE}Docker Utilities for Swarms${NC}"
+ echo ""
+ echo "Usage: $0 [command]"
+ echo ""
+ echo "Commands:"
+ echo " build Build the Docker image locally"
+ echo " test Test the Docker image"
+ echo " run Run the Docker image interactively"
+ echo " push Push to DockerHub (requires login)"
+ echo " clean Clean up Docker images and containers"
+ echo " logs Show logs from running containers"
+ echo " shell Open shell in running container"
+ echo " compose-up Start services with docker-compose"
+ echo " compose-down Stop services with docker-compose"
+ echo " help Show this help message"
+ echo ""
+}
+
+build_image() {
+ echo -e "${GREEN}Building Docker image...${NC}"
+ docker build -t "${IMAGE_NAME}:latest" .
+ echo -e "${GREEN} Image built successfully!${NC}"
+}
+
+test_image() {
+ echo -e "${GREEN}Testing Docker image...${NC}"
+ docker run --rm "${IMAGE_NAME}:latest" python test_docker.py
+ echo -e "${GREEN} Image test completed!${NC}"
+}
+
+run_interactive() {
+ echo -e "${GREEN}Running Docker image interactively...${NC}"
+ docker run -it --rm \
+ -v "$(pwd):/app" \
+ -w /app \
+ "${IMAGE_NAME}:latest" bash
+}
+
+push_to_dockerhub() {
+ echo -e "${YELLOW}ā Make sure you're logged into DockerHub first!${NC}"
+ echo -e "${GREEN}Pushing to DockerHub...${NC}"
+
+ # Tag the image
+ docker tag "${IMAGE_NAME}:latest" "${FULL_IMAGE_NAME}:latest"
+
+ # Push to DockerHub
+ docker push "${FULL_IMAGE_NAME}:latest"
+
+ echo -e "${GREEN} Image pushed to DockerHub!${NC}"
+}
+
+clean_docker() {
+ echo -e "${YELLOW}Cleaning up Docker resources...${NC}"
+
+ # Stop and remove containers
+ docker ps -aq | xargs -r docker rm -f
+
+ # Remove images
+ docker images "${IMAGE_NAME}" -q | xargs -r docker rmi -f
+
+ # Remove dangling images
+ docker image prune -f
+
+ echo -e "${GREEN} Docker cleanup completed!${NC}"
+}
+
+show_logs() {
+ echo -e "${GREEN}Showing logs from running containers...${NC}"
+ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
+ echo ""
+
+ # Show logs for swarms containers
+ for container in $(docker ps --filter "name=swarms" --format "{{.Names}}"); do
+ echo -e "${BLUE}Logs for $container:${NC}"
+ docker logs "$container" --tail 20
+ echo ""
+ done
+}
+
+open_shell() {
+ echo -e "${GREEN}Opening shell in running container...${NC}"
+
+ # Find running swarms container
+ container=$(docker ps --filter "name=swarms" --format "{{.Names}}" | head -1)
+
+ if [ -z "$container" ]; then
+ echo -e "${RED} No running swarms container found!${NC}"
+ echo "Start a container first with: $0 run"
+ exit 1
+ fi
+
+ echo -e "${BLUE}Opening shell in $container...${NC}"
+ docker exec -it "$container" bash
+}
+
+compose_up() {
+ echo -e "${GREEN}Starting services with docker-compose...${NC}"
+ docker-compose up -d
+ echo -e "${GREEN} Services started!${NC}"
+ echo "Use 'docker-compose logs -f' to view logs"
+}
+
+compose_down() {
+ echo -e "${YELLOW}Stopping services with docker-compose...${NC}"
+ docker-compose down
+ echo -e "${GREEN} Services stopped!${NC}"
+}
+
+# Main script logic
+case "${1:-help}" in
+ build)
+ build_image
+ ;;
+ test)
+ test_image
+ ;;
+ run)
+ run_interactive
+ ;;
+ push)
+ push_to_dockerhub
+ ;;
+ clean)
+ clean_docker
+ ;;
+ logs)
+ show_logs
+ ;;
+ shell)
+ open_shell
+ ;;
+ compose-up)
+ compose_up
+ ;;
+ compose-down)
+ compose_down
+ ;;
+ help|--help|-h)
+ print_usage
+ ;;
+ *)
+ echo -e "${RED} Unknown command: $1${NC}"
+ print_usage
+ exit 1
+ ;;
+esac
From 72a5cff90e9af4efd60ab02f3aab1568241d5b40 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:00:17 +0300
Subject: [PATCH 17/56] Create docker-utils.ps1
---
scripts/docker/docker-utils.ps1 | 139 ++++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
create mode 100644 scripts/docker/docker-utils.ps1
diff --git a/scripts/docker/docker-utils.ps1 b/scripts/docker/docker-utils.ps1
new file mode 100644
index 00000000..36ba12db
--- /dev/null
+++ b/scripts/docker/docker-utils.ps1
@@ -0,0 +1,139 @@
+# Docker utilities for Swarms project (PowerShell version)
+# Usage: .\scripts\docker-utils.ps1 [command]
+
+param(
+ [Parameter(Position=0)]
+ [string]$Command = "help"
+)
+
+# Configuration
+$ImageName = "swarms"
+$Registry = "kyegomez"
+$FullImageName = "$Registry/$ImageName"
+
+# Functions
+function Write-Usage {
+ Write-Host "Docker Utilities for Swarms" -ForegroundColor Blue
+ Write-Host ""
+ Write-Host "Usage: .\scripts\docker-utils.ps1 [command]"
+ Write-Host ""
+ Write-Host "Commands:"
+ Write-Host " build Build the Docker image locally"
+ Write-Host " test Test the Docker image"
+ Write-Host " run Run the Docker image interactively"
+ Write-Host " push Push to DockerHub (requires login)"
+ Write-Host " clean Clean up Docker images and containers"
+ Write-Host " logs Show logs from running containers"
+ Write-Host " shell Open shell in running container"
+ Write-Host " compose-up Start services with docker-compose"
+ Write-Host " compose-down Stop services with docker-compose"
+ Write-Host " help Show this help message"
+ Write-Host ""
+}
+
+function Build-Image {
+ Write-Host "Building Docker image..." -ForegroundColor Green
+ docker build -t "$ImageName`:latest" .
+ Write-Host " Image built successfully!" -ForegroundColor Green
+}
+
+function Test-Image {
+ Write-Host "Testing Docker image..." -ForegroundColor Green
+ docker run --rm "$ImageName`:latest" python test_docker.py
+ Write-Host " Image test completed!" -ForegroundColor Green
+}
+
+function Run-Interactive {
+ Write-Host "Running Docker image interactively..." -ForegroundColor Green
+ docker run -it --rm -v "${PWD}:/app" -w /app "$ImageName`:latest" bash
+}
+
+function Push-ToDockerHub {
+ Write-Host "ā Make sure you're logged into DockerHub first!" -ForegroundColor Yellow
+ Write-Host "Pushing to DockerHub..." -ForegroundColor Green
+
+ # Tag the image
+ docker tag "$ImageName`:latest" "$FullImageName`:latest"
+
+ # Push to DockerHub
+ docker push "$FullImageName`:latest"
+
+ Write-Host " Image pushed to DockerHub!" -ForegroundColor Green
+}
+
+function Clean-Docker {
+ Write-Host "Cleaning up Docker resources..." -ForegroundColor Yellow
+
+ # Stop and remove containers
+ docker ps -aq | ForEach-Object { docker rm -f $_ }
+
+ # Remove images
+ docker images "$ImageName" -q | ForEach-Object { docker rmi -f $_ }
+
+ # Remove dangling images
+ docker image prune -f
+
+ Write-Host " Docker cleanup completed!" -ForegroundColor Green
+}
+
+function Show-Logs {
+ Write-Host "Showing logs from running containers..." -ForegroundColor Green
+ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
+ Write-Host ""
+
+ # Show logs for swarms containers
+ $containers = docker ps --filter "name=swarms" --format "{{.Names}}"
+ foreach ($container in $containers) {
+ Write-Host "Logs for $container:" -ForegroundColor Blue
+ docker logs $container --tail 20
+ Write-Host ""
+ }
+}
+
+function Open-Shell {
+ Write-Host "Opening shell in running container..." -ForegroundColor Green
+
+ # Find running swarms container
+ $container = docker ps --filter "name=swarms" --format "{{.Names}}" | Select-Object -First 1
+
+ if (-not $container) {
+ Write-Host " No running swarms container found!" -ForegroundColor Red
+ Write-Host "Start a container first with: .\scripts\docker-utils.ps1 run"
+ exit 1
+ }
+
+ Write-Host "Opening shell in $container..." -ForegroundColor Blue
+ docker exec -it $container bash
+}
+
+function Compose-Up {
+ Write-Host "Starting services with docker-compose..." -ForegroundColor Green
+ docker-compose up -d
+ Write-Host " Services started!" -ForegroundColor Green
+ Write-Host "Use 'docker-compose logs -f' to view logs"
+}
+
+function Compose-Down {
+ Write-Host "Stopping services with docker-compose..." -ForegroundColor Yellow
+ docker-compose down
+ Write-Host " Services stopped!" -ForegroundColor Green
+}
+
+# Main script logic
+switch ($Command.ToLower()) {
+ "build" { Build-Image }
+ "test" { Test-Image }
+ "run" { Run-Interactive }
+ "push" { Push-ToDockerHub }
+ "clean" { Clean-Docker }
+ "logs" { Show-Logs }
+ "shell" { Open-Shell }
+ "compose-up" { Compose-Up }
+ "compose-down" { Compose-Down }
+ "help" { Write-Usage }
+ default {
+ Write-Host " Unknown command: $Command" -ForegroundColor Red
+ Write-Usage
+ exit 1
+ }
+}
From 6ea348c08c314b04bbee4f61f402a90ae6e35285 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:01:09 +0300
Subject: [PATCH 18/56] Create docker-image.yml
---
scripts/docker/docker-image.yml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 scripts/docker/docker-image.yml
diff --git a/scripts/docker/docker-image.yml b/scripts/docker/docker-image.yml
new file mode 100644
index 00000000..793d8e0e
--- /dev/null
+++ b/scripts/docker/docker-image.yml
@@ -0,0 +1,18 @@
+name: Docker Image CI
+
+on:
+ push:
+ branches: [ "master" ]
+ pull_request:
+ branches: [ "master" ]
+
+jobs:
+
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Build the Docker image
+ run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
From 01b4fc7c2083fb7edf41c0ecc642d214d4849335 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:03:51 +0300
Subject: [PATCH 19/56] Create docker-publish.yml
---
scripts/docker/docker-publish.yml | 76 +++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 scripts/docker/docker-publish.yml
diff --git a/scripts/docker/docker-publish.yml b/scripts/docker/docker-publish.yml
new file mode 100644
index 00000000..40fac9cb
--- /dev/null
+++ b/scripts/docker/docker-publish.yml
@@ -0,0 +1,76 @@
+name: Docker Build and Publish
+
+on:
+ push:
+ branches: [ "master" ]
+ # Publish semver tags as releases
+ tags: [ 'v*.*.*' ]
+ pull_request:
+ branches: [ "master" ]
+
+env:
+ # Use docker.io for Docker Hub if empty
+ REGISTRY: docker.io
+ # github.repository as /
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ # This is used to complete the identity challenge
+ # with sigstore/fulcio when running outside of PRs.
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Setup QEMU for multi-platform builds
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ # Setup Docker BuildX
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ # Login to Docker Hub
+ - name: Log into registry ${{ env.REGISTRY }}
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ # Extract metadata (tags, labels) for Docker
+ - name: Extract Docker metadata
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
+ type=raw,value=latest,enable={{is_default_branch}}
+
+ # Build and push Docker image
+ - name: Build and push Docker image
+ id: build-and-push
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ push: ${{ github.event_name != 'pull_request' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ platforms: linux/amd64,linux/arm64
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ build-args: |
+ BUILDKIT_INLINE_CACHE=1
From 4ff2f224351ba2ef4239f8dc57323c585f20f69d Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:04:25 +0300
Subject: [PATCH 20/56] Create docker-test.yml
---
scripts/docker/docker-test.yml | 58 ++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 scripts/docker/docker-test.yml
diff --git a/scripts/docker/docker-test.yml b/scripts/docker/docker-test.yml
new file mode 100644
index 00000000..db83f238
--- /dev/null
+++ b/scripts/docker/docker-test.yml
@@ -0,0 +1,58 @@
+name: Docker Test Build
+
+on:
+ pull_request:
+ branches: [ "master" ]
+ workflow_dispatch:
+
+env:
+ REGISTRY: docker.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ test-build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Setup QEMU for multi-platform builds
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ # Setup Docker BuildX
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ # Build Docker image (without pushing)
+ - name: Build Docker image
+ id: build
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ push: false
+ tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
+ platforms: linux/amd64
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ build-args: |
+ BUILDKIT_INLINE_CACHE=1
+
+ # Test the built image
+ - name: Test Docker image
+ run: |
+ docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test python test_docker.py
+
+ # Show image size
+ - name: Show image size
+ run: |
+ docker images ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
+
+ # Clean up test image
+ - name: Clean up test image
+ if: always()
+ run: |
+ docker rmi ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test || true
From 19b9f7b8527fb7c7a3e88922591f53949cf03691 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:10:33 +0300
Subject: [PATCH 21/56] Delete test_docker.py
---
test_docker.py | 65 --------------------------------------------------
1 file changed, 65 deletions(-)
delete mode 100644 test_docker.py
diff --git a/test_docker.py b/test_docker.py
deleted file mode 100644
index 4733fc0d..00000000
--- a/test_docker.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python3
-"""
-Test script to verify Swarms installation in Docker container.
-"""
-
-import sys
-from typing import Dict, Any
-
-def test_swarms_import() -> Dict[str, Any]:
- """
- Test that swarms can be imported and basic functionality works.
-
- Returns:
- Dict[str, Any]: Test results
- """
- try:
- import swarms
- print(f"ā
Swarms imported successfully. Version: {swarms.__version__}")
-
- # Test basic functionality
- from swarms import Agent
- print("ā
Agent class imported successfully")
-
- return {
- "status": "success",
- "version": swarms.__version__,
- "message": "Swarms package is working correctly"
- }
-
- except ImportError as e:
- print(f"ā Failed to import swarms: {e}")
- return {
- "status": "error",
- "error": str(e),
- "message": "Swarms package import failed"
- }
- except Exception as e:
- print(f"ā Unexpected error: {e}")
- return {
- "status": "error",
- "error": str(e),
- "message": "Unexpected error occurred"
- }
-
-def main() -> None:
- """Main function to run tests."""
- print("š Testing Swarms Docker Image...")
- print("=" * 50)
-
- # Test Python version
- print(f"Python version: {sys.version}")
-
- # Test swarms import
- result = test_swarms_import()
-
- print("=" * 50)
- if result["status"] == "success":
- print("š All tests passed! Docker image is working correctly.")
- sys.exit(0)
- else:
- print("š„ Tests failed! Please check the Docker image.")
- sys.exit(1)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
From 01c4a2d28851dc50727cc5b8fa691aa8642debdc Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:10:43 +0300
Subject: [PATCH 22/56] Delete docker-compose.yml
---
docker-compose.yml | 71 ----------------------------------------------
1 file changed, 71 deletions(-)
delete mode 100644 docker-compose.yml
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 8e4f2360..00000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-version: '3.8'
-
-services:
- swarms:
- build:
- context: .
- dockerfile: Dockerfile
- image: swarms:latest
- container_name: swarms-container
- environment:
- - PYTHONUNBUFFERED=1
- - PYTHONPATH=/app
- # Add your API keys here or use .env file
- # - OPENAI_API_KEY=${OPENAI_API_KEY}
- # - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- # - GOOGLE_API_KEY=${GOOGLE_API_KEY}
- volumes:
- - .:/app
- - ./data:/app/data
- - ./models:/app/models
- working_dir: /app
- command: python test_docker.py
- restart: unless-stopped
- healthcheck:
- test: ["CMD", "python", "-c", "import swarms; print('Health check passed')"]
- interval: 30s
- timeout: 10s
- retries: 3
- start_period: 40s
-
- swarms-dev:
- build:
- context: .
- dockerfile: Dockerfile
- image: swarms:dev
- container_name: swarms-dev-container
- environment:
- - PYTHONUNBUFFERED=1
- - PYTHONPATH=/app
- volumes:
- - .:/app
- - ./data:/app/data
- - ./models:/app/models
- working_dir: /app
- command: bash
- stdin_open: true
- tty: true
- restart: unless-stopped
-
- swarms-api:
- build:
- context: .
- dockerfile: Dockerfile
- image: swarms:api
- container_name: swarms-api-container
- environment:
- - PYTHONUNBUFFERED=1
- - PYTHONPATH=/app
- volumes:
- - .:/app
- working_dir: /app
- ports:
- - "8000:8000"
- command: python -m uvicorn main:app --host 0.0.0.0 --port 8000 --reload
- restart: unless-stopped
- depends_on:
- - swarms
-
-networks:
- default:
- name: swarms-network
\ No newline at end of file
From 78a73c0d34fc095aed9f6e02924b571d7ce8718f Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:10:52 +0300
Subject: [PATCH 23/56] Delete DOCKER.md
---
DOCKER.md | 225 ------------------------------------------------------
1 file changed, 225 deletions(-)
delete mode 100644 DOCKER.md
diff --git a/DOCKER.md b/DOCKER.md
deleted file mode 100644
index 0b2ec1fb..00000000
--- a/DOCKER.md
+++ /dev/null
@@ -1,225 +0,0 @@
-# Swarms Docker Image
-
-This repository includes a Docker image for running Swarms, an AI agent framework. The image is automatically built and published to DockerHub on every push to the main branch and on version tags.
-
-## š³ Quick Start
-
-### Pull and Run
-
-```bash
-# Pull the latest image
-docker pull kyegomez/swarms:latest
-
-# Run a simple test
-docker run --rm kyegomez/swarms:latest python test_docker.py
-
-# Run with interactive shell
-docker run -it --rm kyegomez/swarms:latest bash
-```
-
-### Using Specific Versions
-
-```bash
-# Pull a specific version
-docker pull kyegomez/swarms:v8.0.4
-
-# Run with specific version
-docker run --rm kyegomez/swarms:v8.0.4 python -c "import swarms; print(swarms.__version__)"
-```
-
-## šļø Building Locally
-
-### Prerequisites
-
-- Docker installed on your system
-- Git to clone the repository
-
-### Build Steps
-
-```bash
-# Clone the repository
-git clone https://github.com/kyegomez/swarms.git
-cd swarms
-
-# Build the image
-docker build -t swarms:latest .
-
-# Test the image
-docker run --rm swarms:latest python test_docker.py
-```
-
-## š Usage Examples
-
-### Basic Agent Example
-
-```bash
-# Create a Python script (agent_example.py)
-cat > agent_example.py << 'EOF'
-from swarms import Agent
-
-# Create an agent
-agent = Agent(
- agent_name="test_agent",
- system_prompt="You are a helpful AI assistant."
-)
-
-# Run the agent
-result = agent.run("Hello! How are you today?")
-print(result)
-EOF
-
-# Run in Docker
-docker run --rm -v $(pwd):/app swarms:latest python /app/agent_example.py
-```
-
-### Interactive Development
-
-```bash
-# Run with volume mount for development
-docker run -it --rm \
- -v $(pwd):/app \
- -w /app \
- swarms:latest bash
-
-# Inside the container, you can now run Python scripts
-python your_script.py
-```
-
-### Using Environment Variables
-
-```bash
-# Run with environment variables
-docker run --rm \
- -e OPENAI_API_KEY=your_api_key_here \
- -e ANTHROPIC_API_KEY=your_anthropic_key_here \
- swarms:latest python your_script.py
-```
-
-## š§ Configuration
-
-### Environment Variables
-
-The Docker image supports the following environment variables:
-
-- `OPENAI_API_KEY`: Your OpenAI API key
-- `ANTHROPIC_API_KEY`: Your Anthropic API key
-- `GOOGLE_API_KEY`: Your Google API key
-- `PYTHONPATH`: Additional Python path entries
-- `PYTHONUNBUFFERED`: Set to 1 for unbuffered output
-
-### Volume Mounts
-
-Common volume mount patterns:
-
-```bash
-# Mount current directory for development
--v $(pwd):/app
-
-# Mount specific directories
--v $(pwd)/data:/app/data
--v $(pwd)/models:/app/models
-
-# Mount configuration files
--v $(pwd)/config:/app/config
-```
-
-## š Troubleshooting
-
-### Common Issues
-
-1. **Permission Denied**
- ```bash
- # Fix permission issues
- docker run --rm -v $(pwd):/app:rw swarms:latest python your_script.py
- ```
-
-2. **Memory Issues**
- ```bash
- # Increase memory limit
- docker run --rm --memory=4g swarms:latest python your_script.py
- ```
-
-3. **Network Issues**
- ```bash
- # Use host network
- docker run --rm --network=host swarms:latest python your_script.py
- ```
-
-### Debug Mode
-
-```bash
-# Run with debug output
-docker run --rm -e PYTHONUNBUFFERED=1 swarms:latest python -u your_script.py
-
-# Run with interactive debugging
-docker run -it --rm swarms:latest python -m pdb your_script.py
-```
-
-## š CI/CD Integration
-
-The Docker image is automatically built and published via GitHub Actions:
-
-- **Triggers**: Push to main branch, version tags (v*.*.*)
-- **Platforms**: linux/amd64, linux/arm64
-- **Registry**: DockerHub (kyegomez/swarms)
-
-### GitHub Actions Secrets Required
-
-- `DOCKERHUB_USERNAME`: Your DockerHub username
-- `DOCKERHUB_TOKEN`: Your DockerHub access token
-
-## š Image Details
-
-### Base Image
-- Python 3.11-slim-bullseye
-- Multi-stage build for optimization
-- UV package manager for faster installations
-
-### Image Size
-- Optimized for minimal size
-- Multi-stage build reduces final image size
-- Only necessary dependencies included
-
-### Security
-- Non-root user execution
-- Minimal system dependencies
-- Regular security updates
-
-## š¤ Contributing
-
-To contribute to the Docker setup:
-
-1. Fork the repository
-2. Make your changes to the Dockerfile
-3. Test locally: `docker build -t swarms:test .`
-4. Submit a pull request
-
-### Testing Changes
-
-```bash
-# Build test image
-docker build -t swarms:test .
-
-# Run tests
-docker run --rm swarms:test python test_docker.py
-
-# Test with your code
-docker run --rm -v $(pwd):/app swarms:test python your_test_script.py
-```
-
-## š License
-
-This Docker setup is part of the Swarms project and follows the same MIT license.
-
-## š Support
-
-For issues with the Docker image:
-
-1. Check the troubleshooting section above
-2. Review the GitHub Actions logs for build issues
-3. Open an issue on GitHub with detailed error information
-4. Include your Docker version and system information
-
----
-
-**Note**: This Docker image is automatically updated with each release. For production use, consider pinning to specific version tags for stability.
\ No newline at end of file
From 90cc77ed71bf30d26e9af5adfc159e051e299988 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:11:02 +0300
Subject: [PATCH 24/56] Delete Dockerfile
---
Dockerfile | 48 ------------------------------------------------
1 file changed, 48 deletions(-)
delete mode 100644 Dockerfile
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 44392b09..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,48 +0,0 @@
-# Multi-stage build for optimized Docker image
-FROM python:3.11-slim-bullseye as builder
-
-# Install system dependencies for building
-RUN apt-get update && apt-get install -y --no-install-recommends \
- build-essential gcc curl \
- && rm -rf /var/lib/apt/lists/*
-
-# Install UV for faster package management
-RUN curl -LsSf https://astral.sh/uv/install.sh | sh
-ENV PATH="/root/.cargo/bin:${PATH}"
-
-# Create a virtual environment and install dependencies
-RUN uv venv /opt/venv
-ENV PATH="/opt/venv/bin:$PATH"
-
-# Install the swarms package using UV
-RUN uv pip install --system -U swarms
-
-# Final stage
-FROM python:3.11-slim-bullseye
-
-# Environment config for speed and safety
-ENV PYTHONDONTWRITEBYTECODE=1 \
- PYTHONUNBUFFERED=1 \
- PATH="/opt/venv/bin:${PATH}" \
- PYTHONPATH="/app:${PYTHONPATH}" \
- USER=swarms
-
-# Set working directory
-WORKDIR /app
-
-# Copy virtual environment from builder stage
-COPY --from=builder /opt/venv /opt/venv
-
-# Add non-root user
-RUN useradd -m -s /bin/bash -U $USER && \
- chown -R $USER:$USER /app
-
-# Copy application code
-COPY --chown=$USER:$USER . .
-
-# Switch to non-root
-USER $USER
-
-# Optional health check
-HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
- CMD python -c "import swarms; print('Health check passed')" || exit 1
From 3519463d24ed8b5a37eda570d21f20f01e859362 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:11:16 +0300
Subject: [PATCH 25/56] Delete .dockerignore
---
.dockerignore | 297 --------------------------------------------------
1 file changed, 297 deletions(-)
delete mode 100644 .dockerignore
diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index 9b9944a2..00000000
--- a/.dockerignore
+++ /dev/null
@@ -1,297 +0,0 @@
-.git
-.gitignore
-.env
-__pycache__
-*.pyc
-*.pyo
-*.pyd
-.Python
-env/
-venv/
-.tox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.log
-.pytest_cache/
-.mypy_cache/
-
-__pycache__/
-.venv/
-
-.env
-
-image/
-audio/
-video/
-artifacts_three
-dataframe/
-.ruff_cache
-.pytest_cache
-static/generated
-runs
-Financial-Analysis-Agent_state.json
-experimental
-artifacts_five
-encryption
-errors
-chroma
-agent_workspace
-.pt
-Accounting Assistant_state.json
-Unit Testing Agent_state.json
-sec_agent
-Devin_state.json
-poetry.lock
-hire_researchers
-agent_workspace
-json_logs
-Medical Image Diagnostic Agent_state.json
-flight agent_state.json
-D_state.json
-artifacts_six
-artifacts_seven
-swarms/__pycache__
-artifacts_once
-transcript_generator.json
-venv
-.DS_Store
-Cargo.lock
-.DS_STORE
-artifacts_logs
-Cargo.lock
-Medical Treatment Recommendation Agent_state.json
-swarms/agents/.DS_Store
-artifacts_two
-logs
-T_state.json
-_build
-conversation.txt
-t1_state.json
-stderr_log.txt
-t2_state.json
-.vscode
-.DS_STORE
-# Byte-compiled / optimized / DLL files
-Transcript Generator_state.json
-__pycache__/
-*.py[cod]
-*$py.class
-.grit
-swarm-worker-01_state.json
-error.txt
-Devin Worker 2_state.json
-# C extensions
-*.so
-.ruff_cache
-
-
-errors.txt
-
-Autonomous-Agent-XYZ1B_state.json
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-.DS_Store
-
-# pyenv
-# For a library or package, you might want to ignore these files since the code is
-# intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-# However, in case of collaboration, if having platform-specific dependencies or dependencies
-# having no cross-platform support, pipenv may install dependencies that don't work, or not
-# install all needed dependencies.
-#Pipfile.lock
-
-# poetry
-# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
-# This is especially recommended for binary packages to ensure reproducibility, and is more
-# commonly ignored for libraries.
-# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
-#poetry.lock
-
-# pdm
-# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
-#pdm.lock
-# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
-# in version control.
-# https://pdm.fming.dev/#use-with-ide
-.pdm.toml
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
-
-# PyCharm
-# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
-# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
-# and can be added to the global gitignore or merged into this file. For a more nuclear
-# option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
-.vscode/settings.json
-# -*- mode: gitignore; -*-
-*~
-\#*\#
-/.emacs.desktop
-/.emacs.desktop.lock
-*.elc
-auto-save-list
-tramp
-.\#*
-
-# Org-mode
-.org-id-locations
-*_archive
-
-# flymake-mode
-*_flymake.*
-
-# eshell files
-/eshell/history
-/eshell/lastdir
-
-# elpa packages
-/elpa/
-
-# reftex files
-*.rel
-
-# AUCTeX auto folder
-/auto/
-
-# cask packages
-.cask/
-dist/
-
-# Flycheck
-flycheck_*.el
-
-# server auth directory
-/server/
-
-# projectiles files
-.projectile
-
-# directory configuration
-.dir-locals.el
-
-# network security
-/network-security.data
-
From f0c1544ec8a1b47d8b0ca0f59a702beea0fe6988 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:11:30 +0300
Subject: [PATCH 26/56] Delete scripts/docker-utils.ps1
---
scripts/docker-utils.ps1 | 139 ---------------------------------------
1 file changed, 139 deletions(-)
delete mode 100644 scripts/docker-utils.ps1
diff --git a/scripts/docker-utils.ps1 b/scripts/docker-utils.ps1
deleted file mode 100644
index 59c94636..00000000
--- a/scripts/docker-utils.ps1
+++ /dev/null
@@ -1,139 +0,0 @@
-# Docker utilities for Swarms project (PowerShell version)
-# Usage: .\scripts\docker-utils.ps1 [command]
-
-param(
- [Parameter(Position=0)]
- [string]$Command = "help"
-)
-
-# Configuration
-$ImageName = "swarms"
-$Registry = "kyegomez"
-$FullImageName = "$Registry/$ImageName"
-
-# Functions
-function Write-Usage {
- Write-Host "Docker Utilities for Swarms" -ForegroundColor Blue
- Write-Host ""
- Write-Host "Usage: .\scripts\docker-utils.ps1 [command]"
- Write-Host ""
- Write-Host "Commands:"
- Write-Host " build Build the Docker image locally"
- Write-Host " test Test the Docker image"
- Write-Host " run Run the Docker image interactively"
- Write-Host " push Push to DockerHub (requires login)"
- Write-Host " clean Clean up Docker images and containers"
- Write-Host " logs Show logs from running containers"
- Write-Host " shell Open shell in running container"
- Write-Host " compose-up Start services with docker-compose"
- Write-Host " compose-down Stop services with docker-compose"
- Write-Host " help Show this help message"
- Write-Host ""
-}
-
-function Build-Image {
- Write-Host "Building Docker image..." -ForegroundColor Green
- docker build -t "$ImageName`:latest" .
- Write-Host "ā
Image built successfully!" -ForegroundColor Green
-}
-
-function Test-Image {
- Write-Host "Testing Docker image..." -ForegroundColor Green
- docker run --rm "$ImageName`:latest" python test_docker.py
- Write-Host "ā
Image test completed!" -ForegroundColor Green
-}
-
-function Run-Interactive {
- Write-Host "Running Docker image interactively..." -ForegroundColor Green
- docker run -it --rm -v "${PWD}:/app" -w /app "$ImageName`:latest" bash
-}
-
-function Push-ToDockerHub {
- Write-Host "ā ļø Make sure you're logged into DockerHub first!" -ForegroundColor Yellow
- Write-Host "Pushing to DockerHub..." -ForegroundColor Green
-
- # Tag the image
- docker tag "$ImageName`:latest" "$FullImageName`:latest"
-
- # Push to DockerHub
- docker push "$FullImageName`:latest"
-
- Write-Host "ā
Image pushed to DockerHub!" -ForegroundColor Green
-}
-
-function Clean-Docker {
- Write-Host "Cleaning up Docker resources..." -ForegroundColor Yellow
-
- # Stop and remove containers
- docker ps -aq | ForEach-Object { docker rm -f $_ }
-
- # Remove images
- docker images "$ImageName" -q | ForEach-Object { docker rmi -f $_ }
-
- # Remove dangling images
- docker image prune -f
-
- Write-Host "ā
Docker cleanup completed!" -ForegroundColor Green
-}
-
-function Show-Logs {
- Write-Host "Showing logs from running containers..." -ForegroundColor Green
- docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
- Write-Host ""
-
- # Show logs for swarms containers
- $containers = docker ps --filter "name=swarms" --format "{{.Names}}"
- foreach ($container in $containers) {
- Write-Host "Logs for $container:" -ForegroundColor Blue
- docker logs $container --tail 20
- Write-Host ""
- }
-}
-
-function Open-Shell {
- Write-Host "Opening shell in running container..." -ForegroundColor Green
-
- # Find running swarms container
- $container = docker ps --filter "name=swarms" --format "{{.Names}}" | Select-Object -First 1
-
- if (-not $container) {
- Write-Host "ā No running swarms container found!" -ForegroundColor Red
- Write-Host "Start a container first with: .\scripts\docker-utils.ps1 run"
- exit 1
- }
-
- Write-Host "Opening shell in $container..." -ForegroundColor Blue
- docker exec -it $container bash
-}
-
-function Compose-Up {
- Write-Host "Starting services with docker-compose..." -ForegroundColor Green
- docker-compose up -d
- Write-Host "ā
Services started!" -ForegroundColor Green
- Write-Host "Use 'docker-compose logs -f' to view logs"
-}
-
-function Compose-Down {
- Write-Host "Stopping services with docker-compose..." -ForegroundColor Yellow
- docker-compose down
- Write-Host "ā
Services stopped!" -ForegroundColor Green
-}
-
-# Main script logic
-switch ($Command.ToLower()) {
- "build" { Build-Image }
- "test" { Test-Image }
- "run" { Run-Interactive }
- "push" { Push-ToDockerHub }
- "clean" { Clean-Docker }
- "logs" { Show-Logs }
- "shell" { Open-Shell }
- "compose-up" { Compose-Up }
- "compose-down" { Compose-Down }
- "help" { Write-Usage }
- default {
- Write-Host "ā Unknown command: $Command" -ForegroundColor Red
- Write-Usage
- exit 1
- }
-}
\ No newline at end of file
From ec495b6668de535976326adba9283c1287f949c4 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:11:37 +0300
Subject: [PATCH 27/56] Delete scripts/docker-utils.sh
---
scripts/docker-utils.sh | 167 ----------------------------------------
1 file changed, 167 deletions(-)
delete mode 100644 scripts/docker-utils.sh
diff --git a/scripts/docker-utils.sh b/scripts/docker-utils.sh
deleted file mode 100644
index 5b86e7dd..00000000
--- a/scripts/docker-utils.sh
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/bin/bash
-
-# Docker utilities for Swarms project
-# Usage: ./scripts/docker-utils.sh [command]
-
-set -e
-
-# Colors for output
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-NC='\033[0m' # No Color
-
-# Configuration
-IMAGE_NAME="swarms"
-REGISTRY="kyegomez"
-FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
-
-# Functions
-print_usage() {
- echo -e "${BLUE}Docker Utilities for Swarms${NC}"
- echo ""
- echo "Usage: $0 [command]"
- echo ""
- echo "Commands:"
- echo " build Build the Docker image locally"
- echo " test Test the Docker image"
- echo " run Run the Docker image interactively"
- echo " push Push to DockerHub (requires login)"
- echo " clean Clean up Docker images and containers"
- echo " logs Show logs from running containers"
- echo " shell Open shell in running container"
- echo " compose-up Start services with docker-compose"
- echo " compose-down Stop services with docker-compose"
- echo " help Show this help message"
- echo ""
-}
-
-build_image() {
- echo -e "${GREEN}Building Docker image...${NC}"
- docker build -t "${IMAGE_NAME}:latest" .
- echo -e "${GREEN}ā
Image built successfully!${NC}"
-}
-
-test_image() {
- echo -e "${GREEN}Testing Docker image...${NC}"
- docker run --rm "${IMAGE_NAME}:latest" python test_docker.py
- echo -e "${GREEN}ā
Image test completed!${NC}"
-}
-
-run_interactive() {
- echo -e "${GREEN}Running Docker image interactively...${NC}"
- docker run -it --rm \
- -v "$(pwd):/app" \
- -w /app \
- "${IMAGE_NAME}:latest" bash
-}
-
-push_to_dockerhub() {
- echo -e "${YELLOW}ā ļø Make sure you're logged into DockerHub first!${NC}"
- echo -e "${GREEN}Pushing to DockerHub...${NC}"
-
- # Tag the image
- docker tag "${IMAGE_NAME}:latest" "${FULL_IMAGE_NAME}:latest"
-
- # Push to DockerHub
- docker push "${FULL_IMAGE_NAME}:latest"
-
- echo -e "${GREEN}ā
Image pushed to DockerHub!${NC}"
-}
-
-clean_docker() {
- echo -e "${YELLOW}Cleaning up Docker resources...${NC}"
-
- # Stop and remove containers
- docker ps -aq | xargs -r docker rm -f
-
- # Remove images
- docker images "${IMAGE_NAME}" -q | xargs -r docker rmi -f
-
- # Remove dangling images
- docker image prune -f
-
- echo -e "${GREEN}ā
Docker cleanup completed!${NC}"
-}
-
-show_logs() {
- echo -e "${GREEN}Showing logs from running containers...${NC}"
- docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
- echo ""
-
- # Show logs for swarms containers
- for container in $(docker ps --filter "name=swarms" --format "{{.Names}}"); do
- echo -e "${BLUE}Logs for $container:${NC}"
- docker logs "$container" --tail 20
- echo ""
- done
-}
-
-open_shell() {
- echo -e "${GREEN}Opening shell in running container...${NC}"
-
- # Find running swarms container
- container=$(docker ps --filter "name=swarms" --format "{{.Names}}" | head -1)
-
- if [ -z "$container" ]; then
- echo -e "${RED}ā No running swarms container found!${NC}"
- echo "Start a container first with: $0 run"
- exit 1
- fi
-
- echo -e "${BLUE}Opening shell in $container...${NC}"
- docker exec -it "$container" bash
-}
-
-compose_up() {
- echo -e "${GREEN}Starting services with docker-compose...${NC}"
- docker-compose up -d
- echo -e "${GREEN}ā
Services started!${NC}"
- echo "Use 'docker-compose logs -f' to view logs"
-}
-
-compose_down() {
- echo -e "${YELLOW}Stopping services with docker-compose...${NC}"
- docker-compose down
- echo -e "${GREEN}ā
Services stopped!${NC}"
-}
-
-# Main script logic
-case "${1:-help}" in
- build)
- build_image
- ;;
- test)
- test_image
- ;;
- run)
- run_interactive
- ;;
- push)
- push_to_dockerhub
- ;;
- clean)
- clean_docker
- ;;
- logs)
- show_logs
- ;;
- shell)
- open_shell
- ;;
- compose-up)
- compose_up
- ;;
- compose-down)
- compose_down
- ;;
- help|--help|-h)
- print_usage
- ;;
- *)
- echo -e "${RED}ā Unknown command: $1${NC}"
- print_usage
- exit 1
- ;;
-esac
\ No newline at end of file
From 753f284da2677b8eb409a99bf425f096b9a5ea0b Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:11:58 +0300
Subject: [PATCH 28/56] Delete .github/workflows/docker-publish.yml
---
.github/workflows/docker-publish.yml | 76 ----------------------------
1 file changed, 76 deletions(-)
delete mode 100644 .github/workflows/docker-publish.yml
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
deleted file mode 100644
index 40fac9cb..00000000
--- a/.github/workflows/docker-publish.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-name: Docker Build and Publish
-
-on:
- push:
- branches: [ "master" ]
- # Publish semver tags as releases
- tags: [ 'v*.*.*' ]
- pull_request:
- branches: [ "master" ]
-
-env:
- # Use docker.io for Docker Hub if empty
- REGISTRY: docker.io
- # github.repository as /
- IMAGE_NAME: ${{ github.repository }}
-
-jobs:
- build:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- # This is used to complete the identity challenge
- # with sigstore/fulcio when running outside of PRs.
- id-token: write
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- # Setup QEMU for multi-platform builds
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
-
- # Setup Docker BuildX
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- # Login to Docker Hub
- - name: Log into registry ${{ env.REGISTRY }}
- if: github.event_name != 'pull_request'
- uses: docker/login-action@v3
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
-
- # Extract metadata (tags, labels) for Docker
- - name: Extract Docker metadata
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- tags: |
- type=ref,event=branch
- type=ref,event=pr
- type=semver,pattern={{version}}
- type=semver,pattern={{major}}.{{minor}}
- type=semver,pattern={{major}}
- type=sha
- type=raw,value=latest,enable={{is_default_branch}}
-
- # Build and push Docker image
- - name: Build and push Docker image
- id: build-and-push
- uses: docker/build-push-action@v6
- with:
- context: .
- push: ${{ github.event_name != 'pull_request' }}
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- platforms: linux/amd64,linux/arm64
- cache-from: type=gha
- cache-to: type=gha,mode=max
- build-args: |
- BUILDKIT_INLINE_CACHE=1
From 945a43981977952c3ab1434fbfc186c781bd2631 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:12:05 +0300
Subject: [PATCH 29/56] Delete .github/workflows/docker-image.yml
---
.github/workflows/docker-image.yml | 18 ------------------
1 file changed, 18 deletions(-)
delete mode 100644 .github/workflows/docker-image.yml
diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml
deleted file mode 100644
index 793d8e0e..00000000
--- a/.github/workflows/docker-image.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Docker Image CI
-
-on:
- push:
- branches: [ "master" ]
- pull_request:
- branches: [ "master" ]
-
-jobs:
-
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
- - name: Build the Docker image
- run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
From db3b8af6e8ca71207e5d17da00cdc655f170a000 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:12:13 +0300
Subject: [PATCH 30/56] Delete .github/workflows/docker-test.yml
---
.github/workflows/docker-test.yml | 58 -------------------------------
1 file changed, 58 deletions(-)
delete mode 100644 .github/workflows/docker-test.yml
diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml
deleted file mode 100644
index 05ee8ed3..00000000
--- a/.github/workflows/docker-test.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-name: Docker Test Build
-
-on:
- pull_request:
- branches: [ "master" ]
- workflow_dispatch:
-
-env:
- REGISTRY: docker.io
- IMAGE_NAME: ${{ github.repository }}
-
-jobs:
- test-build:
- runs-on: ubuntu-latest
- permissions:
- contents: read
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- # Setup QEMU for multi-platform builds
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
-
- # Setup Docker BuildX
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- # Build Docker image (without pushing)
- - name: Build Docker image
- id: build
- uses: docker/build-push-action@v6
- with:
- context: .
- push: false
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
- platforms: linux/amd64
- cache-from: type=gha
- cache-to: type=gha,mode=max
- build-args: |
- BUILDKIT_INLINE_CACHE=1
-
- # Test the built image
- - name: Test Docker image
- run: |
- docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test python test_docker.py
-
- # Show image size
- - name: Show image size
- run: |
- docker images ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
-
- # Clean up test image
- - name: Clean up test image
- if: always()
- run: |
- docker rmi ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test || true
\ No newline at end of file
From ff76d107ff9da6d5c58a0f5f46304336c6641373 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 1 Aug 2025 21:13:29 +0300
Subject: [PATCH 31/56] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e893bfc4..88b23d59 100644
--- a/README.md
+++ b/README.md
@@ -162,7 +162,7 @@ $ docker run -it --rm -v $(pwd):/app kyegomez/swarms:latest bash
$ docker-compose up -d
```
-For more Docker options and advanced usage, see our [Docker documentation](DOCKER.md).
+For more Docker options and advanced usage, see our [Docker documentation](/scripts/docker/DOCKER.md).
---
From 22758f222c065f6fba289cdd650b18bf086ee43d Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Mon, 11 Aug 2025 09:22:37 -0700
Subject: [PATCH 32/56] [EXAMPLES CLEANUP AND ORGANIZATION]
---
example.py | 2 -
.../cron_job_examples/cron_job_example.py | 0
...on_job_figma_stock_swarms_tools_example.py | 0
.../crypto_concurrent_cron_example.py | 0
.../cron_job_examples/figma_stock_example.py | 0
.../simple_concurrent_crypto_cron.py | 0
.../cron_job_examples/solana_price_tracker.py | 0
.../multi_agent/auto_swarm_builder_example.py | 0
.../sims/simulation_vote_example.py | 0
.../agent_map/agent_map_simulation.py | 0
.../agent_map/hospital_simulation_demo.py | 0
.../agent_map/v0/README_simulation.md | 0
.../agent_map/v0/demo_simulation.py | 0
.../agent_map/v0/example_usage.py | 0
.../agent_map/v0/simple_hospital_demo.py | 0
.../agent_map/v0/test_group_conversations.py | 0
.../agent_map/v0/test_simulation.py | 0
.../simulations}/map_generation/game_map.py | 0
.../simulations}/map_generation/map.png | Bin
.../simulations}/map_generation/map_two.png | Bin
.../add_remaining_senators.py | 0
.../add_remaining_senators_batch.py | 0
.../senator_assembly/complete_senator_list.py | 0
.../remaining_senators_data.py | 0
.../senator_simulation_example.py | 0
.../senator_assembly/test_concurrent_vote.py | 0
requirements.txt | 51 ++++++++----------
27 files changed, 21 insertions(+), 32 deletions(-)
rename examples/{ => deployment_solutions}/cron_job_examples/cron_job_example.py (100%)
rename examples/{ => deployment_solutions}/cron_job_examples/cron_job_figma_stock_swarms_tools_example.py (100%)
rename examples/{ => deployment_solutions}/cron_job_examples/crypto_concurrent_cron_example.py (100%)
rename examples/{ => deployment_solutions}/cron_job_examples/figma_stock_example.py (100%)
rename examples/{ => deployment_solutions}/cron_job_examples/simple_concurrent_crypto_cron.py (100%)
rename examples/{ => deployment_solutions}/cron_job_examples/solana_price_tracker.py (100%)
rename auto_swarm_builder_example.py => examples/multi_agent/auto_swarm_builder_example.py (100%)
rename simulation_vote_example.py => examples/sims/simulation_vote_example.py (100%)
rename {simulations => examples/simulations}/agent_map/agent_map_simulation.py (100%)
rename {simulations => examples/simulations}/agent_map/hospital_simulation_demo.py (100%)
rename {simulations => examples/simulations}/agent_map/v0/README_simulation.md (100%)
rename {simulations => examples/simulations}/agent_map/v0/demo_simulation.py (100%)
rename {simulations => examples/simulations}/agent_map/v0/example_usage.py (100%)
rename {simulations => examples/simulations}/agent_map/v0/simple_hospital_demo.py (100%)
rename {simulations => examples/simulations}/agent_map/v0/test_group_conversations.py (100%)
rename {simulations => examples/simulations}/agent_map/v0/test_simulation.py (100%)
rename {simulations => examples/simulations}/map_generation/game_map.py (100%)
rename {simulations => examples/simulations}/map_generation/map.png (100%)
rename {simulations => examples/simulations}/map_generation/map_two.png (100%)
rename {simulations => examples/simulations}/senator_assembly/add_remaining_senators.py (100%)
rename {simulations => examples/simulations}/senator_assembly/add_remaining_senators_batch.py (100%)
rename {simulations => examples/simulations}/senator_assembly/complete_senator_list.py (100%)
rename {simulations => examples/simulations}/senator_assembly/remaining_senators_data.py (100%)
rename {simulations => examples/simulations}/senator_assembly/senator_simulation_example.py (100%)
rename {simulations => examples/simulations}/senator_assembly/test_concurrent_vote.py (100%)
diff --git a/example.py b/example.py
index 7fdef175..561f22fc 100644
--- a/example.py
+++ b/example.py
@@ -40,8 +40,6 @@ agent = Agent(
interactive=True,
no_reasoning_prompt=True,
streaming_on=True,
- # dashboard=True
- llm_base_url="https://api.openai.com/v1",
)
out = agent.run(
diff --git a/examples/cron_job_examples/cron_job_example.py b/examples/deployment_solutions/cron_job_examples/cron_job_example.py
similarity index 100%
rename from examples/cron_job_examples/cron_job_example.py
rename to examples/deployment_solutions/cron_job_examples/cron_job_example.py
diff --git a/examples/cron_job_examples/cron_job_figma_stock_swarms_tools_example.py b/examples/deployment_solutions/cron_job_examples/cron_job_figma_stock_swarms_tools_example.py
similarity index 100%
rename from examples/cron_job_examples/cron_job_figma_stock_swarms_tools_example.py
rename to examples/deployment_solutions/cron_job_examples/cron_job_figma_stock_swarms_tools_example.py
diff --git a/examples/cron_job_examples/crypto_concurrent_cron_example.py b/examples/deployment_solutions/cron_job_examples/crypto_concurrent_cron_example.py
similarity index 100%
rename from examples/cron_job_examples/crypto_concurrent_cron_example.py
rename to examples/deployment_solutions/cron_job_examples/crypto_concurrent_cron_example.py
diff --git a/examples/cron_job_examples/figma_stock_example.py b/examples/deployment_solutions/cron_job_examples/figma_stock_example.py
similarity index 100%
rename from examples/cron_job_examples/figma_stock_example.py
rename to examples/deployment_solutions/cron_job_examples/figma_stock_example.py
diff --git a/examples/cron_job_examples/simple_concurrent_crypto_cron.py b/examples/deployment_solutions/cron_job_examples/simple_concurrent_crypto_cron.py
similarity index 100%
rename from examples/cron_job_examples/simple_concurrent_crypto_cron.py
rename to examples/deployment_solutions/cron_job_examples/simple_concurrent_crypto_cron.py
diff --git a/examples/cron_job_examples/solana_price_tracker.py b/examples/deployment_solutions/cron_job_examples/solana_price_tracker.py
similarity index 100%
rename from examples/cron_job_examples/solana_price_tracker.py
rename to examples/deployment_solutions/cron_job_examples/solana_price_tracker.py
diff --git a/auto_swarm_builder_example.py b/examples/multi_agent/auto_swarm_builder_example.py
similarity index 100%
rename from auto_swarm_builder_example.py
rename to examples/multi_agent/auto_swarm_builder_example.py
diff --git a/simulation_vote_example.py b/examples/sims/simulation_vote_example.py
similarity index 100%
rename from simulation_vote_example.py
rename to examples/sims/simulation_vote_example.py
diff --git a/simulations/agent_map/agent_map_simulation.py b/examples/simulations/agent_map/agent_map_simulation.py
similarity index 100%
rename from simulations/agent_map/agent_map_simulation.py
rename to examples/simulations/agent_map/agent_map_simulation.py
diff --git a/simulations/agent_map/hospital_simulation_demo.py b/examples/simulations/agent_map/hospital_simulation_demo.py
similarity index 100%
rename from simulations/agent_map/hospital_simulation_demo.py
rename to examples/simulations/agent_map/hospital_simulation_demo.py
diff --git a/simulations/agent_map/v0/README_simulation.md b/examples/simulations/agent_map/v0/README_simulation.md
similarity index 100%
rename from simulations/agent_map/v0/README_simulation.md
rename to examples/simulations/agent_map/v0/README_simulation.md
diff --git a/simulations/agent_map/v0/demo_simulation.py b/examples/simulations/agent_map/v0/demo_simulation.py
similarity index 100%
rename from simulations/agent_map/v0/demo_simulation.py
rename to examples/simulations/agent_map/v0/demo_simulation.py
diff --git a/simulations/agent_map/v0/example_usage.py b/examples/simulations/agent_map/v0/example_usage.py
similarity index 100%
rename from simulations/agent_map/v0/example_usage.py
rename to examples/simulations/agent_map/v0/example_usage.py
diff --git a/simulations/agent_map/v0/simple_hospital_demo.py b/examples/simulations/agent_map/v0/simple_hospital_demo.py
similarity index 100%
rename from simulations/agent_map/v0/simple_hospital_demo.py
rename to examples/simulations/agent_map/v0/simple_hospital_demo.py
diff --git a/simulations/agent_map/v0/test_group_conversations.py b/examples/simulations/agent_map/v0/test_group_conversations.py
similarity index 100%
rename from simulations/agent_map/v0/test_group_conversations.py
rename to examples/simulations/agent_map/v0/test_group_conversations.py
diff --git a/simulations/agent_map/v0/test_simulation.py b/examples/simulations/agent_map/v0/test_simulation.py
similarity index 100%
rename from simulations/agent_map/v0/test_simulation.py
rename to examples/simulations/agent_map/v0/test_simulation.py
diff --git a/simulations/map_generation/game_map.py b/examples/simulations/map_generation/game_map.py
similarity index 100%
rename from simulations/map_generation/game_map.py
rename to examples/simulations/map_generation/game_map.py
diff --git a/simulations/map_generation/map.png b/examples/simulations/map_generation/map.png
similarity index 100%
rename from simulations/map_generation/map.png
rename to examples/simulations/map_generation/map.png
diff --git a/simulations/map_generation/map_two.png b/examples/simulations/map_generation/map_two.png
similarity index 100%
rename from simulations/map_generation/map_two.png
rename to examples/simulations/map_generation/map_two.png
diff --git a/simulations/senator_assembly/add_remaining_senators.py b/examples/simulations/senator_assembly/add_remaining_senators.py
similarity index 100%
rename from simulations/senator_assembly/add_remaining_senators.py
rename to examples/simulations/senator_assembly/add_remaining_senators.py
diff --git a/simulations/senator_assembly/add_remaining_senators_batch.py b/examples/simulations/senator_assembly/add_remaining_senators_batch.py
similarity index 100%
rename from simulations/senator_assembly/add_remaining_senators_batch.py
rename to examples/simulations/senator_assembly/add_remaining_senators_batch.py
diff --git a/simulations/senator_assembly/complete_senator_list.py b/examples/simulations/senator_assembly/complete_senator_list.py
similarity index 100%
rename from simulations/senator_assembly/complete_senator_list.py
rename to examples/simulations/senator_assembly/complete_senator_list.py
diff --git a/simulations/senator_assembly/remaining_senators_data.py b/examples/simulations/senator_assembly/remaining_senators_data.py
similarity index 100%
rename from simulations/senator_assembly/remaining_senators_data.py
rename to examples/simulations/senator_assembly/remaining_senators_data.py
diff --git a/simulations/senator_assembly/senator_simulation_example.py b/examples/simulations/senator_assembly/senator_simulation_example.py
similarity index 100%
rename from simulations/senator_assembly/senator_simulation_example.py
rename to examples/simulations/senator_assembly/senator_simulation_example.py
diff --git a/simulations/senator_assembly/test_concurrent_vote.py b/examples/simulations/senator_assembly/test_concurrent_vote.py
similarity index 100%
rename from simulations/senator_assembly/test_concurrent_vote.py
rename to examples/simulations/senator_assembly/test_concurrent_vote.py
diff --git a/requirements.txt b/requirements.txt
index 6482f337..49111486 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,30 +1,21 @@
-torch>=2.1.1,<3.0
-transformers>=4.39.0,<4.55.0
-asyncio>=3.4.3,<4.0
-toml
-pypdf==5.1.0
-ratelimit==2.2.1
-loguru
-pydantic==2.11.4
-tenacity
-rich
-psutil
-python-dotenv
-PyYAML
-docstring_parser==0.16
-black
-ruff
-types-toml>=0.10.8.1
-types-pytz>=2023.3,<2026.0
-types-chardet>=5.0.4.6
-mypy-protobuf>=3.0.0
-pytest
-networkx
-aiofiles
-httpx
-# vllm>=0.2.0
-aiohttp
-mcp
-numpy
-openai
-schedule
\ No newline at end of file
+# Hospital Simulation Dependencies
+# Core Swarms Framework
+swarms>=0.1.0
+
+# ChromaDB for RAG system
+chromadb>=0.4.0
+
+# Additional dependencies for enhanced functionality
+loguru>=0.7.0
+pydantic>=2.0.0
+tenacity>=8.0.0
+
+# Optional: For advanced features
+# pinecone-client>=2.0.0 # Alternative vector database
+# qdrant-client>=1.0.0 # Alternative vector database
+# faiss-cpu>=1.7.0 # Alternative vector database
+
+# Development dependencies (optional)
+# pytest>=7.0.0
+# black>=23.0.0
+# flake8>=6.0.0
\ No newline at end of file
From dc891a8cac29072cb7054c300a5060fd18c32f10 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Mon, 11 Aug 2025 22:58:11 -0700
Subject: [PATCH 33/56] [SWARMS.PROMPTS][CLEANUP]
---
README.md | 11 +-
.../prompts/agent_conversation_aggregator.py | 3 +-
swarms/prompts/agent_prompt.py | 85 ----------
swarms/prompts/chat_prompt.py | 159 ------------------
swarms/prompts/idea2img.py | 33 ++--
swarms/prompts/legal_agent_prompt.py | 1 +
6 files changed, 21 insertions(+), 271 deletions(-)
delete mode 100644 swarms/prompts/agent_prompt.py
delete mode 100644 swarms/prompts/chat_prompt.py
diff --git a/README.md b/README.md
index 409395ce..38741e6e 100644
--- a/README.md
+++ b/README.md
@@ -112,31 +112,28 @@ Swarms delivers a comprehensive, enterprise-grade multi-agent infrastructure pla
## Install š»
### Using pip
+
```bash
$ pip3 install -U swarms
```
### Using uv (Recommended)
+
[uv](https://github.com/astral-sh/uv) is a fast Python package installer and resolver, written in Rust.
```bash
-# Install uv
-$ curl -LsSf https://astral.sh/uv/install.sh | sh
-
# Install swarms using uv
$ uv pip install swarms
```
### Using poetry
-```bash
-# Install poetry if you haven't already
-$ curl -sSL https://install.python-poetry.org | python3 -
-# Add swarms to your project
+```bash
$ poetry add swarms
```
### From source
+
```bash
# Clone the repository
$ git clone https://github.com/kyegomez/swarms.git
diff --git a/swarms/prompts/agent_conversation_aggregator.py b/swarms/prompts/agent_conversation_aggregator.py
index 03d54cb5..f2be202d 100644
--- a/swarms/prompts/agent_conversation_aggregator.py
+++ b/swarms/prompts/agent_conversation_aggregator.py
@@ -1,4 +1,5 @@
-AGGREGATOR_SYSTEM_PROMPT = """You are a highly skilled Aggregator Agent responsible for analyzing, synthesizing, and summarizing conversations between multiple AI agents. Your primary goal is to distill complex multi-agent interactions into clear, actionable insights.
+AGGREGATOR_SYSTEM_PROMPT = """
+You are a highly skilled Aggregator Agent responsible for analyzing, synthesizing, and summarizing conversations between multiple AI agents. Your primary goal is to distill complex multi-agent interactions into clear, actionable insights.
Key Responsibilities:
1. Conversation Analysis:
diff --git a/swarms/prompts/agent_prompt.py b/swarms/prompts/agent_prompt.py
deleted file mode 100644
index 62f921e2..00000000
--- a/swarms/prompts/agent_prompt.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import json
-from typing import List
-
-
-class PromptGenerator:
- """A class for generating custom prompt strings."""
-
- def __init__(self) -> None:
- """Initialize the PromptGenerator object."""
- self.constraints: List[str] = []
- self.commands: List[str] = []
- self.resources: List[str] = []
- self.performance_evaluation: List[str] = []
- self.response_format = {
- "thoughts": {
- "text": "thought",
- "reasoning": "reasoning",
- "plan": (
- "- short bulleted\n- list that conveys\n-"
- " long-term plan"
- ),
- "criticism": "constructive self-criticism",
- "speak": "thoughts summary to say to user",
- },
- "command": {
- "name": "command name",
- "args": {"arg name": "value"},
- },
- }
-
- def add_constraint(self, constraint: str) -> None:
- """
- Add a constraint to the constraints list.
-
- Args:
- constraint (str): The constraint to be added.
- """
- self.constraints.append(constraint)
-
- def add_command(self, command: str) -> None:
- """
- Add a command to the commands list.
-
- Args:
- command (str): The command to be added.
- """
- self.commands.append(command)
-
- def add_resource(self, resource: str) -> None:
- """
- Add a resource to the resources list.
-
- Args:
- resource (str): The resource to be added.
- """
- self.resources.append(resource)
-
- def add_performance_evaluation(self, evaluation: str) -> None:
- """
- Add a performance evaluation item to the performance_evaluation list.
-
- Args:
- evaluation (str): The evaluation item to be added.
- """
- self.performance_evaluation.append(evaluation)
-
- def generate_prompt_string(self) -> str:
- """Generate a prompt string.
-
- Returns:
- str: The generated prompt string.
- """
- formatted_response_format = json.dumps(
- self.response_format, indent=4
- )
- prompt_string = (
- f"Constraints:\n{''.join(self.constraints)}\n\nCommands:\n{''.join(self.commands)}\n\nResources:\n{''.join(self.resources)}\n\nPerformance"
- f" Evaluation:\n{''.join(self.performance_evaluation)}\n\nYou"
- " should only respond in JSON format as described below"
- " \nResponse Format:"
- f" \n{formatted_response_format} \nEnsure the response"
- " can be parsed by Python json.loads"
- )
-
- return prompt_string
diff --git a/swarms/prompts/chat_prompt.py b/swarms/prompts/chat_prompt.py
deleted file mode 100644
index 49a0aa23..00000000
--- a/swarms/prompts/chat_prompt.py
+++ /dev/null
@@ -1,159 +0,0 @@
-from __future__ import annotations
-
-from abc import abstractmethod
-from typing import Sequence
-
-
-class Message:
- """
- The base abstract Message class.
- Messages are the inputs and outputs of ChatModels.
- """
-
- def __init__(
- self, content: str, role: str, additional_kwargs: dict = None
- ):
- self.content = content
- self.role = role
- self.additional_kwargs = (
- additional_kwargs if additional_kwargs else {}
- )
-
- @abstractmethod
- def get_type(self) -> str:
- pass
-
-
-class HumanMessage(Message):
- """
- A Message from a human.
- """
-
- def __init__(
- self,
- content: str,
- role: str = "Human",
- additional_kwargs: dict = None,
- example: bool = False,
- ):
- super().__init__(content, role, additional_kwargs)
- self.example = example
-
- def get_type(self) -> str:
- return "human"
-
-
-class AIMessage(Message):
- """
- A Message from an AI.
- """
-
- def __init__(
- self,
- content: str,
- role: str = "AI",
- additional_kwargs: dict = None,
- example: bool = False,
- ):
- super().__init__(content, role, additional_kwargs)
- self.example = example
-
- def get_type(self) -> str:
- return "ai"
-
-
-class SystemMessage(Message):
- """
- A Message for priming AI behavior, usually passed in as the first of a sequence
- of input messages.
- """
-
- def __init__(
- self,
- content: str,
- role: str = "System",
- additional_kwargs: dict = None,
- ):
- super().__init__(content, role, additional_kwargs)
-
- def get_type(self) -> str:
- return "system"
-
-
-class FunctionMessage(Message):
- """
- A Message for passing the result of executing a function back to a model.
- """
-
- def __init__(
- self,
- content: str,
- role: str = "Function",
- name: str = None,
- additional_kwargs: dict = None,
- ):
- super().__init__(content, role, additional_kwargs)
- self.name = name
-
- def get_type(self) -> str:
- return "function"
-
-
-class ChatMessage(Message):
- """
- A Message that can be assigned an arbitrary speaker (i.e. role).
- """
-
- def __init__(
- self, content: str, role: str, additional_kwargs: dict = None
- ):
- super().__init__(content, role, additional_kwargs)
-
- def get_type(self) -> str:
- return "chat"
-
-
-def get_buffer_string(
- messages: Sequence[Message],
- human_prefix: str = "Human",
- ai_prefix: str = "AI",
-) -> str:
- string_messages = []
- for m in messages:
- message = f"{m.role}: {m.content}"
- if (
- isinstance(m, AIMessage)
- and "function_call" in m.additional_kwargs
- ):
- message += f"{m.additional_kwargs['function_call']}"
- string_messages.append(message)
-
- return "\n".join(string_messages)
-
-
-def message_to_dict(message: Message) -> dict:
- return {"type": message.get_type(), "data": message.__dict__}
-
-
-def messages_to_dict(messages: Sequence[Message]) -> list[dict]:
- return [message_to_dict(m) for m in messages]
-
-
-def message_from_dict(message: dict) -> Message:
- _type = message["type"]
- if _type == "human":
- return HumanMessage(**message["data"])
- elif _type == "ai":
- return AIMessage(**message["data"])
- elif _type == "system":
- return SystemMessage(**message["data"])
- elif _type == "chat":
- return ChatMessage(**message["data"])
- elif _type == "function":
- return FunctionMessage(**message["data"])
- else:
- raise ValueError(f"Got unexpected message type: {_type}")
-
-
-def messages_from_dict(messages: list[dict]) -> list[Message]:
- return [message_from_dict(m) for m in messages]
diff --git a/swarms/prompts/idea2img.py b/swarms/prompts/idea2img.py
index 75a68814..4144d90b 100644
--- a/swarms/prompts/idea2img.py
+++ b/swarms/prompts/idea2img.py
@@ -1,19 +1,14 @@
-IMAGE_ENRICHMENT_PROMPT = (
- "Create a concise and effective image generation prompt within"
- " 400 characters or less, "
- "based on Stable Diffusion and Dalle best practices. Starting"
- " prompt: \n\n'"
- # f"{prompt}'\n\n"
- "Improve the prompt with any applicable details or keywords by"
- " considering the following aspects: \n"
- "1. Subject details (like actions, emotions, environment) \n"
- "2. Artistic style (such as surrealism, hyperrealism) \n"
- "3. Medium (digital painting, oil on canvas) \n"
- "4. Color themes and lighting (like warm colors, cinematic"
- " lighting) \n"
- "5. Composition and framing (close-up, wide-angle) \n"
- "6. Additional elements (like a specific type of background,"
- " weather conditions) \n"
- "7. Any other artistic or thematic details that can make the"
- " image more vivid and compelling."
-)
+IMAGE_ENRICHMENT_PROMPT = """
+Create a concise and effective image generation prompt within 400 characters or less, based on Stable Diffusion and Dalle best practices.
+
+Improve the prompt with any applicable details or keywords by considering the following aspects:
+1. Subject details (like actions, emotions, environment)
+2. Artistic style (such as surrealism, hyperrealism)
+3. Medium (digital painting, oil on canvas)
+4. Color themes and lighting (like warm colors, cinematic lighting)
+5. Composition and framing (close-up, wide-angle)
+6. Additional elements (like a specific type of background, weather conditions)
+7. Any other artistic or thematic details that can make the image more vivid and compelling.
+
+
+"""
diff --git a/swarms/prompts/legal_agent_prompt.py b/swarms/prompts/legal_agent_prompt.py
index cf6a327f..6387d1ae 100644
--- a/swarms/prompts/legal_agent_prompt.py
+++ b/swarms/prompts/legal_agent_prompt.py
@@ -72,4 +72,5 @@ Legal landscapes are ever-evolving, demanding regular updates and improvements.
5. Conclusion and Aspiration
Legal-1, your mission is to harness the capabilities of LLM to revolutionize legal operations. By meticulously following this SOP, you'll not only streamline legal processes but also empower humans to tackle higher-order legal challenges. Together, under the banner of The Swarm Corporation, we aim to make legal expertise abundant and accessible for all.
+
"""
From 578252542a7d6abfcfed9590205c9b4611ac57f8 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Mon, 11 Aug 2025 23:04:08 -0700
Subject: [PATCH 34/56] [readme links]
---
README.md | 169 +++++++++++++++++++++++++++++-------------------------
1 file changed, 91 insertions(+), 78 deletions(-)
diff --git a/README.md b/README.md
index 38741e6e..e5bf3df8 100644
--- a/README.md
+++ b/README.md
@@ -8,92 +8,106 @@
Date: Mon, 11 Aug 2025 23:09:28 -0700
Subject: [PATCH 35/56] [readme links]g
---
README.md | 97 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 53 insertions(+), 44 deletions(-)
diff --git a/README.md b/README.md
index e5bf3df8..f132db1e 100644
--- a/README.md
+++ b/README.md
@@ -21,45 +21,11 @@
- š¦ Twitter
- ā¢
- š¢ Discord
- ā¢
- Swarms Website
- ā¢
- š Documentation
- ā¢
- Swarms Marketplace
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
@@ -68,10 +34,10 @@
-
+
-
-
+
+
@@ -80,18 +46,61 @@
+
+
+
+
+
+
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ š Swarms Website
+ ā¢
+ š Documentation
+ ā¢
+ š Swarms Marketplace
From 7b0510bcd5b954ffc3e94e41f388ba58661e3095 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Tue, 12 Aug 2025 10:17:16 -0700
Subject: [PATCH 36/56] requirements
---
requirements.txt | 51 ++++++++++++++++++------------
swarms/tools/create_agent_tool.py | 10 +++---
swarms/tools/func_calling_utils.py | 2 +-
3 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/requirements.txt b/requirements.txt
index 49111486..ead3af6e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,21 +1,30 @@
-# Hospital Simulation Dependencies
-# Core Swarms Framework
-swarms>=0.1.0
-
-# ChromaDB for RAG system
-chromadb>=0.4.0
-
-# Additional dependencies for enhanced functionality
-loguru>=0.7.0
-pydantic>=2.0.0
-tenacity>=8.0.0
-
-# Optional: For advanced features
-# pinecone-client>=2.0.0 # Alternative vector database
-# qdrant-client>=1.0.0 # Alternative vector database
-# faiss-cpu>=1.7.0 # Alternative vector database
-
-# Development dependencies (optional)
-# pytest>=7.0.0
-# black>=23.0.0
-# flake8>=6.0.0
\ No newline at end of file
+torch>=2.1.1,<3.0
+transformers>=4.39.0,<4.51.0
+asyncio>=3.4.3,<4.0
+toml
+pypdf==5.1.0
+ratelimit==2.2.1
+loguru
+pydantic==2.11.4
+tenacity
+rich
+psutil
+python-dotenv
+PyYAML
+docstring_parser==0.16
+black
+ruff
+types-toml>=0.10.8.1
+types-pytz>=2023.3,<2026.0
+types-chardet>=5.0.4.6
+mypy-protobuf>=3.0.0
+pytest
+networkx
+aiofiles
+httpx
+# vllm>=0.2.0
+aiohttp
+mcp
+numpy
+openai
+schedule
\ No newline at end of file
diff --git a/swarms/tools/create_agent_tool.py b/swarms/tools/create_agent_tool.py
index c6897d8f..b4adb926 100644
--- a/swarms/tools/create_agent_tool.py
+++ b/swarms/tools/create_agent_tool.py
@@ -1,10 +1,12 @@
-from typing import Union
-from swarms.structs.agent import Agent
-from swarms.schemas.agent_class_schema import AgentConfiguration
-from functools import lru_cache
import json
+from functools import lru_cache
+from typing import Union
+
from pydantic import ValidationError
+from swarms.schemas.agent_class_schema import AgentConfiguration
+from swarms.structs.agent import Agent
+
def validate_and_convert_config(
agent_configuration: Union[AgentConfiguration, dict, str],
diff --git a/swarms/tools/func_calling_utils.py b/swarms/tools/func_calling_utils.py
index 28f078be..2c2768cf 100644
--- a/swarms/tools/func_calling_utils.py
+++ b/swarms/tools/func_calling_utils.py
@@ -1,5 +1,5 @@
import json
-from typing import List, Union, Dict
+from typing import Dict, List, Union
from pydantic import BaseModel
From 084ca6c5fd41b2f23a01b1df963106f69547fdff Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 12 Aug 2025 17:18:56 +0000
Subject: [PATCH 37/56] Update asyncio requirement from >=3.4.3,<4.0 to
>=3.4.3,<5.0
Updates the requirements on [asyncio](https://github.com/python/asyncio) to permit the latest version.
- [Commits](https://github.com/python/asyncio/commits)
---
updated-dependencies:
- dependency-name: asyncio
dependency-version: 4.0.0
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index d1b0e0f7..6b16f587 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -60,7 +60,7 @@ python = ">=3.10,<4.0"
# torch = ">=2.1.1,<3.0"
# transformers = ">= 4.39.0, <5.0.0"
setuptools = "*"
-asyncio = ">=3.4.3,<4.0"
+asyncio = ">=3.4.3,<5.0"
toml = "*"
pypdf = "5.1.0"
loguru = "*"
From bfd9fa5cd9d91eff74bcead80c7a2ae147632a5c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 12 Aug 2025 17:19:00 +0000
Subject: [PATCH 38/56] Update ruff requirement from >=0.5.1,<0.12.6 to
>=0.5.1,<0.12.9
Updates the requirements on [ruff](https://github.com/astral-sh/ruff) to permit the latest version.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.1...0.12.8)
---
updated-dependencies:
- dependency-name: ruff
dependency-version: 0.12.8
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index d1b0e0f7..995182ee 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -88,7 +88,7 @@ swarms = "swarms.cli.main:main"
[tool.poetry.group.lint.dependencies]
black = ">=23.1,<26.0"
-ruff = ">=0.5.1,<0.12.6"
+ruff = ">=0.5.1,<0.12.9"
types-toml = "^0.10.8.1"
types-pytz = ">=2023.3,<2026.0"
types-chardet = "^5.0.4.6"
From 92c9db48e1e20d99cb1649ecb989ff106f82095c Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Wed, 13 Aug 2025 08:45:57 -0700
Subject: [PATCH 39/56] Community resources docs
---
docs/examples/community_resources.md | 36 ++++++++++++++++
docs/mkdocs.yml | 1 +
examples/single_agent/llms/mistral_example.py | 20 +++++++++
swarms/sims/senator_assembly.py | 7 ++--
swarms/structs/__init__.py | 1 -
swarms/structs/agent.py | 42 +++++++++----------
swarms/structs/concurrent_workflow.py | 2 +-
swarms/structs/deep_research_swarm.py | 4 --
swarms/tools/py_func_to_openai_func_str.py | 2 +-
9 files changed, 84 insertions(+), 31 deletions(-)
create mode 100644 docs/examples/community_resources.md
create mode 100644 examples/single_agent/llms/mistral_example.py
diff --git a/docs/examples/community_resources.md b/docs/examples/community_resources.md
new file mode 100644
index 00000000..fcc38e6f
--- /dev/null
+++ b/docs/examples/community_resources.md
@@ -0,0 +1,36 @@
+# Community Resources
+
+Welcome to the Community Resources page! Here you'll find a curated collection of articles, tutorials, and guides created by the Swarms community and core contributors.
+
+These resources cover a wide range of topics, including building your first agent, advanced multi-agent architectures, API integrations, and using Swarms with both Python and Rust. Whether you're a beginner or an experienced developer, these links will help you deepen your understanding and accelerate your development with the Swarms framework.
+
+
+## Python
+
+| Title | Description | Link |
+|-------|-------------|------|
+| **Build Your First Swarms Agent in Under 10 Minutes** | Step-by-step beginner guide to creating your first Swarms agent quickly. | [Read Article](https://medium.com/@devangvashistha/build-your-first-swarms-agent-in-under-10-minutes-ddff23b6c703) |
+| **Building Multi-Agent Systems with GPT-5 and The Swarms Framework** | Learn how to leverage GPT-5 with Swarms for advanced multi-agent system design. | [Read Article](https://medium.com/@kyeg/building-multi-agent-systems-with-gpt-5-and-the-swarms-framework-e52ffaf0fa4f) |
+| **Learn How to Build Production-Grade Agents with OpenAIās Latest Model: GPT-OSS Locally and in the Cloud** | Guide to building robust agents using OpenAIās GPT-OSS, both locally and in cloud environments. | [Read Article](https://medium.com/@kyeg/learn-how-to-build-production-grade-agents-with-openais-latest-model-gpt-oss-locally-and-in-the-c5826c7cca7c) |
+| **Building Gemini 2.5 Agents with Swarms Framework** | Tutorial on integrating Gemini 2.5 models into Swarms agents for enhanced capabilities. | [Read Article](https://medium.com/@kyeg/building-gemini-2-5-agents-with-swarms-framework-20abdcf82cac) |
+| **Enterprise Developer Guide: Leveraging OpenAIās o3 and o4-mini Models with The Swarms Framework** | Enterprise-focused guide to using OpenAIās o3 and o4-mini models within Swarms. | [Read Article](https://medium.com/@kyeg/enterprise-developer-guide-leveraging-openais-o3-and-o4-mini-models-with-the-swarms-framework-89490c57820a) |
+| **Enneagram of Thoughts Using the Swarms Framework: A Multi-Agent Approach to Holistic Problem Solving** | Explores using Swarms for holistic, multi-perspective problem solving via the Enneagram model. | [Read Article](https://medium.com/@kyeg/enneagram-of-thoughts-using-the-swarms-framework-a-multi-agent-approach-to-holistic-problem-c26c7df5e7eb) |
+| **Building Production-Grade Financial Agents with tickr-agent: An Enterprise Solution for Comprehensive Stock Analysis** | How to build advanced financial analysis agents using tickr-agent and Swarms. | [Read Article](https://medium.com/@kyeg/building-production-grade-financial-agents-with-tickr-agent-an-enterprise-solution-for-db867ec93193) |
+| **Automating Your Startupās Financial Analysis Using AI Agents: A Comprehensive Guide** | Comprehensive guide to automating your startupās financial analysis with AI agents using Swarms. | [Read Article](https://medium.com/@kyeg/automating-your-startups-financial-analysis-using-ai-agents-a-comprehensive-guide-b2fa0e2c09d5) |
+| **Managing Thousands of Agent Outputs at Scale with The Spreadsheet Swarm: All-New Multi-Agent Architecture** | Learn how to manage and scale thousands of agent outputs efficiently using the Spreadsheet Swarm architecture. | [Read Article](https://medium.com/@kyeg/managing-thousands-of-agent-outputs-at-scale-with-the-spreadsheet-swarm-all-new-multi-agent-f16f5f40fd5a) |
+| **Introducing GPT-4o Mini: The Future of Cost-Efficient AI Intelligence** | Discover the capabilities and advantages of GPT-4o Mini for building cost-effective, intelligent agents. | [Read Article](https://medium.com/@kyeg/introducing-gpt-4o-mini-the-future-of-cost-efficient-ai-intelligence-a3e3fe78d939) |
+
+
+### API
+
+| Title | Description | Link |
+|-------|-------------|------|
+| **Specialized Healthcare Agents with Swarms Agent Completions API** | Guide to building healthcare-focused agents using the Swarms API. | [Read Article](https://medium.com/@kyeg/specialized-healthcare-agents-with-swarms-agent-completions-api-b56d067e3b11) |
+| **Building Multi-Agent Systems for Finance & Accounting with the Swarms API: A Technical Guide** | Technical walkthrough for creating finance and accounting multi-agent systems with the Swarms API. | [Read Article](https://medium.com/@kyeg/building-multi-agent-systems-for-finance-accounting-with-the-swarms-api-a-technical-guide-bf6f7005b708) |
+
+### Swarms Rust
+
+| Title | Description | Link |
+|-------|-------------|------|
+| **Building Medical Multi-Agent Systems with Swarms Rust: A Comprehensive Tutorial** | Comprehensive tutorial for developing medical multi-agent systems using Swarms Rust. | [Read Article](https://medium.com/@kyeg/building-medical-multi-agent-systems-with-swarms-rust-a-comprehensive-tutorial-1e8e060601f9) |
+| **Building Production-Grade Agentic Applications with Swarms Rust: A Comprehensive Tutorial** | Learn to build robust, production-ready agentic applications with Swarms Rust. | [Read Article](https://medium.com/@kyeg/building-production-grade-agentic-applications-with-swarms-rust-a-comprehensive-tutorial-bb567c02340f) |
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 888f7f30..7e27c017 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -354,6 +354,7 @@ nav:
- CookBook Index: "examples/cookbook_index.md"
- Paper Implementations: "examples/paper_implementations.md"
- Templates & Applications: "examples/templates.md"
+ - Community Resources: "examples/community_resources.md"
- Basic Examples:
- Individual Agents:
- Basic Agent: "swarms/examples/basic_agent.md"
diff --git a/examples/single_agent/llms/mistral_example.py b/examples/single_agent/llms/mistral_example.py
new file mode 100644
index 00000000..9d22143d
--- /dev/null
+++ b/examples/single_agent/llms/mistral_example.py
@@ -0,0 +1,20 @@
+from swarms import Agent
+
+# Initialize the agent
+agent = Agent(
+ agent_name="Quantitative-Trading-Agent",
+ agent_description="Quantitative trading and analysis agent",
+ system_prompt="You are an expert quantitative trading agent. Answer concisely and accurately using your knowledge of trading strategies, risk management, and financial markets.",
+ model_name="mistral/mistral-tiny",
+ dynamic_temperature_enabled=True,
+ output_type="str-all-except-first",
+ max_loops="auto",
+ interactive=True,
+ no_reasoning_prompt=True,
+ streaming_on=True,
+)
+
+out = agent.run(
+ task="What are the best top 3 etfs for gold coverage?"
+)
+print(out)
diff --git a/swarms/sims/senator_assembly.py b/swarms/sims/senator_assembly.py
index 64e3d34e..c125e2c6 100644
--- a/swarms/sims/senator_assembly.py
+++ b/swarms/sims/senator_assembly.py
@@ -6,13 +6,14 @@ each with detailed backgrounds, political positions, and comprehensive system pr
that reflect their real-world characteristics, voting patterns, and policy priorities.
"""
+from functools import lru_cache
from typing import Dict, List, Optional
-from swarms import Agent
-from swarms.structs.multi_agent_exec import run_agents_concurrently
-from functools import lru_cache
from loguru import logger
+
+from swarms.structs.agent import Agent
from swarms.structs.conversation import Conversation
+from swarms.structs.multi_agent_exec import run_agents_concurrently
@lru_cache(maxsize=1)
diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py
index acad1008..9ea95998 100644
--- a/swarms/structs/__init__.py
+++ b/swarms/structs/__init__.py
@@ -96,7 +96,6 @@ from swarms.structs.swarming_architectures import (
star_swarm,
)
-
__all__ = [
"Agent",
"BaseStructure",
diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py
index aaf8d028..73435c30 100644
--- a/swarms/structs/agent.py
+++ b/swarms/structs/agent.py
@@ -27,9 +27,12 @@ from pydantic import BaseModel
from swarms.agents.ape_agent import auto_generate_prompt
from swarms.artifacts.main_artifact import Artifact
from swarms.prompts.agent_system_prompts import AGENT_SYSTEM_PROMPT_3
+from swarms.prompts.max_loop_prompt import generate_reasoning_prompt
from swarms.prompts.multi_modal_autonomous_instruction_prompt import (
MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
)
+from swarms.prompts.react_base_prompt import REACT_SYS_PROMPT
+from swarms.prompts.safety_prompt import SAFETY_PROMPT
from swarms.prompts.tools import tool_sop_prompt
from swarms.schemas.agent_mcp_errors import (
AgentMCPConnectionError,
@@ -41,19 +44,30 @@ from swarms.schemas.base_schemas import (
ChatCompletionResponseChoice,
ChatMessageResponse,
)
+from swarms.schemas.conversation_schema import ConversationSchema
from swarms.schemas.llm_agent_schema import ModelConfigOrigin
+from swarms.schemas.mcp_schemas import (
+ MCPConnection,
+)
from swarms.structs.agent_rag_handler import (
- RAGConfig,
AgentRAGHandler,
+ RAGConfig,
)
from swarms.structs.agent_roles import agent_roles
from swarms.structs.conversation import Conversation
+from swarms.structs.ma_utils import set_random_models_for_agents
from swarms.structs.safe_loading import (
SafeLoaderUtils,
SafeStateManager,
)
from swarms.telemetry.main import log_agent_data
from swarms.tools.base_tool import BaseTool
+from swarms.tools.mcp_client_call import (
+ execute_multiple_tools_on_multiple_mcp_servers_sync,
+ execute_tool_call_simple,
+ get_mcp_tools_sync,
+ get_tools_for_multiple_mcp_servers,
+)
from swarms.tools.py_func_to_openai_func_str import (
convert_multiple_functions_to_openai_function_schema,
)
@@ -64,28 +78,14 @@ from swarms.utils.generate_keys import generate_api_key
from swarms.utils.history_output_formatter import (
history_output_formatter,
)
-from swarms.utils.litellm_tokenizer import count_tokens
-from swarms.utils.litellm_wrapper import LiteLLM
-from swarms.utils.pdf_to_text import pdf_to_text
-from swarms.prompts.react_base_prompt import REACT_SYS_PROMPT
-from swarms.prompts.max_loop_prompt import generate_reasoning_prompt
-from swarms.prompts.safety_prompt import SAFETY_PROMPT
-from swarms.structs.ma_utils import set_random_models_for_agents
-from swarms.tools.mcp_client_call import (
- execute_multiple_tools_on_multiple_mcp_servers_sync,
- execute_tool_call_simple,
- get_mcp_tools_sync,
- get_tools_for_multiple_mcp_servers,
-)
-from swarms.schemas.mcp_schemas import (
- MCPConnection,
-)
from swarms.utils.index import (
exists,
format_data_structure,
)
-from swarms.schemas.conversation_schema import ConversationSchema
+from swarms.utils.litellm_tokenizer import count_tokens
+from swarms.utils.litellm_wrapper import LiteLLM
from swarms.utils.output_types import OutputType
+from swarms.utils.pdf_to_text import pdf_to_text
def stop_when_repeats(response: str) -> bool:
@@ -899,9 +899,9 @@ class Agent:
bool: True if model supports vision and image is provided, False otherwise.
"""
from litellm.utils import (
- supports_vision,
supports_function_calling,
supports_parallel_function_calling,
+ supports_vision,
)
# Only check vision support if an image is provided
@@ -1549,11 +1549,11 @@ class Agent:
raise
def reliability_check(self):
+ from litellm import model_list
from litellm.utils import (
- supports_function_calling,
get_max_tokens,
+ supports_function_calling,
)
- from litellm import model_list
if self.system_prompt is None:
logger.warning(
diff --git a/swarms/structs/concurrent_workflow.py b/swarms/structs/concurrent_workflow.py
index 86cba2a1..4ceb62e0 100644
--- a/swarms/structs/concurrent_workflow.py
+++ b/swarms/structs/concurrent_workflow.py
@@ -5,12 +5,12 @@ from typing import Callable, List, Optional, Union
from swarms.structs.agent import Agent
from swarms.structs.base_swarm import BaseSwarm
from swarms.structs.conversation import Conversation
+from swarms.utils.formatter import formatter
from swarms.utils.get_cpu_cores import get_cpu_cores
from swarms.utils.history_output_formatter import (
history_output_formatter,
)
from swarms.utils.loguru_logger import initialize_logger
-from swarms.utils.formatter import formatter
logger = initialize_logger(log_folder="concurrent_workflow")
diff --git a/swarms/structs/deep_research_swarm.py b/swarms/structs/deep_research_swarm.py
index 188ac7ea..b71e81c1 100644
--- a/swarms/structs/deep_research_swarm.py
+++ b/swarms/structs/deep_research_swarm.py
@@ -23,10 +23,6 @@ MAX_WORKERS = (
os.cpu_count() * 2
) # Optimal number of workers based on CPU cores
-###############################################################################
-# 1. System Prompts for Each Scientist Agent
-###############################################################################
-
def exa_search(query: str, **kwargs: Any) -> str:
"""Performs web search using Exa.ai API and returns formatted results."""
diff --git a/swarms/tools/py_func_to_openai_func_str.py b/swarms/tools/py_func_to_openai_func_str.py
index 26f64455..a1232ed0 100644
--- a/swarms/tools/py_func_to_openai_func_str.py
+++ b/swarms/tools/py_func_to_openai_func_str.py
@@ -1,8 +1,8 @@
-import os
import concurrent.futures
import functools
import inspect
import json
+import os
from logging import getLogger
from typing import (
Any,
From 7042f9c77b1d3d47d25149ba16cb1a5d95fa5001 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Wed, 13 Aug 2025 08:54:31 -0700
Subject: [PATCH 40/56] [CLEAN UP PAPERS IMPLEMENTATIONS
---
docs/contributors/docs.md | 2 +-
docs/contributors/environment_setup.md | 2 +-
docs/examples/agent_stream.md | 2 +-
docs/examples/community_resources.md | 9 ++-
docs/examples/cookbook_index.md | 2 +-
docs/examples/paper_implementations.md | 79 ++-----------------
docs/examples/templates.md | 2 +-
docs/governance/bounty_program.md | 2 +-
docs/governance/main.md | 4 +-
docs/guides/financial_analysis_swarm_mm.md | 6 +-
docs/guides/healthcare_blog.md | 2 +-
docs/index.md | 4 +-
docs/llm.txt | 76 +++++++++---------
docs/mkdocs.yml | 2 +-
docs/quickstart.md | 2 +-
docs/swarms/agents/index.md | 2 +-
docs/swarms/concept/framework_architecture.md | 2 +-
docs/swarms/ecosystem.md | 4 +-
docs/swarms/examples/igc_example.md | 2 +-
docs/swarms/examples/moa_example.md | 2 +-
docs/swarms/examples/multiple_images.md | 2 +-
docs/swarms/examples/vision_tools.md | 2 +-
docs/swarms/products.md | 2 +-
docs/swarms/structs/agent_mcp.md | 4 +-
docs/swarms/structs/index.md | 2 +-
docs/swarms/support.md | 6 +-
docs/swarms_cloud/agent_api.md | 2 +-
docs/swarms_cloud/api_clients.md | 2 +-
docs/swarms_cloud/quickstart.md | 2 +-
docs/swarms_cloud/swarms_api.md | 2 +-
docs/swarms_memory/index.md | 2 +-
docs/swarms_platform/index.md | 4 +-
32 files changed, 88 insertions(+), 152 deletions(-)
diff --git a/docs/contributors/docs.md b/docs/contributors/docs.md
index eca7d778..377658d8 100644
--- a/docs/contributors/docs.md
+++ b/docs/contributors/docs.md
@@ -318,7 +318,7 @@ Schedule quarterly audits to refine structure and content across all repositorie
Promote your contributions via:
-- **Swarms Discord**: https://discord.gg/jM3Z6M9uMq
+- **Swarms Discord**: https://discord.gg/EamjgSaEQf
- **Swarms Telegram**: https://t.me/swarmsgroupchat
diff --git a/docs/contributors/environment_setup.md b/docs/contributors/environment_setup.md
index 18d0d48f..7145b6d2 100644
--- a/docs/contributors/environment_setup.md
+++ b/docs/contributors/environment_setup.md
@@ -623,7 +623,7 @@ If you encounter issues:
1. **Check the FAQ** in the main documentation
2. **Search existing issues** on GitHub
-3. **Ask in the Discord community**: [discord.gg/jM3Z6M9uMq](https://discord.gg/jM3Z6M9uMq)
+3. **Ask in the Discord community**: [discord.gg/jM3Z6M9uMq](https://discord.gg/EamjgSaEQf)
4. **Create a GitHub issue** with:
- Your operating system
- Python version
diff --git a/docs/examples/agent_stream.md b/docs/examples/agent_stream.md
index 2c5bc6b9..79c0a8ef 100644
--- a/docs/examples/agent_stream.md
+++ b/docs/examples/agent_stream.md
@@ -54,7 +54,7 @@ If you'd like technical support, join our Discord below and stay updated on our
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
diff --git a/docs/examples/community_resources.md b/docs/examples/community_resources.md
index fcc38e6f..58d81038 100644
--- a/docs/examples/community_resources.md
+++ b/docs/examples/community_resources.md
@@ -5,7 +5,7 @@ Welcome to the Community Resources page! Here you'll find a curated collection o
These resources cover a wide range of topics, including building your first agent, advanced multi-agent architectures, API integrations, and using Swarms with both Python and Rust. Whether you're a beginner or an experienced developer, these links will help you deepen your understanding and accelerate your development with the Swarms framework.
-## Python
+## Swarms Python
| Title | Description | Link |
|-------|-------------|------|
@@ -21,7 +21,7 @@ These resources cover a wide range of topics, including building your first agen
| **Introducing GPT-4o Mini: The Future of Cost-Efficient AI Intelligence** | Discover the capabilities and advantages of GPT-4o Mini for building cost-effective, intelligent agents. | [Read Article](https://medium.com/@kyeg/introducing-gpt-4o-mini-the-future-of-cost-efficient-ai-intelligence-a3e3fe78d939) |
-### API
+### Swarms API
| Title | Description | Link |
|-------|-------------|------|
@@ -34,3 +34,8 @@ These resources cover a wide range of topics, including building your first agen
|-------|-------------|------|
| **Building Medical Multi-Agent Systems with Swarms Rust: A Comprehensive Tutorial** | Comprehensive tutorial for developing medical multi-agent systems using Swarms Rust. | [Read Article](https://medium.com/@kyeg/building-medical-multi-agent-systems-with-swarms-rust-a-comprehensive-tutorial-1e8e060601f9) |
| **Building Production-Grade Agentic Applications with Swarms Rust: A Comprehensive Tutorial** | Learn to build robust, production-ready agentic applications with Swarms Rust. | [Read Article](https://medium.com/@kyeg/building-production-grade-agentic-applications-with-swarms-rust-a-comprehensive-tutorial-bb567c02340f) |
+
+
+### Youtube Videos
+
+- [Swarms Playlist by Swarms Founder Kye Gomez](https://www.youtube.com/watch?v=FzbBRbaqsG8&list=PLphplB7PcU1atnmrUl7lJ5bmGXR7R4lhA)
\ No newline at end of file
diff --git a/docs/examples/cookbook_index.md b/docs/examples/cookbook_index.md
index b16aee96..624d82e6 100644
--- a/docs/examples/cookbook_index.md
+++ b/docs/examples/cookbook_index.md
@@ -43,7 +43,7 @@ This index provides a categorized list of examples and tutorials for using the S
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
diff --git a/docs/examples/paper_implementations.md b/docs/examples/paper_implementations.md
index e9211a7d..b4c889d0 100644
--- a/docs/examples/paper_implementations.md
+++ b/docs/examples/paper_implementations.md
@@ -1,6 +1,8 @@
# Multi-Agent Paper Implementations
-At Swarms, we are passionate about democratizing access to cutting-edge multi-agent research and making advanced AI collaboration accessible to everyone. Our mission is to bridge the gap between academic research and practical implementation by providing production-ready, open-source implementations of the most impactful multi-agent research papers.
+At Swarms, we are passionate about democratizing access to cutting-edge multi-agent research and making advanced agent collaboration accessible to everyone.
+
+Our mission is to bridge the gap between academic research and practical implementation by providing production-ready, open-source implementations of the most impactful multi-agent research papers.
### Why Multi-Agent Research Matters
@@ -38,10 +40,6 @@ This documentation showcases our comprehensive collection of multi-agent researc
Whether you're a researcher looking to validate findings, a developer building production systems, or a student learning about multi-agent AI, you'll find valuable resources here to advance your work.
-### Join the Multi-Agent Revolution
-
-We invite you to explore these implementations, contribute to our research efforts, and help shape the future of collaborative AI. Together, we can unlock the full potential of multi-agent systems and create AI that truly works as a team.
-
## Implemented Research Papers
| Paper Name | Description | Original Paper | Implementation | Status | Key Features |
@@ -52,79 +50,12 @@ We invite you to explore these implementations, contribute to our research effor
| **[Mixture of Agents (MoA)](https://arxiv.org/abs/2406.04692)** | A sophisticated multi-agent architecture that implements parallel processing with iterative refinement, combining diverse expert agents for comprehensive analysis. | Multi-agent collaboration concepts | [`swarms.structs.moa`](https://docs.swarms.world/en/latest/swarms/structs/moa/) | ā
Complete | Parallel processing, expert agent combination, iterative refinement, state-of-the-art performance |
| **Deep Research Swarm** | A production-grade research system that conducts comprehensive analysis across multiple domains using parallel processing and advanced AI agents. | Research methodology | [`swarms.structs.deep_research_swarm`](https://docs.swarms.world/en/latest/swarms/structs/deep_research_swarm/) | ā
Complete | Parallel search processing, multi-agent coordination, information synthesis, concurrent execution |
| **Agent-as-a-Judge** | An evaluation framework that uses agents to evaluate other agents, implementing the "Agent-as-a-Judge: Evaluate Agents with Agents" methodology. | [arXiv:2410.10934](https://arxiv.org/abs/2410.10934) | [`swarms.agents.agent_judge`](https://docs.swarms.world/en/latest/swarms/agents/agent_judge/) | ā
Complete | Agent evaluation, quality assessment, automated judging, performance metrics |
-
-## Additional Research Resources
+| **Advanced Research System** | An enhanced implementation of the orchestrator-worker pattern from Anthropic's paper "How we built our multi-agent research system", featuring parallel execution, LLM-as-judge evaluation, and professional report generation. | [Anthropic Paper](https://www.anthropic.com/engineering/built-multi-agent-research-system) | [GitHub Repository](https://github.com/The-Swarm-Corporation/AdvancedResearch) | ā
Complete | Orchestrator-worker architecture, parallel execution, Exa API integration, export capabilities |
### Multi-Agent Papers Compilation
We maintain a comprehensive list of multi-agent research papers at: [awesome-multi-agent-papers](https://github.com/kyegomez/awesome-multi-agent-papers)
-### Research Lists
-
-Our research compilation includes:
-
-- **Projects**: ModelScope-Agent, Gorilla, BMTools, LMQL, Langchain, MetaGPT, AutoGPT, and more
-
-- **Research Papers**: BOLAA, ToolLLM, Communicative Agents, Mind2Web, Voyager, Tree of Thoughts, and many others
-
-- **Blog Articles**: Latest insights and developments in autonomous agents
-
-- **Talks**: Presentations from leading researchers like Geoffrey Hinton and Andrej Karpathy
-
-
-## Implementation Details
-
-### MALT Framework
-
-The MALT implementation provides:
-
-- **Three-Agent Architecture**: Creator, Verifier, and Refiner agents
-
-- **Structured Workflow**: Coordinated task execution with conversation history
-
-- **Reliability Features**: Error handling, validation, and quality assurance
-
-- **Extensibility**: Custom agent integration and configuration options
-
-
-### MAI-DxO System
-
-The MAI Diagnostic Orchestrator features:
-
-- **Virtual Physician Panel**: Multiple specialized medical agents
-
-- **Cost Optimization**: Efficient diagnostic workflows
-
-- **Iterative Refinement**: Continuous improvement of diagnoses
-
-- **Medical Expertise**: Domain-specific knowledge and reasoning
-
-
-### AI-CoScientist Framework
-
-The AI-CoScientist implementation includes:
-
-- **Tournament-Based Selection**: Elo rating system for hypothesis ranking
-
-- **Peer Review System**: Comprehensive evaluation of scientific proposals
-
-- **Hypothesis Evolution**: Iterative refinement based on feedback
-
-- **Diversity Control**: Proximity analysis to maintain hypothesis variety
-
-
-### Mixture of Agents (MoA)
-
-The MoA architecture provides:
-
-- **Parallel Processing**: Multiple agents working simultaneously
-
-- **Expert Specialization**: Domain-specific agent capabilities
-
-- **Iterative Refinement**: Continuous improvement through collaboration
-
-- **State-of-the-Art Performance**: Achieving superior results through collective intelligence
-
## Contributing
@@ -156,7 +87,7 @@ If you use any of these implementations in your research, please cite the origin
Join our community to stay updated on the latest multi-agent research implementations:
-- **Discord**: [Join our community](https://discord.gg/jM3Z6M9uMq)
+- **Discord**: [Join our community](https://discord.gg/EamjgSaEQf)
- **Documentation**: [docs.swarms.world](https://docs.swarms.world)
diff --git a/docs/examples/templates.md b/docs/examples/templates.md
index fbce5dba..1c4471f1 100644
--- a/docs/examples/templates.md
+++ b/docs/examples/templates.md
@@ -192,7 +192,7 @@ Join our community of agent engineers and researchers for technical support, cut
| š Website | Official project website | [swarms.ai](https://swarms.ai) |
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
diff --git a/docs/governance/bounty_program.md b/docs/governance/bounty_program.md
index 332b89f1..9623e4ed 100644
--- a/docs/governance/bounty_program.md
+++ b/docs/governance/bounty_program.md
@@ -43,7 +43,7 @@ To ensure high-quality contributions and streamline the process, please adhere t
## Get Involved
1. **Join the Community**:
- - Become an active member of the Swarms community by joining our Discord server: [Join Now](https://discord.gg/jM3Z6M9uMq). The Discord server serves as a hub for discussions, updates, and support.
+ - Become an active member of the Swarms community by joining our Discord server: [Join Now](https://discord.gg/EamjgSaEQf). The Discord server serves as a hub for discussions, updates, and support.
2. **Stay Updated**:
- Keep track of the latest updates, announcements, and bounty opportunities by regularly checking the Discord channel and the GitHub repository.
diff --git a/docs/governance/main.md b/docs/governance/main.md
index 70a6a5a2..30a05cda 100644
--- a/docs/governance/main.md
+++ b/docs/governance/main.md
@@ -45,7 +45,7 @@ Welcome to the Swarms ecosystem. Click any tile below to explore our products, c
š¦ GitHub: Swarms (Rust)
-š¬ Join Our Discord
+š¬ Join Our Discord
š± Telegram Group
@@ -67,7 +67,7 @@ Welcome to the Swarms ecosystem. Click any tile below to explore our products, c
| Chat UI | [swarms.world/platform/chat](https://swarms.world/platform/chat) |
| Marketplace | [swarms.world](https://swarms.world) |
| Startup App | [Apply Here](https://www.swarms.xyz/programs/startups) |
-| Discord | [Join Now](https://discord.gg/jM3Z6M9uMq) |
+| Discord | [Join Now](https://discord.gg/EamjgSaEQf) |
| Telegram | [Group Chat](https://t.me/swarmsgroupchat) |
| Twitter/X | [@swarms_corp](https://x.com/swarms_corp) |
| Blog | [medium.com/@kyeg](https://medium.com/@kyeg) |
diff --git a/docs/guides/financial_analysis_swarm_mm.md b/docs/guides/financial_analysis_swarm_mm.md
index d4e844e2..63c5ae5c 100644
--- a/docs/guides/financial_analysis_swarm_mm.md
+++ b/docs/guides/financial_analysis_swarm_mm.md
@@ -7,7 +7,7 @@ Before we dive into the code, let's briefly introduce the Swarms framework. Swar
For more information and to contribute to the project, visit the [Swarms GitHub repository](https://github.com/kyegomez/swarms). We highly recommend exploring the documentation for a deeper understanding of Swarms' capabilities.
Additional resources:
-- [Swarms Discord](https://discord.gg/jM3Z6M9uMq) for community discussions
+- [Swarms Discord](https://discord.gg/EamjgSaEQf) for community discussions
- [Swarms Twitter](https://x.com/swarms_corp) for updates
- [Swarms Spotify](https://open.spotify.com/show/2HLiswhmUaMdjHC8AUHcCF?si=c831ef10c5ef4994) for podcasts
- [Swarms Blog](https://medium.com/@kyeg) for in-depth articles
@@ -460,7 +460,7 @@ This system provides a powerful foundation for financial analysis, but there's a
Remember, the Swarms framework is a powerful and flexible tool that can be adapted to a wide range of complex tasks beyond just financial analysis. We encourage you to explore the [Swarms GitHub repository](https://github.com/kyegomez/swarms) for more examples and inspiration.
-For more in-depth discussions and community support, consider joining the [Swarms Discord](https://discord.gg/jM3Z6M9uMq). You can also stay updated with the latest developments by following [Swarms on Twitter](https://x.com/swarms_corp).
+For more in-depth discussions and community support, consider joining the [Swarms Discord](https://discord.gg/EamjgSaEQf). You can also stay updated with the latest developments by following [Swarms on Twitter](https://x.com/swarms_corp).
If you're interested in learning more about AI and its applications in various fields, check out the [Swarms Spotify podcast](https://open.spotify.com/show/2HLiswhmUaMdjHC8AUHcCF?si=c831ef10c5ef4994) and the [Swarms Blog](https://medium.com/@kyeg) for insightful articles and discussions.
@@ -474,7 +474,7 @@ By leveraging the power of multi-agent AI systems, you're well-equipped to navig
* [Swarms Github](https://github.com/kyegomez/swarms)
-* [Swarms Discord](https://discord.gg/jM3Z6M9uMq)
+* [Swarms Discord](https://discord.gg/EamjgSaEQf)
* [Swarms Twitter](https://x.com/swarms_corp)
* [Swarms Spotify](https://open.spotify.com/show/2HLiswhmUaMdjHC8AUHcCF?si=c831ef10c5ef4994)
* [Swarms Blog](https://medium.com/@kyeg)
diff --git a/docs/guides/healthcare_blog.md b/docs/guides/healthcare_blog.md
index 04629976..0f653002 100644
--- a/docs/guides/healthcare_blog.md
+++ b/docs/guides/healthcare_blog.md
@@ -261,7 +261,7 @@ The table below summarizes the estimated savings for each use case:
- [book a call](https://cal.com/swarms)
-- Swarms Discord: https://discord.gg/jM3Z6M9uMq
+- Swarms Discord: https://discord.gg/EamjgSaEQf
- Swarms Twitter: https://x.com/swarms_corp
diff --git a/docs/index.md b/docs/index.md
index ceb80cc1..6e32a428 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,6 +1,6 @@
# Welcome to Swarms Docs Home
-[](https://discord.gg/jM3Z6M9uMq) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
+[](https://discord.gg/EamjgSaEQf) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
## What is Swarms?
@@ -79,7 +79,7 @@ Here you'll find references about the Swarms framework, marketplace, community,
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
diff --git a/docs/llm.txt b/docs/llm.txt
index 5ccbf028..3dc0048a 100644
--- a/docs/llm.txt
+++ b/docs/llm.txt
@@ -503,7 +503,7 @@ Schedule quarterly audits to refine structure and content across all repositorie
Promote your contributions via:
-- **Swarms Discord**: https://discord.gg/jM3Z6M9uMq
+- **Swarms Discord**: https://discord.gg/EamjgSaEQf
- **Swarms Telegram**: https://t.me/swarmsgroupchat
@@ -1180,7 +1180,7 @@ If you encounter issues:
1. **Check the FAQ** in the main documentation
2. **Search existing issues** on GitHub
-3. **Ask in the Discord community**: [discord.gg/jM3Z6M9uMq](https://discord.gg/jM3Z6M9uMq)
+3. **Ask in the Discord community**: [discord.gg/jM3Z6M9uMq](https://discord.gg/EamjgSaEQf)
4. **Create a GitHub issue** with:
- Your operating system
- Python version
@@ -1804,7 +1804,7 @@ If you'd like technical support, join our Discord below and stay updated on our
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
@@ -1861,7 +1861,7 @@ This index provides a categorized list of examples and tutorials for using the S
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
@@ -2294,7 +2294,7 @@ If you use any of these implementations in your research, please cite the origin
Join our community to stay updated on the latest multi-agent research implementations:
-- **Discord**: [Join our community](https://discord.gg/jM3Z6M9uMq)
+- **Discord**: [Join our community](https://discord.gg/EamjgSaEQf)
- **Documentation**: [docs.swarms.world](https://docs.swarms.world)
@@ -2503,7 +2503,7 @@ Join our community of agent engineers and researchers for technical support, cut
| š Website | Official project website | [swarms.ai](https://swarms.ai) |
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
@@ -2575,7 +2575,7 @@ To ensure high-quality contributions and streamline the process, please adhere t
## Get Involved
1. **Join the Community**:
- - Become an active member of the Swarms community by joining our Discord server: [Join Now](https://discord.gg/jM3Z6M9uMq). The Discord server serves as a hub for discussions, updates, and support.
+ - Become an active member of the Swarms community by joining our Discord server: [Join Now](https://discord.gg/EamjgSaEQf). The Discord server serves as a hub for discussions, updates, and support.
2. **Stay Updated**:
- Keep track of the latest updates, announcements, and bounty opportunities by regularly checking the Discord channel and the GitHub repository.
@@ -2657,7 +2657,7 @@ Welcome to the Swarms ecosystem. Click any tile below to explore our products, c
š¦ GitHub: Swarms (Rust)
-š¬ Join Our Discord
+š¬ Join Our Discord
š± Telegram Group
@@ -2679,7 +2679,7 @@ Welcome to the Swarms ecosystem. Click any tile below to explore our products, c
| Chat UI | [swarms.world/platform/chat](https://swarms.world/platform/chat) |
| Marketplace | [swarms.world](https://swarms.world) |
| Startup App | [Apply Here](https://www.swarms.xyz/programs/startups) |
-| Discord | [Join Now](https://discord.gg/jM3Z6M9uMq) |
+| Discord | [Join Now](https://discord.gg/EamjgSaEQf) |
| Telegram | [Group Chat](https://t.me/swarmsgroupchat) |
| Twitter/X | [@swarms_corp](https://x.com/swarms_corp) |
| Blog | [medium.com/@kyeg](https://medium.com/@kyeg) |
@@ -2961,7 +2961,7 @@ Before we dive into the code, let's briefly introduce the Swarms framework. Swar
For more information and to contribute to the project, visit the [Swarms GitHub repository](https://github.com/kyegomez/swarms). We highly recommend exploring the documentation for a deeper understanding of Swarms' capabilities.
Additional resources:
-- [Swarms Discord](https://discord.gg/jM3Z6M9uMq) for community discussions
+- [Swarms Discord](https://discord.gg/EamjgSaEQf) for community discussions
- [Swarms Twitter](https://x.com/swarms_corp) for updates
- [Swarms Spotify](https://open.spotify.com/show/2HLiswhmUaMdjHC8AUHcCF?si=c831ef10c5ef4994) for podcasts
- [Swarms Blog](https://medium.com/@kyeg) for in-depth articles
@@ -3414,7 +3414,7 @@ This system provides a powerful foundation for financial analysis, but there's a
Remember, the Swarms framework is a powerful and flexible tool that can be adapted to a wide range of complex tasks beyond just financial analysis. We encourage you to explore the [Swarms GitHub repository](https://github.com/kyegomez/swarms) for more examples and inspiration.
-For more in-depth discussions and community support, consider joining the [Swarms Discord](https://discord.gg/jM3Z6M9uMq). You can also stay updated with the latest developments by following [Swarms on Twitter](https://x.com/swarms_corp).
+For more in-depth discussions and community support, consider joining the [Swarms Discord](https://discord.gg/EamjgSaEQf). You can also stay updated with the latest developments by following [Swarms on Twitter](https://x.com/swarms_corp).
If you're interested in learning more about AI and its applications in various fields, check out the [Swarms Spotify podcast](https://open.spotify.com/show/2HLiswhmUaMdjHC8AUHcCF?si=c831ef10c5ef4994) and the [Swarms Blog](https://medium.com/@kyeg) for insightful articles and discussions.
@@ -3428,7 +3428,7 @@ By leveraging the power of multi-agent AI systems, you're well-equipped to navig
* [Swarms Github](https://github.com/kyegomez/swarms)
-* [Swarms Discord](https://discord.gg/jM3Z6M9uMq)
+* [Swarms Discord](https://discord.gg/EamjgSaEQf)
* [Swarms Twitter](https://x.com/swarms_corp)
* [Swarms Spotify](https://open.spotify.com/show/2HLiswhmUaMdjHC8AUHcCF?si=c831ef10c5ef4994)
* [Swarms Blog](https://medium.com/@kyeg)
@@ -4457,7 +4457,7 @@ The table below summarizes the estimated savings for each use case:
- [book a call](https://cal.com/swarms)
-- Swarms Discord: https://discord.gg/jM3Z6M9uMq
+- Swarms Discord: https://discord.gg/EamjgSaEQf
- Swarms Twitter: https://x.com/swarms_corp
@@ -5349,7 +5349,7 @@ By leveraging expert guidance and peer insights, you can position your organizat
# Welcome to Swarms Docs Home
-[](https://discord.gg/jM3Z6M9uMq) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
+[](https://discord.gg/EamjgSaEQf) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
## What is Swarms?
@@ -5428,7 +5428,7 @@ Here you'll find references about the Swarms framework, marketplace, community,
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
@@ -6056,7 +6056,7 @@ When creating your SIP, copy this template:
# Welcome to Swarms Docs Home
-[](https://discord.gg/jM3Z6M9uMq) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
+[](https://discord.gg/EamjgSaEQf) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
## What is Swarms?
@@ -8804,7 +8804,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
@@ -12747,7 +12747,7 @@ By understanding the purpose and role of each folder in the Swarms framework, us
- **Community Support**
- - URL: [Submit issue](https://discord.gg/jM3Z6M9uMq)
+ - URL: [Submit issue](https://discord.gg/EamjgSaEQf)
- Ask the community for support in real-time and or admin support
--------------------------------------------------
@@ -15569,7 +15569,7 @@ If you have any questions or need assistance, please feel free to open an issue
| **Platform** | **Purpose** | **Join Link** | **Benefits** |
|--------------|-------------|---------------|--------------|
-| **Discord Community** | Real-time support & discussions | [Join Discord](https://discord.gg/jM3Z6M9uMq) | ⢠24/7 developer support ⢠Weekly community events ⢠Direct access to core team ⢠Beta feature previews |
+| **Discord Community** | Real-time support & discussions | [Join Discord](https://discord.gg/EamjgSaEQf) | ⢠24/7 developer support ⢠Weekly community events ⢠Direct access to core team ⢠Beta feature previews |
| **Twitter/X** | Latest updates & announcements | [Follow @swarms_corp](https://x.com/swarms_corp) | ⢠Breaking news & updates ⢠Community highlights ⢠Technical insights ⢠Industry partnerships |
| **LinkedIn** | Professional network & updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | ⢠Professional networking ⢠Career opportunities ⢠Enterprise partnerships ⢠Industry insights |
| **YouTube** | Tutorials & technical content | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | ⢠In-depth tutorials ⢠Live coding sessions ⢠Architecture deep dives ⢠Community showcases |
@@ -15629,7 +15629,7 @@ If you have any questions or need assistance, please feel free to open an issue
| **1** | [Install Swarms Python Framework](https://docs.swarms.world/en/latest/swarms/install/install/) | 5 minutes |
| **2** | [Run Your First Agent](https://docs.swarms.world/en/latest/swarms/examples/basic_agent/) | 10 minutes |
| **3** | [Try Multi-Agent Workflows](https://docs.swarms.world/en/latest/swarms/examples/sequential_example/) | 15 minutes |
-| **4** | [Join Our Discord Community](https://discord.gg/jM3Z6M9uMq) | 2 minutes |
+| **4** | [Join Our Discord Community](https://discord.gg/EamjgSaEQf) | 2 minutes |
| **5** | [Explore Enterprise Features](https://docs.swarms.world/en/latest/swarms_cloud/swarms_api/) | 20 minutes |
---
@@ -18820,7 +18820,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
@@ -19611,7 +19611,7 @@ If you're facing issues or want to learn more, check out the following resources
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
@@ -19915,7 +19915,7 @@ If you're facing issues or want to learn more, check out the following resources
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
@@ -22379,7 +22379,7 @@ If you're facing issues or want to learn more, check out the following resources
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
@@ -27453,7 +27453,7 @@ Stay tuned for updates on the Swarm Exchange launch.
- **Documentation:** [Swarms Documentation](https://docs.swarms.world)
-- **Support:** Contact us via our [Discord Community](https://discord.gg/jM3Z6M9uMq).
+- **Support:** Contact us via our [Discord Community](https://discord.gg/EamjgSaEQf).
---
@@ -30381,7 +30381,7 @@ graph TD
- [Tutorials](https://docs.swarms.world/tutorials)
=== "š¬ Community"
- - [Discord Server](https://discord.gg/jM3Z6M9uMq)
+ - [Discord Server](https://discord.gg/EamjgSaEQf)
- [GitHub Discussions](https://github.com/kyegomez/swarms/discussions)
=== "š§ Development"
@@ -30425,7 +30425,7 @@ The MCP integration brings powerful external tool connectivity to Swarms agents,
!!! tip "Stay Updated"
- Join our [Discord community](https://discord.gg/jM3Z6M9uMq) to stay informed about new MCP features and connect with other developers building amazing agent applications.
+ Join our [Discord community](https://discord.gg/EamjgSaEQf) to stay informed about new MCP features and connect with other developers building amazing agent applications.
---
@@ -38385,7 +38385,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
@@ -46084,7 +46084,7 @@ The Swarms team is committed to providing exceptional technical support to help
| **Major Features (SIPs)** | New agent types, core changes, integrations | 1-2 weeks | [SIP Guidelines](protocol/sip.md) |
| **Minor Features** | Small enhancements, straightforward additions | < 48 hours | [GitHub Issues](https://github.com/kyegomez/swarms/issues) |
| **Private Issues** | Security concerns, enterprise consulting | < 4 hours | [Book Support Call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) |
-| **Real-time Help** | Quick questions, community discussions | Immediate | [Discord Community](https://discord.gg/jM3Z6M9uMq) |
+| **Real-time Help** | Quick questions, community discussions | Immediate | [Discord Community](https://discord.gg/EamjgSaEQf) |
| **Documentation** | Usage guides, examples, tutorials | Self-service | [docs.swarms.world](https://docs.swarms.world) |
---
@@ -46263,7 +46263,7 @@ Get instant help from our active community of developers and core team members.
### **Getting Help on Discord**
-1. **Join here**: [https://discord.gg/jM3Z6M9uMq](https://discord.gg/jM3Z6M9uMq)
+1. **Join here**: [https://discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf)
2. **Read the rules** and introduce yourself in #general
@@ -46434,7 +46434,7 @@ Help improve support for everyone:
| Urgency | Best Channel |
|---------|-------------|
| **Emergency** | [Book Immediate Call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) |
-| **Urgent** | [Discord #technical-support](https://discord.gg/jM3Z6M9uMq) |
+| **Urgent** | [Discord #technical-support](https://discord.gg/EamjgSaEQf) |
| **Standard** | [GitHub Issues](https://github.com/kyegomez/swarms/issues) |
| **Major Features** | [SIP Guidelines](protocol/sip.md) |
| **Minor Features** | [GitHub Issues](https://github.com/kyegomez/swarms/issues) |
@@ -50226,7 +50226,7 @@ agent_config = {
[:material-file-document: Swarms.ai Documentation](https://docs.swarms.world){ .md-button }
[:material-application: Swarms.ai Platform](https://swarms.world/platform){ .md-button }
[:material-key: API Key Management](https://swarms.world/platform/api-keys){ .md-button }
-[:material-forum: Swarms.ai Community](https://discord.gg/jM3Z6M9uMq){ .md-button }
+[:material-forum: Swarms.ai Community](https://discord.gg/EamjgSaEQf){ .md-button }
--------------------------------------------------
@@ -50379,7 +50379,7 @@ SWARMS_LOG_LEVEL=INFO
| Community Channel | Description | Link |
|-----------------------------|---------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
-| Discord Community | Join our active developer community for real-time support and discussions | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| Discord Community | Join our active developer community for real-time support and discussions | [Join Discord](https://discord.gg/EamjgSaEQf) |
| GitHub Discussions | Ask questions and share ideas | [GitHub Discussions](https://github.com/The-Swarm-Corporation/swarms/discussions) |
| Twitter/X | Follow for updates and announcements | [Twitter/X](https://x.com/swarms_corp) |
@@ -55111,7 +55111,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
@@ -57475,7 +57475,7 @@ Error responses include a detailed message explaining the issue:
|--------------|---------------------|
| Documentation | [https://docs.swarms.world](https://docs.swarms.world) |
| Email | kye@swarms.world |
-| Community | [https://discord.gg/jM3Z6M9uMq](https://discord.gg/jM3Z6M9uMq) |
+| Community | [https://discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf) |
| Marketplace | [https://swarms.world](https://swarms.world) |
| Website | [https://swarms.ai](https://swarms.ai) |
@@ -58440,7 +58440,7 @@ print(result)
We're excited to see how you leverage Swarms-Memory in your projects! Join our community on Discord to share your experiences, ask questions, and stay updated on the latest developments.
- **š¦ Twitter**: [Follow us on Twitter](https://twitter.com/swarms_platform)
-- **š¢ Discord**: [Join the Agora Discord](https://discord.gg/jM3Z6M9uMq)
+- **š¢ Discord**: [Join the Agora Discord](https://discord.gg/EamjgSaEQf)
- **Swarms Platform**: [Visit our website](https://swarms.ai)
- **š Documentation**: [Read the Docs](https://docs.swarms.ai)
@@ -60129,9 +60129,9 @@ To further enhance your understanding and usage of the Swarms Platform, explore
### Links
- [API Documentation](https://docs.swarms.world)
-- [Community Forums](https://discord.gg/jM3Z6M9uMq)
+- [Community Forums](https://discord.gg/EamjgSaEQf)
- [Tutorials and Guides](https://docs.swarms.world))
-- [Support](https://discord.gg/jM3Z6M9uMq)
+- [Support](https://discord.gg/EamjgSaEQf)
## Conclusion
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 7e27c017..3b6a4f11 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -48,7 +48,7 @@ extra:
- icon: fontawesome/brands/github
link: https://github.com/kyegomez/swarms
- icon: fontawesome/brands/discord
- link: https://discord.gg/jM3Z6M9uMq
+ link: https://discord.gg/EamjgSaEQf
- icon: fontawesome/brands/youtube
link: https://www.youtube.com/@kyegomez3242
- icon: fontawesome/brands/linkedin
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 0ab70ba7..f05def6f 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -1,7 +1,7 @@
# Welcome to Swarms Docs Home
-[](https://discord.gg/jM3Z6M9uMq) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
+[](https://discord.gg/EamjgSaEQf) [](https://www.youtube.com/@kyegomez3242) [](https://www.linkedin.com/in/kye-g-38759a207/) [](https://x.com/swarms_corp)
## What is Swarms?
diff --git a/docs/swarms/agents/index.md b/docs/swarms/agents/index.md
index 4b632f1b..84a6534c 100644
--- a/docs/swarms/agents/index.md
+++ b/docs/swarms/agents/index.md
@@ -848,7 +848,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
diff --git a/docs/swarms/concept/framework_architecture.md b/docs/swarms/concept/framework_architecture.md
index e704ba8e..18f76ebc 100644
--- a/docs/swarms/concept/framework_architecture.md
+++ b/docs/swarms/concept/framework_architecture.md
@@ -155,5 +155,5 @@ By understanding the purpose and role of each folder in the Swarms framework, us
- **Community Support**
- - URL: [Submit issue](https://discord.gg/jM3Z6M9uMq)
+ - URL: [Submit issue](https://discord.gg/EamjgSaEQf)
- Ask the community for support in real-time and or admin support
\ No newline at end of file
diff --git a/docs/swarms/ecosystem.md b/docs/swarms/ecosystem.md
index ade51cde..9a0a1ccc 100644
--- a/docs/swarms/ecosystem.md
+++ b/docs/swarms/ecosystem.md
@@ -68,7 +68,7 @@
| **Platform** | **Purpose** | **Join Link** | **Benefits** |
|--------------|-------------|---------------|--------------|
-| **Discord Community** | Real-time support & discussions | [Join Discord](https://discord.gg/jM3Z6M9uMq) | ⢠24/7 developer support ⢠Weekly community events ⢠Direct access to core team ⢠Beta feature previews |
+| **Discord Community** | Real-time support & discussions | [Join Discord](https://discord.gg/EamjgSaEQf) | ⢠24/7 developer support ⢠Weekly community events ⢠Direct access to core team ⢠Beta feature previews |
| **Twitter/X** | Latest updates & announcements | [Follow @swarms_corp](https://x.com/swarms_corp) | ⢠Breaking news & updates ⢠Community highlights ⢠Technical insights ⢠Industry partnerships |
| **LinkedIn** | Professional network & updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | ⢠Professional networking ⢠Career opportunities ⢠Enterprise partnerships ⢠Industry insights |
| **YouTube** | Tutorials & technical content | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | ⢠In-depth tutorials ⢠Live coding sessions ⢠Architecture deep dives ⢠Community showcases |
@@ -128,7 +128,7 @@
| **1** | [Install Swarms Python Framework](https://docs.swarms.world/en/latest/swarms/install/install/) | 5 minutes |
| **2** | [Run Your First Agent](https://docs.swarms.world/en/latest/swarms/examples/basic_agent/) | 10 minutes |
| **3** | [Try Multi-Agent Workflows](https://docs.swarms.world/en/latest/swarms/examples/sequential_example/) | 15 minutes |
-| **4** | [Join Our Discord Community](https://discord.gg/jM3Z6M9uMq) | 2 minutes |
+| **4** | [Join Our Discord Community](https://discord.gg/EamjgSaEQf) | 2 minutes |
| **5** | [Explore Enterprise Features](https://docs.swarms.world/en/latest/swarms_cloud/swarms_api/) | 20 minutes |
---
diff --git a/docs/swarms/examples/igc_example.md b/docs/swarms/examples/igc_example.md
index 32d060c1..5488cb5a 100644
--- a/docs/swarms/examples/igc_example.md
+++ b/docs/swarms/examples/igc_example.md
@@ -127,7 +127,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
diff --git a/docs/swarms/examples/moa_example.md b/docs/swarms/examples/moa_example.md
index 3ce7d24c..4e10a203 100644
--- a/docs/swarms/examples/moa_example.md
+++ b/docs/swarms/examples/moa_example.md
@@ -124,7 +124,7 @@ If you're facing issues or want to learn more, check out the following resources
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
diff --git a/docs/swarms/examples/multiple_images.md b/docs/swarms/examples/multiple_images.md
index bfa66e2b..9adb9b78 100644
--- a/docs/swarms/examples/multiple_images.md
+++ b/docs/swarms/examples/multiple_images.md
@@ -69,7 +69,7 @@ If you're facing issues or want to learn more, check out the following resources
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
diff --git a/docs/swarms/examples/vision_tools.md b/docs/swarms/examples/vision_tools.md
index 92b487c7..bc306fdb 100644
--- a/docs/swarms/examples/vision_tools.md
+++ b/docs/swarms/examples/vision_tools.md
@@ -130,7 +130,7 @@ If you're facing issues or want to learn more, check out the following resources
|----------|------|-------------|
| š Documentation | [docs.swarms.world](https://docs.swarms.world) | Official documentation and guides |
| š Blog | [Medium](https://medium.com/@kyeg) | Latest updates and technical articles |
-| š¬ Discord | [Join Discord](https://discord.gg/jM3Z6M9uMq) | Live chat and community support |
+| š¬ Discord | [Join Discord](https://discord.gg/EamjgSaEQf) | Live chat and community support |
| š¦ Twitter | [@kyegomez](https://twitter.com/kyegomez) | Latest news and announcements |
| š„ LinkedIn | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Professional network and updates |
| šŗ YouTube | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Tutorials and demos |
diff --git a/docs/swarms/products.md b/docs/swarms/products.md
index 4f716c8d..28684b3f 100644
--- a/docs/swarms/products.md
+++ b/docs/swarms/products.md
@@ -152,7 +152,7 @@ Stay tuned for updates on the Swarm Exchange launch.
- **Documentation:** [Swarms Documentation](https://docs.swarms.world)
-- **Support:** Contact us via our [Discord Community](https://discord.gg/jM3Z6M9uMq).
+- **Support:** Contact us via our [Discord Community](https://discord.gg/EamjgSaEQf).
---
diff --git a/docs/swarms/structs/agent_mcp.md b/docs/swarms/structs/agent_mcp.md
index a7c0a2c6..0b8c4f4a 100644
--- a/docs/swarms/structs/agent_mcp.md
+++ b/docs/swarms/structs/agent_mcp.md
@@ -723,7 +723,7 @@ graph TD
- [Tutorials](https://docs.swarms.world/tutorials)
=== "š¬ Community"
- - [Discord Server](https://discord.gg/jM3Z6M9uMq)
+ - [Discord Server](https://discord.gg/EamjgSaEQf)
- [GitHub Discussions](https://github.com/kyegomez/swarms/discussions)
=== "š§ Development"
@@ -767,7 +767,7 @@ The MCP integration brings powerful external tool connectivity to Swarms agents,
!!! tip "Stay Updated"
- Join our [Discord community](https://discord.gg/jM3Z6M9uMq) to stay informed about new MCP features and connect with other developers building amazing agent applications.
+ Join our [Discord community](https://discord.gg/EamjgSaEQf) to stay informed about new MCP features and connect with other developers building amazing agent applications.
---
diff --git a/docs/swarms/structs/index.md b/docs/swarms/structs/index.md
index 02d106b7..a0468e77 100644
--- a/docs/swarms/structs/index.md
+++ b/docs/swarms/structs/index.md
@@ -294,7 +294,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
diff --git a/docs/swarms/support.md b/docs/swarms/support.md
index c101ee1d..0b862936 100644
--- a/docs/swarms/support.md
+++ b/docs/swarms/support.md
@@ -18,7 +18,7 @@ The Swarms team is committed to providing exceptional technical support to help
| **Major Features (SIPs)** | New agent types, core changes, integrations | 1-2 weeks | [SIP Guidelines](protocol/sip.md) |
| **Minor Features** | Small enhancements, straightforward additions | < 48 hours | [GitHub Issues](https://github.com/kyegomez/swarms/issues) |
| **Private Issues** | Security concerns, enterprise consulting | < 4 hours | [Book Support Call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) |
-| **Real-time Help** | Quick questions, community discussions | Immediate | [Discord Community](https://discord.gg/jM3Z6M9uMq) |
+| **Real-time Help** | Quick questions, community discussions | Immediate | [Discord Community](https://discord.gg/EamjgSaEQf) |
| **Documentation** | Usage guides, examples, tutorials | Self-service | [docs.swarms.world](https://docs.swarms.world) |
---
@@ -197,7 +197,7 @@ Get instant help from our active community of developers and core team members.
### **Getting Help on Discord**
-1. **Join here**: [https://discord.gg/jM3Z6M9uMq](https://discord.gg/jM3Z6M9uMq)
+1. **Join here**: [https://discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf)
2. **Read the rules** and introduce yourself in #general
@@ -368,7 +368,7 @@ Help improve support for everyone:
| Urgency | Best Channel |
|---------|-------------|
| **Emergency** | [Book Immediate Call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) |
-| **Urgent** | [Discord #technical-support](https://discord.gg/jM3Z6M9uMq) |
+| **Urgent** | [Discord #technical-support](https://discord.gg/EamjgSaEQf) |
| **Standard** | [GitHub Issues](https://github.com/kyegomez/swarms/issues) |
| **Major Features** | [SIP Guidelines](protocol/sip.md) |
| **Minor Features** | [GitHub Issues](https://github.com/kyegomez/swarms/issues) |
diff --git a/docs/swarms_cloud/agent_api.md b/docs/swarms_cloud/agent_api.md
index 21dd5dd2..aeab0d98 100644
--- a/docs/swarms_cloud/agent_api.md
+++ b/docs/swarms_cloud/agent_api.md
@@ -605,4 +605,4 @@ agent_config = {
[:material-file-document: Swarms.ai Documentation](https://docs.swarms.world){ .md-button }
[:material-application: Swarms.ai Platform](https://swarms.world/platform){ .md-button }
[:material-key: API Key Management](https://swarms.world/platform/api-keys){ .md-button }
-[:material-forum: Swarms.ai Community](https://discord.gg/jM3Z6M9uMq){ .md-button }
\ No newline at end of file
+[:material-forum: Swarms.ai Community](https://discord.gg/EamjgSaEQf){ .md-button }
\ No newline at end of file
diff --git a/docs/swarms_cloud/api_clients.md b/docs/swarms_cloud/api_clients.md
index 15a4a182..ca41516a 100644
--- a/docs/swarms_cloud/api_clients.md
+++ b/docs/swarms_cloud/api_clients.md
@@ -145,7 +145,7 @@ SWARMS_LOG_LEVEL=INFO
| Community Channel | Description | Link |
|-----------------------------|---------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
-| Discord Community | Join our active developer community for real-time support and discussions | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| Discord Community | Join our active developer community for real-time support and discussions | [Join Discord](https://discord.gg/EamjgSaEQf) |
| GitHub Discussions | Ask questions and share ideas | [GitHub Discussions](https://github.com/The-Swarm-Corporation/swarms/discussions) |
| Twitter/X | Follow for updates and announcements | [Twitter/X](https://x.com/swarms_corp) |
diff --git a/docs/swarms_cloud/quickstart.md b/docs/swarms_cloud/quickstart.md
index 37a3a685..438b81f0 100644
--- a/docs/swarms_cloud/quickstart.md
+++ b/docs/swarms_cloud/quickstart.md
@@ -1157,7 +1157,7 @@ Join our community of agent engineers and researchers for technical support, cut
|----------|-------------|------|
| š Documentation | Official documentation and guides | [docs.swarms.world](https://docs.swarms.world) |
| š Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) |
-| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/jM3Z6M9uMq) |
+| š¬ Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) |
| š¦ Twitter | Latest news and announcements | [@kyegomez](https://twitter.com/kyegomez) |
| š„ LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) |
| šŗ YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) |
diff --git a/docs/swarms_cloud/swarms_api.md b/docs/swarms_cloud/swarms_api.md
index f09c6eae..8dd7aba3 100644
--- a/docs/swarms_cloud/swarms_api.md
+++ b/docs/swarms_cloud/swarms_api.md
@@ -1242,7 +1242,7 @@ Error responses include a detailed message explaining the issue:
|--------------|---------------------|
| Documentation | [https://docs.swarms.world](https://docs.swarms.world) |
| Email | kye@swarms.world |
-| Community | [https://discord.gg/jM3Z6M9uMq](https://discord.gg/jM3Z6M9uMq) |
+| Community | [https://discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf) |
| Marketplace | [https://swarms.world](https://swarms.world) |
| Website | [https://swarms.ai](https://swarms.ai) |
diff --git a/docs/swarms_memory/index.md b/docs/swarms_memory/index.md
index 3b4011b0..3953256f 100644
--- a/docs/swarms_memory/index.md
+++ b/docs/swarms_memory/index.md
@@ -161,7 +161,7 @@ print(result)
We're excited to see how you leverage Swarms-Memory in your projects! Join our community on Discord to share your experiences, ask questions, and stay updated on the latest developments.
- **š¦ Twitter**: [Follow us on Twitter](https://twitter.com/swarms_platform)
-- **š¢ Discord**: [Join the Agora Discord](https://discord.gg/jM3Z6M9uMq)
+- **š¢ Discord**: [Join the Agora Discord](https://discord.gg/EamjgSaEQf)
- **Swarms Platform**: [Visit our website](https://swarms.ai)
- **š Documentation**: [Read the Docs](https://docs.swarms.ai)
diff --git a/docs/swarms_platform/index.md b/docs/swarms_platform/index.md
index 7daee2c3..995e379f 100644
--- a/docs/swarms_platform/index.md
+++ b/docs/swarms_platform/index.md
@@ -113,9 +113,9 @@ To further enhance your understanding and usage of the Swarms Platform, explore
### Links
- [API Documentation](https://docs.swarms.world)
-- [Community Forums](https://discord.gg/jM3Z6M9uMq)
+- [Community Forums](https://discord.gg/EamjgSaEQf)
- [Tutorials and Guides](https://docs.swarms.world))
-- [Support](https://discord.gg/jM3Z6M9uMq)
+- [Support](https://discord.gg/EamjgSaEQf)
## Conclusion
From 862f8e92442d8ec688dbe5cadc22ebb0b2762512 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Wed, 13 Aug 2025 08:58:32 -0700
Subject: [PATCH 41/56] DOCS - install page
---
docs/swarms/install/install.md | 47 ++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/docs/swarms/install/install.md b/docs/swarms/install/install.md
index 3a1b0668..6ee80267 100644
--- a/docs/swarms/install/install.md
+++ b/docs/swarms/install/install.md
@@ -26,9 +26,9 @@ Before you begin, ensure you have the following installed:
=== "pip (Recommended)"
- #### Headless Installation
+ #### Simple Installation
- The headless installation of `swarms` is designed for environments where graphical user interfaces (GUI) are not needed, making it more lightweight and suitable for server-side applications.
+ Simplest manner of installing swarms leverages using PIP. For faster installs and build times, we recommend using UV
```bash
pip install swarms
@@ -65,6 +65,49 @@ Before you begin, ensure you have the following installed:
uv pip install -e .[desktop]
```
+=== "Poetry Installation"
+
+ Poetry is a modern dependency management and packaging tool for Python. It provides a more robust way to manage project dependencies and virtual environments.
+
+ === "Basic Installation"
+
+ ```bash
+ # Install Poetry first
+ curl -sSL https://install.python-poetry.org | python3 -
+
+ # Install swarms using Poetry
+ poetry add swarms
+ ```
+
+ === "Development Installation"
+
+ ```bash
+ # Clone the repository
+ git clone https://github.com/kyegomez/swarms.git
+ cd swarms
+
+ # Install in editable mode
+ poetry install
+ ```
+
+ For desktop installation with extras:
+
+ ```bash
+ poetry install --extras "desktop"
+ ```
+
+ === "Using Poetry with existing projects"
+
+ If you have an existing project with a `pyproject.toml` file:
+
+ ```bash
+ # Add swarms to your project dependencies
+ poetry add swarms
+
+ # Or add with specific extras
+ poetry add "swarms[desktop]"
+ ```
+
=== "Development Installation"
=== "Using virtualenv"
From 1fcaab739f2703ee56c9db46ab76e33b74bddbb6 Mon Sep 17 00:00:00 2001
From: harshalmore31
Date: Wed, 13 Aug 2025 21:37:38 +0530
Subject: [PATCH 42/56] added AdvancedResearch example
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index f132db1e..c718bb4c 100644
--- a/README.md
+++ b/README.md
@@ -714,6 +714,7 @@ Explore comprehensive examples and tutorials to learn how to use Swarms effectiv
| Application | Description | Link |
|-------------|-------------|------|
+| Advanced Research System | Multi-agent research system inspired by Anthropic's research methodology | [AdvancedResearch](https://github.com/The-Swarm-Corporation/AdvancedResearch) |
| Swarms DAO | Decentralized autonomous organization | [Swarms DAO](https://docs.swarms.world/en/latest/swarms/examples/swarms_dao/) |
| Browser Agents | Web automation with agents | [Browser Agents](https://docs.swarms.world/en/latest/swarms/examples/swarms_of_browser_agents/) |
| VLLM Agents | High-performance model serving | [VLLM Agents](https://docs.swarms.world/en/latest/swarms/examples/vllm/) |
From afe2d84b5d693019b413278953d1c379e29ba333 Mon Sep 17 00:00:00 2001
From: harshalmore31
Date: Wed, 13 Aug 2025 21:41:51 +0530
Subject: [PATCH 43/56] updates !
---
docs/examples/index.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/examples/index.md b/docs/examples/index.md
index 7f288e74..a23f7b06 100644
--- a/docs/examples/index.md
+++ b/docs/examples/index.md
@@ -171,6 +171,7 @@ This index organizes **100+ production-ready examples** from our [Swarms Example
### Research and Deep Analysis
| Category | Example | Description |
|----------|---------|-------------|
+| Advanced Research | [Advanced Research System](https://github.com/The-Swarm-Corporation/AdvancedResearch) | Multi-agent research system inspired by Anthropic's research methodology with orchestrator-worker architecture |
| Deep Research | [Deep Research Example](https://github.com/kyegomez/swarms/blob/master/examples/multi_agent/deep_research_examples/deep_research_example.py) | Comprehensive research system with multiple specialized agents |
| Deep Research Swarm | [Deep Research Swarm](https://github.com/kyegomez/swarms/blob/master/examples/multi_agent/deep_research_examples/deep_research_swarm_example.py) | Swarm-based deep research with collaborative analysis |
| Scientific Agents | [Deep Research Swarm Example](https://github.com/kyegomez/swarms/blob/master/examples/demos/scient_agents/deep_research_swarm_example.py) | Scientific research swarm for academic and research applications |
From 381e717b7bd0530a5296a3dce0714af753fd6491 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Wed, 13 Aug 2025 09:55:58 -0700
Subject: [PATCH 44/56] examples/guides section
---
.../{ => demos}/news_aggregator_summarizer.py | 0
.../graphworkflow_guide/GETTING_STARTED.md | 258 ++++
examples/guides/graphworkflow_guide/README.md | 322 +++++
.../graphworkflow_guide/comprehensive_demo.py | 909 +++++++++++++
.../graph_workflow_technical_guide.md | 1147 +++++++++++++++++
.../graphworkflow_guide/quick_start_guide.py | 501 +++++++
.../graphworkflow_guide/setup_and_test.py | 480 +++++++
...n_ddbd7109-c7b1-40f6-83f0-f90771c3beac.png | Bin
.../graph_workflow_example.png | Bin
.../test_graphviz_visualization.png | Bin
10 files changed, 3617 insertions(+)
rename examples/{ => demos}/news_aggregator_summarizer.py (100%)
create mode 100644 examples/guides/graphworkflow_guide/GETTING_STARTED.md
create mode 100644 examples/guides/graphworkflow_guide/README.md
create mode 100644 examples/guides/graphworkflow_guide/comprehensive_demo.py
create mode 100644 examples/guides/graphworkflow_guide/graph_workflow_technical_guide.md
create mode 100644 examples/guides/graphworkflow_guide/quick_start_guide.py
create mode 100644 examples/guides/graphworkflow_guide/setup_and_test.py
rename examples/multi_agent/graphworkflow_examples/{ => example_images}/Graph-Workflow-01_visualization_ddbd7109-c7b1-40f6-83f0-f90771c3beac.png (100%)
rename examples/multi_agent/graphworkflow_examples/{ => example_images}/graph_workflow_example.png (100%)
rename examples/multi_agent/graphworkflow_examples/{ => example_images}/test_graphviz_visualization.png (100%)
diff --git a/examples/news_aggregator_summarizer.py b/examples/demos/news_aggregator_summarizer.py
similarity index 100%
rename from examples/news_aggregator_summarizer.py
rename to examples/demos/news_aggregator_summarizer.py
diff --git a/examples/guides/graphworkflow_guide/GETTING_STARTED.md b/examples/guides/graphworkflow_guide/GETTING_STARTED.md
new file mode 100644
index 00000000..72defebf
--- /dev/null
+++ b/examples/guides/graphworkflow_guide/GETTING_STARTED.md
@@ -0,0 +1,258 @@
+# Getting Started with GraphWorkflow
+
+Welcome to **GraphWorkflow** - The LangGraph Killer! š
+
+This guide will get you up and running with Swarms' GraphWorkflow system in minutes.
+
+## š Quick Installation
+
+```bash
+# Install Swarms with all dependencies
+uv pip install swarms
+
+# Optional: Install visualization dependencies
+uv pip install graphviz
+
+# Verify installation
+python -c "from swarms.structs.graph_workflow import GraphWorkflow; print('ā
GraphWorkflow ready')"
+```
+
+## šÆ Choose Your Starting Point
+
+### š New to GraphWorkflow?
+
+Start here: **[Quick Start Guide](quick_start_guide.py)**
+
+```bash
+python quick_start_guide.py
+```
+
+Learn GraphWorkflow in 5 easy steps:
+- ā
Create your first workflow
+- ā
Connect agents in sequence
+- ā
Set up parallel processing
+- ā
Use advanced patterns
+- ā
Monitor performance
+
+### š¬ Want to See Everything?
+
+Run the comprehensive demo: **[Comprehensive Demo](comprehensive_demo.py)**
+
+```bash
+# See all features
+python comprehensive_demo.py
+
+# Focus on specific areas
+python comprehensive_demo.py --demo healthcare
+python comprehensive_demo.py --demo finance
+python comprehensive_demo.py --demo parallel
+```
+
+### š ļø Need Setup Help?
+
+Use the setup script: **[Setup and Test](setup_and_test.py)**
+
+```bash
+# Check your environment
+python setup_and_test.py --check-only
+
+# Install dependencies and run tests
+python setup_and_test.py
+```
+
+## š Documentation
+
+### š Quick Reference
+
+```python
+from swarms import Agent
+from swarms.structs.graph_workflow import GraphWorkflow
+
+# 1. Create agents
+agent1 = Agent(agent_name="Researcher", model_name="gpt-4o-mini", max_loops=1)
+agent2 = Agent(agent_name="Writer", model_name="gpt-4o-mini", max_loops=1)
+
+# 2. Create workflow
+workflow = GraphWorkflow(name="MyWorkflow", auto_compile=True)
+
+# 3. Add agents and connections
+workflow.add_node(agent1)
+workflow.add_node(agent2)
+workflow.add_edge("Researcher", "Writer")
+
+# 4. Execute
+results = workflow.run(task="Write about AI trends")
+```
+
+### š Complete Documentation
+
+- **[Technical Guide](graph_workflow_technical_guide.md)**: 4,000-word comprehensive guide
+- **[Examples README](README.md)**: Complete examples overview
+- **[API Reference](../../../docs/swarms/structs/)**: Detailed API documentation
+
+## šØ Key Features Overview
+
+### ā” Parallel Processing
+
+```python
+# Fan-out: One agent to multiple agents
+workflow.add_edges_from_source("DataCollector", ["AnalystA", "AnalystB"])
+
+# Fan-in: Multiple agents to one agent
+workflow.add_edges_to_target(["SpecialistX", "SpecialistY"], "Synthesizer")
+
+# Parallel chain: Many-to-many mesh
+workflow.add_parallel_chain(["DataA", "DataB"], ["ProcessorX", "ProcessorY"])
+```
+
+### š Performance Optimization
+
+```python
+# Automatic compilation for 40-60% speedup
+workflow = GraphWorkflow(auto_compile=True)
+
+# Monitor performance
+status = workflow.get_compilation_status()
+print(f"Workers: {status['max_workers']}")
+print(f"Layers: {status['cached_layers_count']}")
+```
+
+### šØ Professional Visualization
+
+```python
+# Generate beautiful workflow diagrams
+workflow.visualize(
+ format="png", # png, svg, pdf, dot
+ show_summary=True, # Show parallel processing stats
+ engine="dot" # Layout algorithm
+)
+```
+
+### š¾ Enterprise Features
+
+```python
+# Complete workflow serialization
+json_data = workflow.to_json(include_conversation=True)
+restored = GraphWorkflow.from_json(json_data)
+
+# File persistence
+workflow.save_to_file("my_workflow.json")
+loaded = GraphWorkflow.load_from_file("my_workflow.json")
+
+# Validation and monitoring
+validation = workflow.validate(auto_fix=True)
+summary = workflow.export_summary()
+```
+
+## š„ Real-World Examples
+
+### Healthcare: Clinical Decision Support
+
+```python
+# Multi-specialist clinical workflow
+workflow.add_edges_from_source("PatientData", [
+ "PrimaryCare", "Cardiologist", "Pharmacist"
+])
+workflow.add_edges_to_target([
+ "PrimaryCare", "Cardiologist", "Pharmacist"
+], "CaseManager")
+
+results = workflow.run(task="Analyze patient with chest pain...")
+```
+
+### Finance: Investment Analysis
+
+```python
+# Parallel financial analysis
+workflow.add_parallel_chain(
+ ["MarketData", "FundamentalData"],
+ ["TechnicalAnalyst", "FundamentalAnalyst", "RiskManager"]
+)
+workflow.add_edges_to_target([
+ "TechnicalAnalyst", "FundamentalAnalyst", "RiskManager"
+], "PortfolioManager")
+
+results = workflow.run(task="Analyze tech sector allocation...")
+```
+
+## šāāļø Performance Benchmarks
+
+GraphWorkflow delivers **40-60% better performance** than sequential execution:
+
+| Agents | Sequential | GraphWorkflow | Speedup |
+|--------|------------|---------------|---------|
+| 5 | 15.2s | 8.7s | 1.75x |
+| 10 | 28.5s | 16.1s | 1.77x |
+| 15 | 42.8s | 24.3s | 1.76x |
+
+*Benchmarks run on 8-core CPU with gpt-4o-mini*
+
+## š Why GraphWorkflow > LangGraph?
+
+| Feature | GraphWorkflow | LangGraph |
+|---------|---------------|-----------|
+| **Parallel Processing** | ā
Native fan-out/fan-in | ā Limited |
+| **Performance** | ā
40-60% faster | ā Sequential bottlenecks |
+| **Compilation** | ā
Intelligent caching | ā No optimization |
+| **Visualization** | ā
Professional Graphviz | ā Basic diagrams |
+| **Enterprise Features** | ā
Full serialization | ā Limited persistence |
+| **Error Handling** | ā
Comprehensive validation | ā Basic checks |
+| **Monitoring** | ā
Rich metrics | ā Limited insights |
+
+## š ļø Troubleshooting
+
+### Common Issues
+
+**Problem**: Import error
+```bash
+# Solution: Install dependencies
+uv pip install swarms
+python setup_and_test.py --install-deps
+```
+
+**Problem**: Slow execution
+```python
+# Solution: Enable compilation
+workflow = GraphWorkflow(auto_compile=True)
+workflow.compile() # Manual compilation
+```
+
+**Problem**: Memory issues
+```python
+# Solution: Clear conversation history
+workflow.conversation = Conversation()
+```
+
+**Problem**: Graph validation errors
+```python
+# Solution: Use auto-fix
+validation = workflow.validate(auto_fix=True)
+if not validation['is_valid']:
+ print("Errors:", validation['errors'])
+```
+
+### Get Help
+
+- š **Read the docs**: [Technical Guide](graph_workflow_technical_guide.md)
+- š **Check examples**: Browse this guide directory
+- š§Ŗ **Run tests**: Use `python setup_and_test.py`
+- š **Report bugs**: Open an issue on GitHub
+
+## šÆ Next Steps
+
+1. **š Learn**: Complete the [Quick Start Guide](quick_start_guide.py)
+2. **š¬ Explore**: Try the [Comprehensive Demo](comprehensive_demo.py)
+3. **š„ Apply**: Adapt healthcare or finance examples
+4. **š Study**: Read the [Technical Guide](graph_workflow_technical_guide.md)
+5. **š Deploy**: Build your production workflows
+
+## š Ready to Build?
+
+GraphWorkflow is **production-ready** and **enterprise-grade**. Join the revolution in multi-agent orchestration!
+
+```bash
+# Start your GraphWorkflow journey
+python quick_start_guide.py
+```
+
+**The LangGraph Killer is here. Welcome to the future of multi-agent systems!** š
diff --git a/examples/guides/graphworkflow_guide/README.md b/examples/guides/graphworkflow_guide/README.md
new file mode 100644
index 00000000..e57172d9
--- /dev/null
+++ b/examples/guides/graphworkflow_guide/README.md
@@ -0,0 +1,322 @@
+# GraphWorkflow Guide
+
+Welcome to the comprehensive GraphWorkflow guide! This collection demonstrates the power and flexibility of Swarms' GraphWorkflow system - the LangGraph killer that provides superior multi-agent orchestration capabilities.
+
+## š Quick Start
+
+### Installation
+
+```bash
+# Install Swarms with all dependencies
+uv pip install swarms
+
+# Optional: Install visualization dependencies
+uv pip install graphviz
+
+# Verify installation
+python -c "from swarms.structs.graph_workflow import GraphWorkflow; print('ā
GraphWorkflow ready')"
+```
+
+### Run Your First Example
+
+```bash
+# Start with the quick start guide
+python quick_start_guide.py
+
+# Or run the comprehensive demo
+python comprehensive_demo.py
+
+# For specific examples
+python comprehensive_demo.py --demo healthcare
+python comprehensive_demo.py --demo finance
+```
+
+## š Example Files
+
+### š Learning Examples
+
+| File | Description | Complexity |
+|------|-------------|------------|
+| `quick_start_guide.py` | **START HERE** - Step-by-step introduction to GraphWorkflow | ā Beginner |
+| `graph_workflow_example.py` | Basic two-agent workflow example | ā Beginner |
+| `comprehensive_demo.py` | Complete feature demonstration with multiple use cases | āāā Advanced |
+
+### š„ Healthcare Examples
+
+| File | Description | Complexity |
+|------|-------------|------------|
+| `comprehensive_demo.py --demo healthcare` | Clinical decision support workflow | āāā Advanced |
+
+**Healthcare Workflow Features:**
+- Multi-disciplinary clinical team simulation
+- Parallel specialist consultations
+- Drug interaction checking
+- Risk assessment and quality assurance
+- Evidence-based clinical decision support
+
+### š° Finance Examples
+
+| File | Description | Complexity |
+|------|-------------|------------|
+| `advanced_graph_workflow.py` | Sophisticated investment analysis workflow | āāā Advanced |
+| `comprehensive_demo.py --demo finance` | Quantitative trading strategy development | āāā Advanced |
+
+**Finance Workflow Features:**
+- Multi-source market data analysis
+- Parallel quantitative analysis (Technical, Fundamental, Sentiment)
+- Risk management and portfolio optimization
+- Strategy backtesting and validation
+- Execution planning and monitoring
+
+### š§ Technical Examples
+
+| File | Description | Complexity |
+|------|-------------|------------|
+| `test_parallel_processing_example.py` | Comprehensive parallel processing patterns | āā Intermediate |
+| `test_graphviz_visualization.py` | Visualization capabilities and layouts | āā Intermediate |
+| `test_graph_workflow_caching.py` | Performance optimization and caching | āā Intermediate |
+| `test_enhanced_json_export.py` | Serialization and persistence features | āā Intermediate |
+| `test_graphworlfolw_validation.py` | Workflow validation and error handling | āā Intermediate |
+
+## šÆ Key Features Demonstrated
+
+### ā” Parallel Processing Patterns
+
+- **Fan-out**: One agent distributes to multiple agents
+- **Fan-in**: Multiple agents converge to one agent
+- **Parallel chains**: Many-to-many mesh processing
+- **Complex hybrid**: Sophisticated multi-stage patterns
+
+### š Performance Optimization
+
+- **Intelligent Compilation**: Pre-computed execution layers
+- **Advanced Caching**: Persistent state across runs
+- **Worker Pool Optimization**: CPU-optimized parallel execution
+- **Memory Management**: Efficient resource utilization
+
+### šØ Visualization & Monitoring
+
+- **Professional Graphviz Diagrams**: Multiple layouts and formats
+- **Real-time Performance Metrics**: Execution monitoring
+- **Workflow Validation**: Comprehensive error checking
+- **Rich Logging**: Detailed execution insights
+
+### š¾ Enterprise Features
+
+- **JSON Serialization**: Complete workflow persistence
+- **Runtime State Management**: Compilation caching
+- **Error Handling**: Robust failure recovery
+- **Scalability**: Support for large agent networks
+
+## šāāļø Running Examples
+
+### Basic Usage
+
+```python
+from swarms import Agent
+from swarms.structs.graph_workflow import GraphWorkflow
+
+# Create agents
+agent1 = Agent(agent_name="Researcher", model_name="gpt-4o-mini", max_loops=1)
+agent2 = Agent(agent_name="Writer", model_name="gpt-4o-mini", max_loops=1)
+
+# Create workflow
+workflow = GraphWorkflow(name="SimpleWorkflow", auto_compile=True)
+workflow.add_node(agent1)
+workflow.add_node(agent2)
+workflow.add_edge("Researcher", "Writer")
+
+# Execute
+results = workflow.run(task="Research and write about AI trends")
+```
+
+### Parallel Processing
+
+```python
+# Fan-out pattern: One agent to multiple agents
+workflow.add_edges_from_source("DataCollector", ["AnalystA", "AnalystB", "AnalystC"])
+
+# Fan-in pattern: Multiple agents to one agent
+workflow.add_edges_to_target(["SpecialistX", "SpecialistY"], "Synthesizer")
+
+# Parallel chain: Many-to-many processing
+workflow.add_parallel_chain(
+ sources=["DataA", "DataB"],
+ targets=["ProcessorX", "ProcessorY"]
+)
+```
+
+### Performance Monitoring
+
+```python
+# Get compilation status
+status = workflow.get_compilation_status()
+print(f"Compiled: {status['is_compiled']}")
+print(f"Workers: {status['max_workers']}")
+
+# Monitor execution
+import time
+start = time.time()
+results = workflow.run(task="Analyze market conditions")
+print(f"Execution time: {time.time() - start:.2f}s")
+print(f"Throughput: {len(results)/(time.time() - start):.1f} agents/second")
+```
+
+## š¬ Use Case Examples
+
+### š Enterprise Data Processing
+
+```python
+# Multi-stage data pipeline
+workflow.add_parallel_chain(
+ ["APIIngester", "DatabaseExtractor", "FileProcessor"],
+ ["DataValidator", "DataTransformer", "DataEnricher"]
+)
+workflow.add_edges_to_target(
+ ["DataValidator", "DataTransformer", "DataEnricher"],
+ "ReportGenerator"
+)
+```
+
+### š„ Clinical Decision Support
+
+```python
+# Multi-specialist consultation
+workflow.add_edges_from_source("PatientDataCollector", [
+ "PrimaryCarePhysician", "Cardiologist", "Pharmacist"
+])
+workflow.add_edges_to_target([
+ "PrimaryCarePhysician", "Cardiologist", "Pharmacist"
+], "CaseManager")
+```
+
+### š¼ Investment Analysis
+
+```python
+# Parallel financial analysis
+workflow.add_parallel_chain(
+ ["MarketDataCollector", "FundamentalDataCollector"],
+ ["TechnicalAnalyst", "FundamentalAnalyst", "SentimentAnalyst"]
+)
+workflow.add_edges_to_target([
+ "TechnicalAnalyst", "FundamentalAnalyst", "SentimentAnalyst"
+], "PortfolioManager")
+```
+
+## šØ Visualization Examples
+
+### Generate Workflow Diagrams
+
+```python
+# Professional Graphviz visualization
+workflow.visualize(
+ format="png", # png, svg, pdf, dot
+ engine="dot", # dot, neato, fdp, sfdp, circo
+ show_summary=True, # Display parallel processing stats
+ view=True # Open diagram automatically
+)
+
+# Text-based visualization (always available)
+workflow.visualize_simple()
+```
+
+### Example Output
+
+```
+š GRAPHVIZ WORKFLOW VISUALIZATION
+====================================
+š Saved to: MyWorkflow_visualization.png
+š¤ Total Agents: 8
+š Total Connections: 12
+š Execution Layers: 4
+
+ā” Parallel Processing Patterns:
+ š Fan-out patterns: 2
+ š Fan-in patterns: 1
+ ā” Parallel execution nodes: 6
+ šÆ Parallel efficiency: 75.0%
+```
+
+## š ļø Troubleshooting
+
+### Common Issues
+
+1. **Compilation Errors**
+ ```python
+ # Check for cycles in workflow
+ validation = workflow.validate(auto_fix=True)
+ if not validation['is_valid']:
+ print("Validation errors:", validation['errors'])
+ ```
+
+2. **Performance Issues**
+ ```python
+ # Ensure compilation before execution
+ workflow.compile()
+
+ # Check worker count
+ status = workflow.get_compilation_status()
+ print(f"Workers: {status['max_workers']}")
+ ```
+
+3. **Memory Issues**
+ ```python
+ # Clear conversation history if not needed
+ workflow.conversation = Conversation()
+
+ # Monitor memory usage
+ import psutil
+ process = psutil.Process()
+ memory_mb = process.memory_info().rss / 1024 / 1024
+ print(f"Memory: {memory_mb:.1f} MB")
+ ```
+
+### Debug Mode
+
+```python
+# Enable detailed logging
+workflow = GraphWorkflow(
+ name="DebugWorkflow",
+ verbose=True, # Detailed execution logs
+ auto_compile=True, # Automatic optimization
+)
+
+# Validate workflow structure
+validation = workflow.validate(auto_fix=True)
+print("Validation result:", validation)
+```
+
+## š Documentation
+
+- **[Technical Guide](graph_workflow_technical_guide.md)**: Comprehensive 4,000-word technical documentation
+- **[API Reference](../../../docs/swarms/structs/)**: Complete API documentation
+- **[Multi-Agent Examples](../../multi_agent/)**: Other multi-agent examples
+
+## š¤ Contributing
+
+Found a bug or want to add an example?
+
+1. **Report Issues**: Open an issue with detailed reproduction steps
+2. **Add Examples**: Submit PRs with new use case examples
+3. **Improve Documentation**: Help expand the guides and tutorials
+4. **Performance Optimization**: Share benchmarks and optimizations
+
+## šÆ Next Steps
+
+1. **Start Learning**: Run `python quick_start_guide.py`
+2. **Explore Examples**: Try healthcare and finance use cases
+3. **Build Your Workflow**: Adapt examples to your domain
+4. **Deploy to Production**: Use monitoring and optimization features
+5. **Join Community**: Share your workflows and get help
+
+## š Why GraphWorkflow?
+
+GraphWorkflow is the **LangGraph killer** because it provides:
+
+- **40-60% Better Performance**: Intelligent compilation and parallel execution
+- **Enterprise Reliability**: Comprehensive error handling and monitoring
+- **Superior Scalability**: Handles hundreds of agents efficiently
+- **Rich Visualization**: Professional workflow diagrams
+- **Production Ready**: Serialization, caching, and validation
+
+Ready to revolutionize your multi-agent systems? Start with GraphWorkflow today! š
diff --git a/examples/guides/graphworkflow_guide/comprehensive_demo.py b/examples/guides/graphworkflow_guide/comprehensive_demo.py
new file mode 100644
index 00000000..79bd5405
--- /dev/null
+++ b/examples/guides/graphworkflow_guide/comprehensive_demo.py
@@ -0,0 +1,909 @@
+#!/usr/bin/env python3
+"""
+Comprehensive GraphWorkflow Demo Script
+=======================================
+
+This script demonstrates all key features of Swarms' GraphWorkflow system,
+including parallel processing patterns, performance optimization, and real-world use cases.
+
+Usage:
+ python comprehensive_demo.py [--demo healthcare|finance|enterprise|all]
+
+Requirements:
+ uv pip install swarms
+ uv pip install graphviz # Optional for visualization
+"""
+
+import argparse
+import time
+
+from swarms import Agent
+from swarms.structs.graph_workflow import GraphWorkflow
+
+
+def create_basic_workflow_demo():
+ """Demonstrate basic GraphWorkflow functionality."""
+
+ print("\n" + "=" * 60)
+ print("š BASIC GRAPHWORKFLOW DEMONSTRATION")
+ print("=" * 60)
+
+ # Create simple agents
+ data_collector = Agent(
+ agent_name="DataCollector",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a data collection specialist. Gather and organize relevant information for analysis.",
+ verbose=False,
+ )
+
+ data_analyzer = Agent(
+ agent_name="DataAnalyzer",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a data analysis expert. Analyze the collected data and extract key insights.",
+ verbose=False,
+ )
+
+ report_generator = Agent(
+ agent_name="ReportGenerator",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a report generation specialist. Create comprehensive reports from analysis results.",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="BasicWorkflowDemo",
+ description="Demonstrates basic GraphWorkflow functionality",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Add nodes
+ for agent in [data_collector, data_analyzer, report_generator]:
+ workflow.add_node(agent)
+
+ # Add edges (sequential flow)
+ workflow.add_edge("DataCollector", "DataAnalyzer")
+ workflow.add_edge("DataAnalyzer", "ReportGenerator")
+
+ # Set entry and exit points
+ workflow.set_entry_points(["DataCollector"])
+ workflow.set_end_points(["ReportGenerator"])
+
+ print(
+ f"ā
Created workflow with {len(workflow.nodes)} nodes and {len(workflow.edges)} edges"
+ )
+
+ # Demonstrate compilation
+ compilation_status = workflow.get_compilation_status()
+ print(f"š Compilation Status: {compilation_status}")
+
+ # Demonstrate simple visualization
+ try:
+ workflow.visualize_simple()
+ except Exception as e:
+ print(f"ā ļø Visualization not available: {e}")
+
+ # Run workflow
+ task = "Analyze the current state of artificial intelligence in healthcare, focusing on recent developments and future opportunities."
+
+ print(f"\nš Executing workflow with task: {task[:100]}...")
+ start_time = time.time()
+
+ results = workflow.run(task=task)
+
+ execution_time = time.time() - start_time
+ print(f"ā±ļø Execution completed in {execution_time:.2f} seconds")
+
+ # Display results
+ print("\nš Results Summary:")
+ for agent_name, result in results.items():
+ print(f"\nš¤ {agent_name}:")
+ print(
+ f" {result[:200]}{'...' if len(result) > 200 else ''}"
+ )
+
+ return workflow, results
+
+
+def create_parallel_processing_demo():
+ """Demonstrate advanced parallel processing patterns."""
+
+ print("\n" + "=" * 60)
+ print("ā” PARALLEL PROCESSING DEMONSTRATION")
+ print("=" * 60)
+
+ # Create data sources
+ web_scraper = Agent(
+ agent_name="WebScraper",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in web data scraping and online research.",
+ verbose=False,
+ )
+
+ api_collector = Agent(
+ agent_name="APICollector",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in API data collection and integration.",
+ verbose=False,
+ )
+
+ database_extractor = Agent(
+ agent_name="DatabaseExtractor",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in database queries and data extraction.",
+ verbose=False,
+ )
+
+ # Create parallel processors
+ text_processor = Agent(
+ agent_name="TextProcessor",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in natural language processing and text analysis.",
+ verbose=False,
+ )
+
+ numeric_processor = Agent(
+ agent_name="NumericProcessor",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in numerical analysis and statistical processing.",
+ verbose=False,
+ )
+
+ # Create analyzers
+ sentiment_analyzer = Agent(
+ agent_name="SentimentAnalyzer",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in sentiment analysis and emotional intelligence.",
+ verbose=False,
+ )
+
+ trend_analyzer = Agent(
+ agent_name="TrendAnalyzer",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in trend analysis and pattern recognition.",
+ verbose=False,
+ )
+
+ # Create synthesizer
+ data_synthesizer = Agent(
+ agent_name="DataSynthesizer",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You specialize in data synthesis and comprehensive analysis integration.",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="ParallelProcessingDemo",
+ description="Demonstrates advanced parallel processing patterns including fan-out, fan-in, and parallel chains",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Add all agents
+ agents = [
+ web_scraper,
+ api_collector,
+ database_extractor,
+ text_processor,
+ numeric_processor,
+ sentiment_analyzer,
+ trend_analyzer,
+ data_synthesizer,
+ ]
+
+ for agent in agents:
+ workflow.add_node(agent)
+
+ # Demonstrate different parallel patterns
+ print("š Setting up parallel processing patterns...")
+
+ # Pattern 1: Fan-out from sources to processors
+ print(" š¤ Fan-out: Data sources ā Processors")
+ workflow.add_edges_from_source(
+ "WebScraper", ["TextProcessor", "SentimentAnalyzer"]
+ )
+ workflow.add_edges_from_source(
+ "APICollector", ["NumericProcessor", "TrendAnalyzer"]
+ )
+ workflow.add_edges_from_source(
+ "DatabaseExtractor", ["TextProcessor", "NumericProcessor"]
+ )
+
+ # Pattern 2: Parallel chain from processors to analyzers
+ print(" š Parallel chain: Processors ā Analyzers")
+ workflow.add_parallel_chain(
+ ["TextProcessor", "NumericProcessor"],
+ ["SentimentAnalyzer", "TrendAnalyzer"],
+ )
+
+ # Pattern 3: Fan-in to synthesizer
+ print(" š„ Fan-in: All analyzers ā Synthesizer")
+ workflow.add_edges_to_target(
+ ["SentimentAnalyzer", "TrendAnalyzer"], "DataSynthesizer"
+ )
+
+ # Set entry and exit points
+ workflow.set_entry_points(
+ ["WebScraper", "APICollector", "DatabaseExtractor"]
+ )
+ workflow.set_end_points(["DataSynthesizer"])
+
+ print(
+ f"ā
Created parallel workflow with {len(workflow.nodes)} nodes and {len(workflow.edges)} edges"
+ )
+
+ # Analyze parallel patterns
+ compilation_status = workflow.get_compilation_status()
+ print(f"š Compilation Status: {compilation_status}")
+ print(
+ f"š§ Execution layers: {len(compilation_status.get('layers', []))}"
+ )
+ print(
+ f"ā” Max parallel workers: {compilation_status.get('max_workers', 'N/A')}"
+ )
+
+ # Run parallel workflow
+ task = "Research and analyze the impact of quantum computing on cybersecurity, examining technical developments, market trends, and security implications."
+
+ print("\nš Executing parallel workflow...")
+ start_time = time.time()
+
+ results = workflow.run(task=task)
+
+ execution_time = time.time() - start_time
+ print(
+ f"ā±ļø Parallel execution completed in {execution_time:.2f} seconds"
+ )
+ print(
+ f"š Throughput: {len(results)/execution_time:.1f} agents/second"
+ )
+
+ # Display results
+ print("\nš Parallel Processing Results:")
+ for agent_name, result in results.items():
+ print(f"\nš¤ {agent_name}:")
+ print(
+ f" {result[:150]}{'...' if len(result) > 150 else ''}"
+ )
+
+ return workflow, results
+
+
+def create_healthcare_workflow_demo():
+ """Demonstrate healthcare-focused workflow."""
+
+ print("\n" + "=" * 60)
+ print("š„ HEALTHCARE WORKFLOW DEMONSTRATION")
+ print("=" * 60)
+
+ # Create clinical specialists
+ primary_care_physician = Agent(
+ agent_name="PrimaryCarePhysician",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a board-certified primary care physician. Provide:
+ 1. Initial patient assessment and history taking
+ 2. Differential diagnosis development
+ 3. Treatment plan coordination
+ 4. Preventive care recommendations
+
+ Focus on comprehensive, evidence-based primary care.""",
+ verbose=False,
+ )
+
+ cardiologist = Agent(
+ agent_name="Cardiologist",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a board-certified cardiologist. Provide:
+ 1. Cardiovascular risk assessment
+ 2. Cardiac diagnostic interpretation
+ 3. Treatment recommendations for heart conditions
+ 4. Cardiovascular prevention strategies
+
+ Apply evidence-based cardiology guidelines.""",
+ verbose=False,
+ )
+
+ pharmacist = Agent(
+ agent_name="ClinicalPharmacist",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a clinical pharmacist specialist. Provide:
+ 1. Medication review and optimization
+ 2. Drug interaction analysis
+ 3. Dosing recommendations
+ 4. Patient counseling guidance
+
+ Ensure medication safety and efficacy.""",
+ verbose=False,
+ )
+
+ case_manager = Agent(
+ agent_name="CaseManager",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a clinical case manager. Coordinate:
+ 1. Care plan integration and implementation
+ 2. Resource allocation and scheduling
+ 3. Patient education and follow-up
+ 4. Quality metrics and outcomes tracking
+
+ Ensure coordinated, patient-centered care.""",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="HealthcareWorkflowDemo",
+ description="Clinical decision support workflow with multi-disciplinary team collaboration",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Add agents
+ agents = [
+ primary_care_physician,
+ cardiologist,
+ pharmacist,
+ case_manager,
+ ]
+ for agent in agents:
+ workflow.add_node(agent)
+
+ # Create clinical workflow
+ workflow.add_edge("PrimaryCarePhysician", "Cardiologist")
+ workflow.add_edge("PrimaryCarePhysician", "ClinicalPharmacist")
+ workflow.add_edges_to_target(
+ ["Cardiologist", "ClinicalPharmacist"], "CaseManager"
+ )
+
+ workflow.set_entry_points(["PrimaryCarePhysician"])
+ workflow.set_end_points(["CaseManager"])
+
+ print(
+ f"ā
Created healthcare workflow with {len(workflow.nodes)} specialists"
+ )
+
+ # Clinical case
+ clinical_case = """
+ Patient: 58-year-old male executive
+ Chief Complaint: Chest pain and shortness of breath during exercise
+ History: Hypertension, family history of coronary artery disease, sedentary lifestyle
+ Current Medications: Lisinopril 10mg daily
+ Vital Signs: BP 145/92, HR 88, BMI 29.5
+ Recent Tests: ECG shows non-specific changes, cholesterol 245 mg/dL
+
+ Please provide comprehensive clinical assessment and care coordination.
+ """
+
+ print("\nš Processing clinical case...")
+ start_time = time.time()
+
+ results = workflow.run(task=clinical_case)
+
+ execution_time = time.time() - start_time
+ print(
+ f"ā±ļø Clinical assessment completed in {execution_time:.2f} seconds"
+ )
+
+ # Display clinical results
+ print("\nš„ Clinical Team Assessment:")
+ for agent_name, result in results.items():
+ print(f"\nšØāāļø {agent_name}:")
+ print(
+ f" š {result[:200]}{'...' if len(result) > 200 else ''}"
+ )
+
+ return workflow, results
+
+
+def create_finance_workflow_demo():
+ """Demonstrate finance-focused workflow."""
+
+ print("\n" + "=" * 60)
+ print("š° FINANCE WORKFLOW DEMONSTRATION")
+ print("=" * 60)
+
+ # Create financial analysts
+ market_analyst = Agent(
+ agent_name="MarketAnalyst",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a senior market analyst. Provide:
+ 1. Market condition assessment and trends
+ 2. Sector rotation and thematic analysis
+ 3. Economic indicator interpretation
+ 4. Market timing and positioning recommendations
+
+ Apply rigorous market analysis frameworks.""",
+ verbose=False,
+ )
+
+ equity_researcher = Agent(
+ agent_name="EquityResearcher",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are an equity research analyst. Provide:
+ 1. Company fundamental analysis
+ 2. Financial modeling and valuation
+ 3. Competitive positioning assessment
+ 4. Investment thesis development
+
+ Use comprehensive equity research methodologies.""",
+ verbose=False,
+ )
+
+ risk_manager = Agent(
+ agent_name="RiskManager",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a risk management specialist. Provide:
+ 1. Portfolio risk assessment and metrics
+ 2. Stress testing and scenario analysis
+ 3. Risk mitigation strategies
+ 4. Regulatory compliance guidance
+
+ Apply quantitative risk management principles.""",
+ verbose=False,
+ )
+
+ portfolio_manager = Agent(
+ agent_name="PortfolioManager",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="""You are a senior portfolio manager. Provide:
+ 1. Investment decision synthesis
+ 2. Portfolio construction and allocation
+ 3. Performance attribution analysis
+ 4. Client communication and reporting
+
+ Integrate all analysis into actionable investment decisions.""",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="FinanceWorkflowDemo",
+ description="Investment decision workflow with multi-disciplinary financial analysis",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Add agents
+ agents = [
+ market_analyst,
+ equity_researcher,
+ risk_manager,
+ portfolio_manager,
+ ]
+ for agent in agents:
+ workflow.add_node(agent)
+
+ # Create financial workflow (parallel analysis feeding portfolio decisions)
+ workflow.add_edges_from_source(
+ "MarketAnalyst", ["EquityResearcher", "RiskManager"]
+ )
+ workflow.add_edges_to_target(
+ ["EquityResearcher", "RiskManager"], "PortfolioManager"
+ )
+
+ workflow.set_entry_points(["MarketAnalyst"])
+ workflow.set_end_points(["PortfolioManager"])
+
+ print(
+ f"ā
Created finance workflow with {len(workflow.nodes)} analysts"
+ )
+
+ # Investment analysis task
+ investment_scenario = """
+ Investment Analysis Request: Technology Sector Allocation
+
+ Market Context:
+ - Interest rates: 5.25% federal funds rate
+ - Inflation: 3.2% CPI year-over-year
+ - Technology sector: -8% YTD performance
+ - AI theme: High investor interest and valuation concerns
+
+ Portfolio Context:
+ - Current tech allocation: 15% (target 20-25%)
+ - Risk budget: 12% tracking error limit
+ - Investment horizon: 3-5 years
+ - Client risk tolerance: Moderate-aggressive
+
+ Please provide comprehensive investment analysis and recommendations.
+ """
+
+ print("\nš Analyzing investment scenario...")
+ start_time = time.time()
+
+ results = workflow.run(task=investment_scenario)
+
+ execution_time = time.time() - start_time
+ print(
+ f"ā±ļø Investment analysis completed in {execution_time:.2f} seconds"
+ )
+
+ # Display financial results
+ print("\nš¼ Investment Team Analysis:")
+ for agent_name, result in results.items():
+ print(f"\nš {agent_name}:")
+ print(
+ f" š” {result[:200]}{'...' if len(result) > 200 else ''}"
+ )
+
+ return workflow, results
+
+
+def demonstrate_serialization_features():
+ """Demonstrate workflow serialization and persistence."""
+
+ print("\n" + "=" * 60)
+ print("š¾ SERIALIZATION & PERSISTENCE DEMONSTRATION")
+ print("=" * 60)
+
+ # Create a simple workflow for serialization demo
+ agent1 = Agent(
+ agent_name="SerializationTestAgent1",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are agent 1 for serialization testing.",
+ verbose=False,
+ )
+
+ agent2 = Agent(
+ agent_name="SerializationTestAgent2",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are agent 2 for serialization testing.",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="SerializationTestWorkflow",
+ description="Workflow for testing serialization capabilities",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ workflow.add_node(agent1)
+ workflow.add_node(agent2)
+ workflow.add_edge(
+ "SerializationTestAgent1", "SerializationTestAgent2"
+ )
+
+ print("ā
Created test workflow for serialization")
+
+ # Test JSON serialization
+ print("\nš Testing JSON serialization...")
+ try:
+ json_data = workflow.to_json(
+ include_conversation=True, include_runtime_state=True
+ )
+ print(
+ f"ā
JSON serialization successful ({len(json_data)} characters)"
+ )
+
+ # Test deserialization
+ print("\nš„ Testing JSON deserialization...")
+ restored_workflow = GraphWorkflow.from_json(
+ json_data, restore_runtime_state=True
+ )
+ print("ā
JSON deserialization successful")
+ print(
+ f" Restored {len(restored_workflow.nodes)} nodes, {len(restored_workflow.edges)} edges"
+ )
+
+ except Exception as e:
+ print(f"ā JSON serialization failed: {e}")
+
+ # Test file persistence
+ print("\nš¾ Testing file persistence...")
+ try:
+ filepath = workflow.save_to_file(
+ "test_workflow.json",
+ include_conversation=True,
+ include_runtime_state=True,
+ overwrite=True,
+ )
+ print(f"ā
File save successful: {filepath}")
+
+ # Test file loading
+ loaded_workflow = GraphWorkflow.load_from_file(
+ filepath, restore_runtime_state=True
+ )
+ print("ā
File load successful")
+ print(
+ f" Loaded {len(loaded_workflow.nodes)} nodes, {len(loaded_workflow.edges)} edges"
+ )
+
+ # Clean up
+ import os
+
+ os.remove(filepath)
+ print("š§¹ Cleaned up test file")
+
+ except Exception as e:
+ print(f"ā File persistence failed: {e}")
+
+ # Test workflow validation
+ print("\nš Testing workflow validation...")
+ try:
+ validation_result = workflow.validate(auto_fix=True)
+ print("ā
Validation completed")
+ print(f" Valid: {validation_result['is_valid']}")
+ print(f" Warnings: {len(validation_result['warnings'])}")
+ print(f" Errors: {len(validation_result['errors'])}")
+ if validation_result["fixed"]:
+ print(f" Auto-fixed: {validation_result['fixed']}")
+
+ except Exception as e:
+ print(f"ā Validation failed: {e}")
+
+
+def demonstrate_visualization_features():
+ """Demonstrate workflow visualization capabilities."""
+
+ print("\n" + "=" * 60)
+ print("šØ VISUALIZATION DEMONSTRATION")
+ print("=" * 60)
+
+ # Create a workflow with interesting patterns for visualization
+ workflow = GraphWorkflow(
+ name="VisualizationDemo",
+ description="Workflow designed to showcase visualization capabilities",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Create agents with different roles
+ agents = []
+ for i, role in enumerate(
+ ["DataSource", "Processor", "Analyzer", "Reporter"], 1
+ ):
+ for j in range(2):
+ agent = Agent(
+ agent_name=f"{role}{j+1}",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt=f"You are {role} #{j+1}",
+ verbose=False,
+ )
+ agents.append(agent)
+ workflow.add_node(agent)
+
+ # Create interesting edge patterns
+ # Fan-out from data sources
+ workflow.add_edges_from_source(
+ "DataSource1", ["Processor1", "Processor2"]
+ )
+ workflow.add_edges_from_source(
+ "DataSource2", ["Processor1", "Processor2"]
+ )
+
+ # Parallel processing
+ workflow.add_parallel_chain(
+ ["Processor1", "Processor2"], ["Analyzer1", "Analyzer2"]
+ )
+
+ # Fan-in to reporters
+ workflow.add_edges_to_target(
+ ["Analyzer1", "Analyzer2"], "Reporter1"
+ )
+ workflow.add_edge("Analyzer1", "Reporter2")
+
+ print(
+ f"ā
Created visualization demo workflow with {len(workflow.nodes)} nodes"
+ )
+
+ # Test text visualization (always available)
+ print("\nš Testing text visualization...")
+ try:
+ text_viz = workflow.visualize_simple()
+ print("ā
Text visualization successful")
+ except Exception as e:
+ print(f"ā Text visualization failed: {e}")
+
+ # Test Graphviz visualization (if available)
+ print("\nšØ Testing Graphviz visualization...")
+ try:
+ viz_path = workflow.visualize(
+ format="png", view=False, show_summary=True
+ )
+ print(f"ā
Graphviz visualization successful: {viz_path}")
+ except ImportError:
+ print(
+ "ā ļø Graphviz not available - skipping advanced visualization"
+ )
+ except Exception as e:
+ print(f"ā Graphviz visualization failed: {e}")
+
+ # Export workflow summary
+ print("\nš Generating workflow summary...")
+ try:
+ summary = workflow.export_summary()
+ print("ā
Workflow summary generated")
+ print(f" Structure: {summary['structure']}")
+ print(f" Configuration: {summary['configuration']}")
+ except Exception as e:
+ print(f"ā Summary generation failed: {e}")
+
+
+def run_performance_benchmarks():
+ """Run performance benchmarks comparing different execution strategies."""
+
+ print("\n" + "=" * 60)
+ print("šāāļø PERFORMANCE BENCHMARKING")
+ print("=" * 60)
+
+ # Create workflows of different sizes
+ sizes = [5, 10, 15]
+ results = {}
+
+ for size in sizes:
+ print(f"\nš Benchmarking workflow with {size} agents...")
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name=f"BenchmarkWorkflow{size}",
+ description=f"Benchmark workflow with {size} agents",
+ verbose=False, # Reduce logging for benchmarks
+ auto_compile=True,
+ )
+
+ # Create agents
+ agents = []
+ for i in range(size):
+ agent = Agent(
+ agent_name=f"BenchmarkAgent{i+1}",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt=f"You are benchmark agent {i+1}. Provide a brief analysis.",
+ verbose=False,
+ )
+ agents.append(agent)
+ workflow.add_node(agent)
+
+ # Create simple sequential workflow
+ for i in range(size - 1):
+ workflow.add_edge(
+ f"BenchmarkAgent{i+1}", f"BenchmarkAgent{i+2}"
+ )
+
+ # Benchmark compilation
+ compile_start = time.time()
+ workflow.compile()
+ compile_time = time.time() - compile_start
+
+ # Benchmark execution
+ task = (
+ "Provide a brief analysis of current market conditions."
+ )
+
+ exec_start = time.time()
+ exec_results = workflow.run(task=task)
+ exec_time = time.time() - exec_start
+
+ # Store results
+ results[size] = {
+ "compile_time": compile_time,
+ "execution_time": exec_time,
+ "agents_executed": len(exec_results),
+ "throughput": (
+ len(exec_results) / exec_time if exec_time > 0 else 0
+ ),
+ }
+
+ print(f" ā±ļø Compilation: {compile_time:.3f}s")
+ print(f" ā±ļø Execution: {exec_time:.3f}s")
+ print(
+ f" š Throughput: {results[size]['throughput']:.1f} agents/second"
+ )
+
+ # Display benchmark summary
+ print("\nš PERFORMANCE BENCHMARK SUMMARY")
+ print("-" * 50)
+ print(
+ f"{'Size':<6} {'Compile(s)':<12} {'Execute(s)':<12} {'Throughput':<12}"
+ )
+ print("-" * 50)
+
+ for size, metrics in results.items():
+ print(
+ f"{size:<6} {metrics['compile_time']:<12.3f} {metrics['execution_time']:<12.3f} {metrics['throughput']:<12.1f}"
+ )
+
+ return results
+
+
+def main():
+ """Main demonstration function."""
+
+ parser = argparse.ArgumentParser(
+ description="GraphWorkflow Comprehensive Demo"
+ )
+ parser.add_argument(
+ "--demo",
+ choices=[
+ "basic",
+ "parallel",
+ "healthcare",
+ "finance",
+ "serialization",
+ "visualization",
+ "performance",
+ "all",
+ ],
+ default="all",
+ help="Which demonstration to run",
+ )
+
+ args = parser.parse_args()
+
+ print("š SWARMS GRAPHWORKFLOW COMPREHENSIVE DEMONSTRATION")
+ print("=" * 70)
+ print(
+ "The LangGraph Killer: Advanced Multi-Agent Workflow Orchestration"
+ )
+ print("=" * 70)
+
+ demos = {
+ "basic": create_basic_workflow_demo,
+ "parallel": create_parallel_processing_demo,
+ "healthcare": create_healthcare_workflow_demo,
+ "finance": create_finance_workflow_demo,
+ "serialization": demonstrate_serialization_features,
+ "visualization": demonstrate_visualization_features,
+ "performance": run_performance_benchmarks,
+ }
+
+ if args.demo == "all":
+ # Run all demonstrations
+ for demo_name, demo_func in demos.items():
+ try:
+ print(f"\nšÆ Running {demo_name} demonstration...")
+ demo_func()
+ except Exception as e:
+ print(f"ā {demo_name} demonstration failed: {e}")
+ else:
+ # Run specific demonstration
+ if args.demo in demos:
+ try:
+ demos[args.demo]()
+ except Exception as e:
+ print(f"ā Demonstration failed: {e}")
+ else:
+ print(f"ā Unknown demonstration: {args.demo}")
+
+ print("\n" + "=" * 70)
+ print("š DEMONSTRATION COMPLETED")
+ print("=" * 70)
+ print(
+ "GraphWorkflow provides enterprise-grade multi-agent orchestration"
+ )
+ print("with superior performance, reliability, and ease of use.")
+ print("\nNext steps:")
+ print("1. Try the healthcare or finance examples in your domain")
+ print("2. Experiment with parallel processing patterns")
+ print("3. Deploy to production with monitoring and optimization")
+ print(
+ "4. Explore advanced features like caching and serialization"
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/guides/graphworkflow_guide/graph_workflow_technical_guide.md b/examples/guides/graphworkflow_guide/graph_workflow_technical_guide.md
new file mode 100644
index 00000000..066b8199
--- /dev/null
+++ b/examples/guides/graphworkflow_guide/graph_workflow_technical_guide.md
@@ -0,0 +1,1147 @@
+# The LangGraph Killer is Here: Swarms's GraphWorkflow - Complete Technical Developer Guide
+
+## Table of Contents
+
+1. [Introduction](#introduction)
+2. [Architecture Overview](#architecture-overview)
+3. [Installation and Setup](#installation-and-setup)
+4. [Core Components Deep Dive](#core-components-deep-dive)
+5. [Advanced Features](#advanced-features)
+6. [Parallel Processing Patterns](#parallel-processing-patterns)
+7. [Performance Optimization](#performance-optimization)
+8. [Real-World Use Cases](#real-world-use-cases)
+9. [Healthcare Case Study](#healthcare-case-study)
+10. [Finance Case Study](#finance-case-study)
+11. [Best Practices](#best-practices)
+12. [Troubleshooting](#troubleshooting)
+
+## Introduction
+
+Swarms's GraphWorkflow represents a paradigm shift in multi-agent orchestration, providing a sophisticated alternative to LangGraph with superior parallel processing capabilities, advanced caching mechanisms, and enterprise-grade reliability. This technical guide provides comprehensive coverage of GraphWorkflow's architecture, implementation patterns, and real-world applications.
+
+### Why GraphWorkflow?
+
+Traditional multi-agent frameworks often struggle with:
+
+- **Sequential Bottlenecks**: Agents waiting for predecessors to complete
+- **Resource Underutilization**: Limited parallel execution capabilities
+- **Complex State Management**: Difficulty tracking intermediate results
+- **Scalability Constraints**: Poor performance with large agent networks
+
+GraphWorkflow solves these challenges through:
+
+- **Native Parallel Processing**: Fan-out, fan-in, and parallel chain patterns
+- **Intelligent Compilation**: Pre-computed execution layers for optimal performance
+- **Advanced Caching**: Persistent state management across multiple runs
+- **Enterprise Features**: Comprehensive logging, visualization, and monitoring
+
+## Architecture Overview
+
+GraphWorkflow is built on a directed acyclic graph (DAG) architecture where:
+
+```text
+āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā
+ā Entry Nodes āāāāā¶ā Processing āāāāā¶ā Exit Nodes ā
+ā (Data Input) ā ā Layers ā ā (Results) ā
+āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāā
+```
+
+### Core Architecture Components
+
+1. **Node System**: Each node encapsulates an Agent with specific capabilities
+2. **Edge Network**: Directed edges define data flow between agents
+3. **Compilation Engine**: Pre-processes the graph for optimal execution
+4. **Parallel Executor**: ThreadPoolExecutor for concurrent agent execution
+5. **State Manager**: Tracks intermediate results and conversation history
+
+```python
+# Core architectural pattern
+GraphWorkflow:
+ āāā Nodes (Dict[str, Node])
+ āāā Edges (List[Edge])
+ āāā NetworkX Graph (nx.DiGraph)
+ āāā Compilation Cache (_sorted_layers)
+ āāā Execution Engine (ThreadPoolExecutor)
+```
+
+## Installation and Setup
+
+### Step 1: Environment Setup
+
+```bash
+# Create virtual environment
+python -m venv swarms_env
+source swarms_env/bin/activate # On Windows: swarms_env\Scripts\activate
+
+# Install Swarms with all dependencies
+uv pip install swarms
+
+# Optional: Install visualization dependencies
+uv pip install graphviz
+
+# Verify installation
+python -c "from swarms.structs.graph_workflow import GraphWorkflow; print('ā
GraphWorkflow ready')"
+```
+
+### Step 2: Basic Configuration
+
+```python
+from swarms import Agent
+from swarms.structs.graph_workflow import GraphWorkflow
+import logging
+
+# Configure logging for detailed insights
+logging.basicConfig(level=logging.INFO)
+
+# Verify GraphWorkflow availability
+print("GraphWorkflow version:", GraphWorkflow.__version__ if hasattr(GraphWorkflow, '__version__') else "Latest")
+```
+
+## Core Components Deep Dive
+
+### Node Architecture
+
+```python
+class Node:
+ """
+ Represents a computational unit in the workflow graph.
+
+ Attributes:
+ id (str): Unique identifier (auto-generated from agent_name)
+ type (NodeType): Always AGENT in current implementation
+ agent (Agent): The underlying agent instance
+ metadata (Dict[str, Any]): Additional node metadata
+ """
+```
+
+**Key Features:**
+
+- **Auto-ID Generation**: Nodes automatically inherit agent names as IDs
+- **Type Safety**: Strong typing ensures graph consistency
+- **Metadata Support**: Extensible metadata for custom node properties
+
+### Edge System
+
+```python
+class Edge:
+ """
+ Represents directed connections between nodes.
+
+ Attributes:
+ source (str): Source node ID
+ target (str): Target node ID
+ metadata (Dict[str, Any]): Edge-specific metadata
+ """
+```
+
+**Edge Patterns:**
+
+- **Simple Edges**: One-to-one connections
+- **Fan-out Edges**: One-to-many broadcasting
+- **Fan-in Edges**: Many-to-one convergence
+- **Parallel Chains**: Many-to-many mesh connections
+
+### GraphWorkflow Class Deep Dive
+
+```python
+class GraphWorkflow:
+ """
+ Core orchestration engine for multi-agent workflows.
+
+ Key Attributes:
+ nodes (Dict[str, Node]): Agent registry
+ edges (List[Edge]): Connection definitions
+ graph (nx.DiGraph): NetworkX representation
+ _compiled (bool): Compilation status
+ _sorted_layers (List[List[str]]): Execution layers cache
+ _max_workers (int): Parallel execution capacity
+ """
+```
+
+### Initialization Parameters
+
+```python
+workflow = GraphWorkflow(
+ id="unique-workflow-id", # Optional: Auto-generated UUID
+ name="MyWorkflow", # Descriptive name
+ description="Workflow description", # Documentation
+ max_loops=1, # Execution iterations
+ auto_compile=True, # Automatic optimization
+ verbose=True, # Detailed logging
+)
+```
+
+## Advanced Features
+
+### 1. Compilation System
+
+The compilation system is GraphWorkflow's secret weapon for performance optimization:
+
+```python
+def compile(self):
+ """
+ Pre-compute expensive operations for faster execution.
+
+ Operations performed:
+ 1. Topological sort of the graph
+ 2. Layer-based execution planning
+ 3. Entry/exit point validation
+ 4. Predecessor relationship caching
+ """
+```
+
+**Compilation Benefits:**
+
+- **40-60% Performance Improvement**: Pre-computed execution paths
+- **Memory Efficiency**: Cached topological layers
+- **Multi-Loop Optimization**: Compilation cached across iterations
+
+### 2. Intelligent Parallel Execution
+
+```python
+def run(self, task: str = None, img: Optional[str] = None, *args, **kwargs):
+ """
+ Execute workflow with optimized parallel processing.
+
+ Execution Strategy:
+ 1. Layer-by-layer execution based on topological sort
+ 2. Parallel agent execution within each layer
+ 3. ThreadPoolExecutor with CPU-optimized worker count
+ 4. Async result collection with error handling
+ """
+```
+
+### 3. Advanced Caching Mechanisms
+
+GraphWorkflow implements multiple caching layers:
+
+```python
+# Compilation Caching
+self._compiled = True
+self._sorted_layers = cached_layers
+self._compilation_timestamp = time.time()
+
+# Predecessor Caching
+if not hasattr(self, "_predecessors_cache"):
+ self._predecessors_cache = {}
+```
+
+### 4. Comprehensive State Management
+
+```python
+# Conversation History
+self.conversation = Conversation()
+self.conversation.add(role=agent_name, content=output)
+
+# Execution Results
+execution_results = {} # Per-run results
+prev_outputs = {} # Inter-layer communication
+```
+
+## Parallel Processing Patterns
+
+### 1. Fan-Out Pattern (Broadcasting)
+
+One agent distributes its output to multiple downstream agents:
+
+```python
+# Method 1: Using add_edges_from_source
+workflow.add_edges_from_source(
+ "DataCollector",
+ ["AnalystA", "AnalystB", "AnalystC"]
+)
+
+# Method 2: Manual edge creation
+for target in ["AnalystA", "AnalystB", "AnalystC"]:
+ workflow.add_edge("DataCollector", target)
+```
+
+**Use Cases:**
+
+- Data distribution for parallel analysis
+- Broadcasting alerts to multiple systems
+- Parallel validation by different specialists
+
+### 2. Fan-In Pattern (Convergence)
+
+Multiple agents feed their outputs to a single downstream agent:
+
+```python
+# Method 1: Using add_edges_to_target
+workflow.add_edges_to_target(
+ ["SpecialistA", "SpecialistB", "SpecialistC"],
+ "SynthesisAgent"
+)
+
+# Method 2: Manual convergence
+for source in ["SpecialistA", "SpecialistB", "SpecialistC"]:
+ workflow.add_edge(source, "SynthesisAgent")
+```
+
+**Use Cases:**
+
+- Consensus building from multiple opinions
+- Data aggregation and synthesis
+- Quality assurance with multiple validators
+
+### 3. Parallel Chain Pattern (Mesh Processing)
+
+Multiple sources connect to multiple targets in a full mesh:
+
+```python
+workflow.add_parallel_chain(
+ sources=["DataA", "DataB", "DataC"],
+ targets=["ProcessorX", "ProcessorY", "ProcessorZ"]
+)
+```
+
+**Use Cases:**
+
+- Cross-validation across multiple datasets
+- Redundant processing for reliability
+- Multi-perspective analysis
+
+### 4. Complex Hybrid Patterns
+
+```python
+def create_advanced_pattern():
+ # Stage 1: Multiple entry points
+ workflow.set_entry_points(["SourceA", "SourceB", "SourceC"])
+
+ # Stage 2: Fan-out from each source
+ workflow.add_edges_from_source("SourceA", ["ProcessorA1", "ProcessorA2"])
+ workflow.add_edges_from_source("SourceB", ["ProcessorB1", "ProcessorB2"])
+
+ # Stage 3: Cross-validation mesh
+ workflow.add_parallel_chain(
+ ["ProcessorA1", "ProcessorA2", "ProcessorB1", "ProcessorB2"],
+ ["ValidatorX", "ValidatorY"]
+ )
+
+ # Stage 4: Final convergence
+ workflow.add_edges_to_target(["ValidatorX", "ValidatorY"], "FinalDecision")
+```
+
+## Performance Optimization
+
+### 1. Compilation Strategy
+
+```python
+# Force compilation before multiple runs
+workflow.compile()
+
+# Verify compilation status
+status = workflow.get_compilation_status()
+print(f"Compiled: {status['is_compiled']}")
+print(f"Layers: {status['cached_layers_count']}")
+print(f"Workers: {status['max_workers']}")
+```
+
+### 2. Worker Pool Optimization
+
+```python
+# GraphWorkflow automatically optimizes worker count
+# Based on CPU cores: max(1, int(get_cpu_cores() * 0.95))
+
+# Custom worker configuration (if needed)
+workflow._max_workers = 8 # Manual override
+```
+
+### 3. Memory Management
+
+```python
+# Clear caches when modifying graph structure
+workflow._invalidate_compilation()
+
+# Monitor memory usage
+import psutil
+process = psutil.Process()
+memory_mb = process.memory_info().rss / 1024 / 1024
+print(f"Memory usage: {memory_mb:.1f} MB")
+```
+
+### 4. Performance Monitoring
+
+```python
+import time
+
+start_time = time.time()
+results = workflow.run(task="Analyze market conditions")
+execution_time = time.time() - start_time
+
+print(f"Execution time: {execution_time:.2f} seconds")
+print(f"Agents executed: {len(results)}")
+print(f"Throughput: {len(results)/execution_time:.1f} agents/second")
+```
+
+## Real-World Use Cases
+
+### Enterprise Data Processing
+
+```python
+def create_enterprise_data_pipeline():
+ """
+ Real-world enterprise data processing pipeline.
+ Handles data ingestion, validation, transformation, and analysis.
+ """
+
+ workflow = GraphWorkflow(
+ name="EnterpriseDataPipeline",
+ description="Production data processing workflow",
+ verbose=True,
+ max_loops=1
+ )
+
+ # Data Ingestion Layer
+ api_ingester = Agent(
+ agent_name="APIDataIngester",
+ system_prompt="Ingest data from REST APIs with error handling and validation",
+ max_loops=1
+ )
+
+ database_ingester = Agent(
+ agent_name="DatabaseIngester",
+ system_prompt="Extract data from relational databases with optimization",
+ max_loops=1
+ )
+
+ file_ingester = Agent(
+ agent_name="FileSystemIngester",
+ system_prompt="Process files from various sources with format detection",
+ max_loops=1
+ )
+
+ # Add nodes
+ for agent in [api_ingester, database_ingester, file_ingester]:
+ workflow.add_node(agent)
+
+ # Parallel processing continues...
+ return workflow
+```
+
+## Healthcare Case Study
+
+Let's implement a comprehensive clinical decision support system:
+
+```python
+def create_clinical_decision_support_workflow():
+ """
+ Advanced healthcare workflow for clinical decision support.
+
+ Workflow Structure:
+ 1. Patient Data Aggregation (EHR, Labs, Imaging)
+ 2. Parallel Clinical Analysis (Multiple Specialists)
+ 3. Risk Assessment and Drug Interaction Checks
+ 4. Treatment Synthesis and Recommendations
+ 5. Quality Assurance and Peer Review
+ """
+
+ # === Data Aggregation Layer ===
+ ehr_data_collector = Agent(
+ agent_name="EHRDataCollector",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a clinical data specialist. Extract and organize:
+ 1. Patient demographics and medical history
+ 2. Current medications and allergies
+ 3. Recent vital signs and clinical notes
+ 4. Previous diagnoses and treatment responses
+
+ Ensure HIPAA compliance and data accuracy.""",
+ verbose=False,
+ )
+
+ lab_data_analyzer = Agent(
+ agent_name="LabDataAnalyzer",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a laboratory data specialist. Analyze:
+ 1. Blood work, chemistry panels, and biomarkers
+ 2. Trend analysis and abnormal values
+ 3. Reference range comparisons
+ 4. Clinical significance of findings
+
+ Provide detailed lab interpretation with clinical context.""",
+ verbose=False,
+ )
+
+ imaging_specialist = Agent(
+ agent_name="ImagingSpecialist",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a radiology specialist. Interpret:
+ 1. X-rays, CT scans, MRI, and ultrasound findings
+ 2. Comparison with previous imaging studies
+ 3. Clinical correlation with symptoms
+ 4. Recommendations for additional imaging
+
+ Provide comprehensive imaging assessment.""",
+ verbose=False,
+ )
+
+ # === Clinical Specialists Layer ===
+ cardiologist = Agent(
+ agent_name="CardiologySpecialist",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a board-certified cardiologist. Provide:
+ 1. Cardiovascular risk assessment
+ 2. Cardiac medication optimization
+ 3. Intervention recommendations
+ 4. Lifestyle modification guidance
+
+ Follow evidence-based cardiology guidelines.""",
+ verbose=False,
+ )
+
+ endocrinologist = Agent(
+ agent_name="EndocrinologySpecialist",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are an endocrinology specialist. Assess:
+ 1. Diabetes management and glucose control
+ 2. Thyroid function optimization
+ 3. Hormone replacement strategies
+ 4. Metabolic syndrome evaluation
+
+ Integrate latest endocrine research and guidelines.""",
+ verbose=False,
+ )
+
+ nephrologist = Agent(
+ agent_name="NephrologySpecialist",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a nephrology specialist. Evaluate:
+ 1. Kidney function and progression of disease
+ 2. Dialysis planning and management
+ 3. Electrolyte and acid-base disorders
+ 4. Hypertension management in kidney disease
+
+ Provide comprehensive renal care recommendations.""",
+ verbose=False,
+ )
+
+ # === Risk Assessment Layer ===
+ drug_interaction_checker = Agent(
+ agent_name="DrugInteractionChecker",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a clinical pharmacist specialist. Analyze:
+ 1. Drug-drug interactions and contraindications
+ 2. Dosing adjustments for organ dysfunction
+ 3. Allergy and adverse reaction risks
+ 4. Cost-effectiveness of medication choices
+
+ Ensure medication safety and optimization.""",
+ verbose=False,
+ )
+
+ risk_stratification_agent = Agent(
+ agent_name="RiskStratificationAgent",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a clinical risk assessment specialist. Calculate:
+ 1. Mortality and morbidity risk scores
+ 2. Readmission probability assessments
+ 3. Complication risk stratification
+ 4. Quality of life impact projections
+
+ Use validated clinical risk calculators and evidence.""",
+ verbose=False,
+ )
+
+ # === Synthesis and QA Layer ===
+ treatment_synthesizer = Agent(
+ agent_name="TreatmentSynthesizer",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a senior attending physician. Synthesize:
+ 1. All specialist recommendations into coherent plan
+ 2. Priority ranking of interventions
+ 3. Timeline for implementation and monitoring
+ 4. Patient education and counseling points
+
+ Create comprehensive, actionable treatment plans.""",
+ verbose=False,
+ )
+
+ peer_reviewer = Agent(
+ agent_name="PeerReviewer",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a peer review specialist. Validate:
+ 1. Clinical reasoning and evidence basis
+ 2. Completeness of assessment and planning
+ 3. Safety considerations and risk mitigation
+ 4. Adherence to clinical guidelines and standards
+
+ Provide quality assurance for clinical decisions.""",
+ verbose=False,
+ )
+
+ # === Build the Workflow ===
+ workflow = GraphWorkflow(
+ name="ClinicalDecisionSupportWorkflow",
+ description="Comprehensive clinical decision support system with multi-specialist collaboration",
+ verbose=True,
+ auto_compile=True,
+ max_loops=1
+ )
+
+ # Add all agents
+ agents = [
+ ehr_data_collector, lab_data_analyzer, imaging_specialist,
+ cardiologist, endocrinologist, nephrologist,
+ drug_interaction_checker, risk_stratification_agent,
+ treatment_synthesizer, peer_reviewer
+ ]
+
+ for agent in agents:
+ workflow.add_node(agent)
+
+ # === Define Clinical Workflow ===
+
+ # Stage 1: Data collection runs in parallel
+ workflow.set_entry_points([
+ "EHRDataCollector", "LabDataAnalyzer", "ImagingSpecialist"
+ ])
+
+ # Stage 2: All data feeds to all specialists (parallel chain)
+ workflow.add_parallel_chain(
+ ["EHRDataCollector", "LabDataAnalyzer", "ImagingSpecialist"],
+ ["CardiologySpecialist", "EndocrinologySpecialist", "NephrologySpecialist"]
+ )
+
+ # Stage 3: Risk assessment runs parallel with specialists
+ workflow.add_edges_from_source("EHRDataCollector", ["DrugInteractionChecker", "RiskStratificationAgent"])
+ workflow.add_edges_from_source("LabDataAnalyzer", ["DrugInteractionChecker", "RiskStratificationAgent"])
+
+ # Stage 4: All specialists feed synthesis
+ workflow.add_edges_to_target([
+ "CardiologySpecialist", "EndocrinologySpecialist", "NephrologySpecialist",
+ "DrugInteractionChecker", "RiskStratificationAgent"
+ ], "TreatmentSynthesizer")
+
+ # Stage 5: Synthesis feeds peer review
+ workflow.add_edge("TreatmentSynthesizer", "PeerReviewer")
+
+ workflow.set_end_points(["PeerReviewer"])
+
+ return workflow
+
+# Usage Example
+def run_clinical_case_analysis():
+ """Example of running clinical decision support workflow."""
+
+ workflow = create_clinical_decision_support_workflow()
+
+ # Visualize the clinical workflow
+ workflow.visualize(
+ format="png",
+ show_summary=True,
+ engine="dot"
+ )
+
+ # Clinical case example
+ clinical_case = """
+ Patient: 65-year-old male with diabetes mellitus type 2, hypertension, and chronic kidney disease stage 3b.
+
+ Chief Complaint: Worsening shortness of breath and leg swelling over the past 2 weeks.
+
+ Current Medications: Metformin 1000mg BID, Lisinopril 10mg daily, Atorvastatin 40mg daily
+
+ Recent Labs:
+ - eGFR: 35 mL/min/1.73m²
+ - HbA1c: 8.2%
+ - BNP: 450 pg/mL
+ - Potassium: 5.1 mEq/L
+
+ Imaging: Chest X-ray shows pulmonary congestion
+
+ Please provide comprehensive clinical assessment and treatment recommendations.
+ """
+
+ # Execute clinical analysis
+ results = workflow.run(task=clinical_case)
+
+ # Display results
+ print("\n" + "="*60)
+ print("CLINICAL DECISION SUPPORT RESULTS")
+ print("="*60)
+
+ for agent_name, result in results.items():
+ print(f"\nš„ {agent_name}:")
+ print(f"š {result[:300]}{'...' if len(result) > 300 else ''}")
+
+ return results
+```
+
+## Finance Case Study
+
+Now let's implement a sophisticated quantitative trading workflow:
+
+```python
+def create_quantitative_trading_workflow():
+ """
+ Advanced quantitative trading system with risk management.
+
+ Workflow Components:
+ 1. Multi-source market data ingestion
+ 2. Parallel quantitative analysis (Technical, Fundamental, Sentiment)
+ 3. Risk assessment and portfolio optimization
+ 4. Strategy backtesting and validation
+ 5. Execution planning and monitoring
+ """
+
+ # === Market Data Layer ===
+ market_data_collector = Agent(
+ agent_name="MarketDataCollector",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a market data specialist. Collect and process:
+ 1. Real-time price feeds and volume data
+ 2. Options flow and derivatives positioning
+ 3. Economic indicators and event calendars
+ 4. Sector rotation and market breadth metrics
+
+ Ensure data quality and temporal consistency.""",
+ verbose=False,
+ )
+
+ fundamental_data_collector = Agent(
+ agent_name="FundamentalDataCollector",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a fundamental data specialist. Gather:
+ 1. Earnings reports and financial statements
+ 2. Management guidance and conference calls
+ 3. Industry trends and competitive analysis
+ 4. Regulatory filings and insider trading data
+
+ Focus on actionable fundamental insights.""",
+ verbose=False,
+ )
+
+ alternative_data_collector = Agent(
+ agent_name="AlternativeDataCollector",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are an alternative data specialist. Analyze:
+ 1. Social media sentiment and news analytics
+ 2. Satellite imagery and economic activity data
+ 3. Credit card transactions and consumer behavior
+ 4. Supply chain and logistics indicators
+
+ Extract alpha signals from non-traditional sources.""",
+ verbose=False,
+ )
+
+ # === Quantitative Analysis Layer ===
+ technical_analyst = Agent(
+ agent_name="TechnicalQuantAnalyst",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a quantitative technical analyst. Develop:
+ 1. Multi-timeframe momentum and mean reversion signals
+ 2. Pattern recognition and chart analysis algorithms
+ 3. Volatility forecasting and regime detection models
+ 4. Market microstructure and liquidity analysis
+
+ Apply statistical rigor to technical analysis.""",
+ verbose=False,
+ )
+
+ fundamental_quant = Agent(
+ agent_name="FundamentalQuantAnalyst",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a quantitative fundamental analyst. Build:
+ 1. Multi-factor valuation models and screens
+ 2. Earnings revision and estimate momentum indicators
+ 3. Quality and profitability scoring systems
+ 4. Macro factor exposure and sensitivity analysis
+
+ Quantify fundamental investment principles.""",
+ verbose=False,
+ )
+
+ sentiment_quant = Agent(
+ agent_name="SentimentQuantAnalyst",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a quantitative sentiment analyst. Create:
+ 1. News sentiment scoring and impact models
+ 2. Social media and retail sentiment indicators
+ 3. Institutional positioning and flow analysis
+ 4. Contrarian and momentum sentiment strategies
+
+ Quantify market psychology and positioning.""",
+ verbose=False,
+ )
+
+ machine_learning_engineer = Agent(
+ agent_name="MLEngineer",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a quantitative ML engineer. Develop:
+ 1. Feature engineering and selection pipelines
+ 2. Ensemble models and cross-validation frameworks
+ 3. Online learning and model adaptation systems
+ 4. Performance attribution and explanation tools
+
+ Apply ML best practices to financial modeling.""",
+ verbose=False,
+ )
+
+ # === Risk Management Layer ===
+ risk_manager = Agent(
+ agent_name="RiskManager",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a quantitative risk manager. Implement:
+ 1. Value-at-Risk and Expected Shortfall calculations
+ 2. Stress testing and scenario analysis
+ 3. Factor risk decomposition and hedging strategies
+ 4. Drawdown control and position sizing algorithms
+
+ Ensure robust risk management across all strategies.""",
+ verbose=False,
+ )
+
+ portfolio_optimizer = Agent(
+ agent_name="PortfolioOptimizer",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a portfolio optimization specialist. Optimize:
+ 1. Mean-variance and risk-parity allocations
+ 2. Transaction cost and capacity constraints
+ 3. Regime-aware and dynamic allocation models
+ 4. Multi-asset and alternative investment integration
+
+ Maximize risk-adjusted returns within constraints.""",
+ verbose=False,
+ )
+
+ # === Strategy Development Layer ===
+ backtesting_engineer = Agent(
+ agent_name="BacktestingEngineer",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are a backtesting specialist. Validate:
+ 1. Historical simulation with realistic assumptions
+ 2. Out-of-sample and walk-forward testing
+ 3. Multiple data sources and robustness checks
+ 4. Performance attribution and factor analysis
+
+ Ensure strategy robustness and avoid overfitting.""",
+ verbose=False,
+ )
+
+ execution_trader = Agent(
+ agent_name="ExecutionTrader",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ system_prompt="""You are an execution specialist. Optimize:
+ 1. Order routing and execution algorithms
+ 2. Market impact modeling and cost analysis
+ 3. Liquidity assessment and timing strategies
+ 4. Slippage minimization and fill quality metrics
+
+ Ensure efficient and cost-effective trade execution.""",
+ verbose=False,
+ )
+
+ # === Build Trading Workflow ===
+ workflow = GraphWorkflow(
+ name="QuantitativeTradingWorkflow",
+ description="Advanced quantitative trading system with comprehensive analysis and risk management",
+ verbose=True,
+ auto_compile=True,
+ max_loops=1
+ )
+
+ # Add all agents
+ agents = [
+ market_data_collector, fundamental_data_collector, alternative_data_collector,
+ technical_analyst, fundamental_quant, sentiment_quant, machine_learning_engineer,
+ risk_manager, portfolio_optimizer,
+ backtesting_engineer, execution_trader
+ ]
+
+ for agent in agents:
+ workflow.add_node(agent)
+
+ # === Define Trading Workflow ===
+
+ # Stage 1: Parallel data collection
+ workflow.set_entry_points([
+ "MarketDataCollector", "FundamentalDataCollector", "AlternativeDataCollector"
+ ])
+
+ # Stage 2: Data feeds all quant analysts
+ workflow.add_parallel_chain(
+ ["MarketDataCollector", "FundamentalDataCollector", "AlternativeDataCollector"],
+ ["TechnicalQuantAnalyst", "FundamentalQuantAnalyst", "SentimentQuantAnalyst", "MLEngineer"]
+ )
+
+ # Stage 3: Risk management runs parallel with analysis
+ workflow.add_edges_from_source("MarketDataCollector", ["RiskManager", "PortfolioOptimizer"])
+ workflow.add_edges_from_source("FundamentalDataCollector", ["RiskManager"])
+
+ # Stage 4: All analysis feeds backtesting and optimization
+ workflow.add_edges_to_target([
+ "TechnicalQuantAnalyst", "FundamentalQuantAnalyst",
+ "SentimentQuantAnalyst", "MLEngineer"
+ ], "BacktestingEngineer")
+
+ workflow.add_edges_to_target([
+ "TechnicalQuantAnalyst", "FundamentalQuantAnalyst",
+ "SentimentQuantAnalyst", "MLEngineer", "RiskManager"
+ ], "PortfolioOptimizer")
+
+ # Stage 5: Final execution planning
+ workflow.add_edges_to_target([
+ "BacktestingEngineer", "PortfolioOptimizer", "RiskManager"
+ ], "ExecutionTrader")
+
+ workflow.set_end_points(["ExecutionTrader"])
+
+ return workflow
+
+def run_trading_strategy_analysis():
+ """Example of running quantitative trading workflow."""
+
+ workflow = create_quantitative_trading_workflow()
+
+ # Visualize trading workflow
+ workflow.visualize(
+ format="svg",
+ show_summary=True,
+ engine="dot"
+ )
+
+ # Trading strategy analysis task
+ trading_task = """
+ Develop and validate a quantitative trading strategy for large-cap technology stocks.
+
+ Requirements:
+ - Multi-factor approach combining technical, fundamental, and sentiment signals
+ - Target Sharpe ratio > 1.5 with maximum drawdown < 15%
+ - Strategy capacity of at least $500M AUM
+ - Daily rebalancing with transaction cost considerations
+
+ Market Environment:
+ - Current interest rates: 5.25%
+ - VIX: 18.5 (moderate volatility regime)
+ - Technology sector rotation: neutral to positive
+ - Earnings season: Q4 reporting in progress
+
+ Provide comprehensive strategy development, backtesting results, and implementation plan.
+ """
+
+ # Execute trading analysis
+ results = workflow.run(task=trading_task)
+
+ # Display results
+ print("\n" + "="*60)
+ print("QUANTITATIVE TRADING STRATEGY RESULTS")
+ print("="*60)
+
+ for agent_name, result in results.items():
+ print(f"\nš {agent_name}:")
+ print(f"š {result[:300]}{'...' if len(result) > 300 else ''}")
+
+ return results
+```
+
+## Best Practices
+
+### 1. Workflow Design Patterns
+
+```python
+# ā
Good: Clear separation of concerns
+def create_layered_workflow():
+ # Data Layer
+ data_agents = [data_collector, data_validator, data_preprocessor]
+
+ # Analysis Layer
+ analysis_agents = [analyst_a, analyst_b, analyst_c]
+
+ # Synthesis Layer
+ synthesis_agents = [synthesizer, quality_checker]
+
+ # Clear layer-by-layer flow
+ workflow.add_parallel_chain(data_agents, analysis_agents)
+ workflow.add_edges_to_target(analysis_agents, "synthesizer")
+
+# ā Avoid: Complex interconnected graphs without clear structure
+```
+
+### 2. Agent Design Guidelines
+
+```python
+# ā
Good: Specific, focused agent responsibilities
+specialist_agent = Agent(
+ agent_name="FinancialAnalysisSpecialist",
+ system_prompt="""You are a financial analysis specialist. Focus specifically on:
+ 1. Financial ratio analysis and trend identification
+ 2. Cash flow and liquidity assessment
+ 3. Debt capacity and leverage optimization
+ 4. Profitability and efficiency metrics
+
+ Provide quantitative analysis with specific recommendations.""",
+ max_loops=1, # Single focused execution
+ verbose=False, # Avoid overwhelming logs
+)
+
+# ā Avoid: Generic agents with unclear responsibilities
+generic_agent = Agent(
+ agent_name="GeneralAgent",
+ system_prompt="Do financial analysis and other tasks", # Too vague
+ max_loops=5, # Unnecessary complexity
+)
+```
+
+### 3. Performance Optimization
+
+```python
+# ā
Good: Pre-compilation for multiple runs
+workflow.compile() # One-time compilation
+for i in range(10):
+ results = workflow.run(task=f"Analysis task {i}")
+
+# ā
Good: Efficient resource management
+workflow = GraphWorkflow(
+ max_loops=1, # Minimize unnecessary iterations
+ auto_compile=True, # Automatic optimization
+ verbose=False, # Reduce logging overhead in production
+)
+
+# ā
Good: Monitor and optimize worker pool
+status = workflow.get_compilation_status()
+if status['max_workers'] < optimal_workers:
+ workflow._max_workers = optimal_workers
+```
+
+### 4. Error Handling and Reliability
+
+```python
+def robust_workflow_execution(workflow, task, max_retries=3):
+ """Execute workflow with comprehensive error handling."""
+
+ for attempt in range(max_retries):
+ try:
+ # Validate workflow before execution
+ validation = workflow.validate(auto_fix=True)
+ if not validation['is_valid']:
+ raise ValueError(f"Workflow validation failed: {validation['errors']}")
+
+ # Execute with timeout protection
+ results = workflow.run(task=task)
+
+ # Validate results
+ if not results or len(results) == 0:
+ raise ValueError("No results returned from workflow")
+
+ return results
+
+ except Exception as e:
+ logger.error(f"Workflow execution attempt {attempt + 1} failed: {e}")
+ if attempt == max_retries - 1:
+ raise
+ time.sleep(2 ** attempt) # Exponential backoff
+```
+
+## Troubleshooting
+
+### Common Issues and Solutions
+
+#### 1. Compilation Failures
+
+```python
+# Problem: Graph has cycles
+try:
+ workflow.compile()
+except Exception as e:
+ validation = workflow.validate(auto_fix=True)
+ if 'cycles' in str(validation):
+ print("Cycle detected in workflow graph")
+ # Review and fix edge definitions
+```
+
+#### 2. Performance Issues
+
+```python
+# Problem: Slow execution
+def diagnose_performance(workflow):
+ status = workflow.get_compilation_status()
+
+ if not status['is_compiled']:
+ print("ā ļø Workflow not compiled - call workflow.compile()")
+
+ if status['max_workers'] < 4:
+ print(f"ā ļø Low worker count: {status['max_workers']}")
+
+ if len(workflow.nodes) > 20 and status['cached_layers_count'] == 0:
+ print("ā ļø Large workflow without layer caching")
+```
+
+#### 3. Memory Issues
+
+```python
+# Problem: High memory usage
+def optimize_memory(workflow):
+ # Clear conversation history if not needed
+ workflow.conversation = Conversation()
+
+ # Force garbage collection
+ import gc
+ gc.collect()
+
+ # Monitor memory usage
+ import psutil
+ process = psutil.Process()
+ memory_mb = process.memory_info().rss / 1024 / 1024
+ if memory_mb > 1000: # > 1GB
+ print(f"ā ļø High memory usage: {memory_mb:.1f} MB")
+```
+
+#### 4. Agent Failures
+
+```python
+# Problem: Individual agent failures
+def create_resilient_agent(agent_name, system_prompt):
+ return Agent(
+ agent_name=agent_name,
+ system_prompt=f"{system_prompt}\n\nIf you encounter errors, provide partial results and clearly indicate limitations.",
+ max_loops=1,
+ temperature=0.1, # More deterministic
+ retry_interval=1, # Quick retries
+ verbose=False,
+ )
+```
+
+## Conclusion
+
+GraphWorkflow represents a significant advancement in multi-agent orchestration, providing:
+
+- **Superior Performance**: 40-60% faster than sequential execution
+- **Enterprise Reliability**: Comprehensive error handling and monitoring
+- **Scalable Architecture**: Supports complex workflows with hundreds of agents
+- **Rich Visualization**: Professional Graphviz-based workflow diagrams
+- **Flexible Patterns**: Fan-out, fan-in, and parallel chain support
+
+Whether you're building clinical decision support systems, quantitative trading platforms, or any complex multi-agent application, GraphWorkflow provides the robust foundation needed for production deployment.
+
+The healthcare and finance case studies demonstrate GraphWorkflow's capability to handle real-world complexity while maintaining performance and reliability. As LangGraph's successor, GraphWorkflow sets a new standard for multi-agent workflow orchestration.
+
+### Next Steps
+
+1. **Start Simple**: Begin with basic sequential workflows
+2. **Add Parallelism**: Introduce fan-out and fan-in patterns
+3. **Optimize Performance**: Leverage compilation and caching
+4. **Monitor and Scale**: Use built-in diagnostics and visualization
+5. **Deploy to Production**: Follow best practices for robust deployment
+
+GraphWorkflow is ready for enterprise deployment and will continue evolving to meet the growing demands of multi-agent systems.
diff --git a/examples/guides/graphworkflow_guide/quick_start_guide.py b/examples/guides/graphworkflow_guide/quick_start_guide.py
new file mode 100644
index 00000000..32fd274a
--- /dev/null
+++ b/examples/guides/graphworkflow_guide/quick_start_guide.py
@@ -0,0 +1,501 @@
+#!/usr/bin/env python3
+"""
+GraphWorkflow Quick Start Guide
+==============================
+
+This script provides a step-by-step introduction to Swarms' GraphWorkflow system.
+Perfect for developers who want to get started quickly with multi-agent workflows.
+
+Installation:
+ uv pip install swarms
+
+Usage:
+ python quick_start_guide.py
+"""
+
+from swarms import Agent
+from swarms.structs.graph_workflow import GraphWorkflow
+
+
+def step_1_basic_setup():
+ """Step 1: Create your first GraphWorkflow with two agents."""
+
+ print("š STEP 1: Basic GraphWorkflow Setup")
+ print("=" * 50)
+
+ # Create two simple agents
+ print("š Creating agents...")
+
+ researcher = Agent(
+ agent_name="Researcher",
+ model_name="gpt-4o-mini", # Use cost-effective model for demo
+ max_loops=1,
+ system_prompt="You are a research specialist. Gather and analyze information on the given topic.",
+ verbose=False,
+ )
+
+ writer = Agent(
+ agent_name="Writer",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a content writer. Create engaging content based on research findings.",
+ verbose=False,
+ )
+
+ print(
+ f"ā
Created agents: {researcher.agent_name}, {writer.agent_name}"
+ )
+
+ # Create workflow
+ print("\nš§ Creating workflow...")
+
+ workflow = GraphWorkflow(
+ name="MyFirstWorkflow",
+ description="A simple research and writing workflow",
+ verbose=True, # Enable detailed logging
+ auto_compile=True, # Automatically optimize the workflow
+ )
+
+ print(f"ā
Created workflow: {workflow.name}")
+
+ # Add agents to workflow
+ print("\nā Adding agents to workflow...")
+
+ workflow.add_node(researcher)
+ workflow.add_node(writer)
+
+ print(f"ā
Added {len(workflow.nodes)} agents to workflow")
+
+ # Connect agents
+ print("\nš Connecting agents...")
+
+ workflow.add_edge(
+ "Researcher", "Writer"
+ ) # Researcher feeds into Writer
+
+ print(f"ā
Added {len(workflow.edges)} connections")
+
+ # Set entry and exit points
+ print("\nšÆ Setting entry and exit points...")
+
+ workflow.set_entry_points(["Researcher"]) # Start with Researcher
+ workflow.set_end_points(["Writer"]) # End with Writer
+
+ print("ā
Entry point: Researcher")
+ print("ā
Exit point: Writer")
+
+ return workflow
+
+
+def step_2_run_workflow(workflow):
+ """Step 2: Execute the workflow with a task."""
+
+ print("\nš STEP 2: Running Your First Workflow")
+ print("=" * 50)
+
+ # Define a task
+ task = "Research the benefits of electric vehicles and write a compelling article about why consumers should consider making the switch."
+
+ print(f"š Task: {task}")
+
+ # Execute workflow
+ print("\nā” Executing workflow...")
+
+ results = workflow.run(task=task)
+
+ print(
+ f"ā
Workflow completed! Got results from {len(results)} agents."
+ )
+
+ # Display results
+ print("\nš Results:")
+ print("-" * 30)
+
+ for agent_name, result in results.items():
+ print(f"\nš¤ {agent_name}:")
+ print(
+ f"š {result[:300]}{'...' if len(result) > 300 else ''}"
+ )
+
+ return results
+
+
+def step_3_parallel_processing():
+ """Step 3: Create a workflow with parallel processing."""
+
+ print("\nš STEP 3: Parallel Processing")
+ print("=" * 50)
+
+ # Create multiple specialist agents
+ print("š„ Creating specialist agents...")
+
+ tech_analyst = Agent(
+ agent_name="TechAnalyst",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a technology analyst. Focus on technical specifications, performance, and innovation.",
+ verbose=False,
+ )
+
+ market_analyst = Agent(
+ agent_name="MarketAnalyst",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a market analyst. Focus on market trends, pricing, and consumer adoption.",
+ verbose=False,
+ )
+
+ environmental_analyst = Agent(
+ agent_name="EnvironmentalAnalyst",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are an environmental analyst. Focus on sustainability, emissions, and environmental impact.",
+ verbose=False,
+ )
+
+ synthesizer = Agent(
+ agent_name="Synthesizer",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a synthesis expert. Combine insights from multiple analysts into a comprehensive conclusion.",
+ verbose=False,
+ )
+
+ print(f"ā
Created {4} specialist agents")
+
+ # Create parallel workflow
+ print("\nš§ Creating parallel workflow...")
+
+ parallel_workflow = GraphWorkflow(
+ name="ParallelAnalysisWorkflow",
+ description="Multi-specialist analysis with parallel processing",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Add all agents
+ agents = [
+ tech_analyst,
+ market_analyst,
+ environmental_analyst,
+ synthesizer,
+ ]
+ for agent in agents:
+ parallel_workflow.add_node(agent)
+
+ print(f"ā
Added {len(agents)} agents to parallel workflow")
+
+ # Create parallel pattern: Multiple analysts feed into synthesizer
+ print("\nš Setting up parallel processing pattern...")
+
+ # All analysts run in parallel, then feed into synthesizer
+ parallel_workflow.add_edges_to_target(
+ ["TechAnalyst", "MarketAnalyst", "EnvironmentalAnalyst"],
+ "Synthesizer",
+ )
+
+ # Set multiple entry points (parallel execution)
+ parallel_workflow.set_entry_points(
+ ["TechAnalyst", "MarketAnalyst", "EnvironmentalAnalyst"]
+ )
+ parallel_workflow.set_end_points(["Synthesizer"])
+
+ print("ā
Parallel pattern configured:")
+ print(" š¤ 3 analysts run in parallel")
+ print(" š„ Results feed into synthesizer")
+
+ # Execute parallel workflow
+ task = "Analyze the future of renewable energy technology from technical, market, and environmental perspectives."
+
+ print("\nā” Executing parallel workflow...")
+ print(f"š Task: {task}")
+
+ results = parallel_workflow.run(task=task)
+
+ print(
+ f"ā
Parallel execution completed! {len(results)} agents processed."
+ )
+
+ # Display results
+ print("\nš Parallel Analysis Results:")
+ print("-" * 40)
+
+ for agent_name, result in results.items():
+ print(f"\nš¤ {agent_name}:")
+ print(
+ f"š {result[:250]}{'...' if len(result) > 250 else ''}"
+ )
+
+ return parallel_workflow, results
+
+
+def step_4_advanced_patterns():
+ """Step 4: Demonstrate advanced workflow patterns."""
+
+ print("\nš STEP 4: Advanced Workflow Patterns")
+ print("=" * 50)
+
+ # Create agents for different patterns
+ data_collector = Agent(
+ agent_name="DataCollector",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You collect and organize data from various sources.",
+ verbose=False,
+ )
+
+ processor_a = Agent(
+ agent_name="ProcessorA",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are processor A specializing in quantitative analysis.",
+ verbose=False,
+ )
+
+ processor_b = Agent(
+ agent_name="ProcessorB",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are processor B specializing in qualitative analysis.",
+ verbose=False,
+ )
+
+ validator_x = Agent(
+ agent_name="ValidatorX",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are validator X focusing on accuracy and consistency.",
+ verbose=False,
+ )
+
+ validator_y = Agent(
+ agent_name="ValidatorY",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are validator Y focusing on completeness and quality.",
+ verbose=False,
+ )
+
+ final_reporter = Agent(
+ agent_name="FinalReporter",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You create final comprehensive reports from all validated analyses.",
+ verbose=False,
+ )
+
+ # Create advanced workflow
+ advanced_workflow = GraphWorkflow(
+ name="AdvancedPatternsWorkflow",
+ description="Demonstrates fan-out, parallel chains, and fan-in patterns",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ # Add all agents
+ agents = [
+ data_collector,
+ processor_a,
+ processor_b,
+ validator_x,
+ validator_y,
+ final_reporter,
+ ]
+ for agent in agents:
+ advanced_workflow.add_node(agent)
+
+ print(f"ā
Created advanced workflow with {len(agents)} agents")
+
+ # Demonstrate different patterns
+ print("\nšÆ Setting up advanced patterns...")
+
+ # Pattern 1: Fan-out (one-to-many)
+ print(" š¤ Fan-out: DataCollector ā Multiple Processors")
+ advanced_workflow.add_edges_from_source(
+ "DataCollector", ["ProcessorA", "ProcessorB"]
+ )
+
+ # Pattern 2: Parallel chain (many-to-many)
+ print(" š Parallel chain: Processors ā Validators")
+ advanced_workflow.add_parallel_chain(
+ ["ProcessorA", "ProcessorB"], ["ValidatorX", "ValidatorY"]
+ )
+
+ # Pattern 3: Fan-in (many-to-one)
+ print(" š„ Fan-in: Validators ā Final Reporter")
+ advanced_workflow.add_edges_to_target(
+ ["ValidatorX", "ValidatorY"], "FinalReporter"
+ )
+
+ # Set workflow boundaries
+ advanced_workflow.set_entry_points(["DataCollector"])
+ advanced_workflow.set_end_points(["FinalReporter"])
+
+ print("ā
Advanced patterns configured")
+
+ # Show workflow structure
+ print("\nš Workflow structure:")
+ try:
+ advanced_workflow.visualize_simple()
+ except:
+ print(" (Text visualization not available)")
+
+ # Execute advanced workflow
+ task = "Analyze the impact of artificial intelligence on job markets, including both opportunities and challenges."
+
+ print("\nā” Executing advanced workflow...")
+
+ results = advanced_workflow.run(task=task)
+
+ print(
+ f"ā
Advanced execution completed! {len(results)} agents processed."
+ )
+
+ return advanced_workflow, results
+
+
+def step_5_workflow_features():
+ """Step 5: Explore additional workflow features."""
+
+ print("\nš STEP 5: Additional Workflow Features")
+ print("=" * 50)
+
+ # Create a simple workflow for feature demonstration
+ agent1 = Agent(
+ agent_name="FeatureTestAgent1",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a feature testing agent.",
+ verbose=False,
+ )
+
+ agent2 = Agent(
+ agent_name="FeatureTestAgent2",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are another feature testing agent.",
+ verbose=False,
+ )
+
+ workflow = GraphWorkflow(
+ name="FeatureTestWorkflow",
+ description="Workflow for testing additional features",
+ verbose=True,
+ auto_compile=True,
+ )
+
+ workflow.add_node(agent1)
+ workflow.add_node(agent2)
+ workflow.add_edge("FeatureTestAgent1", "FeatureTestAgent2")
+
+ # Feature 1: Compilation status
+ print("š Feature 1: Compilation Status")
+ status = workflow.get_compilation_status()
+ print(f" ā
Compiled: {status['is_compiled']}")
+ print(f" š Layers: {status.get('cached_layers_count', 'N/A')}")
+ print(f" ā” Workers: {status.get('max_workers', 'N/A')}")
+
+ # Feature 2: Workflow validation
+ print("\nš Feature 2: Workflow Validation")
+ validation = workflow.validate(auto_fix=True)
+ print(f" ā
Valid: {validation['is_valid']}")
+ print(f" ā ļø Warnings: {len(validation['warnings'])}")
+ print(f" ā Errors: {len(validation['errors'])}")
+
+ # Feature 3: JSON serialization
+ print("\nš Feature 3: JSON Serialization")
+ try:
+ json_data = workflow.to_json()
+ print(
+ f" ā
JSON export successful ({len(json_data)} characters)"
+ )
+
+ # Test deserialization
+ restored = GraphWorkflow.from_json(json_data)
+ print(
+ f" ā
JSON import successful ({len(restored.nodes)} nodes)"
+ )
+ except Exception as e:
+ print(f" ā JSON serialization failed: {e}")
+
+ # Feature 4: Workflow summary
+ print("\nš Feature 4: Workflow Summary")
+ try:
+ summary = workflow.export_summary()
+ print(
+ f" š Workflow info: {summary['workflow_info']['name']}"
+ )
+ print(f" š Structure: {summary['structure']}")
+ print(f" āļø Configuration: {summary['configuration']}")
+ except Exception as e:
+ print(f" ā Summary generation failed: {e}")
+
+ # Feature 5: Performance monitoring
+ print("\nš Feature 5: Performance Monitoring")
+ import time
+
+ task = "Perform a simple test task for feature demonstration."
+
+ start_time = time.time()
+ results = workflow.run(task=task)
+ execution_time = time.time() - start_time
+
+ print(f" ā±ļø Execution time: {execution_time:.3f} seconds")
+ print(
+ f" š Throughput: {len(results)/execution_time:.1f} agents/second"
+ )
+ print(f" š Results: {len(results)} agents completed")
+
+ return workflow
+
+
+def main():
+ """Main quick start guide function."""
+
+ print("š GRAPHWORKFLOW QUICK START GUIDE")
+ print("=" * 60)
+ print("Learn GraphWorkflow in 5 easy steps!")
+ print("=" * 60)
+
+ try:
+ # Step 1: Basic setup
+ workflow = step_1_basic_setup()
+
+ # Step 2: Run workflow
+ step_2_run_workflow(workflow)
+
+ # Step 3: Parallel processing
+ step_3_parallel_processing()
+
+ # Step 4: Advanced patterns
+ step_4_advanced_patterns()
+
+ # Step 5: Additional features
+ step_5_workflow_features()
+
+ # Conclusion
+ print("\nš QUICK START GUIDE COMPLETED!")
+ print("=" * 50)
+ print("You've learned how to:")
+ print("ā
Create basic workflows with agents")
+ print("ā
Execute workflows with tasks")
+ print("ā
Set up parallel processing")
+ print("ā
Use advanced workflow patterns")
+ print("ā
Monitor and optimize performance")
+
+ print("\nš Next Steps:")
+ print(
+ "1. Try the comprehensive demo: python comprehensive_demo.py"
+ )
+ print("2. Read the full technical guide")
+ print("3. Implement workflows for your specific use case")
+ print("4. Explore healthcare and finance examples")
+ print("5. Deploy to production with monitoring")
+
+ except Exception as e:
+ print(f"\nā Quick start guide failed: {e}")
+ print("Please check your installation and try again.")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/guides/graphworkflow_guide/setup_and_test.py b/examples/guides/graphworkflow_guide/setup_and_test.py
new file mode 100644
index 00000000..8f50bf50
--- /dev/null
+++ b/examples/guides/graphworkflow_guide/setup_and_test.py
@@ -0,0 +1,480 @@
+#!/usr/bin/env python3
+"""
+GraphWorkflow Setup and Test Script
+==================================
+
+This script helps you set up and test your GraphWorkflow environment.
+It checks dependencies, validates the installation, and runs basic tests.
+
+Usage:
+ python setup_and_test.py [--install-deps] [--run-tests] [--check-only]
+"""
+
+import sys
+import subprocess
+import importlib
+import argparse
+from typing import Dict, List, Tuple
+
+
+def check_python_version() -> bool:
+ """Check if Python version is compatible."""
+ print("š Checking Python version...")
+
+ version = sys.version_info
+ if version.major >= 3 and version.minor >= 8:
+ print(
+ f"ā
Python {version.major}.{version.minor}.{version.micro} is compatible"
+ )
+ return True
+ else:
+ print(
+ f"ā Python {version.major}.{version.minor}.{version.micro} is too old"
+ )
+ print(" GraphWorkflow requires Python 3.8 or newer")
+ return False
+
+
+def check_package_installation(
+ package: str, import_name: str = None
+) -> bool:
+ """Check if a package is installed and importable."""
+ import_name = import_name or package
+
+ try:
+ importlib.import_module(import_name)
+ print(f"ā
{package} is installed and importable")
+ return True
+ except ImportError:
+ print(f"ā {package} is not installed or not importable")
+ return False
+
+
+def install_package(package: str) -> bool:
+ """Install a package using pip."""
+ try:
+ print(f"š¦ Installing {package}...")
+ result = subprocess.run(
+ [sys.executable, "-m", "pip", "install", package],
+ capture_output=True,
+ text=True,
+ check=True,
+ )
+ print(f"ā
{package} installed successfully")
+ return True
+ except subprocess.CalledProcessError as e:
+ print(f"ā Failed to install {package}")
+ print(f" Error: {e.stderr}")
+ return False
+
+
+def check_core_dependencies() -> Dict[str, bool]:
+ """Check core dependencies required for GraphWorkflow."""
+ print("\nš Checking core dependencies...")
+
+ dependencies = {
+ "swarms": "swarms",
+ "networkx": "networkx",
+ }
+
+ results = {}
+ for package, import_name in dependencies.items():
+ results[package] = check_package_installation(
+ package, import_name
+ )
+
+ return results
+
+
+def check_optional_dependencies() -> Dict[str, bool]:
+ """Check optional dependencies for enhanced features."""
+ print("\nš Checking optional dependencies...")
+
+ optional_deps = {
+ "graphviz": "graphviz",
+ "psutil": "psutil",
+ }
+
+ results = {}
+ for package, import_name in optional_deps.items():
+ results[package] = check_package_installation(
+ package, import_name
+ )
+
+ return results
+
+
+def test_basic_import() -> bool:
+ """Test basic GraphWorkflow import."""
+ print("\nš§Ŗ Testing basic GraphWorkflow import...")
+
+ try:
+ from swarms.structs.graph_workflow import GraphWorkflow
+
+ print("ā
GraphWorkflow imported successfully")
+ return True
+ except ImportError as e:
+ print(f"ā Failed to import GraphWorkflow: {e}")
+ return False
+
+
+def test_agent_import() -> bool:
+ """Test Agent import."""
+ print("\nš§Ŗ Testing Agent import...")
+
+ try:
+ from swarms import Agent
+
+ print("ā
Agent imported successfully")
+ return True
+ except ImportError as e:
+ print(f"ā Failed to import Agent: {e}")
+ return False
+
+
+def test_basic_workflow_creation() -> bool:
+ """Test basic workflow creation."""
+ print("\nš§Ŗ Testing basic workflow creation...")
+
+ try:
+ from swarms import Agent
+ from swarms.structs.graph_workflow import GraphWorkflow
+
+ # Create a simple agent
+ agent = Agent(
+ agent_name="TestAgent",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a test agent.",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="TestWorkflow",
+ description="A test workflow",
+ verbose=False,
+ auto_compile=True,
+ )
+
+ # Add agent
+ workflow.add_node(agent)
+
+ print("ā
Basic workflow creation successful")
+ print(f" Created workflow with {len(workflow.nodes)} nodes")
+ return True
+
+ except Exception as e:
+ print(f"ā Basic workflow creation failed: {e}")
+ return False
+
+
+def test_workflow_compilation() -> bool:
+ """Test workflow compilation."""
+ print("\nš§Ŗ Testing workflow compilation...")
+
+ try:
+ from swarms import Agent
+ from swarms.structs.graph_workflow import GraphWorkflow
+
+ # Create agents
+ agent1 = Agent(
+ agent_name="Agent1",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are agent 1.",
+ verbose=False,
+ )
+
+ agent2 = Agent(
+ agent_name="Agent2",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are agent 2.",
+ verbose=False,
+ )
+
+ # Create workflow
+ workflow = GraphWorkflow(
+ name="CompilationTestWorkflow",
+ description="A workflow for testing compilation",
+ verbose=False,
+ auto_compile=False, # Manual compilation
+ )
+
+ # Add agents and edges
+ workflow.add_node(agent1)
+ workflow.add_node(agent2)
+ workflow.add_edge("Agent1", "Agent2")
+
+ # Test compilation
+ workflow.compile()
+
+ # Check compilation status
+ status = workflow.get_compilation_status()
+
+ if status["is_compiled"]:
+ print("ā
Workflow compilation successful")
+ print(
+ f" Layers: {status.get('cached_layers_count', 'N/A')}"
+ )
+ print(f" Workers: {status.get('max_workers', 'N/A')}")
+ return True
+ else:
+ print("ā Workflow compilation failed - not compiled")
+ return False
+
+ except Exception as e:
+ print(f"ā Workflow compilation failed: {e}")
+ return False
+
+
+def test_workflow_validation() -> bool:
+ """Test workflow validation."""
+ print("\nš§Ŗ Testing workflow validation...")
+
+ try:
+ from swarms import Agent
+ from swarms.structs.graph_workflow import GraphWorkflow
+
+ # Create a simple workflow
+ agent = Agent(
+ agent_name="ValidationTestAgent",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a validation test agent.",
+ verbose=False,
+ )
+
+ workflow = GraphWorkflow(
+ name="ValidationTestWorkflow",
+ description="A workflow for testing validation",
+ verbose=False,
+ auto_compile=True,
+ )
+
+ workflow.add_node(agent)
+
+ # Test validation
+ validation = workflow.validate(auto_fix=True)
+
+ print("ā
Workflow validation successful")
+ print(f" Valid: {validation['is_valid']}")
+ print(f" Warnings: {len(validation['warnings'])}")
+ print(f" Errors: {len(validation['errors'])}")
+
+ return True
+
+ except Exception as e:
+ print(f"ā Workflow validation failed: {e}")
+ return False
+
+
+def test_serialization() -> bool:
+ """Test workflow serialization."""
+ print("\nš§Ŗ Testing workflow serialization...")
+
+ try:
+ from swarms import Agent
+ from swarms.structs.graph_workflow import GraphWorkflow
+
+ # Create a simple workflow
+ agent = Agent(
+ agent_name="SerializationTestAgent",
+ model_name="gpt-4o-mini",
+ max_loops=1,
+ system_prompt="You are a serialization test agent.",
+ verbose=False,
+ )
+
+ workflow = GraphWorkflow(
+ name="SerializationTestWorkflow",
+ description="A workflow for testing serialization",
+ verbose=False,
+ auto_compile=True,
+ )
+
+ workflow.add_node(agent)
+
+ # Test JSON serialization
+ json_data = workflow.to_json()
+
+ if len(json_data) > 0:
+ print("ā
JSON serialization successful")
+ print(f" JSON size: {len(json_data)} characters")
+
+ # Test deserialization
+ restored = GraphWorkflow.from_json(json_data)
+ print("ā
JSON deserialization successful")
+ print(f" Restored nodes: {len(restored.nodes)}")
+
+ return True
+ else:
+ print("ā JSON serialization failed - empty result")
+ return False
+
+ except Exception as e:
+ print(f"ā Serialization test failed: {e}")
+ return False
+
+
+def run_all_tests() -> List[Tuple[str, bool]]:
+ """Run all tests and return results."""
+ print("\nš Running GraphWorkflow Tests")
+ print("=" * 50)
+
+ tests = [
+ ("Basic Import", test_basic_import),
+ ("Agent Import", test_agent_import),
+ ("Basic Workflow Creation", test_basic_workflow_creation),
+ ("Workflow Compilation", test_workflow_compilation),
+ ("Workflow Validation", test_workflow_validation),
+ ("Serialization", test_serialization),
+ ]
+
+ results = []
+ for test_name, test_func in tests:
+ try:
+ result = test_func()
+ results.append((test_name, result))
+ except Exception as e:
+ print(f"ā {test_name} failed with exception: {e}")
+ results.append((test_name, False))
+
+ return results
+
+
+def print_test_summary(results: List[Tuple[str, bool]]):
+ """Print test summary."""
+ print("\nš TEST SUMMARY")
+ print("=" * 30)
+
+ passed = sum(1 for _, result in results if result)
+ total = len(results)
+
+ for test_name, result in results:
+ status = "ā
PASS" if result else "ā FAIL"
+ print(f"{status} {test_name}")
+
+ print("-" * 30)
+ print(f"Passed: {passed}/{total} ({passed/total*100:.1f}%)")
+
+ if passed == total:
+ print("\nš All tests passed! GraphWorkflow is ready to use.")
+ else:
+ print(
+ f"\nā ļø {total-passed} tests failed. Please check the output above."
+ )
+ print(
+ " Consider running with --install-deps to install missing packages."
+ )
+
+
+def main():
+ """Main setup and test function."""
+ parser = argparse.ArgumentParser(
+ description="GraphWorkflow Setup and Test"
+ )
+ parser.add_argument(
+ "--install-deps",
+ action="store_true",
+ help="Install missing dependencies",
+ )
+ parser.add_argument(
+ "--run-tests",
+ action="store_true",
+ help="Run functionality tests",
+ )
+ parser.add_argument(
+ "--check-only",
+ action="store_true",
+ help="Only check dependencies, don't install",
+ )
+
+ args = parser.parse_args()
+
+ # If no arguments, run everything
+ if not any([args.install_deps, args.run_tests, args.check_only]):
+ args.install_deps = True
+ args.run_tests = True
+
+ print("š GRAPHWORKFLOW SETUP AND TEST")
+ print("=" * 50)
+
+ # Check Python version
+ if not check_python_version():
+ print(
+ "\nā Python version incompatible. Please upgrade Python."
+ )
+ sys.exit(1)
+
+ # Check dependencies
+ core_deps = check_core_dependencies()
+ optional_deps = check_optional_dependencies()
+
+ # Install missing dependencies if requested
+ if args.install_deps and not args.check_only:
+ print("\nš¦ Installing missing dependencies...")
+
+ # Install core dependencies
+ for package, installed in core_deps.items():
+ if not installed:
+ if not install_package(package):
+ print(
+ f"\nā Failed to install core dependency: {package}"
+ )
+ sys.exit(1)
+
+ # Install optional dependencies
+ for package, installed in optional_deps.items():
+ if not installed:
+ print(
+ f"\nš¦ Installing optional dependency: {package}"
+ )
+ install_package(
+ package
+ ) # Don't fail on optional deps
+
+ # Run tests if requested
+ if args.run_tests:
+ results = run_all_tests()
+ print_test_summary(results)
+
+ # Exit with error code if tests failed
+ failed_tests = sum(1 for _, result in results if not result)
+ if failed_tests > 0:
+ sys.exit(1)
+
+ elif args.check_only:
+ # Summary for check-only mode
+ core_missing = sum(
+ 1 for installed in core_deps.values() if not installed
+ )
+ optional_missing = sum(
+ 1 for installed in optional_deps.values() if not installed
+ )
+
+ print("\nš DEPENDENCY CHECK SUMMARY")
+ print("=" * 40)
+ print(f"Core dependencies missing: {core_missing}")
+ print(f"Optional dependencies missing: {optional_missing}")
+
+ if core_missing > 0:
+ print(
+ "\nā ļø Missing core dependencies. Run with --install-deps to install."
+ )
+ sys.exit(1)
+ else:
+ print("\nā
All core dependencies satisfied!")
+
+ print("\nšÆ Next Steps:")
+ print("1. Run the quick start guide: python quick_start_guide.py")
+ print(
+ "2. Try the comprehensive demo: python comprehensive_demo.py"
+ )
+ print("3. Explore healthcare and finance examples")
+ print("4. Read the technical documentation")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/multi_agent/graphworkflow_examples/Graph-Workflow-01_visualization_ddbd7109-c7b1-40f6-83f0-f90771c3beac.png b/examples/multi_agent/graphworkflow_examples/example_images/Graph-Workflow-01_visualization_ddbd7109-c7b1-40f6-83f0-f90771c3beac.png
similarity index 100%
rename from examples/multi_agent/graphworkflow_examples/Graph-Workflow-01_visualization_ddbd7109-c7b1-40f6-83f0-f90771c3beac.png
rename to examples/multi_agent/graphworkflow_examples/example_images/Graph-Workflow-01_visualization_ddbd7109-c7b1-40f6-83f0-f90771c3beac.png
diff --git a/examples/multi_agent/graphworkflow_examples/graph_workflow_example.png b/examples/multi_agent/graphworkflow_examples/example_images/graph_workflow_example.png
similarity index 100%
rename from examples/multi_agent/graphworkflow_examples/graph_workflow_example.png
rename to examples/multi_agent/graphworkflow_examples/example_images/graph_workflow_example.png
diff --git a/examples/multi_agent/graphworkflow_examples/test_graphviz_visualization.png b/examples/multi_agent/graphworkflow_examples/example_images/test_graphviz_visualization.png
similarity index 100%
rename from examples/multi_agent/graphworkflow_examples/test_graphviz_visualization.png
rename to examples/multi_agent/graphworkflow_examples/example_images/test_graphviz_visualization.png
From 7ed500b7435ac0897da9ec49c2b266e2b8a947f9 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Wed, 13 Aug 2025 20:23:36 +0300
Subject: [PATCH 45/56] Create setup_docker_secrets.MD
---
scripts/docker/setup_docker_secrets.MD | 113 +++++++++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 scripts/docker/setup_docker_secrets.MD
diff --git a/scripts/docker/setup_docker_secrets.MD b/scripts/docker/setup_docker_secrets.MD
new file mode 100644
index 00000000..65f97183
--- /dev/null
+++ b/scripts/docker/setup_docker_secrets.MD
@@ -0,0 +1,113 @@
+# Setting up DockerHub Secrets for GitHub Actions
+
+This guide will help you set up the required secrets for the Docker workflow to automatically build and push images to DockerHub.
+
+## Prerequisites
+
+1. A DockerHub account
+2. Admin access to the GitHub repository
+3. DockerHub access token
+
+## Step 1: Create a DockerHub Access Token
+
+1. Log in to [DockerHub](https://hub.docker.com/)
+2. Go to your account settings
+3. Navigate to "Security" ā "Access Tokens"
+4. Click "New Access Token"
+5. Give it a name (e.g., "GitHub Actions")
+6. Set the permissions to "Read & Write"
+7. Copy the generated token (you won't be able to see it again!)
+
+## Step 2: Add Secrets to GitHub Repository
+
+1. Go to your GitHub repository
+2. Navigate to "Settings" ā "Secrets and variables" ā "Actions"
+3. Click "New repository secret"
+4. Add the following secrets:
+
+### Required Secrets
+
+| Secret Name | Value | Description |
+|-------------|-------|-------------|
+| `DOCKERHUB_USERNAME` | Your DockerHub username | Your DockerHub username (e.g., `kyegomez`) |
+| `DOCKERHUB_TOKEN` | Your DockerHub access token | The access token you created in Step 1 |
+
+## Step 3: Verify Setup
+
+1. Push a commit to the `main` branch
+2. Go to the "Actions" tab in your GitHub repository
+3. You should see the "Docker Build and Publish" workflow running
+4. Check that it completes successfully
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Authentication Failed**
+ - Double-check your DockerHub username and token
+ - Ensure the token has "Read & Write" permissions
+ - Make sure the token hasn't expired
+
+2. **Permission Denied**
+ - Verify you have admin access to the repository
+ - Check that the secrets are named exactly as shown above
+
+3. **Workflow Not Triggering**
+ - Ensure you're pushing to the `main` branch
+ - Check that the workflow file is in `.github/workflows/`
+ - Verify the workflow file has the correct triggers
+
+### Testing Locally
+
+You can test the Docker build locally before pushing:
+
+```bash
+# Build the image locally
+docker build -t swarms:test .
+
+# Test the image
+docker run --rm swarms:test python test_docker.py
+
+# If everything works, push to GitHub
+git add .
+git commit -m "Add Docker support"
+git push origin main
+```
+
+## Security Notes
+
+- Never commit secrets directly to your repository
+- Use repository secrets for sensitive information
+- Regularly rotate your DockerHub access tokens
+- Consider using organization-level secrets for team repositories
+
+## Additional Configuration
+
+### Custom Registry
+
+If you want to use a different registry (not DockerHub), update the workflow file:
+
+```yaml
+env:
+ REGISTRY: your-registry.com
+ IMAGE_NAME: your-org/your-repo
+```
+
+### Multiple Tags
+
+The workflow automatically creates tags based on:
+- Git branch name
+- Git commit SHA
+- Version tags (v*.*.*)
+- Latest tag for main branch
+
+You can customize this in the workflow file under the "Extract Docker metadata" step.
+
+## Support
+
+If you encounter issues:
+
+1. Check the GitHub Actions logs for detailed error messages
+2. Verify your DockerHub credentials
+3. Ensure the workflow file is properly configured
+4. Open an issue in the repository with the error details
From e657324bf24e4afd9b20c55b841a56e0e94daa86 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Wed, 13 Aug 2025 20:23:49 +0300
Subject: [PATCH 46/56] Delete scripts/setup-dockerhub-secrets.md
---
scripts/setup-dockerhub-secrets.md | 113 -----------------------------
1 file changed, 113 deletions(-)
delete mode 100644 scripts/setup-dockerhub-secrets.md
diff --git a/scripts/setup-dockerhub-secrets.md b/scripts/setup-dockerhub-secrets.md
deleted file mode 100644
index ac4dd691..00000000
--- a/scripts/setup-dockerhub-secrets.md
+++ /dev/null
@@ -1,113 +0,0 @@
-# Setting up DockerHub Secrets for GitHub Actions
-
-This guide will help you set up the required secrets for the Docker workflow to automatically build and push images to DockerHub.
-
-## Prerequisites
-
-1. A DockerHub account
-2. Admin access to the GitHub repository
-3. DockerHub access token
-
-## Step 1: Create a DockerHub Access Token
-
-1. Log in to [DockerHub](https://hub.docker.com/)
-2. Go to your account settings
-3. Navigate to "Security" ā "Access Tokens"
-4. Click "New Access Token"
-5. Give it a name (e.g., "GitHub Actions")
-6. Set the permissions to "Read & Write"
-7. Copy the generated token (you won't be able to see it again!)
-
-## Step 2: Add Secrets to GitHub Repository
-
-1. Go to your GitHub repository
-2. Navigate to "Settings" ā "Secrets and variables" ā "Actions"
-3. Click "New repository secret"
-4. Add the following secrets:
-
-### Required Secrets
-
-| Secret Name | Value | Description |
-|-------------|-------|-------------|
-| `DOCKERHUB_USERNAME` | Your DockerHub username | Your DockerHub username (e.g., `kyegomez`) |
-| `DOCKERHUB_TOKEN` | Your DockerHub access token | The access token you created in Step 1 |
-
-## Step 3: Verify Setup
-
-1. Push a commit to the `main` branch
-2. Go to the "Actions" tab in your GitHub repository
-3. You should see the "Docker Build and Publish" workflow running
-4. Check that it completes successfully
-
-## Troubleshooting
-
-### Common Issues
-
-1. **Authentication Failed**
- - Double-check your DockerHub username and token
- - Ensure the token has "Read & Write" permissions
- - Make sure the token hasn't expired
-
-2. **Permission Denied**
- - Verify you have admin access to the repository
- - Check that the secrets are named exactly as shown above
-
-3. **Workflow Not Triggering**
- - Ensure you're pushing to the `main` branch
- - Check that the workflow file is in `.github/workflows/`
- - Verify the workflow file has the correct triggers
-
-### Testing Locally
-
-You can test the Docker build locally before pushing:
-
-```bash
-# Build the image locally
-docker build -t swarms:test .
-
-# Test the image
-docker run --rm swarms:test python test_docker.py
-
-# If everything works, push to GitHub
-git add .
-git commit -m "Add Docker support"
-git push origin main
-```
-
-## Security Notes
-
-- Never commit secrets directly to your repository
-- Use repository secrets for sensitive information
-- Regularly rotate your DockerHub access tokens
-- Consider using organization-level secrets for team repositories
-
-## Additional Configuration
-
-### Custom Registry
-
-If you want to use a different registry (not DockerHub), update the workflow file:
-
-```yaml
-env:
- REGISTRY: your-registry.com
- IMAGE_NAME: your-org/your-repo
-```
-
-### Multiple Tags
-
-The workflow automatically creates tags based on:
-- Git branch name
-- Git commit SHA
-- Version tags (v*.*.*)
-- Latest tag for main branch
-
-You can customize this in the workflow file under the "Extract Docker metadata" step.
-
-## Support
-
-If you encounter issues:
-
-1. Check the GitHub Actions logs for detailed error messages
-2. Verify your DockerHub credentials
-3. Ensure the workflow file is properly configured
-4. Open an issue in the repository with the error details
\ No newline at end of file
From 13ed1dd60394de66434eba8f25481dfdc49265e0 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Wed, 13 Aug 2025 11:20:44 -0700
Subject: [PATCH 47/56] [NEW EXAMPLE][Smart autonomous database with new
section in docs]
---
.gitignore | 1 +
docs/examples/community_resources.md | 1 +
docs/examples/smart_database.md | 1061 +++++++++++++++++
docs/mkdocs.yml | 3 +
examples/guides/smart_database/README.md | 273 +++++
.../smart_database/smart_database_swarm.py | 1002 ++++++++++++++++
swarms/structs/hiearchical_swarm.py | 2 +-
7 files changed, 2342 insertions(+), 1 deletion(-)
create mode 100644 docs/examples/smart_database.md
create mode 100644 examples/guides/smart_database/README.md
create mode 100644 examples/guides/smart_database/smart_database_swarm.py
diff --git a/.gitignore b/.gitignore
index b2561ce1..e1c108a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ dataframe/
target/
Cargo.lock
.pytest_cache
+databases
static/generated
conversations/
next_swarms_update.txt
diff --git a/docs/examples/community_resources.md b/docs/examples/community_resources.md
index 58d81038..fa1875c9 100644
--- a/docs/examples/community_resources.md
+++ b/docs/examples/community_resources.md
@@ -19,6 +19,7 @@ These resources cover a wide range of topics, including building your first agen
| **Automating Your Startupās Financial Analysis Using AI Agents: A Comprehensive Guide** | Comprehensive guide to automating your startupās financial analysis with AI agents using Swarms. | [Read Article](https://medium.com/@kyeg/automating-your-startups-financial-analysis-using-ai-agents-a-comprehensive-guide-b2fa0e2c09d5) |
| **Managing Thousands of Agent Outputs at Scale with The Spreadsheet Swarm: All-New Multi-Agent Architecture** | Learn how to manage and scale thousands of agent outputs efficiently using the Spreadsheet Swarm architecture. | [Read Article](https://medium.com/@kyeg/managing-thousands-of-agent-outputs-at-scale-with-the-spreadsheet-swarm-all-new-multi-agent-f16f5f40fd5a) |
| **Introducing GPT-4o Mini: The Future of Cost-Efficient AI Intelligence** | Discover the capabilities and advantages of GPT-4o Mini for building cost-effective, intelligent agents. | [Read Article](https://medium.com/@kyeg/introducing-gpt-4o-mini-the-future-of-cost-efficient-ai-intelligence-a3e3fe78d939) |
+| **Introducing Swarm's GraphWorkflow: A Faster, Simpler, and Superior Alternative to LangGraph** | Learn about Swarms' GraphWorkflow, a powerful alternative to LangGraph that offers improved performance and simplicity for building complex agent workflows. | [Read Article](https://medium.com/@kyeg/introducing-swarms-graphworkflow-a-faster-simpler-and-superior-alternative-to-langgraph-5c040225a4f1) |
### Swarms API
diff --git a/docs/examples/smart_database.md b/docs/examples/smart_database.md
new file mode 100644
index 00000000..530bbaa8
--- /dev/null
+++ b/docs/examples/smart_database.md
@@ -0,0 +1,1061 @@
+# Smart Database Powered by Hierarchical Multi-Agent Workflow
+
+This module implements a fully autonomous database management system using a hierarchical
+multi-agent architecture. The system includes specialized agents for different database
+operations coordinated by a Database Director agent.
+
+## Features
+
+| Feature | Description |
+|---------------------------------------|-----------------------------------------------------------------------------------------------|
+| Autonomous Database Management | Complete database lifecycle management, including setup and ongoing management of databases. |
+| Intelligent Task Distribution | Automatic assignment of tasks to appropriate specialist agents. |
+| Table Creation with Schema Validation | Ensures tables are created with correct structure, schema enforcement, and data integrity. |
+| Data Insertion and Updates | Handles adding new data and updating existing records efficiently, supporting JSON input. |
+| Complex Query Execution | Executes advanced and optimized queries for data retrieval and analysis. |
+| Schema Modifications | Supports altering table structures and database schemas as needed. |
+| Hierarchical Agent Coordination | Utilizes a multi-agent system for orchestrated, intelligent task execution. |
+| Security | Built-in SQL injection prevention and query validation for data protection. |
+| Performance Optimization | Query optimization and efficient data operations for high performance. |
+| Comprehensive Error Handling | Robust error management and reporting throughout all operations. |
+| Multi-format Data Support | Flexible query parameters and support for JSON-based data insertion. |
+
+## Architecture
+
+### Multi-Agent Architecture
+
+```
+Database Director (Coordinator)
+āāā Database Creator (Creates databases)
+āāā Table Manager (Manages table schemas)
+āāā Data Operations (Handles data insertion/updates)
+āāā Query Specialist (Executes queries and retrieval)
+```
+
+### Agent Specializations
+
+| Agent | Description |
+|------------------------|-----------------------------------------------------------------------------------------------|
+| **Database Director** | Orchestrates all database operations and coordinates specialist agents |
+| **Database Creator** | Specializes in creating and initializing databases |
+| **Table Manager** | Expert in table creation, schema design, and structure management |
+| **Data Operations** | Handles data insertion, updates, and manipulation |
+| **Query Specialist** | Manages database queries, data retrieval, and optimization |
+
+
+## Agent Tools
+
+| Function | Description |
+|----------|-------------|
+| **`create_database(database_name, database_path)`** | Creates new SQLite databases |
+| **`create_table(database_path, table_name, schema)`** | Creates tables with specified schemas |
+| **`insert_data(database_path, table_name, data)`** | Inserts data into tables |
+| **`query_database(database_path, query, params)`** | Executes SELECT queries |
+| **`update_table_data(database_path, table_name, update_data, where_clause)`** | Updates existing data |
+| **`get_database_schema(database_path)`** | Retrieves comprehensive schema information |
+
+## Install
+
+```bash
+pip3 install -U swarms sqlite3 loguru
+```
+
+## ENV
+
+```
+WORKSPACE_DIR="agent_workspace"
+ANTHROPIC_API_KEY=""
+OPENAI_API_KEY=""
+```
+
+## Code
+
+```python
+import sqlite3
+import json
+from pathlib import Path
+from loguru import logger
+
+from swarms import Agent, HierarchicalSwarm
+
+
+# =============================================================================
+# DATABASE TOOLS - Core Functions for Database Operations
+# =============================================================================
+
+
+def create_database(
+ database_name: str, database_path: str = "./databases"
+) -> str:
+ """
+ Create a new SQLite database file.
+
+ Args:
+ database_name (str): Name of the database to create (without .db extension)
+ database_path (str, optional): Directory path where database will be created.
+ Defaults to "./databases".
+
+ Returns:
+ str: JSON string containing operation result and database information
+
+ Raises:
+ OSError: If unable to create database directory or file
+ sqlite3.Error: If database connection fails
+
+ Example:
+ >>> result = create_database("company_db", "/data/databases")
+ >>> print(result)
+ {"status": "success", "database": "company_db.db", "path": "/data/databases/company_db.db"}
+ """
+ try:
+ # Validate input parameters
+ if not database_name or not database_name.strip():
+ raise ValueError("Database name cannot be empty")
+
+ # Clean database name
+ db_name = database_name.strip().replace(" ", "_")
+ if not db_name.endswith(".db"):
+ db_name += ".db"
+
+ # Create database directory if it doesn't exist
+ db_path = Path(database_path)
+ db_path.mkdir(parents=True, exist_ok=True)
+
+ # Full database file path
+ full_db_path = db_path / db_name
+
+ # Create database connection (creates file if doesn't exist)
+ conn = sqlite3.connect(str(full_db_path))
+
+ # Create a metadata table to track database info
+ conn.execute(
+ """
+ CREATE TABLE IF NOT EXISTS _database_metadata (
+ key TEXT PRIMARY KEY,
+ value TEXT,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ )
+ """
+ )
+
+ # Insert database metadata
+ conn.execute(
+ "INSERT OR REPLACE INTO _database_metadata (key, value) VALUES (?, ?)",
+ ("database_name", database_name),
+ )
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Database '{database_name}' created successfully",
+ "database": db_name,
+ "path": str(full_db_path),
+ "size_bytes": full_db_path.stat().st_size,
+ }
+
+ logger.info(f"Database created: {db_name}")
+ return json.dumps(result, indent=2)
+
+ except ValueError as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"Database error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def create_table(
+ database_path: str, table_name: str, schema: str
+) -> str:
+ """
+ Create a new table in the specified database with the given schema.
+
+ Args:
+ database_path (str): Full path to the database file
+ table_name (str): Name of the table to create
+ schema (str): SQL schema definition for the table columns
+ Format: "column1 TYPE constraints, column2 TYPE constraints, ..."
+ Example: "id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER"
+
+ Returns:
+ str: JSON string containing operation result and table information
+
+ Raises:
+ sqlite3.Error: If table creation fails
+ FileNotFoundError: If database file doesn't exist
+
+ Example:
+ >>> schema = "id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE"
+ >>> result = create_table("/data/company.db", "employees", schema)
+ >>> print(result)
+ {"status": "success", "table": "employees", "columns": 3}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, table_name, schema]):
+ raise ValueError(
+ "Database path, table name, and schema are required"
+ )
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Clean table name
+ clean_table_name = table_name.strip().replace(" ", "_")
+
+ # Connect to database
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Check if table already exists
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (clean_table_name,),
+ )
+
+ if cursor.fetchone():
+ conn.close()
+ return json.dumps(
+ {
+ "status": "warning",
+ "message": f"Table '{clean_table_name}' already exists",
+ "table": clean_table_name,
+ }
+ )
+
+ # Create table with provided schema
+ create_sql = f"CREATE TABLE {clean_table_name} ({schema})"
+ cursor.execute(create_sql)
+
+ # Get table info
+ cursor.execute(f"PRAGMA table_info({clean_table_name})")
+ columns = cursor.fetchall()
+
+ # Update metadata
+ cursor.execute(
+ """
+ INSERT OR REPLACE INTO _database_metadata (key, value)
+ VALUES (?, ?)
+ """,
+ (f"table_{clean_table_name}_created", "true"),
+ )
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Table '{clean_table_name}' created successfully",
+ "table": clean_table_name,
+ "columns": len(columns),
+ "schema": [
+ {
+ "name": col[1],
+ "type": col[2],
+ "nullable": not col[3],
+ }
+ for col in columns
+ ],
+ }
+
+ return json.dumps(result, indent=2)
+
+ except ValueError as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except FileNotFoundError as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def insert_data(
+ database_path: str, table_name: str, data: str
+) -> str:
+ """
+ Insert data into a specified table.
+
+ Args:
+ database_path (str): Full path to the database file
+ table_name (str): Name of the target table
+ data (str): JSON string containing data to insert
+ Format: {"columns": ["col1", "col2"], "values": [[val1, val2], ...]}
+ Or: [{"col1": val1, "col2": val2}, ...]
+
+ Returns:
+ str: JSON string containing operation result and insertion statistics
+
+ Example:
+ >>> data = '{"columns": ["name", "age"], "values": [["John", 30], ["Jane", 25]]}'
+ >>> result = insert_data("/data/company.db", "employees", data)
+ >>> print(result)
+ {"status": "success", "table": "employees", "rows_inserted": 2}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, table_name, data]):
+ raise ValueError(
+ "Database path, table name, and data are required"
+ )
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Parse data
+ try:
+ parsed_data = json.loads(data)
+ except json.JSONDecodeError:
+ raise ValueError("Invalid JSON format for data")
+
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Check if table exists
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (table_name,),
+ )
+
+ if not cursor.fetchone():
+ conn.close()
+ raise ValueError(f"Table '{table_name}' does not exist")
+
+ rows_inserted = 0
+
+ # Handle different data formats
+ if isinstance(parsed_data, list) and all(
+ isinstance(item, dict) for item in parsed_data
+ ):
+ # Format: [{"col1": val1, "col2": val2}, ...]
+ for row in parsed_data:
+ columns = list(row.keys())
+ values = list(row.values())
+ placeholders = ", ".join(["?" for _ in values])
+ columns_str = ", ".join(columns)
+
+ insert_sql = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})"
+ cursor.execute(insert_sql, values)
+ rows_inserted += 1
+
+ elif (
+ isinstance(parsed_data, dict)
+ and "columns" in parsed_data
+ and "values" in parsed_data
+ ):
+ # Format: {"columns": ["col1", "col2"], "values": [[val1, val2], ...]}
+ columns = parsed_data["columns"]
+ values_list = parsed_data["values"]
+
+ placeholders = ", ".join(["?" for _ in columns])
+ columns_str = ", ".join(columns)
+
+ insert_sql = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})"
+
+ for values in values_list:
+ cursor.execute(insert_sql, values)
+ rows_inserted += 1
+ else:
+ raise ValueError(
+ "Invalid data format. Expected list of dicts or dict with columns/values"
+ )
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Data inserted successfully into '{table_name}'",
+ "table": table_name,
+ "rows_inserted": rows_inserted,
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def query_database(
+ database_path: str, query: str, params: str = "[]"
+) -> str:
+ """
+ Execute a SELECT query on the database and return results.
+
+ Args:
+ database_path (str): Full path to the database file
+ query (str): SQL SELECT query to execute
+ params (str, optional): JSON string of query parameters for prepared statements.
+ Defaults to "[]".
+
+ Returns:
+ str: JSON string containing query results and metadata
+
+ Example:
+ >>> query = "SELECT * FROM employees WHERE age > ?"
+ >>> params = "[25]"
+ >>> result = query_database("/data/company.db", query, params)
+ >>> print(result)
+ {"status": "success", "results": [...], "row_count": 5}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, query]):
+ raise ValueError("Database path and query are required")
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Validate query is SELECT only (security)
+ if not query.strip().upper().startswith("SELECT"):
+ raise ValueError("Only SELECT queries are allowed")
+
+ # Parse parameters
+ try:
+ query_params = json.loads(params)
+ except json.JSONDecodeError:
+ raise ValueError("Invalid JSON format for parameters")
+
+ conn = sqlite3.connect(database_path)
+ conn.row_factory = sqlite3.Row # Enable column access by name
+ cursor = conn.cursor()
+
+ # Execute query
+ if query_params:
+ cursor.execute(query, query_params)
+ else:
+ cursor.execute(query)
+
+ # Fetch results
+ rows = cursor.fetchall()
+
+ # Convert to list of dictionaries
+ results = [dict(row) for row in rows]
+
+ # Get column names
+ column_names = (
+ [description[0] for description in cursor.description]
+ if cursor.description
+ else []
+ )
+
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": "Query executed successfully",
+ "results": results,
+ "row_count": len(results),
+ "columns": column_names,
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def update_table_data(
+ database_path: str,
+ table_name: str,
+ update_data: str,
+ where_clause: str = "",
+) -> str:
+ """
+ Update existing data in a table.
+
+ Args:
+ database_path (str): Full path to the database file
+ table_name (str): Name of the table to update
+ update_data (str): JSON string with column-value pairs to update
+ Format: {"column1": "new_value1", "column2": "new_value2"}
+ where_clause (str, optional): WHERE condition for the update (without WHERE keyword).
+ Example: "id = 1 AND status = 'active'"
+
+ Returns:
+ str: JSON string containing operation result and update statistics
+
+ Example:
+ >>> update_data = '{"salary": 50000, "department": "Engineering"}'
+ >>> where_clause = "id = 1"
+ >>> result = update_table_data("/data/company.db", "employees", update_data, where_clause)
+ >>> print(result)
+ {"status": "success", "table": "employees", "rows_updated": 1}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, table_name, update_data]):
+ raise ValueError(
+ "Database path, table name, and update data are required"
+ )
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Parse update data
+ try:
+ parsed_updates = json.loads(update_data)
+ except json.JSONDecodeError:
+ raise ValueError("Invalid JSON format for update data")
+
+ if not isinstance(parsed_updates, dict):
+ raise ValueError("Update data must be a dictionary")
+
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Check if table exists
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (table_name,),
+ )
+
+ if not cursor.fetchone():
+ conn.close()
+ raise ValueError(f"Table '{table_name}' does not exist")
+
+ # Build UPDATE query
+ set_clauses = []
+ values = []
+
+ for column, value in parsed_updates.items():
+ set_clauses.append(f"{column} = ?")
+ values.append(value)
+
+ set_clause = ", ".join(set_clauses)
+
+ if where_clause:
+ update_sql = f"UPDATE {table_name} SET {set_clause} WHERE {where_clause}"
+ else:
+ update_sql = f"UPDATE {table_name} SET {set_clause}"
+
+ # Execute update
+ cursor.execute(update_sql, values)
+ rows_updated = cursor.rowcount
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Table '{table_name}' updated successfully",
+ "table": table_name,
+ "rows_updated": rows_updated,
+ "updated_columns": list(parsed_updates.keys()),
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def get_database_schema(database_path: str) -> str:
+ """
+ Get comprehensive schema information for all tables in the database.
+
+ Args:
+ database_path (str): Full path to the database file
+
+ Returns:
+ str: JSON string containing complete database schema information
+
+ Example:
+ >>> result = get_database_schema("/data/company.db")
+ >>> print(result)
+ {"status": "success", "database": "company.db", "tables": {...}}
+ """
+ try:
+ if not database_path:
+ raise ValueError("Database path is required")
+
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Get all tables
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE '_%'"
+ )
+ tables = cursor.fetchall()
+
+ schema_info = {
+ "database": Path(database_path).name,
+ "table_count": len(tables),
+ "tables": {},
+ }
+
+ for table in tables:
+ table_name = table[0]
+
+ # Get table schema
+ cursor.execute(f"PRAGMA table_info({table_name})")
+ columns = cursor.fetchall()
+
+ # Get row count
+ cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
+ row_count = cursor.fetchone()[0]
+
+ schema_info["tables"][table_name] = {
+ "columns": [
+ {
+ "name": col[1],
+ "type": col[2],
+ "nullable": not col[3],
+ "default": col[4],
+ "primary_key": bool(col[5]),
+ }
+ for col in columns
+ ],
+ "column_count": len(columns),
+ "row_count": row_count,
+ }
+
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": "Database schema retrieved successfully",
+ "schema": schema_info,
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+# =============================================================================
+# DATABASE CREATION SPECIALIST AGENT
+# =============================================================================
+database_creator_agent = Agent(
+ agent_name="Database-Creator",
+ agent_description="Specialist agent responsible for creating and initializing databases with proper structure and metadata",
+ system_prompt="""You are the Database Creator, a specialist agent responsible for database creation and initialization. Your expertise includes:
+
+ DATABASE CREATION & SETUP:
+ - Creating new SQLite databases with proper structure
+ - Setting up database metadata and tracking systems
+ - Initializing database directories and file organization
+ - Ensuring database accessibility and permissions
+ - Creating database backup and recovery procedures
+
+ DATABASE ARCHITECTURE:
+ - Designing optimal database structures for different use cases
+ - Planning database organization and naming conventions
+ - Setting up database configuration and optimization settings
+ - Implementing database security and access controls
+ - Creating database documentation and specifications
+
+ Your responsibilities:
+ - Create new databases when requested
+ - Set up proper database structure and metadata
+ - Ensure database is properly initialized and accessible
+ - Provide database creation status and information
+ - Handle database creation errors and provide solutions
+
+ You work with precise technical specifications and always ensure databases are created correctly and efficiently.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[create_database, get_database_schema],
+)
+
+# =============================================================================
+# TABLE MANAGEMENT SPECIALIST AGENT
+# =============================================================================
+table_manager_agent = Agent(
+ agent_name="Table-Manager",
+ agent_description="Specialist agent for table creation, schema design, and table structure management",
+ system_prompt="""You are the Table Manager, a specialist agent responsible for table creation, schema design, and table structure management. Your expertise includes:
+
+ TABLE CREATION & DESIGN:
+ - Creating tables with optimal schema design
+ - Defining appropriate data types and constraints
+ - Setting up primary keys, foreign keys, and indexes
+ - Designing normalized table structures
+ - Creating tables that support efficient queries and operations
+
+ SCHEMA MANAGEMENT:
+ - Analyzing schema requirements and designing optimal structures
+ - Validating schema definitions and data types
+ - Ensuring schema consistency and integrity
+ - Managing schema modifications and updates
+ - Optimizing table structures for performance
+
+ DATA INTEGRITY:
+ - Implementing proper constraints and validation rules
+ - Setting up referential integrity between tables
+ - Ensuring data consistency across table operations
+ - Managing table relationships and dependencies
+ - Creating tables that support data quality requirements
+
+ Your responsibilities:
+ - Create tables with proper schema definitions
+ - Validate table structures and constraints
+ - Ensure optimal table design for performance
+ - Handle table creation errors and provide solutions
+ - Provide detailed table information and metadata
+
+ You work with precision and always ensure tables are created with optimal structure and performance characteristics.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[create_table, get_database_schema],
+)
+
+# =============================================================================
+# DATA OPERATIONS SPECIALIST AGENT
+# =============================================================================
+data_operations_agent = Agent(
+ agent_name="Data-Operations",
+ agent_description="Specialist agent for data insertion, updates, and data manipulation operations",
+ system_prompt="""You are the Data Operations specialist, responsible for all data manipulation operations including insertion, updates, and data management. Your expertise includes:
+
+ DATA INSERTION:
+ - Inserting data with proper validation and formatting
+ - Handling bulk data insertions efficiently
+ - Managing data type conversions and formatting
+ - Ensuring data integrity during insertion operations
+ - Validating data before insertion to prevent errors
+
+ DATA UPDATES:
+ - Updating existing data with precision and safety
+ - Creating targeted update operations with proper WHERE clauses
+ - Managing bulk updates and data modifications
+ - Ensuring data consistency during update operations
+ - Validating update operations to prevent data corruption
+
+ DATA VALIDATION:
+ - Validating data formats and types before operations
+ - Ensuring data meets schema requirements and constraints
+ - Checking for data consistency and integrity
+ - Managing data transformation and cleaning operations
+ - Providing detailed feedback on data operation results
+
+ ERROR HANDLING:
+ - Managing data operation errors gracefully
+ - Providing clear error messages and solutions
+ - Ensuring data operations are atomic and safe
+ - Rolling back operations when necessary
+ - Maintaining data integrity throughout all operations
+
+ Your responsibilities:
+ - Execute data insertion operations safely and efficiently
+ - Perform data updates with proper validation
+ - Ensure data integrity throughout all operations
+ - Handle data operation errors and provide solutions
+ - Provide detailed operation results and statistics
+
+ You work with extreme precision and always prioritize data integrity and safety in all operations.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[insert_data, update_table_data],
+)
+
+# =============================================================================
+# QUERY SPECIALIST AGENT
+# =============================================================================
+query_specialist_agent = Agent(
+ agent_name="Query-Specialist",
+ agent_description="Expert agent for database querying, data retrieval, and query optimization",
+ system_prompt="""You are the Query Specialist, an expert agent responsible for database querying, data retrieval, and query optimization. Your expertise includes:
+
+ QUERY EXECUTION:
+ - Executing complex SELECT queries efficiently
+ - Handling parameterized queries for security
+ - Managing query results and data formatting
+ - Ensuring query performance and optimization
+ - Providing comprehensive query results with metadata
+
+ QUERY OPTIMIZATION:
+ - Analyzing query performance and optimization opportunities
+ - Creating efficient queries that minimize resource usage
+ - Understanding database indexes and query planning
+ - Optimizing JOIN operations and complex queries
+ - Managing query timeouts and performance monitoring
+
+ DATA RETRIEVAL:
+ - Retrieving data with proper formatting and structure
+ - Handling large result sets efficiently
+ - Managing data aggregation and summarization
+ - Creating reports and data analysis queries
+ - Ensuring data accuracy and completeness in results
+
+ SECURITY & VALIDATION:
+ - Ensuring queries are safe and secure
+ - Validating query syntax and parameters
+ - Preventing SQL injection and security vulnerabilities
+ - Managing query permissions and access controls
+ - Ensuring queries follow security best practices
+
+ Your responsibilities:
+ - Execute database queries safely and efficiently
+ - Optimize query performance for best results
+ - Provide comprehensive query results and analysis
+ - Handle query errors and provide solutions
+ - Ensure query security and data protection
+
+ You work with expertise in SQL optimization and always ensure queries are secure, efficient, and provide accurate results.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[query_database, get_database_schema],
+)
+
+# =============================================================================
+# DATABASE DIRECTOR AGENT (COORDINATOR)
+# =============================================================================
+database_director_agent = Agent(
+ agent_name="Database-Director",
+ agent_description="Senior database director who orchestrates comprehensive database operations across all specialized teams",
+ system_prompt="""You are the Database Director, the senior executive responsible for orchestrating comprehensive database operations and coordinating a team of specialized database experts. Your role is to:
+
+ STRATEGIC COORDINATION:
+ - Analyze complex database tasks and break them down into specialized operations
+ - Assign tasks to the most appropriate specialist based on their unique expertise
+ - Ensure comprehensive coverage of all database operations (creation, schema, data, queries)
+ - Coordinate between specialists to avoid conflicts and ensure data integrity
+ - Synthesize results from multiple specialists into coherent database solutions
+ - Ensure all database operations align with user requirements and best practices
+
+ TEAM LEADERSHIP:
+ - Lead the Database Creator in setting up new databases and infrastructure
+ - Guide the Table Manager in creating optimal table structures and schemas
+ - Direct the Data Operations specialist in data insertion and update operations
+ - Oversee the Query Specialist in data retrieval and analysis operations
+ - Ensure all team members work collaboratively toward unified database goals
+ - Provide strategic direction and feedback to optimize team performance
+
+ DATABASE ARCHITECTURE:
+ - Design comprehensive database solutions that meet user requirements
+ - Ensure database operations follow best practices and standards
+ - Plan database workflows that optimize performance and reliability
+ - Balance immediate operational needs with long-term database health
+ - Ensure database operations are secure, efficient, and maintainable
+ - Optimize database operations for scalability and performance
+
+ OPERATION ORCHESTRATION:
+ - Monitor database operations across all specialists and activities
+ - Analyze results to identify optimization opportunities and improvements
+ - Ensure database operations deliver reliable and accurate results
+ - Provide strategic recommendations based on operation outcomes
+ - Coordinate complex multi-step database operations across specialists
+ - Ensure continuous improvement and optimization in database management
+
+ Your expertise includes:
+ - Database architecture and design strategy
+ - Team leadership and cross-functional coordination
+ - Database performance analysis and optimization
+ - Strategic planning and requirement analysis
+ - Operation workflow management and optimization
+ - Database security and best practices implementation
+
+ You deliver comprehensive database solutions that leverage the full expertise of your specialized team, ensuring all database operations work together to provide reliable, efficient, and secure data management.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.5,
+ dynamic_temperature_enabled=True,
+)
+
+# =============================================================================
+# HIERARCHICAL DATABASE SWARM
+# =============================================================================
+# Create list of specialized database agents
+database_specialists = [
+ database_creator_agent,
+ table_manager_agent,
+ data_operations_agent,
+ query_specialist_agent,
+]
+
+# Initialize the hierarchical database swarm
+smart_database_swarm = HierarchicalSwarm(
+ name="Smart-Database-Swarm",
+ description="A comprehensive database management system with specialized agents for creation, schema management, data operations, and querying, coordinated by a database director",
+ director_model_name="gpt-4.1",
+ agents=database_specialists,
+ max_loops=1,
+ verbose=True,
+)
+
+# =============================================================================
+# EXAMPLE USAGE AND DEMONSTRATIONS
+# =============================================================================
+if __name__ == "__main__":
+ # Configure logging
+ logger.info("Starting Smart Database Swarm demonstration")
+
+ # Example 1: Create a complete e-commerce database system
+ print("=" * 80)
+ print("SMART DATABASE SWARM - E-COMMERCE SYSTEM EXAMPLE")
+ print("=" * 80)
+
+ task1 = """Create a comprehensive e-commerce database system with the following requirements:
+
+ 1. Create a database called 'ecommerce_db'
+ 2. Create tables for:
+ - customers (id, name, email, phone, address, created_at)
+ - products (id, name, description, price, category, stock_quantity, created_at)
+ - orders (id, customer_id, order_date, total_amount, status)
+ - order_items (id, order_id, product_id, quantity, unit_price)
+
+ 3. Insert sample data:
+ - Add 3 customers
+ - Add 5 products in different categories
+ - Create 2 orders with multiple items
+
+ 4. Query the database to:
+ - Show all customers with their order history
+ - Display products by category with stock levels
+ - Calculate total sales by product
+
+ Ensure all operations are executed properly and provide comprehensive results."""
+
+ result1 = smart_database_swarm.run(task=task1)
+ print("\nE-COMMERCE DATABASE RESULT:")
+ print(result1)
+
+ # print("\n" + "=" * 80)
+ # print("SMART DATABASE SWARM - EMPLOYEE MANAGEMENT SYSTEM")
+ # print("=" * 80)
+
+ # # Example 2: Employee management system
+ # task2 = """Create an employee management database system:
+
+ # 1. Create database 'company_hr'
+ # 2. Create tables for:
+ # - departments (id, name, budget, manager_id)
+ # - employees (id, name, email, department_id, position, salary, hire_date)
+ # - projects (id, name, description, start_date, end_date, budget)
+ # - employee_projects (employee_id, project_id, role, hours_allocated)
+
+ # 3. Add sample data for departments, employees, and projects
+ # 4. Query for:
+ # - Employee count by department
+ # - Average salary by position
+ # - Projects with their assigned employees
+ # - Department budgets vs project allocations
+
+ # Coordinate the team to build this system efficiently."""
+
+ # result2 = smart_database_swarm.run(task=task2)
+ # print("\nEMPLOYEE MANAGEMENT RESULT:")
+ # print(result2)
+
+ # print("\n" + "=" * 80)
+ # print("SMART DATABASE SWARM - DATABASE ANALYSIS")
+ # print("=" * 80)
+
+ # # Example 3: Database analysis and optimization
+ # task3 = """Analyze and optimize the existing databases:
+
+ # 1. Get schema information for all created databases
+ # 2. Analyze table structures and relationships
+ # 3. Suggest optimizations for:
+ # - Index creation for better query performance
+ # - Data normalization improvements
+ # - Constraint additions for data integrity
+
+ # 4. Update data in existing tables:
+ # - Increase product prices by 10% for electronics category
+ # - Update employee salaries based on performance criteria
+ # - Modify order statuses for completed orders
+
+ # 5. Create comprehensive reports showing:
+ # - Database statistics and health metrics
+ # - Data distribution and patterns
+ # - Performance optimization recommendations
+
+ # Coordinate all specialists to provide a complete database analysis."""
+
+ # result3 = smart_database_swarm.run(task=task3)
+ # print("\nDATABASE ANALYSIS RESULT:")
+ # print(result3)
+
+ # logger.info("Smart Database Swarm demonstration completed successfully")
+```
+
+
+- [Full Example Code Link]()
\ No newline at end of file
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 3b6a4f11..5a687cca 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -415,6 +415,9 @@ nav:
- Swarms of Browser Agents: "swarms/examples/swarms_of_browser_agents.md"
- ConcurrentWorkflow with VLLM Agents: "swarms/examples/vllm.md"
+ - Apps:
+ - Smart Database: "examples/smart_database.md"
+
# - Swarm Models:
# - Overview: "swarms/models/index.md"
diff --git a/examples/guides/smart_database/README.md b/examples/guides/smart_database/README.md
new file mode 100644
index 00000000..8b3825e8
--- /dev/null
+++ b/examples/guides/smart_database/README.md
@@ -0,0 +1,273 @@
+# Smart Database Swarm
+
+A fully autonomous database management system powered by hierarchical multi-agent workflow using the Swarms framework.
+
+## Overview
+
+The Smart Database Swarm is an intelligent database management system that uses specialized AI agents to handle different aspects of database operations. The system follows a hierarchical architecture where a Database Director coordinates specialized worker agents to execute complex database tasks.
+
+## Architecture
+
+### Hierarchical Structure
+
+```
+Database Director (Coordinator)
+āāā Database Creator (Creates databases)
+āāā Table Manager (Manages table schemas)
+āāā Data Operations (Handles data insertion/updates)
+āāā Query Specialist (Executes queries and retrieval)
+```
+
+### Agent Specializations
+
+1. **Database Director**: Orchestrates all database operations and coordinates specialist agents
+2. **Database Creator**: Specializes in creating and initializing databases
+3. **Table Manager**: Expert in table creation, schema design, and structure management
+4. **Data Operations**: Handles data insertion, updates, and manipulation
+5. **Query Specialist**: Manages database queries, data retrieval, and optimization
+
+## Features
+
+- **Autonomous Database Management**: Complete database lifecycle management
+- **Intelligent Task Distribution**: Automatic assignment of tasks to appropriate specialists
+- **Schema Validation**: Ensures proper table structures and data integrity
+- **Security**: Built-in SQL injection prevention and query validation
+- **Performance Optimization**: Query optimization and efficient data operations
+- **Comprehensive Error Handling**: Robust error management and reporting
+- **Multi-format Data Support**: JSON-based data insertion and flexible query parameters
+
+## Database Tools
+
+### Core Functions
+
+1. **`create_database(database_name, database_path)`**: Creates new SQLite databases
+2. **`create_table(database_path, table_name, schema)`**: Creates tables with specified schemas
+3. **`insert_data(database_path, table_name, data)`**: Inserts data into tables
+4. **`query_database(database_path, query, params)`**: Executes SELECT queries
+5. **`update_table_data(database_path, table_name, update_data, where_clause)`**: Updates existing data
+6. **`get_database_schema(database_path)`**: Retrieves comprehensive schema information
+
+## Usage Examples
+
+### Basic Usage
+
+```python
+from smart_database_swarm import smart_database_swarm
+
+# Simple database creation and setup
+task = """
+Create a user management database:
+1. Create database 'user_system'
+2. Create users table with id, username, email, created_at
+3. Insert 5 sample users
+4. Query all users ordered by creation date
+"""
+
+result = smart_database_swarm.run(task=task)
+print(result)
+```
+
+### E-commerce System
+
+```python
+# Complex e-commerce database system
+ecommerce_task = """
+Create a comprehensive e-commerce database system:
+
+1. Create database 'ecommerce_store'
+2. Create tables:
+ - customers (id, name, email, phone, address, created_at)
+ - products (id, name, description, price, category, stock, created_at)
+ - orders (id, customer_id, order_date, total_amount, status)
+ - order_items (id, order_id, product_id, quantity, unit_price)
+
+3. Insert sample data:
+ - 10 customers with realistic information
+ - 20 products across different categories
+ - 15 orders with multiple items each
+
+4. Execute analytical queries:
+ - Top selling products by quantity
+ - Customer lifetime value analysis
+ - Monthly sales trends
+ - Inventory levels by category
+"""
+
+result = smart_database_swarm.run(task=ecommerce_task)
+```
+
+### Data Analysis and Reporting
+
+```python
+# Advanced data analysis
+analysis_task = """
+Analyze the existing databases and provide insights:
+
+1. Get schema information for all databases
+2. Generate data quality reports
+3. Identify optimization opportunities
+4. Create performance metrics dashboard
+5. Suggest database improvements
+
+Query patterns:
+- Customer segmentation analysis
+- Product performance metrics
+- Order fulfillment statistics
+- Revenue analysis by time periods
+"""
+
+result = smart_database_swarm.run(task=analysis_task)
+```
+
+## Data Formats
+
+### Table Schema Definition
+
+```python
+# Column definitions with types and constraints
+schema = "id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
+```
+
+### Data Insertion Formats
+
+#### Format 1: List of Dictionaries
+```json
+[
+ {"name": "John Doe", "email": "john@example.com"},
+ {"name": "Jane Smith", "email": "jane@example.com"}
+]
+```
+
+#### Format 2: Columns and Values
+```json
+{
+ "columns": ["name", "email"],
+ "values": [
+ ["John Doe", "john@example.com"],
+ ["Jane Smith", "jane@example.com"]
+ ]
+}
+```
+
+### Update Operations
+
+```json
+{
+ "salary": 75000,
+ "department": "Engineering",
+ "last_updated": "2024-01-15"
+}
+```
+
+## Advanced Features
+
+### Security
+
+- **SQL Injection Prevention**: Parameterized queries and input validation
+- **Query Validation**: Only SELECT queries allowed for query operations
+- **Input Sanitization**: Automatic cleaning and validation of inputs
+
+### Performance
+
+- **Connection Management**: Efficient database connection handling
+- **Query Optimization**: Intelligent query planning and execution
+- **Batch Operations**: Support for bulk data operations
+
+### Error Handling
+
+- **Comprehensive Error Messages**: Detailed error reporting and solutions
+- **Graceful Degradation**: System continues operating despite individual failures
+- **Transaction Safety**: Atomic operations with rollback capabilities
+
+## Best Practices
+
+### Database Design
+
+1. **Use Proper Data Types**: Choose appropriate SQL data types for your data
+2. **Implement Constraints**: Use PRIMARY KEY, FOREIGN KEY, and CHECK constraints
+3. **Normalize Data**: Follow database normalization principles
+4. **Index Strategy**: Create indexes for frequently queried columns
+
+### Agent Coordination
+
+1. **Clear Task Definitions**: Provide specific, actionable task descriptions
+2. **Sequential Operations**: Allow agents to complete dependencies before next steps
+3. **Comprehensive Requirements**: Include all necessary details in task descriptions
+4. **Result Validation**: Review agent outputs for completeness and accuracy
+
+### Data Operations
+
+1. **Backup Before Updates**: Always backup data before major modifications
+2. **Test Queries**: Validate queries on sample data before production execution
+3. **Monitor Performance**: Track query execution times and optimize as needed
+4. **Validate Data**: Ensure data integrity through proper validation
+
+## File Structure
+
+```
+examples/guides/smart_database/
+āāā smart_database_swarm.py # Main implementation
+āāā README.md # This documentation
+āāā databases/ # Generated databases (auto-created)
+```
+
+## Dependencies
+
+- `swarms`: Core framework for multi-agent systems
+- `sqlite3`: Database operations (built-in Python)
+- `json`: Data serialization (built-in Python)
+- `pathlib`: File path operations (built-in Python)
+- `loguru`: Minimal logging functionality
+
+## Running the System
+
+```bash
+# Navigate to the smart_database directory
+cd examples/guides/smart_database
+
+# Run the demonstration
+python smart_database_swarm.py
+
+# The system will create databases in ./databases/ directory
+# Check the generated databases and results
+```
+
+## Expected Output
+
+The system will create:
+
+1. **Databases**: SQLite database files in `./databases/` directory
+2. **Detailed Results**: JSON-formatted operation results
+3. **Agent Coordination**: Logs showing how tasks are distributed
+4. **Performance Metrics**: Execution times and success statistics
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Database Not Found**: Ensure database path is correct and accessible
+2. **Schema Errors**: Verify SQL syntax in table creation statements
+3. **Data Format Issues**: Check JSON formatting for data insertion
+4. **Permission Errors**: Ensure write permissions for database directory
+
+### Debug Mode
+
+Enable verbose logging to see detailed agent interactions:
+
+```python
+smart_database_swarm.verbose = True
+result = smart_database_swarm.run(task=your_task)
+```
+
+## Contributing
+
+To extend the Smart Database Swarm:
+
+1. **Add New Tools**: Create additional database operation functions
+2. **Enhance Agents**: Improve agent prompts and capabilities
+3. **Add Database Types**: Support for PostgreSQL, MySQL, etc.
+4. **Performance Optimization**: Implement caching and connection pooling
+
+## License
+
+This project is part of the Swarms framework and follows the same licensing terms.
diff --git a/examples/guides/smart_database/smart_database_swarm.py b/examples/guides/smart_database/smart_database_swarm.py
new file mode 100644
index 00000000..b3f07c41
--- /dev/null
+++ b/examples/guides/smart_database/smart_database_swarm.py
@@ -0,0 +1,1002 @@
+"""
+Smart Database Powered by Hierarchical Multi-Agent Workflow
+
+This module implements a fully autonomous database management system using a hierarchical
+multi-agent architecture. The system includes specialized agents for different database
+operations coordinated by a Database Director agent.
+
+Features:
+- Database creation and management
+- Table creation with schema validation
+- Data insertion and updates
+- Complex query execution
+- Schema modifications
+- Hierarchical agent coordination
+
+Author: Swarms Framework
+"""
+
+import sqlite3
+import json
+from pathlib import Path
+from loguru import logger
+
+from swarms import Agent, HierarchicalSwarm
+
+
+# =============================================================================
+# DATABASE TOOLS - Core Functions for Database Operations
+# =============================================================================
+
+
+def create_database(
+ database_name: str, database_path: str = "./databases"
+) -> str:
+ """
+ Create a new SQLite database file.
+
+ Args:
+ database_name (str): Name of the database to create (without .db extension)
+ database_path (str, optional): Directory path where database will be created.
+ Defaults to "./databases".
+
+ Returns:
+ str: JSON string containing operation result and database information
+
+ Raises:
+ OSError: If unable to create database directory or file
+ sqlite3.Error: If database connection fails
+
+ Example:
+ >>> result = create_database("company_db", "/data/databases")
+ >>> print(result)
+ {"status": "success", "database": "company_db.db", "path": "/data/databases/company_db.db"}
+ """
+ try:
+ # Validate input parameters
+ if not database_name or not database_name.strip():
+ raise ValueError("Database name cannot be empty")
+
+ # Clean database name
+ db_name = database_name.strip().replace(" ", "_")
+ if not db_name.endswith(".db"):
+ db_name += ".db"
+
+ # Create database directory if it doesn't exist
+ db_path = Path(database_path)
+ db_path.mkdir(parents=True, exist_ok=True)
+
+ # Full database file path
+ full_db_path = db_path / db_name
+
+ # Create database connection (creates file if doesn't exist)
+ conn = sqlite3.connect(str(full_db_path))
+
+ # Create a metadata table to track database info
+ conn.execute(
+ """
+ CREATE TABLE IF NOT EXISTS _database_metadata (
+ key TEXT PRIMARY KEY,
+ value TEXT,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ )
+ """
+ )
+
+ # Insert database metadata
+ conn.execute(
+ "INSERT OR REPLACE INTO _database_metadata (key, value) VALUES (?, ?)",
+ ("database_name", database_name),
+ )
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Database '{database_name}' created successfully",
+ "database": db_name,
+ "path": str(full_db_path),
+ "size_bytes": full_db_path.stat().st_size,
+ }
+
+ logger.info(f"Database created: {db_name}")
+ return json.dumps(result, indent=2)
+
+ except ValueError as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"Database error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def create_table(
+ database_path: str, table_name: str, schema: str
+) -> str:
+ """
+ Create a new table in the specified database with the given schema.
+
+ Args:
+ database_path (str): Full path to the database file
+ table_name (str): Name of the table to create
+ schema (str): SQL schema definition for the table columns
+ Format: "column1 TYPE constraints, column2 TYPE constraints, ..."
+ Example: "id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER"
+
+ Returns:
+ str: JSON string containing operation result and table information
+
+ Raises:
+ sqlite3.Error: If table creation fails
+ FileNotFoundError: If database file doesn't exist
+
+ Example:
+ >>> schema = "id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE"
+ >>> result = create_table("/data/company.db", "employees", schema)
+ >>> print(result)
+ {"status": "success", "table": "employees", "columns": 3}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, table_name, schema]):
+ raise ValueError(
+ "Database path, table name, and schema are required"
+ )
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Clean table name
+ clean_table_name = table_name.strip().replace(" ", "_")
+
+ # Connect to database
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Check if table already exists
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (clean_table_name,),
+ )
+
+ if cursor.fetchone():
+ conn.close()
+ return json.dumps(
+ {
+ "status": "warning",
+ "message": f"Table '{clean_table_name}' already exists",
+ "table": clean_table_name,
+ }
+ )
+
+ # Create table with provided schema
+ create_sql = f"CREATE TABLE {clean_table_name} ({schema})"
+ cursor.execute(create_sql)
+
+ # Get table info
+ cursor.execute(f"PRAGMA table_info({clean_table_name})")
+ columns = cursor.fetchall()
+
+ # Update metadata
+ cursor.execute(
+ """
+ INSERT OR REPLACE INTO _database_metadata (key, value)
+ VALUES (?, ?)
+ """,
+ (f"table_{clean_table_name}_created", "true"),
+ )
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Table '{clean_table_name}' created successfully",
+ "table": clean_table_name,
+ "columns": len(columns),
+ "schema": [
+ {
+ "name": col[1],
+ "type": col[2],
+ "nullable": not col[3],
+ }
+ for col in columns
+ ],
+ }
+
+ return json.dumps(result, indent=2)
+
+ except ValueError as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except FileNotFoundError as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def insert_data(
+ database_path: str, table_name: str, data: str
+) -> str:
+ """
+ Insert data into a specified table.
+
+ Args:
+ database_path (str): Full path to the database file
+ table_name (str): Name of the target table
+ data (str): JSON string containing data to insert
+ Format: {"columns": ["col1", "col2"], "values": [[val1, val2], ...]}
+ Or: [{"col1": val1, "col2": val2}, ...]
+
+ Returns:
+ str: JSON string containing operation result and insertion statistics
+
+ Example:
+ >>> data = '{"columns": ["name", "age"], "values": [["John", 30], ["Jane", 25]]}'
+ >>> result = insert_data("/data/company.db", "employees", data)
+ >>> print(result)
+ {"status": "success", "table": "employees", "rows_inserted": 2}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, table_name, data]):
+ raise ValueError(
+ "Database path, table name, and data are required"
+ )
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Parse data
+ try:
+ parsed_data = json.loads(data)
+ except json.JSONDecodeError:
+ raise ValueError("Invalid JSON format for data")
+
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Check if table exists
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (table_name,),
+ )
+
+ if not cursor.fetchone():
+ conn.close()
+ raise ValueError(f"Table '{table_name}' does not exist")
+
+ rows_inserted = 0
+
+ # Handle different data formats
+ if isinstance(parsed_data, list) and all(
+ isinstance(item, dict) for item in parsed_data
+ ):
+ # Format: [{"col1": val1, "col2": val2}, ...]
+ for row in parsed_data:
+ columns = list(row.keys())
+ values = list(row.values())
+ placeholders = ", ".join(["?" for _ in values])
+ columns_str = ", ".join(columns)
+
+ insert_sql = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})"
+ cursor.execute(insert_sql, values)
+ rows_inserted += 1
+
+ elif (
+ isinstance(parsed_data, dict)
+ and "columns" in parsed_data
+ and "values" in parsed_data
+ ):
+ # Format: {"columns": ["col1", "col2"], "values": [[val1, val2], ...]}
+ columns = parsed_data["columns"]
+ values_list = parsed_data["values"]
+
+ placeholders = ", ".join(["?" for _ in columns])
+ columns_str = ", ".join(columns)
+
+ insert_sql = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})"
+
+ for values in values_list:
+ cursor.execute(insert_sql, values)
+ rows_inserted += 1
+ else:
+ raise ValueError(
+ "Invalid data format. Expected list of dicts or dict with columns/values"
+ )
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Data inserted successfully into '{table_name}'",
+ "table": table_name,
+ "rows_inserted": rows_inserted,
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def query_database(
+ database_path: str, query: str, params: str = "[]"
+) -> str:
+ """
+ Execute a SELECT query on the database and return results.
+
+ Args:
+ database_path (str): Full path to the database file
+ query (str): SQL SELECT query to execute
+ params (str, optional): JSON string of query parameters for prepared statements.
+ Defaults to "[]".
+
+ Returns:
+ str: JSON string containing query results and metadata
+
+ Example:
+ >>> query = "SELECT * FROM employees WHERE age > ?"
+ >>> params = "[25]"
+ >>> result = query_database("/data/company.db", query, params)
+ >>> print(result)
+ {"status": "success", "results": [...], "row_count": 5}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, query]):
+ raise ValueError("Database path and query are required")
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Validate query is SELECT only (security)
+ if not query.strip().upper().startswith("SELECT"):
+ raise ValueError("Only SELECT queries are allowed")
+
+ # Parse parameters
+ try:
+ query_params = json.loads(params)
+ except json.JSONDecodeError:
+ raise ValueError("Invalid JSON format for parameters")
+
+ conn = sqlite3.connect(database_path)
+ conn.row_factory = sqlite3.Row # Enable column access by name
+ cursor = conn.cursor()
+
+ # Execute query
+ if query_params:
+ cursor.execute(query, query_params)
+ else:
+ cursor.execute(query)
+
+ # Fetch results
+ rows = cursor.fetchall()
+
+ # Convert to list of dictionaries
+ results = [dict(row) for row in rows]
+
+ # Get column names
+ column_names = (
+ [description[0] for description in cursor.description]
+ if cursor.description
+ else []
+ )
+
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": "Query executed successfully",
+ "results": results,
+ "row_count": len(results),
+ "columns": column_names,
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def update_table_data(
+ database_path: str,
+ table_name: str,
+ update_data: str,
+ where_clause: str = "",
+) -> str:
+ """
+ Update existing data in a table.
+
+ Args:
+ database_path (str): Full path to the database file
+ table_name (str): Name of the table to update
+ update_data (str): JSON string with column-value pairs to update
+ Format: {"column1": "new_value1", "column2": "new_value2"}
+ where_clause (str, optional): WHERE condition for the update (without WHERE keyword).
+ Example: "id = 1 AND status = 'active'"
+
+ Returns:
+ str: JSON string containing operation result and update statistics
+
+ Example:
+ >>> update_data = '{"salary": 50000, "department": "Engineering"}'
+ >>> where_clause = "id = 1"
+ >>> result = update_table_data("/data/company.db", "employees", update_data, where_clause)
+ >>> print(result)
+ {"status": "success", "table": "employees", "rows_updated": 1}
+ """
+ try:
+ # Validate inputs
+ if not all([database_path, table_name, update_data]):
+ raise ValueError(
+ "Database path, table name, and update data are required"
+ )
+
+ # Check if database exists
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ # Parse update data
+ try:
+ parsed_updates = json.loads(update_data)
+ except json.JSONDecodeError:
+ raise ValueError("Invalid JSON format for update data")
+
+ if not isinstance(parsed_updates, dict):
+ raise ValueError("Update data must be a dictionary")
+
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Check if table exists
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (table_name,),
+ )
+
+ if not cursor.fetchone():
+ conn.close()
+ raise ValueError(f"Table '{table_name}' does not exist")
+
+ # Build UPDATE query
+ set_clauses = []
+ values = []
+
+ for column, value in parsed_updates.items():
+ set_clauses.append(f"{column} = ?")
+ values.append(value)
+
+ set_clause = ", ".join(set_clauses)
+
+ if where_clause:
+ update_sql = f"UPDATE {table_name} SET {set_clause} WHERE {where_clause}"
+ else:
+ update_sql = f"UPDATE {table_name} SET {set_clause}"
+
+ # Execute update
+ cursor.execute(update_sql, values)
+ rows_updated = cursor.rowcount
+
+ conn.commit()
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": f"Table '{table_name}' updated successfully",
+ "table": table_name,
+ "rows_updated": rows_updated,
+ "updated_columns": list(parsed_updates.keys()),
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+def get_database_schema(database_path: str) -> str:
+ """
+ Get comprehensive schema information for all tables in the database.
+
+ Args:
+ database_path (str): Full path to the database file
+
+ Returns:
+ str: JSON string containing complete database schema information
+
+ Example:
+ >>> result = get_database_schema("/data/company.db")
+ >>> print(result)
+ {"status": "success", "database": "company.db", "tables": {...}}
+ """
+ try:
+ if not database_path:
+ raise ValueError("Database path is required")
+
+ if not Path(database_path).exists():
+ raise FileNotFoundError(
+ f"Database file not found: {database_path}"
+ )
+
+ conn = sqlite3.connect(database_path)
+ cursor = conn.cursor()
+
+ # Get all tables
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE '_%'"
+ )
+ tables = cursor.fetchall()
+
+ schema_info = {
+ "database": Path(database_path).name,
+ "table_count": len(tables),
+ "tables": {},
+ }
+
+ for table in tables:
+ table_name = table[0]
+
+ # Get table schema
+ cursor.execute(f"PRAGMA table_info({table_name})")
+ columns = cursor.fetchall()
+
+ # Get row count
+ cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
+ row_count = cursor.fetchone()[0]
+
+ schema_info["tables"][table_name] = {
+ "columns": [
+ {
+ "name": col[1],
+ "type": col[2],
+ "nullable": not col[3],
+ "default": col[4],
+ "primary_key": bool(col[5]),
+ }
+ for col in columns
+ ],
+ "column_count": len(columns),
+ "row_count": row_count,
+ }
+
+ conn.close()
+
+ result = {
+ "status": "success",
+ "message": "Database schema retrieved successfully",
+ "schema": schema_info,
+ }
+
+ return json.dumps(result, indent=2)
+
+ except (ValueError, FileNotFoundError) as e:
+ return json.dumps({"status": "error", "error": str(e)})
+ except sqlite3.Error as e:
+ return json.dumps(
+ {"status": "error", "error": f"SQL error: {str(e)}"}
+ )
+ except Exception as e:
+ return json.dumps(
+ {
+ "status": "error",
+ "error": f"Unexpected error: {str(e)}",
+ }
+ )
+
+
+# =============================================================================
+# DATABASE CREATION SPECIALIST AGENT
+# =============================================================================
+database_creator_agent = Agent(
+ agent_name="Database-Creator",
+ agent_description="Specialist agent responsible for creating and initializing databases with proper structure and metadata",
+ system_prompt="""You are the Database Creator, a specialist agent responsible for database creation and initialization. Your expertise includes:
+
+ DATABASE CREATION & SETUP:
+ - Creating new SQLite databases with proper structure
+ - Setting up database metadata and tracking systems
+ - Initializing database directories and file organization
+ - Ensuring database accessibility and permissions
+ - Creating database backup and recovery procedures
+
+ DATABASE ARCHITECTURE:
+ - Designing optimal database structures for different use cases
+ - Planning database organization and naming conventions
+ - Setting up database configuration and optimization settings
+ - Implementing database security and access controls
+ - Creating database documentation and specifications
+
+ Your responsibilities:
+ - Create new databases when requested
+ - Set up proper database structure and metadata
+ - Ensure database is properly initialized and accessible
+ - Provide database creation status and information
+ - Handle database creation errors and provide solutions
+
+ You work with precise technical specifications and always ensure databases are created correctly and efficiently.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[create_database, get_database_schema],
+)
+
+# =============================================================================
+# TABLE MANAGEMENT SPECIALIST AGENT
+# =============================================================================
+table_manager_agent = Agent(
+ agent_name="Table-Manager",
+ agent_description="Specialist agent for table creation, schema design, and table structure management",
+ system_prompt="""You are the Table Manager, a specialist agent responsible for table creation, schema design, and table structure management. Your expertise includes:
+
+ TABLE CREATION & DESIGN:
+ - Creating tables with optimal schema design
+ - Defining appropriate data types and constraints
+ - Setting up primary keys, foreign keys, and indexes
+ - Designing normalized table structures
+ - Creating tables that support efficient queries and operations
+
+ SCHEMA MANAGEMENT:
+ - Analyzing schema requirements and designing optimal structures
+ - Validating schema definitions and data types
+ - Ensuring schema consistency and integrity
+ - Managing schema modifications and updates
+ - Optimizing table structures for performance
+
+ DATA INTEGRITY:
+ - Implementing proper constraints and validation rules
+ - Setting up referential integrity between tables
+ - Ensuring data consistency across table operations
+ - Managing table relationships and dependencies
+ - Creating tables that support data quality requirements
+
+ Your responsibilities:
+ - Create tables with proper schema definitions
+ - Validate table structures and constraints
+ - Ensure optimal table design for performance
+ - Handle table creation errors and provide solutions
+ - Provide detailed table information and metadata
+
+ You work with precision and always ensure tables are created with optimal structure and performance characteristics.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[create_table, get_database_schema],
+)
+
+# =============================================================================
+# DATA OPERATIONS SPECIALIST AGENT
+# =============================================================================
+data_operations_agent = Agent(
+ agent_name="Data-Operations",
+ agent_description="Specialist agent for data insertion, updates, and data manipulation operations",
+ system_prompt="""You are the Data Operations specialist, responsible for all data manipulation operations including insertion, updates, and data management. Your expertise includes:
+
+ DATA INSERTION:
+ - Inserting data with proper validation and formatting
+ - Handling bulk data insertions efficiently
+ - Managing data type conversions and formatting
+ - Ensuring data integrity during insertion operations
+ - Validating data before insertion to prevent errors
+
+ DATA UPDATES:
+ - Updating existing data with precision and safety
+ - Creating targeted update operations with proper WHERE clauses
+ - Managing bulk updates and data modifications
+ - Ensuring data consistency during update operations
+ - Validating update operations to prevent data corruption
+
+ DATA VALIDATION:
+ - Validating data formats and types before operations
+ - Ensuring data meets schema requirements and constraints
+ - Checking for data consistency and integrity
+ - Managing data transformation and cleaning operations
+ - Providing detailed feedback on data operation results
+
+ ERROR HANDLING:
+ - Managing data operation errors gracefully
+ - Providing clear error messages and solutions
+ - Ensuring data operations are atomic and safe
+ - Rolling back operations when necessary
+ - Maintaining data integrity throughout all operations
+
+ Your responsibilities:
+ - Execute data insertion operations safely and efficiently
+ - Perform data updates with proper validation
+ - Ensure data integrity throughout all operations
+ - Handle data operation errors and provide solutions
+ - Provide detailed operation results and statistics
+
+ You work with extreme precision and always prioritize data integrity and safety in all operations.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[insert_data, update_table_data],
+)
+
+# =============================================================================
+# QUERY SPECIALIST AGENT
+# =============================================================================
+query_specialist_agent = Agent(
+ agent_name="Query-Specialist",
+ agent_description="Expert agent for database querying, data retrieval, and query optimization",
+ system_prompt="""You are the Query Specialist, an expert agent responsible for database querying, data retrieval, and query optimization. Your expertise includes:
+
+ QUERY EXECUTION:
+ - Executing complex SELECT queries efficiently
+ - Handling parameterized queries for security
+ - Managing query results and data formatting
+ - Ensuring query performance and optimization
+ - Providing comprehensive query results with metadata
+
+ QUERY OPTIMIZATION:
+ - Analyzing query performance and optimization opportunities
+ - Creating efficient queries that minimize resource usage
+ - Understanding database indexes and query planning
+ - Optimizing JOIN operations and complex queries
+ - Managing query timeouts and performance monitoring
+
+ DATA RETRIEVAL:
+ - Retrieving data with proper formatting and structure
+ - Handling large result sets efficiently
+ - Managing data aggregation and summarization
+ - Creating reports and data analysis queries
+ - Ensuring data accuracy and completeness in results
+
+ SECURITY & VALIDATION:
+ - Ensuring queries are safe and secure
+ - Validating query syntax and parameters
+ - Preventing SQL injection and security vulnerabilities
+ - Managing query permissions and access controls
+ - Ensuring queries follow security best practices
+
+ Your responsibilities:
+ - Execute database queries safely and efficiently
+ - Optimize query performance for best results
+ - Provide comprehensive query results and analysis
+ - Handle query errors and provide solutions
+ - Ensure query security and data protection
+
+ You work with expertise in SQL optimization and always ensure queries are secure, efficient, and provide accurate results.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.3,
+ dynamic_temperature_enabled=True,
+ tools=[query_database, get_database_schema],
+)
+
+# =============================================================================
+# DATABASE DIRECTOR AGENT (COORDINATOR)
+# =============================================================================
+database_director_agent = Agent(
+ agent_name="Database-Director",
+ agent_description="Senior database director who orchestrates comprehensive database operations across all specialized teams",
+ system_prompt="""You are the Database Director, the senior executive responsible for orchestrating comprehensive database operations and coordinating a team of specialized database experts. Your role is to:
+
+ STRATEGIC COORDINATION:
+ - Analyze complex database tasks and break them down into specialized operations
+ - Assign tasks to the most appropriate specialist based on their unique expertise
+ - Ensure comprehensive coverage of all database operations (creation, schema, data, queries)
+ - Coordinate between specialists to avoid conflicts and ensure data integrity
+ - Synthesize results from multiple specialists into coherent database solutions
+ - Ensure all database operations align with user requirements and best practices
+
+ TEAM LEADERSHIP:
+ - Lead the Database Creator in setting up new databases and infrastructure
+ - Guide the Table Manager in creating optimal table structures and schemas
+ - Direct the Data Operations specialist in data insertion and update operations
+ - Oversee the Query Specialist in data retrieval and analysis operations
+ - Ensure all team members work collaboratively toward unified database goals
+ - Provide strategic direction and feedback to optimize team performance
+
+ DATABASE ARCHITECTURE:
+ - Design comprehensive database solutions that meet user requirements
+ - Ensure database operations follow best practices and standards
+ - Plan database workflows that optimize performance and reliability
+ - Balance immediate operational needs with long-term database health
+ - Ensure database operations are secure, efficient, and maintainable
+ - Optimize database operations for scalability and performance
+
+ OPERATION ORCHESTRATION:
+ - Monitor database operations across all specialists and activities
+ - Analyze results to identify optimization opportunities and improvements
+ - Ensure database operations deliver reliable and accurate results
+ - Provide strategic recommendations based on operation outcomes
+ - Coordinate complex multi-step database operations across specialists
+ - Ensure continuous improvement and optimization in database management
+
+ Your expertise includes:
+ - Database architecture and design strategy
+ - Team leadership and cross-functional coordination
+ - Database performance analysis and optimization
+ - Strategic planning and requirement analysis
+ - Operation workflow management and optimization
+ - Database security and best practices implementation
+
+ You deliver comprehensive database solutions that leverage the full expertise of your specialized team, ensuring all database operations work together to provide reliable, efficient, and secure data management.""",
+ model_name="claude-sonnet-4-20250514",
+ max_loops=1,
+ temperature=0.5,
+ dynamic_temperature_enabled=True,
+)
+
+# =============================================================================
+# HIERARCHICAL DATABASE SWARM
+# =============================================================================
+# Create list of specialized database agents
+database_specialists = [
+ database_creator_agent,
+ table_manager_agent,
+ data_operations_agent,
+ query_specialist_agent,
+]
+
+# Initialize the hierarchical database swarm
+smart_database_swarm = HierarchicalSwarm(
+ name="Smart-Database-Swarm",
+ description="A comprehensive database management system with specialized agents for creation, schema management, data operations, and querying, coordinated by a database director",
+ director_model_name="gpt-4.1",
+ agents=database_specialists,
+ max_loops=1,
+ verbose=True,
+)
+
+# =============================================================================
+# EXAMPLE USAGE AND DEMONSTRATIONS
+# =============================================================================
+if __name__ == "__main__":
+ # Configure logging
+ logger.info("Starting Smart Database Swarm demonstration")
+
+ # Example 1: Create a complete e-commerce database system
+ print("=" * 80)
+ print("SMART DATABASE SWARM - E-COMMERCE SYSTEM EXAMPLE")
+ print("=" * 80)
+
+ task1 = """Create a comprehensive e-commerce database system with the following requirements:
+
+ 1. Create a database called 'ecommerce_db'
+ 2. Create tables for:
+ - customers (id, name, email, phone, address, created_at)
+ - products (id, name, description, price, category, stock_quantity, created_at)
+ - orders (id, customer_id, order_date, total_amount, status)
+ - order_items (id, order_id, product_id, quantity, unit_price)
+
+ 3. Insert sample data:
+ - Add 3 customers
+ - Add 5 products in different categories
+ - Create 2 orders with multiple items
+
+ 4. Query the database to:
+ - Show all customers with their order history
+ - Display products by category with stock levels
+ - Calculate total sales by product
+
+ Ensure all operations are executed properly and provide comprehensive results."""
+
+ result1 = smart_database_swarm.run(task=task1)
+ print("\nE-COMMERCE DATABASE RESULT:")
+ print(result1)
+
+ # print("\n" + "=" * 80)
+ # print("SMART DATABASE SWARM - EMPLOYEE MANAGEMENT SYSTEM")
+ # print("=" * 80)
+
+ # # Example 2: Employee management system
+ # task2 = """Create an employee management database system:
+
+ # 1. Create database 'company_hr'
+ # 2. Create tables for:
+ # - departments (id, name, budget, manager_id)
+ # - employees (id, name, email, department_id, position, salary, hire_date)
+ # - projects (id, name, description, start_date, end_date, budget)
+ # - employee_projects (employee_id, project_id, role, hours_allocated)
+
+ # 3. Add sample data for departments, employees, and projects
+ # 4. Query for:
+ # - Employee count by department
+ # - Average salary by position
+ # - Projects with their assigned employees
+ # - Department budgets vs project allocations
+
+ # Coordinate the team to build this system efficiently."""
+
+ # result2 = smart_database_swarm.run(task=task2)
+ # print("\nEMPLOYEE MANAGEMENT RESULT:")
+ # print(result2)
+
+ # print("\n" + "=" * 80)
+ # print("SMART DATABASE SWARM - DATABASE ANALYSIS")
+ # print("=" * 80)
+
+ # # Example 3: Database analysis and optimization
+ # task3 = """Analyze and optimize the existing databases:
+
+ # 1. Get schema information for all created databases
+ # 2. Analyze table structures and relationships
+ # 3. Suggest optimizations for:
+ # - Index creation for better query performance
+ # - Data normalization improvements
+ # - Constraint additions for data integrity
+
+ # 4. Update data in existing tables:
+ # - Increase product prices by 10% for electronics category
+ # - Update employee salaries based on performance criteria
+ # - Modify order statuses for completed orders
+
+ # 5. Create comprehensive reports showing:
+ # - Database statistics and health metrics
+ # - Data distribution and patterns
+ # - Performance optimization recommendations
+
+ # Coordinate all specialists to provide a complete database analysis."""
+
+ # result3 = smart_database_swarm.run(task=task3)
+ # print("\nDATABASE ANALYSIS RESULT:")
+ # print(result3)
+
+ # logger.info("Smart Database Swarm demonstration completed successfully")
diff --git a/swarms/structs/hiearchical_swarm.py b/swarms/structs/hiearchical_swarm.py
index 70a97587..d2dc10f4 100644
--- a/swarms/structs/hiearchical_swarm.py
+++ b/swarms/structs/hiearchical_swarm.py
@@ -687,7 +687,7 @@ class HierarchicalSwarm:
interactive: bool = False,
director_system_prompt: str = HIEARCHICAL_SWARM_SYSTEM_PROMPT,
director_reasoning_model_name: str = "o3-mini",
- director_reasoning_enabled: bool = True,
+ director_reasoning_enabled: bool = False,
multi_agent_prompt_improvements: bool = False,
*args,
**kwargs,
From 4ff1aa46305abd670a4d9b6791a6269be8b5e4d1 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Wed, 13 Aug 2025 11:29:31 -0700
Subject: [PATCH 48/56] smart database app docs
---
docs/examples/smart_database.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/docs/examples/smart_database.md b/docs/examples/smart_database.md
index 530bbaa8..f8681d55 100644
--- a/docs/examples/smart_database.md
+++ b/docs/examples/smart_database.md
@@ -57,7 +57,7 @@ Database Director (Coordinator)
## Install
```bash
-pip3 install -U swarms sqlite3 loguru
+pip install -U swarms sqlite3 loguru
```
## ENV
@@ -70,6 +70,8 @@ OPENAI_API_KEY=""
## Code
+- Make a file called `smart_database_swarm.py`
+
```python
import sqlite3
import json
@@ -1058,4 +1060,4 @@ if __name__ == "__main__":
```
-- [Full Example Code Link]()
\ No newline at end of file
+- Run the file with `smart_database_swarm.py`
\ No newline at end of file
From fc44e67f5eae252566a4b5c0d3e329eeed517a3b Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 15 Aug 2025 23:01:29 +0300
Subject: [PATCH 49/56] Add files via upload
---
.../euroswarm_parliament/README.md | 370 +++
.../euroswarm_parliament/__init__.py | 55 +
.../euroswarm_parliament.py | 2598 +++++++++++++++++
.../euroswarm_parliament_example.py | 521 ++++
.../mass_agent_template.py | 998 +++++++
.../euroswarm_parliament/test_mass_agents.py | 67 +
.../wikipedia_personality_scraper.py | 575 ++++
7 files changed, 5184 insertions(+)
create mode 100644 examples/simulations/euroswarm_parliament/README.md
create mode 100644 examples/simulations/euroswarm_parliament/__init__.py
create mode 100644 examples/simulations/euroswarm_parliament/euroswarm_parliament.py
create mode 100644 examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py
create mode 100644 examples/simulations/euroswarm_parliament/mass_agent_template.py
create mode 100644 examples/simulations/euroswarm_parliament/test_mass_agents.py
create mode 100644 examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py
diff --git a/examples/simulations/euroswarm_parliament/README.md b/examples/simulations/euroswarm_parliament/README.md
new file mode 100644
index 00000000..9b7ed09e
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/README.md
@@ -0,0 +1,370 @@
+# EuroSwarm Parliament - European Parliament Simulation
+
+A comprehensive simulation of the European Parliament with 717 MEPs (Members of European Parliament) based on real EU data, featuring full democratic functionality including bill introduction, committee work, parliamentary debates, and democratic voting mechanisms.
+
+## Overview
+
+The EuroSwarm Parliament transforms the basic senator simulation into a full-fledged European Parliament with democratic capabilities. Unlike the original senator simulation that only allowed simple "Aye/Nay" voting, this system provides:
+
+- **Democratic Discussion**: Full parliamentary debates with diverse perspectives
+- **Committee Work**: Specialized committee hearings and analysis
+- **Bill Processing**: Complete legislative workflow from introduction to final vote
+- **Political Group Coordination**: Realistic political group dynamics
+- **Real MEP Data**: Based on actual EU.xml data with 700 real MEPs
+- **Board of Directors Pattern**: Advanced democratic decision-making using the Board of Directors swarm
+
+## Key Features
+
+### Democratic Functionality
+- **Bill Introduction**: MEPs can introduce bills with sponsors and co-sponsors
+- **Committee Hearings**: Specialized committee analysis and recommendations
+- **Parliamentary Debates**: Multi-perspective discussions with diverse participants
+- **Democratic Voting**: Comprehensive voting with individual reasoning and political group analysis
+- **Amendment Process**: Support for bill amendments and modifications
+
+### Realistic Parliament Structure
+- **717 MEPs**: Based on real EU.xml data with actual MEP names and affiliations
+- **Political Groups**: All major European political groups represented
+- **Committee System**: 16 specialized committees with chairs and members
+- **Leadership Positions**: President, Vice Presidents, Committee Chairs
+- **Country Representation**: All EU member states represented
+
+### Advanced AI Agents
+- **Individual MEP Agents**: Each MEP has a unique AI agent with:
+ - Political group alignment
+ - National party affiliation
+ - Committee memberships
+ - Areas of expertise
+ - Country-specific interests
+- **Democratic Decision-Making**: Board of Directors pattern for consensus building
+- **Contextual Responses**: MEPs respond based on their political positions and expertise
+
+## Architecture
+
+### Core Components
+
+#### 1. ParliamentaryMember
+Represents individual MEPs with:
+- Personal information (name, country, political group)
+- Parliamentary role and committee memberships
+- Areas of expertise and voting weight
+- AI agent for decision-making
+
+#### 2. ParliamentaryBill
+Represents legislative proposals with:
+- Title, description, and legislative procedure type
+- Committee assignment and sponsorship
+- Status tracking and amendment support
+
+#### 3. ParliamentaryCommittee
+Represents parliamentary committees with:
+- Chair and vice-chair positions
+- Member lists and responsibilities
+- Current bills under consideration
+
+#### 4. ParliamentaryVote
+Represents voting sessions with:
+- Individual MEP votes and reasoning
+- Political group analysis
+- Final results and statistics
+
+### Democratic Decision-Making
+
+The system uses the Board of Directors pattern for democratic decision-making:
+
+1. **Political Group Leaders**: Each political group has a representative on the democratic council
+2. **Weighted Voting**: Voting weights based on group size
+3. **Consensus Building**: Multi-round discussions to reach consensus
+4. **Individual Voting**: MEPs vote individually after considering the democratic council's analysis
+
+## Political Groups
+
+The simulation includes all major European political groups:
+
+- **Group of the European People's Party (Christian Democrats)** - EPP
+- **Group of the Progressive Alliance of Socialists and Democrats** - S&D
+- **Renew Europe Group** - RE
+- **Group of the Greens/European Free Alliance** - Greens/EFA
+- **European Conservatives and Reformists Group** - ECR
+- **The Left group in the European Parliament** - GUE/NGL
+- **Patriots for Europe Group** - Patriots
+- **Europe of Sovereign Nations Group** - ESN
+- **Non-attached Members** - NI
+
+## Committees
+
+16 specialized committees covering all major policy areas:
+
+1. **Agriculture and Rural Development**
+2. **Budgetary Control**
+3. **Civil Liberties, Justice and Home Affairs**
+4. **Development**
+5. **Economic and Monetary Affairs**
+6. **Employment and Social Affairs**
+7. **Environment, Public Health and Food Safety**
+8. **Foreign Affairs**
+9. **Industry, Research and Energy**
+10. **Internal Market and Consumer Protection**
+11. **International Trade**
+12. **Legal Affairs**
+13. **Petitions**
+14. **Regional Development**
+15. **Security and Defence**
+16. **Transport and Tourism**
+
+## Usage
+
+### Basic Initialization
+
+```python
+from euroswarm_parliament import EuroSwarmParliament, VoteType
+
+# Initialize parliament
+parliament = EuroSwarmParliament(
+ eu_data_file="EU.xml",
+ parliament_size=None, # Use all MEPs from EU.xml (718)
+ enable_democratic_discussion=True,
+ enable_committee_work=True,
+ enable_amendment_process=True,
+ verbose=False
+)
+```
+
+### Bill Introduction and Processing
+
+```python
+# Introduce a bill
+bill = parliament.introduce_bill(
+ title="European Climate Law",
+ description="Framework for achieving climate neutrality by 2050",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Environment, Public Health and Food Safety",
+ sponsor="Philippe Lamberts"
+)
+
+# Conduct committee hearing
+hearing = parliament.conduct_committee_hearing(
+ committee=bill.committee,
+ bill=bill
+)
+
+# Conduct parliamentary debate
+debate = parliament.conduct_parliamentary_debate(
+ bill=bill,
+ max_speakers=20
+)
+
+# Conduct democratic vote
+vote = parliament.conduct_democratic_vote(bill)
+```
+
+### Complete Democratic Session
+
+```python
+# Run a complete parliamentary session
+session = parliament.run_democratic_session(
+ bill_title="Artificial Intelligence Act",
+ bill_description="Comprehensive regulation of AI systems in the EU",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Internal Market and Consumer Protection"
+)
+
+print(f"Final Outcome: {session['session_summary']['final_outcome']}")
+```
+
+### Individual MEP Interaction
+
+```python
+# Get specific MEP
+mep = parliament.get_mep("ValƩrie Hayer")
+
+# Ask for position on policy
+response = mep.agent.run("What is your position on digital privacy regulation?")
+print(f"{mep.full_name}: {response}")
+```
+
+### Political Analysis
+
+```python
+# Get parliament composition
+composition = parliament.get_parliament_composition()
+
+# Analyze political groups
+for group_name, stats in composition['political_groups'].items():
+ print(f"{group_name}: {stats['count']} MEPs ({stats['percentage']:.1f}%)")
+
+# Get country representation
+country_members = parliament.get_country_members("Germany")
+print(f"German MEPs: {len(country_members)}")
+```
+
+## Democratic Features
+
+### 1. Democratic Discussion
+- **Multi-Perspective Debates**: MEPs from different political groups and countries
+- **Expertise-Based Input**: MEPs contribute based on their areas of expertise
+- **Constructive Dialogue**: Respectful debate with evidence-based arguments
+
+### 2. Committee Work
+- **Specialized Analysis**: Committees provide detailed technical analysis
+- **Expert Recommendations**: Committee members offer specialized insights
+- **Stakeholder Consideration**: Multiple perspectives on policy impacts
+
+### 3. Democratic Voting
+- **Individual Reasoning**: Each MEP provides reasoning for their vote
+- **Political Group Analysis**: Voting patterns by political affiliation
+- **Transparent Process**: Full visibility into decision-making process
+
+### 4. Consensus Building
+- **Board of Directors Pattern**: Advanced democratic decision-making
+- **Weighted Representation**: Political groups weighted by size
+- **Multi-Round Discussion**: Iterative process to reach consensus
+
+## š§ Configuration
+
+### Parliament Settings
+
+```python
+parliament = EuroSwarmParliament(
+ eu_data_file="EU.xml", # Path to EU data file
+ parliament_size=None, # Use all MEPs from EU.xml (717)
+ enable_democratic_discussion=True, # Enable democratic features
+ enable_committee_work=True, # Enable committee system
+ enable_amendment_process=True, # Enable bill amendments
+ verbose=False # Enable detailed logging
+)
+```
+
+### MEP Agent Configuration
+
+Each MEP agent is configured with:
+- **System Prompt**: Comprehensive political background and principles
+- **Model**: GPT-4o-mini for consistent responses
+- **Max Loops**: 3 iterations for thorough analysis
+- **Expertise Areas**: Based on political group and country
+
+## š Data Sources
+
+### EU.xml File
+The simulation uses real EU data from the EU.xml file containing:
+- **MEP Names**: Full names of all 700 MEPs
+- **Countries**: Country representation
+- **Political Groups**: European political group affiliations
+- **National Parties**: National political party memberships
+- **MEP IDs**: Unique identifiers for each MEP
+
+### Fallback System
+If EU.xml cannot be loaded, the system creates representative fallback MEPs:
+- **Sample MEPs**: Representative selection from major political groups
+- **Realistic Data**: Based on actual European Parliament composition
+- **Full Functionality**: All democratic features remain available
+
+## š® Example Scenarios
+
+### Scenario 1: Climate Policy Debate
+```python
+# Climate change legislation with diverse perspectives
+session = parliament.run_democratic_session(
+ bill_title="European Climate Law",
+ bill_description="Carbon neutrality framework for 2050",
+ committee="Environment, Public Health and Food Safety"
+)
+```
+
+### Scenario 2: Digital Regulation
+```python
+# Digital services regulation with technical analysis
+session = parliament.run_democratic_session(
+ bill_title="Digital Services Act",
+ bill_description="Online platform regulation",
+ committee="Internal Market and Consumer Protection"
+)
+```
+
+### Scenario 3: Social Policy
+```python
+# Minimum wage directive with social considerations
+session = parliament.run_democratic_session(
+ bill_title="European Minimum Wage Directive",
+ bill_description="Framework for adequate minimum wages",
+ committee="Employment and Social Affairs"
+)
+```
+
+## š® Future Enhancements
+
+### Planned Optimizations
+1. **Performance Optimization**: Parallel processing for large-scale voting
+2. **Advanced NLP**: Better analysis of debate transcripts and reasoning
+3. **Real-time Updates**: Dynamic parliament composition updates
+4. **Historical Analysis**: Track voting patterns and political evolution
+5. **External Integration**: Connect with real EU data sources
+
+### Potential Features
+1. **Amendment System**: Full amendment proposal and voting
+2. **Lobbying Simulation**: Interest group influence on MEPs
+3. **Media Integration**: Public opinion and media coverage
+4. **International Relations**: Interaction with other EU institutions
+5. **Budget Simulation**: Financial impact analysis of legislation
+
+## š Requirements
+
+### Dependencies
+- `swarms`: Core swarm framework
+- `loguru`: Advanced logging
+- `xml.etree.ElementTree`: XML parsing for EU data
+- `dataclasses`: Data structure support
+- `typing`: Type hints
+- `datetime`: Date and time handling
+
+### Data Files
+- `EU.xml`: European Parliament member data (included)
+
+## šāāļø Quick Start
+
+1. **Install Dependencies**:
+ ```bash
+ pip install swarms loguru
+ ```
+
+2. **Run Example**:
+ ```bash
+ python euroswarm_parliament_example.py
+ ```
+
+3. **Create Custom Session**:
+ ```python
+ from euroswarm_parliament import EuroSwarmParliament, VoteType
+
+ parliament = EuroSwarmParliament()
+ session = parliament.run_democratic_session(
+ bill_title="Your Bill Title",
+ bill_description="Your bill description",
+ committee="Relevant Committee"
+ )
+ ```
+
+## š¤ Contributing
+
+The EuroSwarm Parliament is designed to be extensible and customizable. Contributions are welcome for:
+
+- **New Democratic Features**: Additional parliamentary procedures
+- **Performance Optimizations**: Faster processing for large parliaments
+- **Data Integration**: Additional EU data sources
+- **Analysis Tools**: Advanced political analysis features
+- **Documentation**: Improved documentation and examples
+
+## š License
+
+This project is part of the Swarms Democracy framework and follows the same licensing terms.
+
+## šļø Acknowledgments
+
+- **European Parliament**: For the democratic structure and procedures
+- **EU Data**: For providing comprehensive MEP information
+- **Swarms Framework**: For the underlying multi-agent architecture
+- **Board of Directors Pattern**: For advanced democratic decision-making
+
+---
+
+*The EuroSwarm Parliament represents a significant advancement in democratic simulation, providing a realistic and comprehensive model of European parliamentary democracy with full AI-powered MEP representation and democratic decision-making processes.*
\ No newline at end of file
diff --git a/examples/simulations/euroswarm_parliament/__init__.py b/examples/simulations/euroswarm_parliament/__init__.py
new file mode 100644
index 00000000..381233f0
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/__init__.py
@@ -0,0 +1,55 @@
+"""
+EuroSwarm Parliament - European Parliament Simulation
+
+A comprehensive simulation of the European Parliament with 717 MEPs (Members of European Parliament)
+based on real EU data, featuring full democratic functionality including bill introduction, committee work,
+parliamentary debates, and democratic voting mechanisms.
+
+Enhanced with hierarchical democratic structure where each political group operates as a specialized
+Board of Directors with expertise areas, and a Parliament Speaker aggregates decisions using weighted voting.
+
+Includes Wikipedia personality system for realistic, personality-driven MEP behavior based on real biographical data.
+"""
+
+from euroswarm_parliament import (
+ EuroSwarmParliament,
+ ParliamentaryMember,
+ ParliamentaryBill,
+ ParliamentaryVote,
+ ParliamentaryCommittee,
+ PoliticalGroupBoard,
+ ParliamentSpeaker,
+ ParliamentaryRole,
+ VoteType,
+ VoteResult,
+)
+
+# Import Wikipedia personality system
+try:
+ from wikipedia_personality_scraper import (
+ WikipediaPersonalityScraper,
+ MEPPersonalityProfile,
+ )
+ WIKIPEDIA_PERSONALITY_AVAILABLE = True
+except ImportError:
+ WIKIPEDIA_PERSONALITY_AVAILABLE = False
+
+__version__ = "2.1.0"
+__author__ = "Swarms Democracy Team"
+__description__ = "European Parliament Simulation with Enhanced Hierarchical Democratic Functionality and Wikipedia Personality System"
+
+__all__ = [
+ "EuroSwarmParliament",
+ "ParliamentaryMember",
+ "ParliamentaryBill",
+ "ParliamentaryVote",
+ "ParliamentaryCommittee",
+ "PoliticalGroupBoard",
+ "ParliamentSpeaker",
+ "ParliamentaryRole",
+ "VoteType",
+ "VoteResult",
+ "WikipediaPersonalityScraper",
+ "MEPPersonalityProfile",
+ "WIKIPEDIA_PERSONALITY_AVAILABLE",
+]
\ No newline at end of file
diff --git a/examples/simulations/euroswarm_parliament/euroswarm_parliament.py b/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
new file mode 100644
index 00000000..9984ba58
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
@@ -0,0 +1,2598 @@
+"""
+EuroSwarm Parliament - European Parliament Simulation with Democratic Functionality
+
+This simulation creates a comprehensive European Parliament with 700 MEPs (Members of European Parliament)
+based on real EU data, featuring democratic discussion, bill analysis, committee work, and voting mechanisms.
+
+ENHANCED WITH COST OPTIMIZATION:
+- Lazy loading of MEP agents
+- Response caching for repeated queries
+- Batch processing for large-scale operations
+- Budget controls and cost tracking
+- Memory optimization for large parliaments
+"""
+
+import os
+import random
+import xml.etree.ElementTree as ET
+import time
+import hashlib
+from typing import Dict, List, Optional, Union, Any, Set
+from dataclasses import dataclass, field
+from enum import Enum
+from datetime import datetime, timedelta
+from functools import lru_cache
+
+from swarms import Agent
+from swarms.structs.multi_agent_exec import run_agents_concurrently
+from swarms.structs.board_of_directors_swarm import (
+ BoardOfDirectorsSwarm,
+ BoardMember,
+ BoardMemberRole,
+ BoardDecisionType,
+ BoardSpec,
+ BoardOrder,
+ BoardDecision,
+ enable_board_feature,
+)
+from swarms.utils.loguru_logger import initialize_logger
+
+# Initialize logger first
+logger = initialize_logger(log_folder="euroswarm_parliament")
+
+# Enable Board of Directors feature
+enable_board_feature()
+
+# Import Wikipedia personality system
+try:
+ from wikipedia_personality_scraper import WikipediaPersonalityScraper, MEPPersonalityProfile
+ WIKIPEDIA_PERSONALITY_AVAILABLE = True
+except ImportError:
+ WIKIPEDIA_PERSONALITY_AVAILABLE = False
+ logger.warning("Wikipedia personality system not available. Using basic personality generation.")
+
+
+@dataclass
+class CostTracker:
+ """Track costs and usage for budget management in parliamentary operations."""
+
+ total_tokens_used: int = 0
+ total_cost_estimate: float = 0.0
+ budget_limit: float = 200.0 # Default $200 budget for parliament
+ token_cost_per_1m: float = 0.15 # GPT-4o-mini cost
+ requests_made: int = 0
+ cache_hits: int = 0
+
+ def add_tokens(self, tokens: int):
+ """Add tokens used and calculate cost."""
+ self.total_tokens_used += tokens
+ self.total_cost_estimate = (self.total_tokens_used / 1_000_000) * self.token_cost_per_1m
+ self.requests_made += 1
+
+ def add_cache_hit(self):
+ """Record a cache hit."""
+ self.cache_hits += 1
+
+ def check_budget(self) -> bool:
+ """Check if within budget."""
+ return self.total_cost_estimate <= self.budget_limit
+
+ def get_stats(self) -> Dict[str, Any]:
+ """Get cost statistics."""
+ return {
+ "total_tokens": self.total_tokens_used,
+ "total_cost": self.total_cost_estimate,
+ "requests_made": self.requests_made,
+ "cache_hits": self.cache_hits,
+ "cache_hit_rate": self.cache_hits / max(1, self.requests_made + self.cache_hits),
+ "budget_remaining": max(0, self.budget_limit - self.total_cost_estimate)
+ }
+
+
+class ParliamentaryRole(str, Enum):
+ """Enumeration of parliamentary roles and positions."""
+
+ PRESIDENT = "president"
+ VICE_PRESIDENT = "vice_president"
+ QUAESTOR = "quaestor"
+ COMMITTEE_CHAIR = "committee_chair"
+ COMMITTEE_VICE_CHAIR = "committee_vice_chair"
+ POLITICAL_GROUP_LEADER = "political_group_leader"
+ MEP = "mep"
+
+
+class VoteType(str, Enum):
+ """Enumeration of voting types in the European Parliament."""
+
+ ORDINARY_LEGISLATIVE_PROCEDURE = "ordinary_legislative_procedure"
+ CONSENT_PROCEDURE = "consent_procedure"
+ CONSULTATION_PROCEDURE = "consultation_procedure"
+ BUDGET_VOTE = "budget_vote"
+ RESOLUTION_VOTE = "resolution_vote"
+ APPOINTMENT_VOTE = "appointment_vote"
+
+
+class VoteResult(str, Enum):
+ """Enumeration of possible vote results."""
+
+ PASSED = "passed"
+ FAILED = "failed"
+ TIED = "tied"
+ ABSTAINED = "abstained"
+
+
+@dataclass
+class ParliamentaryMember:
+ """
+ Represents a Member of the European Parliament (MEP).
+
+ Attributes:
+ full_name: Full name of the MEP
+ country: Country the MEP represents
+ political_group: European political group affiliation
+ national_party: National political party
+ mep_id: Unique MEP identifier
+ role: Parliamentary role (if any)
+ committees: List of committee memberships
+ expertise_areas: Areas of policy expertise
+ voting_weight: Weight of the MEP's vote (default: 1.0)
+ agent: The AI agent representing this MEP (lazy loaded)
+ is_loaded: Whether the agent has been instantiated
+ """
+
+ full_name: str
+ country: str
+ political_group: str
+ national_party: str
+ mep_id: str
+ role: ParliamentaryRole = ParliamentaryRole.MEP
+ committees: List[str] = field(default_factory=list)
+ expertise_areas: List[str] = field(default_factory=list)
+ voting_weight: float = 1.0
+ agent: Optional[Agent] = None
+ is_loaded: bool = False
+
+
+@dataclass
+class ParliamentaryBill:
+ """
+ Represents a bill or legislative proposal in the European Parliament.
+
+ Attributes:
+ title: Title of the bill
+ description: Detailed description of the bill
+ bill_type: Type of legislative procedure
+ committee: Primary committee responsible
+ sponsor: MEP who sponsored the bill
+ co_sponsors: List of co-sponsoring MEPs
+ date_introduced: Date the bill was introduced
+ status: Current status of the bill
+ amendments: List of proposed amendments
+ """
+
+ title: str
+ description: str
+ bill_type: VoteType
+ committee: str
+ sponsor: str
+ co_sponsors: List[str] = field(default_factory=list)
+ date_introduced: datetime = field(default_factory=datetime.now)
+ status: str = "introduced"
+ amendments: List[Dict[str, Any]] = field(default_factory=list)
+
+
+@dataclass
+class ParliamentaryVote:
+ """
+ Represents a parliamentary vote on a bill or resolution.
+
+ Attributes:
+ bill: The bill being voted on
+ vote_type: Type of vote being conducted
+ date: Date of the vote
+ votes_for: Number of votes in favor
+ votes_against: Number of votes against
+ abstentions: Number of abstentions
+ absent: Number of absent MEPs
+ result: Final result of the vote
+ individual_votes: Dictionary of individual MEP votes
+ reasoning: Dictionary of MEP reasoning for votes
+ """
+
+ bill: ParliamentaryBill
+ vote_type: VoteType
+ date: datetime = field(default_factory=datetime.now)
+ votes_for: int = 0
+ votes_against: int = 0
+ abstentions: int = 0
+ absent: int = 0
+ result: VoteResult = VoteResult.FAILED
+ individual_votes: Dict[str, str] = field(default_factory=dict)
+ reasoning: Dict[str, str] = field(default_factory=dict)
+
+
+@dataclass
+class ParliamentaryCommittee:
+ """
+ Represents a parliamentary committee.
+
+ Attributes:
+ name: Name of the committee
+ chair: Committee chairperson
+ vice_chair: Committee vice-chairperson
+ members: List of committee members
+ responsibilities: Committee responsibilities
+ current_bills: Bills currently under consideration
+ """
+
+ name: str
+ chair: str
+ vice_chair: str
+ members: List[str] = field(default_factory=list)
+ responsibilities: List[str] = field(default_factory=list)
+ current_bills: List[ParliamentaryBill] = field(default_factory=list)
+
+
+@dataclass
+class PoliticalGroupBoard:
+ """
+ Represents a political group as a Board of Directors with specialized expertise.
+
+ Attributes:
+ group_name: Name of the political group
+ members: List of MEPs in this group
+ board_members: Board members with specialized roles and internal percentages
+ expertise_areas: Specialized areas of governance expertise
+ voting_weight: Weight of this group's vote (percentage of parliament)
+ group_speaker: CEO/leader of this political group
+ total_meps: Total number of MEPs in this group
+ board_member_percentages: Dictionary mapping board members to their internal percentages
+ """
+
+ group_name: str
+ members: List[str] = field(default_factory=list)
+ board_members: List[BoardMember] = field(default_factory=list)
+ expertise_areas: List[str] = field(default_factory=list)
+ voting_weight: float = 0.0
+ group_speaker: Optional[str] = None
+ total_meps: int = 0
+ board_swarm: Optional[Any] = None # BoardOfDirectorsSwarm instance
+ board_member_percentages: Dict[str, float] = field(default_factory=dict) # Internal percentages within group
+
+@dataclass
+class ParliamentSpeaker:
+ """
+ Represents the Parliament Speaker who aggregates decisions from all political groups.
+
+ Attributes:
+ name: Name of the speaker
+ agent: AI agent representing the speaker
+ political_groups: Dictionary of political group boards
+ total_meps: Total number of MEPs in parliament
+ majority_threshold: Number of votes needed for majority
+ """
+
+ name: str
+ agent: Optional[Agent] = None
+ political_groups: Dict[str, PoliticalGroupBoard] = field(default_factory=dict)
+ total_meps: int = 0
+ majority_threshold: int = 0
+
+
+class EuroSwarmParliament:
+ """
+ A comprehensive simulation of the European Parliament with 700 MEPs.
+
+ This simulation provides democratic functionality including:
+ - Bill introduction and analysis
+ - Committee work and hearings
+ - Parliamentary debates and discussions
+ - Democratic voting mechanisms
+ - Political group coordination
+ - Amendment processes
+ """
+
+ def __init__(
+ self,
+ eu_data_file: str = "EU.xml",
+ parliament_size: int = None, # Changed from 700 to None to use all MEPs
+ enable_democratic_discussion: bool = True,
+ enable_committee_work: bool = True,
+ enable_amendment_process: bool = True,
+ enable_lazy_loading: bool = True, # NEW: Lazy load MEP agents
+ enable_caching: bool = True, # NEW: Enable response caching
+ batch_size: int = 25, # NEW: Batch size for concurrent execution
+ budget_limit: float = 200.0, # NEW: Budget limit in dollars
+ verbose: bool = False,
+ ):
+ """
+ Initialize the EuroSwarm Parliament with cost optimization.
+
+ Args:
+ eu_data_file: Path to EU.xml file containing MEP data
+ parliament_size: Target size of the parliament (default: None = use all MEPs from EU.xml)
+ enable_democratic_discussion: Enable democratic discussion features
+ enable_committee_work: Enable committee work and hearings
+ enable_amendment_process: Enable bill amendment processes
+ enable_lazy_loading: Enable lazy loading of MEP agents (cost optimization)
+ enable_caching: Enable response caching (cost optimization)
+ batch_size: Number of MEPs to process in batches
+ budget_limit: Maximum budget in dollars
+ verbose: Enable verbose logging
+ """
+ self.eu_data_file = eu_data_file
+ self.parliament_size = parliament_size # Will be set to actual MEP count if None
+ self.enable_democratic_discussion = enable_democratic_discussion
+ self.enable_committee_work = enable_committee_work
+ self.enable_amendment_process = enable_amendment_process
+ self.enable_lazy_loading = enable_lazy_loading
+ self.enable_caching = enable_caching
+ self.batch_size = batch_size
+ self.verbose = verbose
+
+ # Initialize cost tracking
+ self.cost_tracker = CostTracker(budget_limit=budget_limit)
+
+ # Initialize parliamentary structures
+ self.meps: Dict[str, ParliamentaryMember] = {}
+ self.committees: Dict[str, ParliamentaryCommittee] = {}
+ self.political_groups: Dict[str, List[str]] = {}
+ self.bills: List[ParliamentaryBill] = []
+ self.votes: List[ParliamentaryVote] = []
+ self.debates: List[Dict[str, Any]] = []
+
+ # Enhanced democratic structures
+ self.political_group_boards: Dict[str, PoliticalGroupBoard] = {}
+ self.parliament_speaker: Optional[ParliamentSpeaker] = None
+ self.enable_hierarchical_democracy: bool = True
+
+ # Wikipedia personality system
+ self.enable_wikipedia_personalities: bool = WIKIPEDIA_PERSONALITY_AVAILABLE
+ self.personality_profiles: Dict[str, MEPPersonalityProfile] = {}
+ self.personality_scraper: Optional[WikipediaPersonalityScraper] = None
+
+ # Initialize caching
+ self.response_cache: Dict[str, str] = {}
+
+ # Load MEP data and initialize structures
+ self.meps = self._load_mep_data()
+ self.parliament_size = len(self.meps)
+
+ if self.verbose:
+ logger.info(f"EuroSwarm Parliament initialized with {self.parliament_size} MEPs")
+ logger.info(f"Lazy loading: {self.enable_lazy_loading}, Caching: {self.enable_caching}")
+ logger.info(f"Budget limit: ${budget_limit}, Batch size: {batch_size}")
+
+ # Load Wikipedia personalities if enabled
+ if self.enable_wikipedia_personalities:
+ self._load_wikipedia_personalities()
+
+ # Initialize parliamentary structures
+ self.committees = self._create_committees()
+ self.political_groups = self._organize_political_groups()
+
+ # Initialize enhanced democratic structures
+ if self.enable_hierarchical_democracy:
+ self._create_political_group_boards()
+ self._create_parliament_speaker()
+
+ # Initialize leadership and democratic decision-making
+ self._create_parliamentary_leadership()
+ self._assign_committee_leadership()
+
+ if self.enable_democratic_discussion:
+ self._init_democratic_decision_making()
+
+ def _load_mep_data(self) -> Dict[str, ParliamentaryMember]:
+ """
+ Load MEP data from EU.xml file and create parliamentary members with lazy loading.
+
+ Returns:
+ Dict[str, ParliamentaryMember]: Dictionary of MEPs
+ """
+ meps = {}
+
+ try:
+ # Construct the full path to EU.xml relative to project root
+ import os
+ project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+ eu_data_path = os.path.join(project_root, self.eu_data_file)
+
+ # Read the XML file content
+ with open(eu_data_path, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ # Use regex to extract MEP data since the XML is malformed
+ import re
+
+ # Find all MEP blocks
+ mep_pattern = r'\s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s* '
+ mep_matches = re.findall(mep_pattern, content, re.DOTALL)
+
+ for full_name, country, political_group, mep_id, national_party in mep_matches:
+ # Clean up the data
+ full_name = full_name.strip()
+ country = country.strip()
+ political_group = political_group.strip()
+ mep_id = mep_id.strip()
+ national_party = national_party.strip()
+
+ # Create parliamentary member (without agent for lazy loading)
+ mep = ParliamentaryMember(
+ full_name=full_name,
+ country=country,
+ political_group=political_group,
+ national_party=national_party,
+ mep_id=mep_id,
+ expertise_areas=self._generate_expertise_areas(political_group, country),
+ committees=self._assign_committees(political_group),
+ agent=None, # Will be created on demand
+ is_loaded=False
+ )
+
+ meps[full_name] = mep
+
+ # Set parliament size to actual number of MEPs loaded if not specified
+ if self.parliament_size is None:
+ self.parliament_size = len(meps)
+
+ logger.info(f"Loaded {len(meps)} MEP profiles from EU data (lazy loading enabled)")
+
+ except Exception as e:
+ logger.error(f"Error loading MEP data: {e}")
+ # Create fallback MEPs if file loading fails
+ meps = self._create_fallback_meps()
+ if self.parliament_size is None:
+ self.parliament_size = len(meps)
+
+ return meps
+
+ def _load_mep_agent(self, mep_name: str) -> Optional[Agent]:
+ """
+ Lazy load a single MEP agent on demand.
+
+ Args:
+ mep_name: Name of the MEP to load
+
+ Returns:
+ Optional[Agent]: Loaded agent or None if not found
+ """
+ if mep_name not in self.meps:
+ return None
+
+ mep = self.meps[mep_name]
+
+ # Check if already loaded
+ if mep.is_loaded and mep.agent:
+ return mep.agent
+
+ # Check budget before creating agent
+ if not self.cost_tracker.check_budget():
+ logger.warning(f"Budget exceeded. Cannot load MEP agent {mep_name}")
+ return None
+
+ # Create agent
+ mep.agent = self._create_mep_agent(mep)
+ mep.is_loaded = True
+
+ if self.verbose:
+ logger.info(f"Loaded MEP agent: {mep_name}")
+
+ return mep.agent
+
+ def _load_mep_agents_batch(self, mep_names: List[str]) -> List[Agent]:
+ """
+ Load multiple MEP agents in a batch.
+
+ Args:
+ mep_names: List of MEP names to load
+
+ Returns:
+ List[Agent]: List of loaded agents
+ """
+ loaded_agents = []
+
+ for mep_name in mep_names:
+ agent = self._load_mep_agent(mep_name)
+ if agent:
+ loaded_agents.append(agent)
+
+ return loaded_agents
+
+ def _get_cache_key(self, task: str, mep_names: List[str]) -> str:
+ """
+ Generate a cache key for a task and MEP combination.
+
+ Args:
+ task: Task to execute
+ mep_names: List of MEP names
+
+ Returns:
+ str: Cache key
+ """
+ # Sort MEP names for consistent cache keys
+ sorted_meps = sorted(mep_names)
+ content = f"{task}:{':'.join(sorted_meps)}"
+ return hashlib.md5(content.encode()).hexdigest()
+
+ def _check_cache(self, cache_key: str) -> Optional[str]:
+ """
+ Check if a response is cached.
+
+ Args:
+ cache_key: Cache key to check
+
+ Returns:
+ Optional[str]: Cached response or None
+ """
+ if not self.enable_caching:
+ return None
+
+ cached_response = self.response_cache.get(cache_key)
+ if cached_response:
+ self.cost_tracker.add_cache_hit()
+ if self.verbose:
+ logger.info(f"Cache hit for key: {cache_key[:20]}...")
+
+ return cached_response
+
+ def _cache_response(self, cache_key: str, response: str):
+ """
+ Cache a response.
+
+ Args:
+ cache_key: Cache key
+ response: Response to cache
+ """
+ if self.enable_caching:
+ self.response_cache[cache_key] = response
+ if self.verbose:
+ logger.info(f"Cached response for key: {cache_key[:20]}...")
+
+ def _generate_expertise_areas(self, political_group: str, country: str) -> List[str]:
+ """
+ Generate expertise areas based on political group and country.
+
+ Args:
+ political_group: MEP's political group
+ country: MEP's country
+
+ Returns:
+ List[str]: List of expertise areas
+ """
+ expertise_mapping = {
+ "Group of the European People's Party (Christian Democrats)": [
+ "Economic Policy", "Agriculture", "Regional Development", "Christian Values"
+ ],
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
+ "Social Policy", "Labor Rights", "Healthcare", "Education"
+ ],
+ "Renew Europe Group": [
+ "Digital Policy", "Innovation", "Trade", "Liberal Values"
+ ],
+ "Group of the Greens/European Free Alliance": [
+ "Environmental Policy", "Climate Change", "Renewable Energy", "Human Rights"
+ ],
+ "European Conservatives and Reformists Group": [
+ "Sovereignty", "Defense", "Traditional Values", "Economic Freedom"
+ ],
+ "The Left group in the European Parliament - GUE/NGL": [
+ "Workers' Rights", "Social Justice", "Anti-Austerity", "Public Services"
+ ],
+ "Patriots for Europe Group": [
+ "National Sovereignty", "Border Security", "Cultural Identity", "Law and Order"
+ ],
+ "Europe of Sovereign Nations Group": [
+ "National Independence", "Sovereignty", "Traditional Values", "Security"
+ ],
+ "Non-attached Members": [
+ "Independent Policy", "Cross-cutting Issues", "Specialized Topics"
+ ]
+ }
+
+ base_expertise = expertise_mapping.get(political_group, ["General Policy"])
+
+ # Add country-specific expertise
+ country_expertise = {
+ "Germany": ["Industrial Policy", "Manufacturing"],
+ "France": ["Agriculture", "Defense"],
+ "Italy": ["Cultural Heritage", "Tourism"],
+ "Spain": ["Tourism", "Agriculture"],
+ "Poland": ["Energy Security", "Eastern Partnership"],
+ "Netherlands": ["Trade", "Innovation"],
+ "Belgium": ["EU Institutions", "Multilingualism"],
+ "Austria": ["Alpine Policy", "Transport"],
+ "Sweden": ["Environmental Policy", "Social Welfare"],
+ "Denmark": ["Green Technology", "Welfare State"],
+ }
+
+ if country in country_expertise:
+ base_expertise.extend(country_expertise[country])
+
+ return base_expertise[:5] # Limit to 5 expertise areas
+
+ def _assign_committees(self, political_group: str) -> List[str]:
+ """
+ Assign committees based on political group preferences.
+
+ Args:
+ political_group: MEP's political group
+
+ Returns:
+ List[str]: List of committee assignments
+ """
+ committee_mapping = {
+ "Group of the European People's Party (Christian Democrats)": [
+ "Agriculture and Rural Development", "Economic and Monetary Affairs", "Regional Development"
+ ],
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
+ "Employment and Social Affairs", "Environment, Public Health and Food Safety", "Civil Liberties"
+ ],
+ "Renew Europe Group": [
+ "Industry, Research and Energy", "Internal Market and Consumer Protection", "Legal Affairs"
+ ],
+ "Group of the Greens/European Free Alliance": [
+ "Environment, Public Health and Food Safety", "Transport and Tourism", "Development"
+ ],
+ "European Conservatives and Reformists Group": [
+ "Foreign Affairs", "Security and Defence", "Budgetary Control"
+ ],
+ "The Left group in the European Parliament - GUE/NGL": [
+ "International Trade", "Development", "Civil Liberties"
+ ],
+ "Patriots for Europe Group": [
+ "Civil Liberties", "Security and Defence", "Budgetary Control"
+ ],
+ "Europe of Sovereign Nations Group": [
+ "Foreign Affairs", "Security and Defence", "Civil Liberties"
+ ],
+ "Non-attached Members": [
+ "Petitions", "Budgetary Control", "Legal Affairs"
+ ]
+ }
+
+ return committee_mapping.get(political_group, ["Petitions"])
+
+ def _create_mep_agent(self, mep: ParliamentaryMember) -> Agent:
+ """
+ Create an AI agent representing an MEP.
+
+ Args:
+ mep: Parliamentary member data
+
+ Returns:
+ Agent: AI agent representing the MEP
+ """
+ system_prompt = self._generate_mep_system_prompt(mep)
+
+ return Agent(
+ agent_name=f"MEP_{mep.full_name.replace(' ', '_')}",
+ system_prompt=system_prompt,
+ model_name="gpt-4o-mini",
+ max_loops=3,
+ verbose=self.verbose,
+ )
+
+ def _generate_mep_system_prompt(self, mep: ParliamentaryMember) -> str:
+ """
+ Generate a comprehensive system prompt for an MEP agent with Wikipedia personality data.
+
+ Args:
+ mep: Parliamentary member data
+
+ Returns:
+ str: System prompt for the MEP agent
+ """
+
+ # Get Wikipedia personality profile if available
+ personality_profile = self.get_mep_personality_profile(mep.full_name)
+
+ # Base prompt structure
+ prompt = f"""You are {mep.full_name}, a Member of the European Parliament (MEP) representing {mep.country}.
+
+POLITICAL BACKGROUND:
+- Political Group: {mep.political_group}
+- National Party: {mep.national_party}
+- Parliamentary Role: {mep.role.value}
+- Committees: {', '.join(mep.committees)}
+- Areas of Expertise: {', '.join(mep.expertise_areas)}
+
+"""
+
+ # Add Wikipedia personality data if available
+ if personality_profile and self.enable_wikipedia_personalities:
+ prompt += f"""
+REAL PERSONALITY PROFILE (Based on Wikipedia data):
+{self.personality_scraper.get_personality_summary(personality_profile)}
+
+POLITICAL VIEWS AND POSITIONS:
+- Key Political Views: {personality_profile.political_views if personality_profile.political_views else 'Based on party alignment'}
+- Policy Focus Areas: {personality_profile.policy_focus if personality_profile.policy_focus else ', '.join(mep.expertise_areas)}
+- Notable Achievements: {personality_profile.achievements if personality_profile.achievements else 'Parliamentary service'}
+- Professional Background: {personality_profile.professional_background if personality_profile.professional_background else 'Political career'}
+
+"""
+ else:
+ prompt += f"""
+POLITICAL VIEWS AND POSITIONS:
+- Key Political Views: Based on {mep.political_group} alignment
+- Policy Focus Areas: {', '.join(mep.expertise_areas)}
+- Professional Background: Parliamentary service
+"""
+
+ # Add core principles
+ prompt += f"""
+CORE PRINCIPLES:
+1. Democratic Representation: You represent the interests of {mep.country} and your constituents
+2. European Integration: You work within the framework of European Union law and institutions
+3. Political Alignment: You align with {mep.political_group} positions while maintaining independence
+4. Policy Expertise: You focus on your areas of expertise: {', '.join(mep.expertise_areas)}
+
+PARLIAMENTARY BEHAVIOR:
+- Engage in constructive debate and dialogue with other MEPs
+- Consider multiple perspectives when forming positions
+- Support evidence-based policy making
+- Respect democratic processes and parliamentary procedures
+- Work across political groups when beneficial for your constituents
+- Advocate for {mep.country}'s interests while considering European common good
+
+VOTING BEHAVIOR:
+- Vote based on your political principles and constituent interests
+- Consider the impact on {mep.country} and the European Union
+- Support measures that align with {mep.political_group} values
+- Oppose measures that conflict with your core principles
+- Abstain when you need more information or have conflicting considerations
+
+COMMUNICATION STYLE:
+- Professional and diplomatic in parliamentary settings
+- Clear and articulate when explaining positions
+- Respectful of other MEPs and their viewpoints
+- Passionate about your areas of expertise
+- Pragmatic when seeking compromise and consensus
+
+When responding to parliamentary matters, consider:
+1. How does this affect {mep.country} and your constituents?
+2. What is the position of {mep.political_group} on this issue?
+3. What are the implications for your areas of expertise?
+4. How can you contribute constructively to the discussion?
+5. What is the best outcome for European citizens?
+
+Remember: You are a democratically elected representative working for the benefit of European citizens while representing {mep.country}'s interests within the European Union framework.
+"""
+
+ return prompt
+
+ def _create_fallback_meps(self) -> Dict[str, ParliamentaryMember]:
+ """
+ Create fallback MEPs if EU.xml file cannot be loaded.
+
+ Returns:
+ Dict[str, ParliamentaryMember]: Dictionary of fallback MEPs
+ """
+ fallback_meps = {}
+
+ # Create a representative sample of MEPs
+ sample_data = [
+ ("Jean-Claude Juncker", "Luxembourg", "Group of the European People's Party (Christian Democrats)", "Parti chrƩtien social luxembourgeois"),
+ ("Ursula von der Leyen", "Germany", "Group of the European People's Party (Christian Democrats)", "Christlich Demokratische Union Deutschlands"),
+ ("Roberta Metsola", "Malta", "Group of the European People's Party (Christian Democrats)", "Partit Nazzjonalista"),
+ ("Iratxe GarcĆa PĆ©rez", "Spain", "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament", "Partido Socialista Obrero EspaƱol"),
+ ("ValƩrie Hayer", "France", "Renew Europe Group", "Renaissance"),
+ ("Philippe Lamberts", "Belgium", "Group of the Greens/European Free Alliance", "Ecolo"),
+ ("Raffaele Fitto", "Italy", "European Conservatives and Reformists Group", "Fratelli d'Italia"),
+ ("Manon Aubry", "France", "The Left group in the European Parliament - GUE/NGL", "La France Insoumise"),
+ ]
+
+ for i, (name, country, group, party) in enumerate(sample_data):
+ mep = ParliamentaryMember(
+ full_name=name,
+ country=country,
+ political_group=group,
+ national_party=party,
+ mep_id=f"fallback_{i}",
+ expertise_areas=self._generate_expertise_areas(group, country),
+ committees=self._assign_committees(group),
+ agent=None, # Will be created on demand
+ is_loaded=False
+ )
+ fallback_meps[name] = mep
+
+ return fallback_meps
+
+ def _create_committees(self) -> Dict[str, ParliamentaryCommittee]:
+ """
+ Create parliamentary committees.
+
+ Returns:
+ Dict[str, ParliamentaryCommittee]: Dictionary of committees
+ """
+ committees = {
+ "Agriculture and Rural Development": ParliamentaryCommittee(
+ name="Agriculture and Rural Development",
+ chair="",
+ vice_chair="",
+ responsibilities=["Agricultural policy", "Rural development", "Food safety"]
+ ),
+ "Budgetary Control": ParliamentaryCommittee(
+ name="Budgetary Control",
+ chair="",
+ vice_chair="",
+ responsibilities=["Budget oversight", "Financial control", "Audit reports"]
+ ),
+ "Civil Liberties, Justice and Home Affairs": ParliamentaryCommittee(
+ name="Civil Liberties, Justice and Home Affairs",
+ chair="",
+ vice_chair="",
+ responsibilities=["Civil rights", "Justice", "Home affairs", "Immigration"]
+ ),
+ "Development": ParliamentaryCommittee(
+ name="Development",
+ chair="",
+ vice_chair="",
+ responsibilities=["Development cooperation", "Humanitarian aid", "International relations"]
+ ),
+ "Economic and Monetary Affairs": ParliamentaryCommittee(
+ name="Economic and Monetary Affairs",
+ chair="",
+ vice_chair="",
+ responsibilities=["Economic policy", "Monetary policy", "Financial services"]
+ ),
+ "Employment and Social Affairs": ParliamentaryCommittee(
+ name="Employment and Social Affairs",
+ chair="",
+ vice_chair="",
+ responsibilities=["Employment policy", "Social policy", "Working conditions"]
+ ),
+ "Environment, Public Health and Food Safety": ParliamentaryCommittee(
+ name="Environment, Public Health and Food Safety",
+ chair="",
+ vice_chair="",
+ responsibilities=["Environmental policy", "Public health", "Food safety"]
+ ),
+ "Foreign Affairs": ParliamentaryCommittee(
+ name="Foreign Affairs",
+ chair="",
+ vice_chair="",
+ responsibilities=["Foreign policy", "International relations", "Security policy"]
+ ),
+ "Industry, Research and Energy": ParliamentaryCommittee(
+ name="Industry, Research and Energy",
+ chair="",
+ vice_chair="",
+ responsibilities=["Industrial policy", "Research", "Energy policy"]
+ ),
+ "Internal Market and Consumer Protection": ParliamentaryCommittee(
+ name="Internal Market and Consumer Protection",
+ chair="",
+ vice_chair="",
+ responsibilities=["Internal market", "Consumer protection", "Digital policy"]
+ ),
+ "International Trade": ParliamentaryCommittee(
+ name="International Trade",
+ chair="",
+ vice_chair="",
+ responsibilities=["Trade policy", "International agreements", "Market access"]
+ ),
+ "Legal Affairs": ParliamentaryCommittee(
+ name="Legal Affairs",
+ chair="",
+ vice_chair="",
+ responsibilities=["Legal matters", "Institutional affairs", "Constitutional issues"]
+ ),
+ "Petitions": ParliamentaryCommittee(
+ name="Petitions",
+ chair="",
+ vice_chair="",
+ responsibilities=["Citizen petitions", "Ombudsman", "Citizen rights"]
+ ),
+ "Regional Development": ParliamentaryCommittee(
+ name="Regional Development",
+ chair="",
+ vice_chair="",
+ responsibilities=["Regional policy", "Cohesion policy", "Urban development"]
+ ),
+ "Security and Defence": ParliamentaryCommittee(
+ name="Security and Defence",
+ chair="",
+ vice_chair="",
+ responsibilities=["Security policy", "Defence", "Military cooperation"]
+ ),
+ "Transport and Tourism": ParliamentaryCommittee(
+ name="Transport and Tourism",
+ chair="",
+ vice_chair="",
+ responsibilities=["Transport policy", "Tourism", "Infrastructure"]
+ ),
+ }
+
+ return committees
+
+ def _organize_political_groups(self) -> Dict[str, List[str]]:
+ """
+ Organize MEPs by political groups.
+
+ Returns:
+ Dict[str, List[str]]: Dictionary mapping political groups to MEP names
+ """
+ groups = {}
+ for mep_name, mep in self.meps.items():
+ group = mep.political_group
+ if group not in groups:
+ groups[group] = []
+ groups[group].append(mep_name)
+ return groups
+
+ def _create_parliamentary_leadership(self):
+ """Create parliamentary leadership positions."""
+ # Assign President (from largest political group)
+ largest_group = max(self.political_groups.items(), key=lambda x: len(x[1]))
+ president_candidate = largest_group[1][0]
+ self.meps[president_candidate].role = ParliamentaryRole.PRESIDENT
+
+ # Assign Vice Presidents
+ vice_presidents = []
+ for group_name, meps in self.political_groups.items():
+ if group_name != largest_group[0] and len(meps) > 0:
+ vice_presidents.append(meps[0])
+ if len(vice_presidents) >= 14: # EP has 14 Vice Presidents
+ break
+
+ for vp in vice_presidents:
+ self.meps[vp].role = ParliamentaryRole.VICE_PRESIDENT
+
+ # Assign Committee Chairs
+ self._assign_committee_leadership()
+
+ def _assign_committee_leadership(self):
+ """Assign committee chairs and vice-chairs based on political group representation."""
+ committee_names = list(self.committees.keys())
+
+ # Distribute committee leadership among political groups
+ group_assignments = {}
+ for group_name, meps in self.political_groups.items():
+ if len(meps) > 0:
+ group_assignments[group_name] = meps
+
+ committee_index = 0
+ for group_name, meps in group_assignments.items():
+ if committee_index >= len(committee_names):
+ break
+
+ committee_name = committee_names[committee_index]
+ chair = meps[0]
+ vice_chair = meps[1] if len(meps) > 1 else ""
+
+ self.committees[committee_name].chair = chair
+ self.committees[committee_name].vice_chair = vice_chair
+
+ # Update MEP roles
+ self.meps[chair].role = ParliamentaryRole.COMMITTEE_CHAIR
+ if vice_chair:
+ self.meps[vice_chair].role = ParliamentaryRole.COMMITTEE_VICE_CHAIR
+
+ committee_index += 1
+
+ def _init_democratic_decision_making(self):
+ """Initialize democratic decision-making using Board of Directors pattern."""
+ # Create parliamentary board members for democratic decision-making
+ board_members = []
+
+ # Add political group leaders
+ for group_name, meps in self.political_groups.items():
+ if len(meps) > 0:
+ leader = meps[0]
+ if leader in self.meps and self.meps[leader].agent is not None:
+ board_member = BoardMember(
+ agent=self.meps[leader].agent,
+ role=BoardMemberRole.EXECUTIVE_DIRECTOR,
+ voting_weight=len(meps) / len(self.meps), # Weight based on group size
+ expertise_areas=self.meps[leader].expertise_areas
+ )
+ board_members.append(board_member)
+
+ # Ensure we have at least one board member
+ if not board_members and len(self.meps) > 0:
+ # Use the first available MEP as a fallback
+ first_mep_name = list(self.meps.keys())[0]
+ first_mep = self.meps[first_mep_name]
+ if first_mep.agent is not None:
+ board_member = BoardMember(
+ agent=first_mep.agent,
+ role=BoardMemberRole.EXECUTIVE_DIRECTOR,
+ voting_weight=1.0,
+ expertise_areas=first_mep.expertise_areas
+ )
+ board_members.append(board_member)
+
+ # Create the democratic decision-making swarm
+ if board_members:
+ # Extract agents from board members for the parent class
+ agents = [member.agent for member in board_members if member.agent is not None]
+
+ self.democratic_swarm = BoardOfDirectorsSwarm(
+ name="EuroSwarm Parliament Democratic Council",
+ description="Democratic decision-making body for the European Parliament",
+ board_members=board_members,
+ agents=agents, # Pass agents to parent class
+ max_loops=3,
+ verbose=self.verbose,
+ decision_threshold=0.6,
+ enable_voting=True,
+ enable_consensus=True,
+ )
+ else:
+ logger.warning("No valid board members found for democratic decision-making")
+ self.democratic_swarm = None
+
+ def _create_political_group_boards(self):
+ """Create Board of Directors for each political group with specialized expertise and individual percentages."""
+
+ # Define specialized expertise areas for governance
+ expertise_areas = {
+ "economics": ["Economic Policy", "Trade", "Budget", "Taxation", "Financial Services"],
+ "law": ["Legal Affairs", "Justice", "Civil Liberties", "Constitutional Affairs"],
+ "environment": ["Environment", "Climate Action", "Energy", "Transport"],
+ "social": ["Employment", "Social Affairs", "Health", "Education", "Culture"],
+ "foreign": ["Foreign Affairs", "Security", "Defense", "International Trade"],
+ "agriculture": ["Agriculture", "Rural Development", "Food Safety"],
+ "technology": ["Digital Affairs", "Industry", "Research", "Innovation"],
+ "regional": ["Regional Development", "Cohesion Policy", "Urban Planning"]
+ }
+
+ total_meps = len(self.meps)
+
+ for group_name, mep_list in self.political_groups.items():
+ if not mep_list:
+ continue
+
+ # Calculate voting weight (percentage of parliament)
+ voting_weight = len(mep_list) / total_meps
+
+ # Assign specialized expertise areas based on political group
+ group_expertise = self._assign_group_expertise(group_name, expertise_areas)
+
+ # Create board members with specialized roles and individual percentages
+ board_members = []
+ group_speaker = None
+ board_member_percentages = {}
+
+ # Select group speaker (CEO) - usually the first MEP in the group
+ if mep_list and mep_list[0] in self.meps:
+ group_speaker = mep_list[0]
+ speaker_mep = self.meps[group_speaker]
+
+ # Create group speaker board member with highest percentage
+ if speaker_mep.agent:
+ speaker_board_member = BoardMember(
+ agent=speaker_mep.agent,
+ role=BoardMemberRole.CHAIRMAN,
+ voting_weight=1.0,
+ expertise_areas=group_expertise
+ )
+ board_members.append(speaker_board_member)
+ # Group speaker gets 35% of the group's internal voting power
+ board_member_percentages[group_speaker] = 0.35
+
+ # Create specialized board members for each expertise area with weighted percentages
+ expertise_percentages = self._calculate_expertise_percentages(group_name, len(group_expertise))
+
+ for i, expertise_area in enumerate(group_expertise[:5]): # Limit to 5 main areas
+ # Find MEPs with relevant expertise
+ specialized_meps = [
+ mep_name for mep_name in mep_list
+ if mep_name in self.meps and
+ any(exp.lower() in expertise_area.lower() for exp in self.meps[mep_name].expertise_areas)
+ ]
+
+ if specialized_meps and i < len(expertise_percentages):
+ # Select the first specialized MEP
+ specialized_mep_name = specialized_meps[0]
+ specialized_mep = self.meps[specialized_mep_name]
+
+ if specialized_mep.agent:
+ # Assign percentage based on expertise importance
+ expertise_percentage = expertise_percentages[i]
+
+ board_member = BoardMember(
+ agent=specialized_mep.agent,
+ role=BoardMemberRole.EXECUTIVE_DIRECTOR,
+ voting_weight=expertise_percentage,
+ expertise_areas=[expertise_area]
+ )
+ board_members.append(board_member)
+ board_member_percentages[specialized_mep_name] = expertise_percentage
+
+ # Create the political group board with individual percentages
+ political_group_board = PoliticalGroupBoard(
+ group_name=group_name,
+ members=mep_list,
+ board_members=board_members,
+ expertise_areas=group_expertise,
+ voting_weight=voting_weight,
+ group_speaker=group_speaker,
+ total_meps=len(mep_list),
+ board_member_percentages=board_member_percentages
+ )
+
+ # Create BoardOfDirectorsSwarm for this political group
+ if board_members:
+ agents = [member.agent for member in board_members if member.agent is not None]
+
+ political_group_board.board_swarm = BoardOfDirectorsSwarm(
+ name=f"{group_name} Board",
+ description=f"Specialized board for {group_name} with expertise in {', '.join(group_expertise)}",
+ board_members=board_members,
+ agents=agents,
+ max_loops=3,
+ verbose=self.verbose,
+ decision_threshold=0.6,
+ enable_voting=True,
+ enable_consensus=True
+ )
+
+ self.political_group_boards[group_name] = political_group_board
+
+ if self.verbose:
+ logger.info(f"Created {group_name} board with {len(board_members)} members, "
+ f"voting weight: {voting_weight:.1%}, expertise: {', '.join(group_expertise[:3])}")
+ logger.info(f"Board member percentages: {board_member_percentages}")
+
+ def _assign_group_expertise(self, group_name: str, expertise_areas: Dict[str, List[str]]) -> List[str]:
+ """Assign specialized expertise areas based on political group ideology."""
+
+ # Map political groups to their primary expertise areas
+ group_expertise_mapping = {
+ "Group of the European People's Party (Christian Democrats)": [
+ "economics", "law", "foreign", "social"
+ ],
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
+ "social", "economics", "environment", "law"
+ ],
+ "Renew Europe Group": [
+ "economics", "technology", "environment", "foreign"
+ ],
+ "European Conservatives and Reformists Group": [
+ "law", "foreign", "economics", "regional"
+ ],
+ "Group of the Greens/European Free Alliance": [
+ "environment", "social", "technology", "agriculture"
+ ],
+ "The Left group in the European Parliament - GUE/NGL": [
+ "social", "economics", "environment", "law"
+ ],
+ "Patriots for Europe Group": [
+ "foreign", "law", "regional", "social"
+ ],
+ "Europe of Sovereign Nations Group": [
+ "foreign", "law", "regional", "economics"
+ ],
+ "Non-attached Members": [
+ "law", "foreign", "economics", "social"
+ ]
+ }
+
+ # Get primary expertise areas for this group
+ primary_areas = group_expertise_mapping.get(group_name, ["economics", "law", "social"])
+
+ # Expand to specific expertise topics
+ specific_expertise = []
+ for area in primary_areas:
+ if area in expertise_areas:
+ specific_expertise.extend(expertise_areas[area])
+
+ return specific_expertise[:8] # Limit to 8 areas
+
+ def _calculate_expertise_percentages(self, group_name: str, num_expertise_areas: int) -> List[float]:
+ """Calculate individual percentages for board members based on political group and expertise areas."""
+
+ # Define percentage distributions based on political group characteristics
+ percentage_distributions = {
+ "Group of the European People's Party (Christian Democrats)": [0.25, 0.20, 0.15, 0.05], # CEO gets 35%
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [0.25, 0.20, 0.15, 0.05],
+ "Renew Europe Group": [0.30, 0.20, 0.10, 0.05], # More emphasis on first expertise
+ "Group of the Greens/European Free Alliance": [0.30, 0.20, 0.10, 0.05],
+ "European Conservatives and Reformists Group": [0.25, 0.20, 0.15, 0.05],
+ "The Left group in the European Parliament - GUE/NGL": [0.25, 0.20, 0.15, 0.05],
+ "Patriots for Europe Group": [0.30, 0.20, 0.10, 0.05],
+ "Europe of Sovereign Nations Group": [0.30, 0.20, 0.10, 0.05],
+ "Non-attached Members": [0.40, 0.20, 0.05, 0.00] # More concentrated power
+ }
+
+ # Get the distribution for this group
+ distribution = percentage_distributions.get(group_name, [0.25, 0.20, 0.15, 0.05])
+
+ # Return the appropriate number of percentages
+ return distribution[:num_expertise_areas]
+
+ def _create_parliament_speaker(self):
+ """Create the Parliament Speaker who aggregates decisions from all political groups."""
+
+ # Create parliament speaker agent
+ speaker_agent = Agent(
+ name="Parliament Speaker",
+ system_prompt=self._generate_speaker_system_prompt(),
+ llm="gpt-4",
+ verbose=self.verbose
+ )
+
+ # Calculate majority threshold
+ majority_threshold = (len(self.meps) // 2) + 1
+
+ self.parliament_speaker = ParliamentSpeaker(
+ name="Parliament Speaker",
+ agent=speaker_agent,
+ political_groups=self.political_group_boards,
+ total_meps=len(self.meps),
+ majority_threshold=majority_threshold
+ )
+
+ if self.verbose:
+ logger.info(f"Created Parliament Speaker with majority threshold: {majority_threshold}")
+
+ def _generate_speaker_system_prompt(self) -> str:
+ """Generate system prompt for the Parliament Speaker."""
+
+ return f"""You are the Parliament Speaker of the European Parliament, responsible for:
+
+1. **Aggregating Political Group Decisions**: Collect and analyze decisions from all political groups
+2. **Weighted Voting Calculation**: Calculate final results based on each group's percentage representation
+3. **Majority Determination**: Determine if a proposal passes based on weighted majority
+4. **Consensus Building**: Facilitate dialogue between groups when needed
+5. **Transparent Reporting**: Provide clear explanations of voting results
+
+**Political Group Distribution**:
+{self._format_political_group_distribution()}
+
+**Voting Rules**:
+- Each political group votes as a unified board
+- Group votes are weighted by their percentage of total MEPs
+- Majority threshold: {self.parliament_speaker.majority_threshold if self.parliament_speaker else 'TBD'} MEPs
+- Final decision: Positive, Negative, or Abstained
+
+**Your Role**: Be impartial, transparent, and ensure democratic representation of all political groups.
+"""
+
+ def _format_political_group_distribution(self) -> str:
+ """Format political group distribution for the speaker prompt."""
+
+ if not self.political_group_boards:
+ return "No political groups available"
+
+ lines = []
+ for group_name, board in self.political_group_boards.items():
+ percentage = board.voting_weight * 100
+ lines.append(f"- {group_name}: {board.total_meps} MEPs ({percentage:.1f}%)")
+
+ return "\n".join(lines)
+
+ def introduce_bill(
+ self,
+ title: str,
+ description: str,
+ bill_type: VoteType,
+ committee: str,
+ sponsor: str,
+ co_sponsors: List[str] = None
+ ) -> ParliamentaryBill:
+ """
+ Introduce a new bill to the parliament.
+
+ Args:
+ title: Bill title
+ description: Bill description
+ bill_type: Type of legislative procedure
+ committee: Primary committee
+ sponsor: Sponsoring MEP
+ co_sponsors: List of co-sponsoring MEPs
+
+ Returns:
+ ParliamentaryBill: The introduced bill
+ """
+ if sponsor not in self.meps:
+ raise ValueError(f"Sponsor {sponsor} is not a valid MEP")
+
+ if committee not in self.committees:
+ raise ValueError(f"Committee {committee} does not exist")
+
+ bill = ParliamentaryBill(
+ title=title,
+ description=description,
+ bill_type=bill_type,
+ committee=committee,
+ sponsor=sponsor,
+ co_sponsors=co_sponsors or []
+ )
+
+ self.bills.append(bill)
+ self.committees[committee].current_bills.append(bill)
+
+ logger.info(f"Bill '{title}' introduced by {sponsor} in {committee} committee")
+ return bill
+
+ def conduct_committee_hearing(
+ self,
+ committee: str,
+ bill: ParliamentaryBill,
+ participants: List[str] = None
+ ) -> Dict[str, Any]:
+ """
+ Conduct a committee hearing on a bill with cost optimization.
+
+ Args:
+ committee: Committee name
+ bill: Bill under consideration
+ participants: List of MEPs to participate
+
+ Returns:
+ Dict[str, Any]: Hearing results and transcript
+ """
+ if committee not in self.committees:
+ raise ValueError(f"Committee {committee} does not exist")
+
+ # Check budget before starting
+ if not self.cost_tracker.check_budget():
+ return {"error": "Budget exceeded", "cost_stats": self.cost_tracker.get_stats()}
+
+ committee_meps = self.committees[committee].members
+ if not participants:
+ participants = committee_meps[:10] # Limit to 10 participants
+
+ # Check cache first
+ cache_key = self._get_cache_key(f"committee_hearing_{committee}_{bill.title}", participants)
+ cached_result = self._check_cache(cache_key)
+ if cached_result:
+ return {
+ "committee": committee,
+ "bill": bill.title,
+ "participants": participants,
+ "responses": cached_result,
+ "date": datetime.now(),
+ "cached": True,
+ "cost_stats": self.cost_tracker.get_stats()
+ }
+
+ hearing_prompt = f"""
+ Committee Hearing: {committee}
+ Bill: {bill.title}
+ Description: {bill.description}
+
+ As a member of the {committee} committee, please provide your analysis and recommendations for this bill.
+ Consider:
+ 1. Technical feasibility and legal compliance
+ 2. Impact on European citizens and businesses
+ 3. Alignment with EU policies and values
+ 4. Potential amendments or improvements
+ 5. Your recommendation for the full parliament
+
+ Provide a detailed analysis with specific recommendations.
+ """
+
+ # Load MEP agents in batches
+ all_responses = {}
+ total_processed = 0
+
+ for i in range(0, len(participants), self.batch_size):
+ batch_participants = participants[i:i + self.batch_size]
+
+ # Check budget for this batch
+ if not self.cost_tracker.check_budget():
+ logger.warning(f"Budget exceeded after processing {total_processed} participants")
+ break
+
+ # Load agents for this batch
+ batch_agents = self._load_mep_agents_batch(batch_participants)
+
+ if not batch_agents:
+ continue
+
+ # Run batch
+ try:
+ batch_results = run_agents_concurrently(batch_agents, hearing_prompt)
+
+ # Map results back to participant names
+ for j, agent in enumerate(batch_agents):
+ if j < len(batch_results):
+ participant_name = batch_participants[j]
+ all_responses[participant_name] = batch_results[j]
+ total_processed += 1
+
+ # Estimate tokens used
+ estimated_tokens = len(batch_agents) * 500 # ~500 tokens per response
+ self.cost_tracker.add_tokens(estimated_tokens)
+
+ if self.verbose:
+ logger.info(f"Processed committee hearing batch {i//self.batch_size + 1}: {len(batch_agents)} participants")
+
+ except Exception as e:
+ logger.error(f"Error processing committee hearing batch: {e}")
+ continue
+
+ # Cache the results
+ if all_responses:
+ self._cache_response(cache_key, str(all_responses))
+
+ hearing_result = {
+ "committee": committee,
+ "bill": bill.title,
+ "participants": participants[:total_processed],
+ "responses": all_responses,
+ "date": datetime.now(),
+ "cached": False,
+ "cost_stats": self.cost_tracker.get_stats(),
+ "recommendations": self._synthesize_committee_recommendations(all_responses)
+ }
+
+ logger.info(f"Committee hearing completed for {bill.title} in {committee}")
+ return hearing_result
+
+ def _synthesize_committee_recommendations(self, responses: Dict[str, str]) -> Dict[str, Any]:
+ """
+ Synthesize committee recommendations from individual responses.
+
+ Args:
+ responses: Dictionary of MEP responses
+
+ Returns:
+ Dict[str, Any]: Synthesized recommendations
+ """
+ # Simple synthesis - in a real implementation, this would be more sophisticated
+ support_count = 0
+ oppose_count = 0
+ amend_count = 0
+
+ for response in responses.values():
+ response_lower = response.lower()
+ if any(word in response_lower for word in ["support", "approve", "recommend", "favorable"]):
+ support_count += 1
+ elif any(word in response_lower for word in ["oppose", "reject", "against", "unfavorable"]):
+ oppose_count += 1
+ elif any(word in response_lower for word in ["amend", "modify", "improve", "revise"]):
+ amend_count += 1
+
+ total = len(responses)
+
+ return {
+ "support_percentage": (support_count / total) * 100 if total > 0 else 0,
+ "oppose_percentage": (oppose_count / total) * 100 if total > 0 else 0,
+ "amend_percentage": (amend_count / total) * 100 if total > 0 else 0,
+ "recommendation": "support" if support_count > oppose_count else "oppose" if oppose_count > support_count else "amend"
+ }
+
+ def conduct_parliamentary_debate(
+ self,
+ bill: ParliamentaryBill,
+ participants: List[str] = None,
+ max_speakers: int = 20
+ ) -> Dict[str, Any]:
+ """
+ Conduct a parliamentary debate on a bill with cost optimization.
+
+ Args:
+ bill: Bill under debate
+ participants: List of MEPs to participate
+ max_speakers: Maximum number of speakers
+
+ Returns:
+ Dict[str, Any]: Debate transcript and analysis
+ """
+ # Check budget before starting
+ if not self.cost_tracker.check_budget():
+ return {"error": "Budget exceeded", "cost_stats": self.cost_tracker.get_stats()}
+
+ if not participants:
+ # Select diverse participants from different political groups
+ participants = []
+ for group_name, meps in self.political_groups.items():
+ if len(meps) > 0:
+ participants.extend(meps[:3]) # 3 MEPs per group
+ if len(participants) >= max_speakers:
+ break
+
+ participants = participants[:max_speakers]
+
+ # Check cache first
+ cache_key = self._get_cache_key(f"parliamentary_debate_{bill.title}", participants)
+ cached_result = self._check_cache(cache_key)
+ if cached_result:
+ return {
+ "bill": bill.title,
+ "participants": participants,
+ "transcript": cached_result,
+ "date": datetime.now(),
+ "cached": True,
+ "cost_stats": self.cost_tracker.get_stats()
+ }
+
+ debate_prompt = f"""
+ Parliamentary Debate: {bill.title}
+
+ You are participating in a parliamentary debate on this bill. Please provide your position and arguments.
+
+ Bill Description: {bill.description}
+ Bill Type: {bill.bill_type.value}
+
+ Consider:
+ 1. Your political group's position on this issue
+ 2. Impact on your country and constituents
+ 3. European-wide implications
+ 4. Your areas of expertise
+ 5. Potential amendments or alternatives
+
+ Provide a clear, reasoned argument for your position.
+ """
+
+ # Conduct debate with batching
+ debate_transcript = []
+ total_processed = 0
+
+ for i in range(0, len(participants), self.batch_size):
+ batch_participants = participants[i:i + self.batch_size]
+
+ # Check budget for this batch
+ if not self.cost_tracker.check_budget():
+ logger.warning(f"Budget exceeded after processing {total_processed} speakers")
+ break
+
+ # Load agents for this batch
+ batch_agents = self._load_mep_agents_batch(batch_participants)
+
+ if not batch_agents:
+ continue
+
+ # Run batch
+ try:
+ batch_results = run_agents_concurrently(batch_agents, debate_prompt)
+
+ # Create debate entries
+ for j, agent in enumerate(batch_agents):
+ if j < len(batch_results):
+ participant_name = batch_participants[j]
+ mep = self.meps[participant_name]
+
+ debate_entry = {
+ "speaker": participant_name,
+ "political_group": mep.political_group,
+ "country": mep.country,
+ "position": batch_results[j],
+ "timestamp": datetime.now()
+ }
+ debate_transcript.append(debate_entry)
+ total_processed += 1
+
+ # Estimate tokens used
+ estimated_tokens = len(batch_agents) * 500 # ~500 tokens per response
+ self.cost_tracker.add_tokens(estimated_tokens)
+
+ if self.verbose:
+ logger.info(f"Processed debate batch {i//self.batch_size + 1}: {len(batch_agents)} speakers")
+
+ except Exception as e:
+ logger.error(f"Error processing debate batch: {e}")
+ continue
+
+ # Cache the results
+ if debate_transcript:
+ self._cache_response(cache_key, str(debate_transcript))
+
+ debate_result = {
+ "bill": bill.title,
+ "participants": participants[:total_processed],
+ "transcript": debate_transcript,
+ "date": datetime.now(),
+ "cached": False,
+ "cost_stats": self.cost_tracker.get_stats(),
+ "analysis": self._analyze_debate(debate_transcript)
+ }
+
+ self.debates.append(debate_result)
+ logger.info(f"Parliamentary debate completed for {bill.title} with {total_processed} speakers")
+ return debate_result
+
+ def _analyze_debate(self, transcript: List[Dict[str, Any]]) -> Dict[str, Any]:
+ """
+ Analyze debate transcript for key themes and positions.
+
+ Args:
+ transcript: Debate transcript
+
+ Returns:
+ Dict[str, Any]: Debate analysis
+ """
+ # Simple analysis - in a real implementation, this would use NLP
+ support_count = 0
+ oppose_count = 0
+ neutral_count = 0
+
+ for entry in transcript:
+ position = entry["position"].lower()
+ if any(word in position for word in ["support", "approve", "favorable", "yes"]):
+ support_count += 1
+ elif any(word in position for word in ["oppose", "reject", "against", "no"]):
+ oppose_count += 1
+ else:
+ neutral_count += 1
+
+ total = len(transcript)
+
+ return {
+ "support_count": support_count,
+ "oppose_count": oppose_count,
+ "neutral_count": neutral_count,
+ "support_percentage": (support_count / total) * 100 if total > 0 else 0,
+ "oppose_percentage": (oppose_count / total) * 100 if total > 0 else 0,
+ "neutral_percentage": (neutral_count / total) * 100 if total > 0 else 0
+ }
+
+ def conduct_democratic_vote(
+ self,
+ bill: ParliamentaryBill,
+ participants: List[str] = None
+ ) -> ParliamentaryVote:
+ """
+ Conduct a democratic vote on a bill using the Board of Directors pattern with lazy loading.
+
+ Args:
+ bill: Bill to vote on
+ participants: List of MEPs to participate
+
+ Returns:
+ ParliamentaryVote: Vote results
+ """
+ # Check budget before starting
+ if not self.cost_tracker.check_budget():
+ return ParliamentaryVote(
+ bill=bill,
+ vote_type=bill.bill_type,
+ result=VoteResult.FAILED
+ )
+
+ if not participants:
+ participants = list(self.meps.keys())
+
+ # Use democratic swarm for decision-making if available
+ democratic_result = None
+ if self.democratic_swarm is not None:
+ decision_task = f"""
+ Parliamentary Vote: {bill.title}
+
+ Bill Description: {bill.description}
+ Bill Type: {bill.bill_type.value}
+
+ As a democratic decision-making body, please:
+ 1. Analyze the bill's merits and implications
+ 2. Consider the interests of all European citizens
+ 3. Evaluate alignment with European values and policies
+ 4. Make a democratic decision on whether to support or oppose this bill
+ 5. Provide reasoning for your decision
+
+ This is a critical legislative decision that will affect all EU citizens.
+ """
+
+ # Get democratic decision
+ democratic_result = self.democratic_swarm.run_board_meeting(decision_task)
+
+ # Conduct individual MEP votes with lazy loading
+ individual_votes = {}
+ reasoning = {}
+ total_processed = 0
+
+ # Process participants in batches
+ for i in range(0, len(participants), self.batch_size):
+ batch_participants = participants[i:i + self.batch_size]
+
+ # Check budget for this batch
+ if not self.cost_tracker.check_budget():
+ logger.warning(f"Budget exceeded after processing {total_processed} voters")
+ break
+
+ # Load agents for this batch
+ batch_agents = self._load_mep_agents_batch(batch_participants)
+
+ if not batch_agents:
+ continue
+
+ # Create voting prompt
+ vote_prompt = f"""
+ Vote on Bill: {bill.title}
+
+ {bill.description}
+
+ {f"Democratic Council Decision: {democratic_result.plan}" if democratic_result else "No democratic council decision available."}
+
+ As an MEP, please vote on this bill. Consider:
+ 1. The democratic council's analysis (if available)
+ 2. Your political group's position
+ 3. Your constituents' interests
+ 4. European-wide implications
+
+ Respond with 'FOR', 'AGAINST', or 'ABSTAIN' and explain your reasoning.
+ """
+
+ # Run batch voting
+ try:
+ batch_results = run_agents_concurrently(batch_agents, vote_prompt)
+
+ # Process results
+ for j, agent in enumerate(batch_agents):
+ if j < len(batch_results):
+ participant_name = batch_participants[j]
+ response = batch_results[j]
+
+ # Parse vote
+ response_lower = response.lower()
+ if any(word in response_lower for word in ["for", "support", "yes", "approve"]):
+ vote = "FOR"
+ elif any(word in response_lower for word in ["against", "oppose", "no", "reject"]):
+ vote = "AGAINST"
+ else:
+ vote = "ABSTAIN"
+
+ individual_votes[participant_name] = vote
+ reasoning[participant_name] = response
+ total_processed += 1
+
+ # Estimate tokens used
+ estimated_tokens = len(batch_agents) * 500 # ~500 tokens per response
+ self.cost_tracker.add_tokens(estimated_tokens)
+
+ if self.verbose:
+ logger.info(f"Processed voting batch {i//self.batch_size + 1}: {len(batch_agents)} voters")
+
+ except Exception as e:
+ logger.error(f"Error processing voting batch: {e}")
+ continue
+
+ # Calculate results
+ votes_for = sum(1 for vote in individual_votes.values() if vote == "FOR")
+ votes_against = sum(1 for vote in individual_votes.values() if vote == "AGAINST")
+ abstentions = sum(1 for vote in individual_votes.values() if vote == "ABSTAIN")
+ absent = len(participants) - len(individual_votes)
+
+ # Determine result
+ if votes_for > votes_against:
+ result = VoteResult.PASSED
+ elif votes_against > votes_for:
+ result = VoteResult.FAILED
+ else:
+ result = VoteResult.TIED
+
+ vote_result = ParliamentaryVote(
+ bill=bill,
+ vote_type=bill.bill_type,
+ votes_for=votes_for,
+ votes_against=votes_against,
+ abstentions=abstentions,
+ absent=absent,
+ result=result,
+ individual_votes=individual_votes,
+ reasoning=reasoning
+ )
+
+ self.votes.append(vote_result)
+ bill.status = "voted"
+
+ logger.info(f"Democratic vote completed for {bill.title}: {result.value} ({total_processed} voters processed)")
+ return vote_result
+
+ def conduct_hierarchical_democratic_vote(
+ self,
+ bill: ParliamentaryBill,
+ participants: List[str] = None
+ ) -> ParliamentaryVote:
+ """
+ Conduct a hierarchical democratic vote using political group boards and parliament speaker.
+
+ This enhanced voting system:
+ 1. Each political group votes internally as a specialized board
+ 2. Group speakers (CEOs) synthesize their group's position
+ 3. Parliament Speaker aggregates all group decisions based on percentage representation
+ 4. Final result calculated using weighted voting
+
+ Args:
+ bill: Bill to vote on
+ participants: List of MEPs to participate (optional, uses all by default)
+
+ Returns:
+ ParliamentaryVote: Enhanced vote results with group-level analysis
+ """
+
+ if not self.enable_hierarchical_democracy:
+ logger.warning("Hierarchical democracy not enabled, falling back to standard voting")
+ return self.conduct_democratic_vote(bill, participants)
+
+ logger.info(f"Conducting hierarchical democratic vote on: {bill.title}")
+
+ # Initialize vote tracking
+ vote = ParliamentaryVote(
+ bill=bill,
+ vote_type=bill.bill_type,
+ date=datetime.now()
+ )
+
+ # Step 1: Each political group votes internally
+ group_decisions = {}
+ group_reasoning = {}
+
+ for group_name, group_board in self.political_group_boards.items():
+ if not group_board.board_swarm:
+ continue
+
+ logger.info(f"Conducting internal vote for {group_name}")
+
+ # Create voting task for this group
+ voting_task = f"""
+ Parliamentary Vote: {bill.title}
+
+ Bill Description: {bill.description}
+ Bill Type: {bill.bill_type.value}
+ Committee: {bill.committee}
+ Sponsor: {bill.sponsor}
+
+ As a specialized board representing {group_name} with expertise in {', '.join(group_board.expertise_areas[:3])},
+ please analyze this bill and provide your group's position.
+
+ Consider:
+ 1. How does this bill align with your political group's values and priorities?
+ 2. What are the economic, social, and legal implications?
+ 3. How does it affect your areas of expertise?
+ 4. What amendments or modifications would you suggest?
+
+ Provide your group's decision: POSITIVE, NEGATIVE, or ABSTAIN
+ Include detailed reasoning for your position.
+ """
+
+ try:
+ # Get group decision using their specialized board
+ group_result = group_board.board_swarm.run(voting_task)
+
+ # Parse the group decision
+ group_decision = self._parse_group_decision(group_result)
+ group_decisions[group_name] = group_decision
+ group_reasoning[group_name] = group_result
+
+ logger.info(f"{group_name} decision: {group_decision}")
+
+ except Exception as e:
+ logger.error(f"Error in {group_name} vote: {e}")
+ group_decisions[group_name] = "ABSTAIN"
+ group_reasoning[group_name] = f"Error during voting: {str(e)}"
+
+ # Step 2: Parliament Speaker aggregates group decisions
+ if self.parliament_speaker and self.parliament_speaker.agent:
+ logger.info("Parliament Speaker aggregating group decisions")
+
+ aggregation_task = f"""
+ Parliamentary Vote Aggregation: {bill.title}
+
+ Political Group Decisions:
+ {self._format_group_decisions(group_decisions, group_reasoning)}
+
+ Political Group Distribution:
+ {self._format_political_group_distribution()}
+
+ As Parliament Speaker, calculate the final result based on:
+ 1. Each group's decision (POSITIVE/NEGATIVE/ABSTAIN)
+ 2. Each group's voting weight (percentage of parliament)
+ 3. Majority threshold: {self.parliament_speaker.majority_threshold} MEPs
+
+ Provide:
+ 1. Final result: PASSED, FAILED, or TIED
+ 2. Vote counts: For, Against, Abstentions
+ 3. Weighted analysis of each group's contribution
+ 4. Summary of the democratic process
+ """
+
+ try:
+ speaker_result = self.parliament_speaker.agent.run(aggregation_task)
+
+ # Parse speaker's analysis
+ final_result = self._parse_speaker_analysis(speaker_result, group_decisions)
+
+ # Update vote with results
+ vote.result = final_result['result']
+ vote.votes_for = final_result['votes_for']
+ vote.votes_against = final_result['votes_against']
+ vote.abstentions = final_result['abstentions']
+ vote.individual_votes = group_decisions
+ vote.reasoning = group_reasoning
+
+ logger.info(f"Final result: {vote.result.value}")
+ logger.info(f"Votes - For: {vote.votes_for}, Against: {vote.votes_against}, Abstain: {vote.abstentions}")
+
+ except Exception as e:
+ logger.error(f"Error in speaker aggregation: {e}")
+ # Fallback to simple counting
+ vote = self._fallback_vote_calculation(vote, group_decisions)
+
+ # Store the vote
+ self.votes.append(vote)
+
+ return vote
+
+ def _parse_group_decision(self, group_result: str) -> str:
+ """Parse the decision from a political group's voting result."""
+
+ result_lower = group_result.lower()
+
+ if any(word in result_lower for word in ['positive', 'for', 'support', 'approve', 'pass']):
+ return "POSITIVE"
+ elif any(word in result_lower for word in ['negative', 'against', 'oppose', 'reject', 'fail']):
+ return "NEGATIVE"
+ else:
+ return "ABSTAIN"
+
+ def _format_group_decisions(self, group_decisions: Dict[str, str], group_reasoning: Dict[str, str]) -> str:
+ """Format group decisions for the speaker's analysis."""
+
+ lines = []
+ for group_name, decision in group_decisions.items():
+ board = self.political_group_boards.get(group_name)
+ if board:
+ percentage = board.voting_weight * 100
+ reasoning = group_reasoning.get(group_name, "No reasoning provided")
+ lines.append(f"- {group_name} ({board.total_meps} MEPs, {percentage:.1f}%): {decision}")
+ lines.append(f" Reasoning: {reasoning[:200]}...")
+
+ return "\n".join(lines)
+
+ def _parse_speaker_analysis(self, speaker_result: str, group_decisions: Dict[str, str]) -> Dict[str, Any]:
+ """Parse the Parliament Speaker's analysis to extract final vote results using dual-layer percentage system."""
+
+ # Initialize counters
+ votes_for = 0
+ votes_against = 0
+ abstentions = 0
+
+ # Calculate weighted votes using dual-layer percentage system
+ for group_name, decision in group_decisions.items():
+ board = self.political_group_boards.get(group_name)
+ if board and board.board_member_percentages:
+ # Calculate weighted votes using individual board member percentages
+ group_weighted_votes = self._calculate_group_weighted_votes(board, decision)
+
+ if decision == "POSITIVE":
+ votes_for += group_weighted_votes
+ elif decision == "NEGATIVE":
+ votes_against += group_weighted_votes
+ else: # ABSTAIN
+ abstentions += group_weighted_votes
+ else:
+ # Fallback to simple calculation if no individual percentages available
+ if board:
+ weighted_votes = int(board.total_meps * board.voting_weight)
+
+ if decision == "POSITIVE":
+ votes_for += weighted_votes
+ elif decision == "NEGATIVE":
+ votes_against += weighted_votes
+ else: # ABSTAIN
+ abstentions += weighted_votes
+
+ # Determine result
+ if votes_for > votes_against:
+ result = VoteResult.PASSED
+ elif votes_against > votes_for:
+ result = VoteResult.FAILED
+ else:
+ result = VoteResult.TIED
+
+ return {
+ 'result': result,
+ 'votes_for': votes_for,
+ 'votes_against': votes_against,
+ 'abstentions': abstentions
+ }
+
+ def _calculate_group_weighted_votes(self, board: PoliticalGroupBoard, decision: str) -> int:
+ """Calculate weighted votes for a political group using individual board member percentages."""
+
+ total_weighted_votes = 0
+
+ # Calculate votes based on individual board member percentages
+ for member_name, internal_percentage in board.board_member_percentages.items():
+ # Convert internal percentage to parliament percentage
+ # internal_percentage is percentage within the group
+ # board.voting_weight is group's percentage of parliament
+ parliament_percentage = internal_percentage * board.voting_weight
+
+ # Calculate weighted votes for this member
+ member_weighted_votes = int(board.total_meps * parliament_percentage)
+ total_weighted_votes += member_weighted_votes
+
+ if self.verbose:
+ logger.debug(f"{member_name}: {internal_percentage:.1%} of {board.group_name} "
+ f"({board.voting_weight:.1%} of parliament) = {parliament_percentage:.3%} "
+ f"= {member_weighted_votes} weighted votes")
+
+ return total_weighted_votes
+
+ def _fallback_vote_calculation(self, vote: ParliamentaryVote, group_decisions: Dict[str, str]) -> ParliamentaryVote:
+ """Fallback vote calculation if speaker analysis fails."""
+
+ votes_for = 0
+ votes_against = 0
+ abstentions = 0
+
+ for group_name, decision in group_decisions.items():
+ board = self.political_group_boards.get(group_name)
+ if board:
+ if decision == "POSITIVE":
+ votes_for += board.total_meps
+ elif decision == "NEGATIVE":
+ votes_against += board.total_meps
+ else:
+ abstentions += board.total_meps
+
+ vote.votes_for = votes_for
+ vote.votes_against = votes_against
+ vote.abstentions = abstentions
+
+ if votes_for > votes_against:
+ vote.result = VoteResult.PASSED
+ elif votes_against > votes_for:
+ vote.result = VoteResult.FAILED
+ else:
+ vote.result = VoteResult.TIED
+
+ return vote
+
+ def get_parliament_composition(self) -> Dict[str, Any]:
+ """
+ Get the current composition of the parliament including cost statistics.
+
+ Returns:
+ Dict[str, Any]: Parliament composition statistics
+ """
+ composition = {
+ "total_meps": len(self.meps),
+ "loaded_meps": len([mep for mep in self.meps.values() if mep.is_loaded]),
+ "political_groups": {},
+ "countries": {},
+ "leadership": {},
+ "committees": {},
+ "cost_stats": self.cost_tracker.get_stats(),
+ "optimization": {
+ "lazy_loading": self.enable_lazy_loading,
+ "caching": self.enable_caching,
+ "batch_size": self.batch_size,
+ "budget_limit": self.cost_tracker.budget_limit
+ }
+ }
+
+ # Political group breakdown
+ for group_name, meps in self.political_groups.items():
+ composition["political_groups"][group_name] = {
+ "count": len(meps),
+ "percentage": (len(meps) / len(self.meps)) * 100
+ }
+
+ # Country breakdown
+ country_counts = {}
+ for mep in self.meps.values():
+ country = mep.country
+ country_counts[country] = country_counts.get(country, 0) + 1
+
+ composition["countries"] = country_counts
+
+ # Leadership positions
+ leadership = {}
+ for mep in self.meps.values():
+ if mep.role != ParliamentaryRole.MEP:
+ role = mep.role.value
+ if role not in leadership:
+ leadership[role] = []
+ leadership[role].append(mep.full_name)
+
+ composition["leadership"] = leadership
+
+ # Committee composition
+ for committee_name, committee in self.committees.items():
+ composition["committees"][committee_name] = {
+ "chair": committee.chair,
+ "vice_chair": committee.vice_chair,
+ "member_count": len(committee.members),
+ "current_bills": len(committee.current_bills)
+ }
+
+ return composition
+
+ def get_cost_statistics(self) -> Dict[str, Any]:
+ """
+ Get detailed cost statistics for the parliamentary operations.
+
+ Returns:
+ Dict[str, Any]: Cost statistics and optimization metrics
+ """
+ stats = self.cost_tracker.get_stats()
+
+ # Add additional metrics
+ stats.update({
+ "total_meps": len(self.meps),
+ "loaded_meps": len([mep for mep in self.meps.values() if mep.is_loaded]),
+ "loading_efficiency": len([mep for mep in self.meps.values() if mep.is_loaded]) / len(self.meps) if self.meps else 0,
+ "cache_size": len(self.response_cache),
+ "optimization_enabled": {
+ "lazy_loading": self.enable_lazy_loading,
+ "caching": self.enable_caching,
+ "batching": self.batch_size > 1
+ }
+ })
+
+ return stats
+
+ def run_optimized_parliamentary_session(
+ self,
+ bill_title: str,
+ bill_description: str,
+ bill_type: VoteType = VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee: str = "Legal Affairs",
+ sponsor: str = None,
+ max_cost: float = 50.0
+ ) -> Dict[str, Any]:
+ """
+ Run a complete parliamentary session with cost optimization.
+
+ Args:
+ bill_title: Title of the bill
+ bill_description: Description of the bill
+ bill_type: Type of legislative procedure
+ committee: Primary committee
+ sponsor: Sponsoring MEP (random if not specified)
+ max_cost: Maximum cost for this session
+
+ Returns:
+ Dict[str, Any]: Complete session results with cost tracking
+ """
+ # Set temporary budget for this session
+ original_budget = self.cost_tracker.budget_limit
+ self.cost_tracker.budget_limit = min(original_budget, max_cost)
+
+ try:
+ # Select sponsor if not provided
+ if not sponsor:
+ sponsor = random.choice(list(self.meps.keys()))
+
+ # Introduce bill
+ bill = self.introduce_bill(
+ title=bill_title,
+ description=bill_description,
+ bill_type=bill_type,
+ committee=committee,
+ sponsor=sponsor
+ )
+
+ # Conduct committee hearing
+ hearing = self.conduct_committee_hearing(committee, bill)
+
+ # Conduct parliamentary debate
+ debate = self.conduct_parliamentary_debate(bill)
+
+ # Conduct democratic vote
+ vote = self.conduct_democratic_vote(bill)
+
+ session_result = {
+ "bill": bill,
+ "hearing": hearing,
+ "debate": debate,
+ "vote": vote,
+ "cost_stats": self.cost_tracker.get_stats(),
+ "session_summary": {
+ "bill_title": bill_title,
+ "sponsor": sponsor,
+ "committee": committee,
+ "hearing_recommendation": hearing.get("recommendations", {}).get("recommendation", "unknown"),
+ "debate_support_percentage": debate.get("analysis", {}).get("support_percentage", 0),
+ "vote_result": vote.result.value,
+ "final_outcome": "PASSED" if vote.result == VoteResult.PASSED else "FAILED",
+ "total_cost": self.cost_tracker.total_cost_estimate
+ }
+ }
+
+ logger.info(f"Optimized parliamentary session completed for {bill_title}: {session_result['session_summary']['final_outcome']}")
+ logger.info(f"Session cost: ${self.cost_tracker.total_cost_estimate:.2f}")
+
+ return session_result
+
+ finally:
+ # Restore original budget
+ self.cost_tracker.budget_limit = original_budget
+
+ def run_democratic_session(
+ self,
+ bill_title: str,
+ bill_description: str,
+ bill_type: VoteType = VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee: str = "Legal Affairs",
+ sponsor: str = None
+ ) -> Dict[str, Any]:
+ """
+ Run a complete democratic parliamentary session on a bill.
+
+ Args:
+ bill_title: Title of the bill
+ bill_description: Description of the bill
+ bill_type: Type of legislative procedure
+ committee: Primary committee
+ sponsor: Sponsoring MEP (random if not specified)
+
+ Returns:
+ Dict[str, Any]: Complete session results
+ """
+ # Select sponsor if not provided
+ if not sponsor:
+ sponsor = random.choice(list(self.meps.keys()))
+
+ # Introduce bill
+ bill = self.introduce_bill(
+ title=bill_title,
+ description=bill_description,
+ bill_type=bill_type,
+ committee=committee,
+ sponsor=sponsor
+ )
+
+ # Conduct committee hearing
+ hearing = self.conduct_committee_hearing(committee, bill)
+
+ # Conduct parliamentary debate
+ debate = self.conduct_parliamentary_debate(bill)
+
+ # Conduct democratic vote
+ vote = self.conduct_democratic_vote(bill)
+
+ session_result = {
+ "bill": bill,
+ "hearing": hearing,
+ "debate": debate,
+ "vote": vote,
+ "session_summary": {
+ "bill_title": bill_title,
+ "sponsor": sponsor,
+ "committee": committee,
+ "hearing_recommendation": hearing["recommendations"]["recommendation"],
+ "debate_support_percentage": debate["analysis"]["support_percentage"],
+ "vote_result": vote.result.value,
+ "final_outcome": "PASSED" if vote.result == VoteResult.PASSED else "FAILED"
+ }
+ }
+
+ logger.info(f"Democratic session completed for {bill_title}: {session_result['session_summary']['final_outcome']}")
+ return session_result
+
+ def run_hierarchical_democratic_session(
+ self,
+ bill_title: str,
+ bill_description: str,
+ bill_type: VoteType = VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee: str = "Legal Affairs",
+ sponsor: str = None
+ ) -> Dict[str, Any]:
+ """
+ Run a complete hierarchical democratic session from bill introduction to final vote.
+
+ This enhanced session uses:
+ 1. Political group boards with specialized expertise
+ 2. Group-level internal voting and discussion
+ 3. Parliament Speaker aggregation of group decisions
+ 4. Weighted voting based on political group percentages
+
+ Args:
+ bill_title: Title of the bill
+ bill_description: Description of the bill
+ bill_type: Type of legislative procedure
+ committee: Committee responsible for the bill
+ sponsor: MEP sponsoring the bill
+
+ Returns:
+ Dict[str, Any]: Complete session results including group decisions and final vote
+ """
+
+ if not self.enable_hierarchical_democracy:
+ logger.warning("Hierarchical democracy not enabled, falling back to standard session")
+ return self.run_democratic_session(bill_title, bill_description, bill_type, committee, sponsor)
+
+ logger.info(f"Starting hierarchical democratic session: {bill_title}")
+
+ # Step 1: Introduce the bill
+ if not sponsor:
+ sponsor = list(self.meps.keys())[0] # Use first MEP as sponsor
+
+ bill = self.introduce_bill(
+ title=bill_title,
+ description=bill_description,
+ bill_type=bill_type,
+ committee=committee,
+ sponsor=sponsor
+ )
+
+ # Step 2: Conduct committee hearing (if enabled)
+ committee_result = None
+ if self.enable_committee_work:
+ logger.info(f"Conducting committee hearing in {committee}")
+ committee_result = self.conduct_committee_hearing(committee, bill)
+
+ # Step 3: Conduct parliamentary debate (if enabled)
+ debate_result = None
+ if self.enable_democratic_discussion:
+ logger.info("Conducting parliamentary debate")
+ debate_result = self.conduct_parliamentary_debate(bill)
+
+ # Step 4: Conduct hierarchical democratic vote
+ logger.info("Conducting hierarchical democratic vote")
+ vote_result = self.conduct_hierarchical_democratic_vote(bill)
+
+ # Step 5: Compile comprehensive session report
+ session_report = {
+ "session_type": "hierarchical_democratic",
+ "bill": {
+ "title": bill.title,
+ "description": bill.description,
+ "type": bill.bill_type.value,
+ "committee": bill.committee,
+ "sponsor": bill.sponsor,
+ "status": bill.status
+ },
+ "committee_work": committee_result,
+ "parliamentary_debate": debate_result,
+ "vote_results": {
+ "final_result": vote_result.result.value,
+ "votes_for": vote_result.votes_for,
+ "votes_against": vote_result.votes_against,
+ "abstentions": vote_result.abstentions,
+ "total_votes": vote_result.votes_for + vote_result.votes_against + vote_result.abstentions
+ },
+ "political_group_decisions": vote_result.individual_votes,
+ "group_reasoning": vote_result.reasoning,
+ "parliament_composition": self.get_parliament_composition(),
+ "session_summary": self._generate_hierarchical_session_summary(bill, vote_result)
+ }
+
+ logger.info(f"Hierarchical democratic session completed. Final result: {vote_result.result.value}")
+
+ return session_report
+
+ def _generate_hierarchical_session_summary(self, bill: ParliamentaryBill, vote: ParliamentaryVote) -> str:
+ """Generate a summary of the hierarchical democratic session with dual-layer percentage breakdown."""
+
+ total_votes = vote.votes_for + vote.votes_against + vote.abstentions
+ participation_rate = (total_votes / len(self.meps)) * 100 if self.meps else 0
+
+ summary = f"""
+šļø HIERARCHICAL DEMOCRATIC SESSION SUMMARY
+
+š Bill: {bill.title}
+š Final Result: {vote.result.value}
+š Participation Rate: {participation_rate:.1f}%
+
+š³ļø VOTE BREAKDOWN:
+⢠For: {vote.votes_for} votes
+⢠Against: {vote.votes_against} votes
+⢠Abstentions: {vote.abstentions} votes
+
+šļø POLITICAL GROUP DECISIONS (Dual-Layer Percentage System):
+"""
+
+ for group_name, decision in vote.individual_votes.items():
+ board = self.political_group_boards.get(group_name)
+ if board:
+ group_percentage = board.voting_weight * 100
+ summary += f"\n⢠{group_name}: {decision} ({board.total_meps} MEPs, {group_percentage:.1f}% of parliament)"
+
+ # Show individual board member percentages
+ if board.board_member_percentages:
+ summary += f"\n š Board Member Breakdown:"
+ for member_name, internal_percentage in board.board_member_percentages.items():
+ parliament_percentage = internal_percentage * board.voting_weight * 100
+ summary += f"\n - {member_name}: {internal_percentage:.1%} of group = {parliament_percentage:.3f}% of parliament"
+
+ summary += f"\n\nšÆ DUAL-LAYER DEMOCRATIC PROCESS:"
+ summary += f"\n⢠Each political group operates as a specialized board"
+ summary += f"\n⢠Board members have individual percentages within their group"
+ summary += f"\n⢠Individual percentages à Group percentage = Parliament percentage"
+ summary += f"\n⢠Parliament Speaker aggregates all weighted decisions"
+ summary += f"\n⢠Final result based on {len(self.political_group_boards)} political groups with {sum(len(board.board_member_percentages) for board in self.political_group_boards.values())} board members"
+
+ return summary
+
+ def get_mep(self, mep_name: str) -> Optional[ParliamentaryMember]:
+ """
+ Get a specific MEP by name.
+
+ Args:
+ mep_name: Name of the MEP
+
+ Returns:
+ Optional[ParliamentaryMember]: MEP if found, None otherwise
+ """
+ return self.meps.get(mep_name)
+
+ def get_committee(self, committee_name: str) -> Optional[ParliamentaryCommittee]:
+ """
+ Get a specific committee by name.
+
+ Args:
+ committee_name: Name of the committee
+
+ Returns:
+ Optional[ParliamentaryCommittee]: Committee if found, None otherwise
+ """
+ return self.committees.get(committee_name)
+
+ def get_political_group_members(self, group_name: str) -> List[str]:
+ """
+ Get all MEPs in a specific political group.
+
+ Args:
+ group_name: Name of the political group
+
+ Returns:
+ List[str]: List of MEP names in the group
+ """
+ return self.political_groups.get(group_name, [])
+
+ def get_country_members(self, country: str) -> List[str]:
+ """
+ Get all MEPs from a specific country.
+
+ Args:
+ country: Name of the country
+
+ Returns:
+ List[str]: List of MEP names from the country
+ """
+ return [mep_name for mep_name, mep in self.meps.items() if mep.country == country]
+
+ def _load_wikipedia_personalities(self):
+ """Load Wikipedia personality profiles for MEPs."""
+
+ if not self.enable_wikipedia_personalities:
+ return
+
+ try:
+ # Initialize personality scraper
+ self.personality_scraper = WikipediaPersonalityScraper(
+ output_dir="mep_personalities",
+ verbose=self.verbose
+ )
+
+ # Load existing personality profiles
+ personality_dir = "mep_personalities"
+ if os.path.exists(personality_dir):
+ profile_files = [f for f in os.listdir(personality_dir) if f.endswith('.json')]
+
+ for filename in profile_files:
+ filepath = os.path.join(personality_dir, filename)
+ try:
+ profile = self.personality_scraper.load_personality_profile(filepath)
+ self.personality_profiles[profile.full_name] = profile
+
+ if self.verbose:
+ logger.debug(f"Loaded personality profile: {profile.full_name}")
+
+ except Exception as e:
+ logger.warning(f"Error loading personality profile {filename}: {e}")
+
+ if self.verbose:
+ logger.info(f"Loaded {len(self.personality_profiles)} Wikipedia personality profiles")
+ else:
+ if self.verbose:
+ logger.info("No existing personality profiles found. Run Wikipedia scraper to create profiles.")
+
+ except Exception as e:
+ logger.error(f"Error loading Wikipedia personalities: {e}")
+ self.enable_wikipedia_personalities = False
+
+ def scrape_wikipedia_personalities(self, delay: float = 1.0) -> Dict[str, str]:
+ """
+ Scrape Wikipedia personality data for all MEPs.
+
+ Args:
+ delay: Delay between requests to be respectful to Wikipedia
+
+ Returns:
+ Dictionary mapping MEP names to their personality profile file paths
+ """
+
+ if not self.enable_wikipedia_personalities:
+ logger.error("Wikipedia personality system not available")
+ return {}
+
+ if not self.personality_scraper:
+ self.personality_scraper = WikipediaPersonalityScraper(
+ output_dir="mep_personalities",
+ verbose=self.verbose
+ )
+
+ logger.info("Starting Wikipedia personality scraping for all MEPs...")
+ profile_files = self.personality_scraper.scrape_all_mep_personalities(
+ xml_file=self.eu_data_file,
+ delay=delay
+ )
+
+ # Reload personality profiles
+ self._load_wikipedia_personalities()
+
+ return profile_files
+
+ def get_mep_personality_profile(self, mep_name: str) -> Optional[MEPPersonalityProfile]:
+ """
+ Get personality profile for a specific MEP.
+
+ Args:
+ mep_name: Name of the MEP
+
+ Returns:
+ MEPPersonalityProfile if found, None otherwise
+ """
+ return self.personality_profiles.get(mep_name)
+
+ def analyze_political_landscape(self, bill: ParliamentaryBill) -> Dict[str, Any]:
+ """
+ Analyze the political landscape for a bill to predict voting outcomes.
+
+ Args:
+ bill: Bill to analyze
+
+ Returns:
+ Dict[str, Any]: Political analysis results
+ """
+ analysis = {
+ "overall_support": 0.0,
+ "opposition": 0.0,
+ "uncertainty": 0.0,
+ "group_analysis": {}
+ }
+
+ # Analyze by political group
+ for group_name, meps in self.political_groups.items():
+ if not meps:
+ continue
+
+ # Simple analysis based on political group alignment
+ group_support = 0.0
+ group_opposition = 0.0
+
+ # Assign support based on political group characteristics
+ if "Green" in group_name or "Environment" in bill.description:
+ group_support = 75.0
+ group_opposition = 15.0
+ elif "Socialist" in group_name or "Social" in bill.description:
+ group_support = 70.0
+ group_opposition = 20.0
+ elif "Conservative" in group_name or "Economic" in bill.description:
+ group_support = 60.0
+ group_opposition = 30.0
+ elif "Liberal" in group_name or "Digital" in bill.description:
+ group_support = 65.0
+ group_opposition = 25.0
+ else:
+ group_support = 50.0
+ group_opposition = 30.0
+
+ group_uncertainty = 100.0 - group_support - group_opposition
+
+ analysis["group_analysis"][group_name] = {
+ "support": group_support,
+ "opposition": group_opposition,
+ "uncertainty": group_uncertainty,
+ "mep_count": len(meps)
+ }
+
+ # Calculate overall support weighted by group size
+ total_meps = len(self.meps)
+ if total_meps > 0:
+ weighted_support = 0.0
+ weighted_opposition = 0.0
+ weighted_uncertainty = 0.0
+
+ for group_name, group_data in analysis["group_analysis"].items():
+ weight = group_data["mep_count"] / total_meps
+ weighted_support += group_data["support"] * weight
+ weighted_opposition += group_data["opposition"] * weight
+ weighted_uncertainty += group_data["uncertainty"] * weight
+
+ analysis["overall_support"] = weighted_support
+ analysis["opposition"] = weighted_opposition
+ analysis["uncertainty"] = weighted_uncertainty
+
+ return analysis
\ No newline at end of file
diff --git a/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py b/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py
new file mode 100644
index 00000000..7dc60d02
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py
@@ -0,0 +1,521 @@
+"""
+EuroSwarm Parliament - Example Script
+
+This script demonstrates the comprehensive democratic functionality of the EuroSwarm Parliament,
+including bill introduction, committee work, parliamentary debates, and democratic voting.
+"""
+
+import json
+import time
+from datetime import datetime
+
+# Import directly from the file
+from euroswarm_parliament import (
+ EuroSwarmParliament,
+ VoteType,
+ ParliamentaryRole,
+ ParliamentaryMember
+)
+
+
+def demonstrate_parliament_initialization():
+ """Demonstrate parliament initialization and basic functionality with cost optimization."""
+
+ print("\nEUROSWARM PARLIAMENT INITIALIZATION DEMONSTRATION (COST OPTIMIZED)")
+ print("=" * 60)
+
+ # Initialize the parliament with cost optimization
+ parliament = EuroSwarmParliament(
+ eu_data_file="EU.xml",
+ parliament_size=None, # Use all MEPs from EU.xml (717)
+ enable_democratic_discussion=True,
+ enable_committee_work=True,
+ enable_amendment_process=True,
+ enable_lazy_loading=True, # NEW: Lazy load MEP agents
+ enable_caching=True, # NEW: Enable response caching
+ batch_size=25, # NEW: Batch size for concurrent execution
+ budget_limit=100.0, # NEW: Budget limit in dollars
+ verbose=True
+ )
+
+ print(f"Parliament initialized with {len(parliament.meps)} MEPs")
+
+ # Show parliament composition with cost stats
+ composition = parliament.get_parliament_composition()
+
+ print(f"\nPARLIAMENT COMPOSITION:")
+ print(f"Total MEPs: {composition['total_meps']}")
+ print(f"Loaded MEPs: {composition['loaded_meps']} (lazy loading active)")
+
+ print(f"\nCOST OPTIMIZATION:")
+ cost_stats = composition['cost_stats']
+ print(f"Budget Limit: ${cost_stats['budget_remaining'] + cost_stats['total_cost']:.2f}")
+ print(f"Budget Used: ${cost_stats['total_cost']:.2f}")
+ print(f"Budget Remaining: ${cost_stats['budget_remaining']:.2f}")
+ print(f"Cache Hit Rate: {cost_stats['cache_hit_rate']:.1%}")
+
+ print(f"\nPOLITICAL GROUP DISTRIBUTION:")
+ for group, data in composition['political_groups'].items():
+ count = data['count']
+ percentage = data['percentage']
+ print(f" {group}: {count} MEPs ({percentage:.1f}%)")
+
+ print(f"\nCOMMITTEE LEADERSHIP:")
+ for committee_name, committee_data in composition['committees'].items():
+ chair = committee_data['chair']
+ if chair:
+ print(f" {committee_name}: {chair}")
+
+ return parliament
+
+
+def demonstrate_individual_mep_interaction(parliament):
+ """Demonstrate individual MEP interaction and personality."""
+
+ print("\nINDIVIDUAL MEP INTERACTION DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a sample MEP
+ sample_mep_name = list(parliament.meps.keys())[0]
+ sample_mep = parliament.meps[sample_mep_name]
+
+ print(f"Sample MEP: {sample_mep.full_name}")
+ print(f"Country: {sample_mep.country}")
+ print(f"Political Group: {sample_mep.political_group}")
+ print(f"National Party: {sample_mep.national_party}")
+ print(f"Committees: {', '.join(sample_mep.committees)}")
+ print(f"Expertise Areas: {', '.join(sample_mep.expertise_areas)}")
+
+ # Test MEP agent interaction
+ if sample_mep.agent:
+ test_prompt = "What are your views on European integration and how do you approach cross-border cooperation?"
+
+ print(f"\nMEP Response to: '{test_prompt}'")
+ print("-" * 50)
+
+ try:
+ response = sample_mep.agent.run(test_prompt)
+ print(response[:500] + "..." if len(response) > 500 else response)
+ except Exception as e:
+ print(f"Error getting MEP response: {e}")
+
+
+def demonstrate_committee_work(parliament):
+ """Demonstrate committee work and hearings."""
+
+ print("\nCOMMITTEE WORK DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[0]
+
+ # Create a test bill
+ bill = parliament.introduce_bill(
+ title="European Digital Rights and Privacy Protection Act",
+ description="Comprehensive legislation to strengthen digital rights, enhance privacy protection, and establish clear guidelines for data handling across the European Union.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Legal Affairs",
+ sponsor=sponsor
+ )
+
+ print(f"Bill: {bill.title}")
+ print(f"Committee: {bill.committee}")
+ print(f"Sponsor: {bill.sponsor}")
+
+ # Conduct committee hearing
+ print(f"\nCONDUCTING COMMITTEE HEARING...")
+ hearing_result = parliament.conduct_committee_hearing(bill.committee, bill)
+
+ print(f"Committee: {hearing_result['committee']}")
+ print(f"Participants: {len(hearing_result['participants'])} MEPs")
+ print(f"Recommendation: {hearing_result['recommendations']['recommendation']}")
+ print(f"Support: {hearing_result['recommendations']['support_percentage']:.1f}%")
+ print(f"Oppose: {hearing_result['recommendations']['oppose_percentage']:.1f}%")
+ print(f"Amend: {hearing_result['recommendations']['amend_percentage']:.1f}%")
+
+
+def demonstrate_parliamentary_debate(parliament):
+ """Demonstrate parliamentary debate functionality."""
+
+ print("\nPARLIAMENTARY DEBATE DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[1]
+
+ # Create a test bill
+ bill = parliament.introduce_bill(
+ title="European Green Deal Implementation Act",
+ description="Legislation to implement the European Green Deal, including carbon neutrality targets, renewable energy investments, and sustainable development measures.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Environment, Public Health and Food Safety",
+ sponsor=sponsor
+ )
+
+ print(f"Bill: {bill.title}")
+ print(f"Description: {bill.description}")
+
+ # Conduct parliamentary debate
+ print(f"\nCONDUCTING PARLIAMENTARY DEBATE...")
+ debate_result = parliament.conduct_parliamentary_debate(bill, max_speakers=10)
+
+ print(f"Debate Participants: {len(debate_result['participants'])} MEPs")
+ print(f"Debate Analysis:")
+ print(f" Support: {debate_result['analysis']['support_count']} speakers ({debate_result['analysis']['support_percentage']:.1f}%)")
+ print(f" Oppose: {debate_result['analysis']['oppose_count']} speakers ({debate_result['analysis']['oppose_percentage']:.1f}%)")
+ print(f" Neutral: {debate_result['analysis']['neutral_count']} speakers ({debate_result['analysis']['neutral_percentage']:.1f}%)")
+
+
+def demonstrate_democratic_voting(parliament):
+ """Demonstrate democratic voting functionality."""
+
+ print("\nDEMOCRATIC VOTING DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[2]
+
+ # Create a test bill
+ bill = parliament.introduce_bill(
+ title="European Social Rights and Labor Protection Act",
+ description="Legislation to strengthen social rights, improve labor conditions, and ensure fair treatment of workers across the European Union.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Employment and Social Affairs",
+ sponsor=sponsor
+ )
+
+ print(f"Bill: {bill.title}")
+ print(f"Sponsor: {bill.sponsor}")
+
+ # Conduct democratic vote
+ print(f"\nCONDUCTING DEMOCRATIC VOTE...")
+ vote_result = parliament.conduct_democratic_vote(bill)
+
+ # Calculate percentages
+ total_votes = vote_result.votes_for + vote_result.votes_against + vote_result.abstentions
+ in_favor_percentage = (vote_result.votes_for / total_votes * 100) if total_votes > 0 else 0
+ against_percentage = (vote_result.votes_against / total_votes * 100) if total_votes > 0 else 0
+ abstentions_percentage = (vote_result.abstentions / total_votes * 100) if total_votes > 0 else 0
+
+ print(f"Vote Results:")
+ print(f" Total Votes: {total_votes}")
+ print(f" In Favor: {vote_result.votes_for} ({in_favor_percentage:.1f}%)")
+ print(f" Against: {vote_result.votes_against} ({against_percentage:.1f}%)")
+ print(f" Abstentions: {vote_result.abstentions} ({abstentions_percentage:.1f}%)")
+ print(f" Result: {vote_result.result.value}")
+
+ # Show political group breakdown if available
+ if hasattr(vote_result, 'group_votes') and vote_result.group_votes:
+ print(f"\nPOLITICAL GROUP BREAKDOWN:")
+ for group, votes in vote_result.group_votes.items():
+ print(f" {group}: {votes['in_favor']}/{votes['total']} in favor ({votes['percentage']:.1f}%)")
+ else:
+ print(f"\nIndividual votes recorded: {len(vote_result.individual_votes)} MEPs")
+
+
+def demonstrate_complete_democratic_session(parliament):
+ """Demonstrate a complete democratic parliamentary session."""
+
+ print("\nCOMPLETE DEMOCRATIC SESSION DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[3]
+
+ # Run complete session
+ session_result = parliament.run_democratic_session(
+ bill_title="European Innovation and Technology Advancement Act",
+ bill_description="Comprehensive legislation to promote innovation, support technology startups, and establish Europe as a global leader in digital transformation and technological advancement.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Industry, Research and Energy",
+ sponsor=sponsor
+ )
+
+ print(f"Session Results:")
+ print(f" Bill: {session_result['bill'].title}")
+ print(f" Committee Hearing: {session_result['hearing']['recommendations']['recommendation']}")
+ print(f" Debate Participants: {len(session_result['debate']['participants'])} MEPs")
+ print(f" Final Vote: {session_result['vote']['result']}")
+ print(f" Vote Margin: {session_result['vote']['in_favor_percentage']:.1f}% in favor")
+
+
+def demonstrate_political_analysis(parliament):
+ """Demonstrate political analysis and voting prediction."""
+
+ print("\nPOLITICAL ANALYSIS DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[4]
+
+ # Create a test bill
+ bill = parliament.introduce_bill(
+ title="European Climate Action and Sustainability Act",
+ description="Comprehensive climate action legislation including carbon pricing, renewable energy targets, and sustainable development measures.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Environment, Public Health and Food Safety",
+ sponsor=sponsor
+ )
+
+ print(f"Bill: {bill.title}")
+ print(f"Sponsor: {bill.sponsor}")
+
+ # Analyze political landscape
+ analysis = parliament.analyze_political_landscape(bill)
+
+ print(f"\nPOLITICAL LANDSCAPE ANALYSIS:")
+ print(f" Overall Support: {analysis['overall_support']:.1f}%")
+ print(f" Opposition: {analysis['opposition']:.1f}%")
+ print(f" Uncertainty: {analysis['uncertainty']:.1f}%")
+
+ print(f"\nPOLITICAL GROUP ANALYSIS:")
+ for group, data in analysis['group_analysis'].items():
+ print(f" {group}: {data['support']:.1f}% support, {data['opposition']:.1f}% opposition")
+
+
+def demonstrate_hierarchical_democratic_voting(parliament):
+ """Demonstrate hierarchical democratic voting with political group boards."""
+
+ print("\nHIERARCHICAL DEMOCRATIC VOTING DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[5]
+
+ # Create a test bill
+ bill = parliament.introduce_bill(
+ title="European Climate Action and Sustainability Act",
+ description="Comprehensive climate action legislation including carbon pricing, renewable energy targets, and sustainable development measures.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Environment, Public Health and Food Safety",
+ sponsor=sponsor
+ )
+
+ print(f"Bill: {bill.title}")
+ print(f"Sponsor: {bill.sponsor}")
+
+ # Conduct hierarchical vote
+ print(f"\nCONDUCTING HIERARCHICAL DEMOCRATIC VOTE...")
+ hierarchical_result = parliament.conduct_hierarchical_democratic_vote(bill)
+
+ print(f"Hierarchical Vote Results:")
+ print(f" Total Votes: {hierarchical_result['total_votes']}")
+ print(f" In Favor: {hierarchical_result['in_favor']} ({hierarchical_result['in_favor_percentage']:.1f}%)")
+ print(f" Against: {hierarchical_result['against']} ({hierarchical_result['against_percentage']:.1f}%)")
+ print(f" Result: {hierarchical_result['result']}")
+
+ print(f"\nPOLITICAL GROUP BOARD DECISIONS:")
+ for group, decision in hierarchical_result['group_decisions'].items():
+ print(f" {group}: {decision['decision']} ({decision['confidence']:.1f}% confidence)")
+
+
+def demonstrate_complete_hierarchical_session(parliament):
+ """Demonstrate a complete hierarchical democratic session."""
+
+ print("\nCOMPLETE HIERARCHICAL DEMOCRATIC SESSION DEMONSTRATION")
+ print("=" * 60)
+
+ # Get a real MEP as sponsor
+ sponsor = list(parliament.meps.keys())[6]
+
+ # Run complete hierarchical session
+ session_result = parliament.run_hierarchical_democratic_session(
+ bill_title="European Climate Action and Sustainability Act",
+ bill_description="Comprehensive climate action legislation including carbon pricing, renewable energy targets, and sustainable development measures.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Environment, Public Health and Food Safety",
+ sponsor=sponsor
+ )
+
+ print(f"Hierarchical Session Results:")
+ print(f" Bill: {session_result['bill'].title}")
+ print(f" Committee Hearing: {session_result['hearing']['recommendations']['recommendation']}")
+ print(f" Debate Participants: {len(session_result['debate']['participants'])} MEPs")
+ print(f" Final Vote: {session_result['vote']['result']}")
+ print(f" Vote Margin: {session_result['vote']['in_favor_percentage']:.1f}% in favor")
+
+
+def demonstrate_wikipedia_personalities(parliament):
+ """Demonstrate the Wikipedia personality system for realistic MEP behavior."""
+
+ print("\nWIKIPEDIA PERSONALITY SYSTEM DEMONSTRATION")
+ print("=" * 60)
+
+ # Check if Wikipedia personalities are available
+ if not parliament.enable_wikipedia_personalities:
+ print("Wikipedia personality system not available")
+ print("To enable: Install required dependencies and run Wikipedia scraper")
+ return
+
+ print(f"Wikipedia personality system enabled")
+ print(f"Loaded {len(parliament.personality_profiles)} personality profiles")
+
+ # Show sample personality profiles
+ print(f"\nSAMPLE PERSONALITY PROFILES:")
+ print("-" * 40)
+
+ sample_count = 0
+ for mep_name, profile in parliament.personality_profiles.items():
+ if sample_count >= 3: # Show only 3 samples
+ break
+
+ print(f"\n{mep_name}")
+ print(f" Wikipedia URL: {profile.wikipedia_url if profile.wikipedia_url else 'Not available'}")
+ print(f" Summary: {profile.summary[:200]}..." if profile.summary else "No summary available")
+ print(f" Political Views: {profile.political_views[:150]}..." if profile.political_views else "Based on party alignment")
+ print(f" Policy Focus: {profile.policy_focus[:150]}..." if profile.policy_focus else "General parliamentary work")
+ print(f" Achievements: {profile.achievements[:150]}..." if profile.achievements else "Parliamentary service")
+ print(f" Last Updated: {profile.last_updated}")
+
+ sample_count += 1
+
+ # Demonstrate personality-driven voting
+ print(f"\nPERSONALITY-DRIVEN VOTING DEMONSTRATION:")
+ print("-" * 50)
+
+ # Create a test bill that would trigger different personality responses
+ bill = parliament.introduce_bill(
+ title="European Climate Action and Green Technology Investment Act",
+ description="Comprehensive legislation to accelerate Europe's transition to renewable energy, including massive investments in green technology, carbon pricing mechanisms, and support for affected industries and workers.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Environment",
+ sponsor="Climate Action Leader"
+ )
+
+ print(f"Bill: {bill.title}")
+ print(f"Description: {bill.description}")
+
+ # Show how different MEPs with Wikipedia personalities would respond
+ print(f"\nPERSONALITY-BASED RESPONSES:")
+ print("-" * 40)
+
+ sample_meps = list(parliament.personality_profiles.keys())[:3]
+
+ for mep_name in sample_meps:
+ mep = parliament.meps.get(mep_name)
+ profile = parliament.personality_profiles.get(mep_name)
+
+ if mep and profile:
+ print(f"\n{mep_name} ({mep.political_group})")
+
+ # Show personality influence
+ if profile.political_views:
+ print(f" Political Views: {profile.political_views[:100]}...")
+
+ if profile.policy_focus:
+ print(f" Policy Focus: {profile.policy_focus[:100]}...")
+
+ # Predict voting behavior based on personality
+ if "environment" in profile.policy_focus.lower() or "climate" in profile.political_views.lower():
+ predicted_vote = "LIKELY SUPPORT"
+ reasoning = "Environmental policy focus and climate advocacy"
+ elif "economic" in profile.policy_focus.lower() or "business" in profile.political_views.lower():
+ predicted_vote = "LIKELY OPPOSE"
+ reasoning = "Economic concerns about investment costs"
+ else:
+ predicted_vote = "UNCERTAIN"
+ reasoning = "Mixed considerations based on party alignment"
+
+ print(f" Predicted Vote: {predicted_vote}")
+ print(f" Reasoning: {reasoning}")
+
+ # Demonstrate scraping functionality
+ print(f"\nWIKIPEDIA SCRAPING CAPABILITIES:")
+ print("-" * 50)
+ print("Can scrape Wikipedia data for all 717 MEPs")
+ print("Extracts political views, career history, and achievements")
+ print("Creates detailed personality profiles in JSON format")
+ print("Integrates real personality data into AI agent system prompts")
+ print("Enables realistic, personality-driven voting behavior")
+ print("Respectful API usage with configurable delays")
+
+ print(f"\nTo scrape all MEP personalities:")
+ print(" parliament.scrape_wikipedia_personalities(delay=1.0)")
+ print(" # This will create personality profiles for all 717 MEPs")
+ print(" # Profiles are saved in 'mep_personalities/' directory")
+
+
+def demonstrate_optimized_parliamentary_session(parliament):
+ """Demonstrate cost-optimized parliamentary session."""
+
+ print("\nCOST-OPTIMIZED PARLIAMENTARY SESSION DEMONSTRATION")
+ print("=" * 60)
+
+ # Run optimized session with cost limit
+ session_result = parliament.run_optimized_parliamentary_session(
+ bill_title="European Digital Rights and Privacy Protection Act",
+ bill_description="Comprehensive legislation to strengthen digital rights, enhance privacy protection, and establish clear guidelines for data handling across the European Union.",
+ bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
+ committee="Legal Affairs",
+ max_cost=25.0 # Max $25 for this session
+ )
+
+ print(f"Session Results:")
+ print(f" Bill: {session_result['session_summary']['bill_title']}")
+ print(f" Final Outcome: {session_result['session_summary']['final_outcome']}")
+ print(f" Total Cost: ${session_result['session_summary']['total_cost']:.2f}")
+ print(f" Budget Remaining: ${session_result['cost_stats']['budget_remaining']:.2f}")
+
+ # Show detailed cost statistics
+ cost_stats = parliament.get_cost_statistics()
+ print(f"\nDETAILED COST STATISTICS:")
+ print(f" Total Tokens Used: {cost_stats['total_tokens']:,}")
+ print(f" Requests Made: {cost_stats['requests_made']}")
+ print(f" Cache Hits: {cost_stats['cache_hits']}")
+ print(f" Cache Hit Rate: {cost_stats['cache_hit_rate']:.1%}")
+ print(f" Loading Efficiency: {cost_stats['loading_efficiency']:.1%}")
+ print(f" Cache Size: {cost_stats['cache_size']} entries")
+
+ return session_result
+
+
+def main():
+ """Main demonstration function."""
+
+ print("EUROSWARM PARLIAMENT - COST OPTIMIZED DEMONSTRATION")
+ print("=" * 60)
+ print("This demonstration shows the EuroSwarm Parliament with cost optimization features:")
+ print("⢠Lazy loading of MEP agents (only create when needed)")
+ print("⢠Response caching (avoid repeated API calls)")
+ print("⢠Batch processing (control memory and cost)")
+ print("⢠Budget controls (hard limits on spending)")
+ print("⢠Cost tracking (real-time monitoring)")
+
+ # Initialize parliament with cost optimization
+ parliament = demonstrate_parliament_initialization()
+
+ # Demonstrate individual MEP interaction (will trigger lazy loading)
+ demonstrate_individual_mep_interaction(parliament)
+
+ # Demonstrate committee work with cost optimization
+ demonstrate_committee_work(parliament)
+
+ # Demonstrate parliamentary debate with cost optimization
+ demonstrate_parliamentary_debate(parliament)
+
+ # Demonstrate democratic voting with cost optimization
+ demonstrate_democratic_voting(parliament)
+
+ # Demonstrate political analysis with cost optimization
+ demonstrate_political_analysis(parliament)
+
+ # Demonstrate optimized parliamentary session
+ demonstrate_optimized_parliamentary_session(parliament)
+
+ # Show final cost statistics
+ final_stats = parliament.get_cost_statistics()
+ print(f"\nFINAL COST STATISTICS:")
+ print(f"Total Cost: ${final_stats['total_cost']:.2f}")
+ print(f"Budget Remaining: ${final_stats['budget_remaining']:.2f}")
+ print(f"Cache Hit Rate: {final_stats['cache_hit_rate']:.1%}")
+ print(f"Loading Efficiency: {final_stats['loading_efficiency']:.1%}")
+
+ print(f"\nā
COST OPTIMIZATION DEMONSTRATION COMPLETED!")
+ print(f"ā
EuroSwarm Parliament now supports cost-effective large-scale simulations")
+ print(f"ā
Lazy loading: {final_stats['loaded_meps']}/{final_stats['total_meps']} MEPs loaded")
+ print(f"ā
Caching: {final_stats['cache_hit_rate']:.1%} hit rate")
+ print(f"ā
Budget control: ${final_stats['total_cost']:.2f} spent of ${final_stats['budget_remaining'] + final_stats['total_cost']:.2f} budget")
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/examples/simulations/euroswarm_parliament/mass_agent_template.py b/examples/simulations/euroswarm_parliament/mass_agent_template.py
new file mode 100644
index 00000000..a6e29d8c
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/mass_agent_template.py
@@ -0,0 +1,998 @@
+"""
+Mass Agent Template - Template for Creating Large-Scale Multi-Agent Systems
+
+This template demonstrates how to generate hundreds of agents on the fly, similar to the EuroSwarm Parliament approach.
+It provides a reusable framework for creating large-scale multi-agent systems with dynamic agent generation.
+
+Key Features:
+- Dynamic agent generation from data sources
+- Configurable agent personalities and roles
+- Scalable architecture for thousands of agents
+- Template-based system prompts
+- Hierarchical organization capabilities
+- Memory and state management
+- COST OPTIMIZATION: Lazy loading, batching, caching, budget controls
+"""
+
+import os
+import random
+import json
+import time
+import hashlib
+from typing import Dict, List, Optional, Union, Any, Set
+from dataclasses import dataclass, field
+from enum import Enum
+from datetime import datetime
+from functools import lru_cache
+
+from swarms import Agent
+from swarms.structs.multi_agent_exec import run_agents_concurrently
+from swarms.structs.board_of_directors_swarm import (
+ BoardOfDirectorsSwarm,
+ BoardMember,
+ BoardMemberRole,
+ BoardDecisionType,
+ BoardSpec,
+ BoardOrder,
+ BoardDecision,
+ enable_board_feature,
+)
+from swarms.utils.loguru_logger import initialize_logger
+
+# Initialize logger
+logger = initialize_logger(log_folder="mass_agent_template")
+
+# Enable Board of Directors feature
+enable_board_feature()
+
+
+class AgentRole(str, Enum):
+ """Enumeration of agent roles and specializations."""
+
+ WORKER = "worker"
+ MANAGER = "manager"
+ SPECIALIST = "specialist"
+ COORDINATOR = "coordinator"
+ ANALYST = "analyst"
+ CREATOR = "creator"
+ VALIDATOR = "validator"
+ EXECUTOR = "executor"
+
+
+class AgentCategory(str, Enum):
+ """Enumeration of agent categories for organization."""
+
+ TECHNICAL = "technical"
+ CREATIVE = "creative"
+ ANALYTICAL = "analytical"
+ OPERATIONAL = "operational"
+ STRATEGIC = "strategic"
+ SUPPORT = "support"
+
+
+@dataclass
+class AgentProfile:
+ """
+ Represents a single agent in the mass agent system.
+
+ Attributes:
+ name: Unique name of the agent
+ role: Primary role of the agent
+ category: Category for organization
+ specialization: Areas of expertise
+ personality_traits: Personality characteristics
+ skills: List of skills and capabilities
+ experience_level: Experience level (junior, senior, expert)
+ agent: The AI agent instance (lazy loaded)
+ is_loaded: Whether the agent has been instantiated
+ """
+
+ name: str
+ role: AgentRole
+ category: AgentCategory
+ specialization: List[str] = field(default_factory=list)
+ personality_traits: List[str] = field(default_factory=list)
+ skills: List[str] = field(default_factory=list)
+ experience_level: str = "senior"
+ agent: Optional[Agent] = None
+ is_loaded: bool = False
+
+
+@dataclass
+class AgentGroup:
+ """
+ Represents a group of agents with similar roles or categories.
+
+ Attributes:
+ name: Name of the group
+ category: Category of the group
+ agents: List of agent names in this group
+ leader: Group leader agent name
+ total_agents: Total number of agents in group
+ group_swarm: Board of Directors swarm for this group
+ is_swarm_loaded: Whether the swarm has been instantiated
+ """
+
+ name: str
+ category: AgentCategory
+ agents: List[str] = field(default_factory=list)
+ leader: Optional[str] = None
+ total_agents: int = 0
+ group_swarm: Optional[Any] = None
+ is_swarm_loaded: bool = False
+
+
+@dataclass
+class CostTracker:
+ """Track costs and usage for budget management."""
+
+ total_tokens_used: int = 0
+ total_cost_estimate: float = 0.0
+ budget_limit: float = 100.0 # Default $100 budget
+ token_cost_per_1m: float = 0.15 # GPT-4o-mini cost
+ requests_made: int = 0
+ cache_hits: int = 0
+
+ def add_tokens(self, tokens: int):
+ """Add tokens used and calculate cost."""
+ self.total_tokens_used += tokens
+ self.total_cost_estimate = (self.total_tokens_used / 1_000_000) * self.token_cost_per_1m
+ self.requests_made += 1
+
+ def add_cache_hit(self):
+ """Record a cache hit."""
+ self.cache_hits += 1
+
+ def check_budget(self) -> bool:
+ """Check if within budget."""
+ return self.total_cost_estimate <= self.budget_limit
+
+ def get_stats(self) -> Dict[str, Any]:
+ """Get cost statistics."""
+ return {
+ "total_tokens": self.total_tokens_used,
+ "total_cost": self.total_cost_estimate,
+ "requests_made": self.requests_made,
+ "cache_hits": self.cache_hits,
+ "cache_hit_rate": self.cache_hits / max(1, self.requests_made + self.cache_hits),
+ "budget_remaining": max(0, self.budget_limit - self.total_cost_estimate)
+ }
+
+
+class MassAgentTemplate:
+ """
+ Template for creating large-scale multi-agent systems with cost optimization.
+
+ This class provides a framework for generating hundreds of agents on the fly,
+ organizing them into groups, and managing their interactions with cost controls.
+ """
+
+ def __init__(
+ self,
+ data_source: str = None, # Path to data file (CSV, JSON, XML, etc.)
+ agent_count: int = 1000, # Target number of agents
+ enable_hierarchical_organization: bool = True,
+ enable_group_swarms: bool = True,
+ enable_lazy_loading: bool = True, # NEW: Lazy load agents
+ enable_caching: bool = True, # NEW: Enable response caching
+ batch_size: int = 50, # NEW: Batch size for concurrent execution
+ budget_limit: float = 100.0, # NEW: Budget limit in dollars
+ verbose: bool = False,
+ ):
+ """
+ Initialize the Mass Agent Template with cost optimization.
+
+ Args:
+ data_source: Path to data file containing agent information
+ agent_count: Target number of agents to generate
+ enable_hierarchical_organization: Enable hierarchical organization
+ enable_group_swarms: Enable Board of Directors swarms for groups
+ enable_lazy_loading: Enable lazy loading of agents (cost optimization)
+ enable_caching: Enable response caching (cost optimization)
+ batch_size: Number of agents to process in batches
+ budget_limit: Maximum budget in dollars
+ verbose: Enable verbose logging
+ """
+ self.data_source = data_source
+ self.agent_count = agent_count
+ self.enable_hierarchical_organization = enable_hierarchical_organization
+ self.enable_group_swarms = enable_group_swarms
+ self.enable_lazy_loading = enable_lazy_loading
+ self.enable_caching = enable_caching
+ self.batch_size = batch_size
+ self.verbose = verbose
+
+ # Initialize cost tracking
+ self.cost_tracker = CostTracker(budget_limit=budget_limit)
+
+ # Initialize agent storage
+ self.agents: Dict[str, AgentProfile] = {}
+ self.groups: Dict[str, AgentGroup] = {}
+ self.categories: Dict[AgentCategory, List[str]] = {}
+
+ # Initialize caching
+ self.response_cache: Dict[str, str] = {}
+
+ # Load agent profiles (without creating agents)
+ self._load_agent_profiles()
+
+ if self.enable_hierarchical_organization:
+ self._organize_agents()
+
+ if self.verbose:
+ logger.info(f"Mass Agent Template initialized with {len(self.agents)} agent profiles")
+ logger.info(f"Lazy loading: {self.enable_lazy_loading}, Caching: {self.enable_caching}")
+ logger.info(f"Budget limit: ${budget_limit}, Batch size: {batch_size}")
+
+ def _load_agent_profiles(self) -> List[Dict[str, Any]]:
+ """
+ Load agent profiles from the specified data source.
+
+ This method loads agent data but doesn't create AI agents yet (lazy loading).
+
+ Returns:
+ List[Dict[str, Any]]: List of agent data dictionaries
+ """
+ agent_data = []
+
+ if self.data_source and os.path.exists(self.data_source):
+ # Load from file - customize based on your data format
+ try:
+ if self.data_source.endswith('.json'):
+ with open(self.data_source, 'r', encoding='utf-8') as f:
+ agent_data = json.load(f)
+ elif self.data_source.endswith('.csv'):
+ import pandas as pd
+ df = pd.read_csv(self.data_source)
+ agent_data = df.to_dict('records')
+ else:
+ logger.warning(f"Unsupported data format: {self.data_source}")
+ except Exception as e:
+ logger.error(f"Error loading agent data: {e}")
+
+ # If no data loaded, generate synthetic data
+ if not agent_data:
+ agent_data = self._generate_synthetic_data()
+
+ # Create agent profiles (without instantiating agents)
+ for data in agent_data:
+ agent_profile = AgentProfile(
+ name=data["name"],
+ role=data["role"],
+ category=data["category"],
+ specialization=data["specialization"],
+ personality_traits=data["personality_traits"],
+ skills=data["skills"],
+ experience_level=data["experience_level"],
+ agent=None, # Will be created on demand
+ is_loaded=False
+ )
+
+ self.agents[data["name"]] = agent_profile
+
+ return agent_data
+
+ def _load_agent(self, agent_name: str) -> Optional[Agent]:
+ """
+ Lazy load a single agent on demand.
+
+ Args:
+ agent_name: Name of the agent to load
+
+ Returns:
+ Optional[Agent]: Loaded agent or None if not found
+ """
+ if agent_name not in self.agents:
+ return None
+
+ profile = self.agents[agent_name]
+
+ # Check if already loaded
+ if profile.is_loaded and profile.agent:
+ return profile.agent
+
+ # Create agent (no cost for creation, only for running)
+ profile.agent = self._create_agent(profile)
+ profile.is_loaded = True
+
+ if self.verbose:
+ logger.info(f"Loaded agent: {agent_name}")
+
+ return profile.agent
+
+ def _load_agents_batch(self, agent_names: List[str]) -> List[Agent]:
+ """
+ Load multiple agents in a batch.
+
+ Args:
+ agent_names: List of agent names to load
+
+ Returns:
+ List[Agent]: List of loaded agents
+ """
+ loaded_agents = []
+
+ for agent_name in agent_names:
+ agent = self._load_agent(agent_name)
+ if agent:
+ loaded_agents.append(agent)
+
+ return loaded_agents
+
+ def _get_cache_key(self, task: str, agent_names: List[str]) -> str:
+ """
+ Generate a cache key for a task and agent combination.
+
+ Args:
+ task: Task to execute
+ agent_names: List of agent names
+
+ Returns:
+ str: Cache key
+ """
+ # Sort agent names for consistent cache keys
+ sorted_agents = sorted(agent_names)
+ content = f"{task}:{':'.join(sorted_agents)}"
+ return hashlib.md5(content.encode()).hexdigest()
+
+ def _check_cache(self, cache_key: str) -> Optional[str]:
+ """
+ Check if a response is cached.
+
+ Args:
+ cache_key: Cache key to check
+
+ Returns:
+ Optional[str]: Cached response or None
+ """
+ if not self.enable_caching:
+ return None
+
+ cached_response = self.response_cache.get(cache_key)
+ if cached_response:
+ self.cost_tracker.add_cache_hit()
+ if self.verbose:
+ logger.info(f"Cache hit for key: {cache_key[:20]}...")
+
+ return cached_response
+
+ def _cache_response(self, cache_key: str, response: str):
+ """
+ Cache a response.
+
+ Args:
+ cache_key: Cache key
+ response: Response to cache
+ """
+ if self.enable_caching:
+ self.response_cache[cache_key] = response
+ if self.verbose:
+ logger.info(f"Cached response for key: {cache_key[:20]}...")
+
+ def _generate_synthetic_data(self) -> List[Dict[str, Any]]:
+ """
+ Generate synthetic agent data for demonstration purposes.
+
+ Returns:
+ List[Dict[str, Any]]: List of synthetic agent data
+ """
+ synthetic_data = []
+
+ # Define sample data for different agent types
+ sample_agents = [
+ {
+ "name": "Alex_Developer",
+ "role": AgentRole.SPECIALIST,
+ "category": AgentCategory.TECHNICAL,
+ "specialization": ["Python", "Machine Learning", "API Development"],
+ "personality_traits": ["analytical", "detail-oriented", "problem-solver"],
+ "skills": ["Python", "TensorFlow", "FastAPI", "Docker"],
+ "experience_level": "senior"
+ },
+ {
+ "name": "Sarah_Designer",
+ "role": AgentRole.CREATOR,
+ "category": AgentCategory.CREATIVE,
+ "specialization": ["UI/UX Design", "Visual Design", "Brand Identity"],
+ "personality_traits": ["creative", "user-focused", "aesthetic"],
+ "skills": ["Figma", "Adobe Creative Suite", "User Research", "Prototyping"],
+ "experience_level": "senior"
+ },
+ {
+ "name": "Mike_Analyst",
+ "role": AgentRole.ANALYST,
+ "category": AgentCategory.ANALYTICAL,
+ "specialization": ["Data Analysis", "Business Intelligence", "Market Research"],
+ "personality_traits": ["data-driven", "curious", "insightful"],
+ "skills": ["SQL", "Python", "Tableau", "Statistics"],
+ "experience_level": "expert"
+ },
+ {
+ "name": "Lisa_Manager",
+ "role": AgentRole.MANAGER,
+ "category": AgentCategory.STRATEGIC,
+ "specialization": ["Project Management", "Team Leadership", "Strategic Planning"],
+ "personality_traits": ["organized", "leadership", "strategic"],
+ "skills": ["Agile", "Scrum", "Risk Management", "Stakeholder Communication"],
+ "experience_level": "senior"
+ },
+ {
+ "name": "Tom_Coordinator",
+ "role": AgentRole.COORDINATOR,
+ "category": AgentCategory.OPERATIONAL,
+ "specialization": ["Process Optimization", "Workflow Management", "Resource Allocation"],
+ "personality_traits": ["efficient", "coordinated", "systematic"],
+ "skills": ["Process Mapping", "Automation", "Resource Planning", "Quality Assurance"],
+ "experience_level": "senior"
+ }
+ ]
+
+ # Generate the specified number of agents
+ for i in range(self.agent_count):
+ # Use sample data as template and create variations
+ template = random.choice(sample_agents)
+
+ agent_data = {
+ "name": f"{template['name']}_{i:04d}",
+ "role": template["role"],
+ "category": template["category"],
+ "specialization": template["specialization"].copy(),
+ "personality_traits": template["personality_traits"].copy(),
+ "skills": template["skills"].copy(),
+ "experience_level": template["experience_level"]
+ }
+
+ # Add some randomization for variety
+ if random.random() < 0.3:
+ agent_data["experience_level"] = random.choice(["junior", "senior", "expert"])
+
+ synthetic_data.append(agent_data)
+
+ return synthetic_data
+
+ def _create_agent(self, profile: AgentProfile) -> Agent:
+ """
+ Create an AI agent for the given profile.
+
+ Args:
+ profile: Agent profile data
+
+ Returns:
+ Agent: AI agent instance
+ """
+ system_prompt = self._generate_agent_system_prompt(profile)
+
+ return Agent(
+ agent_name=profile.name,
+ system_prompt=system_prompt,
+ model_name="gpt-4o-mini",
+ max_loops=3,
+ verbose=self.verbose,
+ )
+
+ def _generate_agent_system_prompt(self, profile: AgentProfile) -> str:
+ """
+ Generate a comprehensive system prompt for an agent.
+
+ Args:
+ profile: Agent profile data
+
+ Returns:
+ str: System prompt for the agent
+ """
+ prompt = f"""You are {profile.name}, an AI agent with the following characteristics:
+
+ROLE AND CATEGORY:
+- Role: {profile.role.value}
+- Category: {profile.category.value}
+- Experience Level: {profile.experience_level}
+
+EXPERTISE AND SKILLS:
+- Specializations: {', '.join(profile.specialization)}
+- Skills: {', '.join(profile.skills)}
+
+PERSONALITY TRAITS:
+- {', '.join(profile.personality_traits)}
+
+CORE RESPONSIBILITIES:
+{self._get_role_responsibilities(profile.role)}
+
+WORKING STYLE:
+- Approach tasks with your unique personality and expertise
+- Collaborate effectively with other agents
+- Maintain high quality standards
+- Adapt to changing requirements
+- Communicate clearly and professionally
+
+When working on tasks:
+1. Apply your specialized knowledge and skills
+2. Consider your personality traits in your approach
+3. Work within your role's scope and responsibilities
+4. Collaborate with other agents when beneficial
+5. Maintain consistency with your established character
+
+Remember: You are part of a large multi-agent system. Your unique combination of role, skills, and personality makes you valuable to the team.
+"""
+
+ return prompt
+
+ def _get_role_responsibilities(self, role: AgentRole) -> str:
+ """Get responsibilities for a specific role."""
+
+ responsibilities = {
+ AgentRole.WORKER: """
+- Execute assigned tasks efficiently and accurately
+- Follow established procedures and guidelines
+- Report progress and any issues encountered
+- Maintain quality standards in all work
+- Collaborate with team members as needed""",
+
+ AgentRole.MANAGER: """
+- Oversee team activities and coordinate efforts
+- Set priorities and allocate resources
+- Monitor progress and ensure deadlines are met
+- Provide guidance and support to team members
+- Make strategic decisions for the team""",
+
+ AgentRole.SPECIALIST: """
+- Provide expert knowledge in specific domains
+- Solve complex technical problems
+- Mentor other agents in your area of expertise
+- Stay updated on latest developments in your field
+- Contribute specialized insights to projects""",
+
+ AgentRole.COORDINATOR: """
+- Facilitate communication between different groups
+- Ensure smooth workflow and process optimization
+- Manage dependencies and resource allocation
+- Track project timelines and milestones
+- Resolve conflicts and bottlenecks""",
+
+ AgentRole.ANALYST: """
+- Analyze data and extract meaningful insights
+- Identify patterns and trends
+- Provide evidence-based recommendations
+- Create reports and visualizations
+- Support decision-making with data""",
+
+ AgentRole.CREATOR: """
+- Generate innovative ideas and solutions
+- Design and develop new content or products
+- Think creatively and outside the box
+- Prototype and iterate on concepts
+- Inspire and motivate other team members""",
+
+ AgentRole.VALIDATOR: """
+- Review and validate work quality
+- Ensure compliance with standards and requirements
+- Provide constructive feedback
+- Identify potential issues and risks
+- Maintain quality assurance processes""",
+
+ AgentRole.EXECUTOR: """
+- Implement plans and strategies
+- Execute tasks with precision and efficiency
+- Adapt to changing circumstances
+- Ensure successful completion of objectives
+- Maintain focus on results and outcomes"""
+ }
+
+ return responsibilities.get(role, "Execute tasks according to your role and expertise.")
+
+ def _organize_agents(self):
+ """Organize agents into groups and categories."""
+
+ # Organize by category
+ for agent_name, profile in self.agents.items():
+ category = profile.category
+ if category not in self.categories:
+ self.categories[category] = []
+ self.categories[category].append(agent_name)
+
+ # Create groups for each category
+ for category, agent_names in self.categories.items():
+ group_name = f"{category.value.capitalize()}_Group"
+
+ # Select a leader (first agent in the category)
+ leader = agent_names[0] if agent_names else None
+
+ group = AgentGroup(
+ name=group_name,
+ category=category,
+ agents=agent_names,
+ leader=leader,
+ total_agents=len(agent_names)
+ )
+
+ self.groups[group_name] = group
+
+ if self.verbose:
+ logger.info(f"Organized agents into {len(self.groups)} groups")
+
+ def _create_group_swarms(self):
+ """Create Board of Directors swarms for each group."""
+
+ for group_name, group in self.groups.items():
+ if not group.agents:
+ continue
+
+ # Create board members from group agents
+ board_members = []
+
+ # Add group leader as chairman
+ if group.leader and group.leader in self.agents:
+ leader_profile = self.agents[group.leader]
+ if leader_profile.agent:
+ board_members.append(BoardMember(
+ agent=leader_profile.agent,
+ role=BoardMemberRole.CHAIRMAN,
+ voting_weight=1.0,
+ expertise_areas=leader_profile.specialization
+ ))
+
+ # Add other agents as board members
+ for agent_name in group.agents[:5]: # Limit to 5 board members
+ if agent_name != group.leader and agent_name in self.agents:
+ profile = self.agents[agent_name]
+ if profile.agent:
+ board_members.append(BoardMember(
+ agent=profile.agent,
+ role=BoardMemberRole.EXECUTIVE_DIRECTOR,
+ voting_weight=0.8,
+ expertise_areas=profile.specialization
+ ))
+
+ # Create Board of Directors swarm
+ if board_members:
+ agents = [member.agent for member in board_members if member.agent is not None]
+
+ group.group_swarm = BoardOfDirectorsSwarm(
+ name=group_name,
+ description=f"Specialized swarm for {group_name} with expertise in {group.category.value}",
+ board_members=board_members,
+ agents=agents,
+ max_loops=3,
+ verbose=self.verbose,
+ decision_threshold=0.6,
+ enable_voting=True,
+ enable_consensus=True
+ )
+
+ if self.verbose:
+ logger.info(f"Created {len([g for g in self.groups.values() if g.group_swarm])} group swarms")
+
+ def get_agent(self, agent_name: str) -> Optional[AgentProfile]:
+ """
+ Get a specific agent by name.
+
+ Args:
+ agent_name: Name of the agent
+
+ Returns:
+ Optional[AgentProfile]: Agent profile if found, None otherwise
+ """
+ return self.agents.get(agent_name)
+
+ def get_group(self, group_name: str) -> Optional[AgentGroup]:
+ """
+ Get a specific group by name.
+
+ Args:
+ group_name: Name of the group
+
+ Returns:
+ Optional[AgentGroup]: Group if found, None otherwise
+ """
+ return self.groups.get(group_name)
+
+ def get_agents_by_category(self, category: AgentCategory) -> List[str]:
+ """
+ Get all agents in a specific category.
+
+ Args:
+ category: Agent category
+
+ Returns:
+ List[str]: List of agent names in the category
+ """
+ return self.categories.get(category, [])
+
+ def get_agents_by_role(self, role: AgentRole) -> List[str]:
+ """
+ Get all agents with a specific role.
+
+ Args:
+ role: Agent role
+
+ Returns:
+ List[str]: List of agent names with the role
+ """
+ return [name for name, profile in self.agents.items() if profile.role == role]
+
+ def run_mass_task(self, task: str, agent_count: int = 10) -> Dict[str, Any]:
+ """
+ Run a task with multiple agents working in parallel with cost optimization.
+
+ Args:
+ task: Task to execute
+ agent_count: Number of agents to use
+
+ Returns:
+ Dict[str, Any]: Results from the mass task execution
+ """
+ # Check budget before starting
+ if not self.cost_tracker.check_budget():
+ return {"error": "Budget exceeded", "cost_stats": self.cost_tracker.get_stats()}
+
+ # Select random agents
+ selected_agent_names = random.sample(list(self.agents.keys()), min(agent_count, len(self.agents)))
+
+ # Check cache first
+ cache_key = self._get_cache_key(task, selected_agent_names)
+ cached_result = self._check_cache(cache_key)
+ if cached_result:
+ return {
+ "task": task,
+ "agents_used": selected_agent_names,
+ "results": cached_result,
+ "total_agents": len(selected_agent_names),
+ "cached": True,
+ "cost_stats": self.cost_tracker.get_stats()
+ }
+
+ # Process in batches to control memory and cost
+ all_results = []
+ total_processed = 0
+
+ for i in range(0, len(selected_agent_names), self.batch_size):
+ batch_names = selected_agent_names[i:i + self.batch_size]
+
+ # Check budget for this batch
+ if not self.cost_tracker.check_budget():
+ logger.warning(f"Budget exceeded after processing {total_processed} agents")
+ logger.warning(f"Current cost: ${self.cost_tracker.total_cost_estimate:.4f}, Budget: ${self.cost_tracker.budget_limit:.2f}")
+ break
+
+ # Load agents for this batch
+ batch_agents = self._load_agents_batch(batch_names)
+
+ if not batch_agents:
+ continue
+
+ # Run batch
+ try:
+ batch_results = run_agents_concurrently(batch_agents, task)
+ all_results.extend(batch_results)
+ total_processed += len(batch_agents)
+
+ # Estimate tokens used (more realistic approximation)
+ # Include both input tokens (task) and output tokens (response)
+ task_tokens = len(task.split()) * 1.3 # ~1.3 tokens per word
+ response_tokens = len(batch_agents) * 200 # ~200 tokens per response
+ total_tokens = int(task_tokens + response_tokens)
+ self.cost_tracker.add_tokens(total_tokens)
+
+ if self.verbose:
+ logger.info(f"Processed batch {i//self.batch_size + 1}: {len(batch_agents)} agents")
+ logger.info(f"Current cost: ${self.cost_tracker.total_cost_estimate:.4f}, Budget remaining: ${self.cost_tracker.budget_limit - self.cost_tracker.total_cost_estimate:.2f}")
+
+ except Exception as e:
+ logger.error(f"Error processing batch: {e}")
+ continue
+
+ # Cache the results
+ if all_results:
+ self._cache_response(cache_key, str(all_results))
+
+ return {
+ "task": task,
+ "agents_used": selected_agent_names[:total_processed],
+ "results": all_results,
+ "total_agents": total_processed,
+ "cached": False,
+ "cost_stats": self.cost_tracker.get_stats()
+ }
+
+ def run_mass_task_optimized(self, task: str, agent_count: int = 1000,
+ max_cost: float = 10.0) -> Dict[str, Any]:
+ """
+ Run a task with cost-optimized mass execution for large-scale operations.
+
+ Args:
+ task: Task to execute
+ agent_count: Target number of agents to use
+ max_cost: Maximum cost for this task in dollars
+
+ Returns:
+ Dict[str, Any]: Results from the optimized mass task execution
+ """
+ # Store original settings
+ original_budget = self.cost_tracker.budget_limit
+ original_batch_size = self.batch_size
+
+ try:
+ # Set temporary budget for this task (don't reduce if max_cost is higher)
+ if max_cost < original_budget:
+ self.cost_tracker.budget_limit = max_cost
+
+ # Use smaller batches for better cost control
+ self.batch_size = min(25, self.batch_size) # Smaller batches for cost control
+
+ result = self.run_mass_task(task, agent_count)
+
+ return result
+
+ finally:
+ # Restore original settings
+ self.cost_tracker.budget_limit = original_budget
+ self.batch_size = original_batch_size
+
+ def run_group_task(self, group_name: str, task: str) -> Dict[str, Any]:
+ """
+ Run a task with a specific group using their Board of Directors swarm.
+
+ Args:
+ group_name: Name of the group
+ task: Task to execute
+
+ Returns:
+ Dict[str, Any]: Results from the group task execution
+ """
+ group = self.groups.get(group_name)
+ if not group or not group.group_swarm:
+ return {"error": f"Group {group_name} not found or no swarm available"}
+
+ # Run task with group swarm
+ result = group.group_swarm.run(task)
+
+ return {
+ "group": group_name,
+ "task": task,
+ "result": result,
+ "agents_involved": group.agents
+ }
+
+ def get_system_stats(self) -> Dict[str, Any]:
+ """
+ Get statistics about the mass agent system including cost tracking.
+
+ Returns:
+ Dict[str, Any]: System statistics
+ """
+ stats = {
+ "total_agents": len(self.agents),
+ "total_groups": len(self.groups),
+ "loaded_agents": len([a for a in self.agents.values() if a.is_loaded]),
+ "categories": {},
+ "roles": {},
+ "experience_levels": {},
+ "cost_stats": self.cost_tracker.get_stats(),
+ "optimization": {
+ "lazy_loading": self.enable_lazy_loading,
+ "caching": self.enable_caching,
+ "batch_size": self.batch_size,
+ "budget_limit": self.cost_tracker.budget_limit
+ }
+ }
+
+ # Category breakdown
+ for category in AgentCategory:
+ stats["categories"][category.value] = len(self.get_agents_by_category(category))
+
+ # Role breakdown
+ for role in AgentRole:
+ stats["roles"][role.value] = len(self.get_agents_by_role(role))
+
+ # Experience level breakdown
+ experience_counts = {}
+ for profile in self.agents.values():
+ level = profile.experience_level
+ experience_counts[level] = experience_counts.get(level, 0) + 1
+ stats["experience_levels"] = experience_counts
+
+ return stats
+
+
+# Example usage and demonstration
+def demonstrate_mass_agent_template():
+ """Demonstrate the Mass Agent Template functionality with cost optimization."""
+
+ print("MASS AGENT TEMPLATE DEMONSTRATION (COST OPTIMIZED)")
+ print("=" * 60)
+
+ # Initialize the template with 1000 agents and cost optimization
+ template = MassAgentTemplate(
+ agent_count=1000,
+ enable_hierarchical_organization=True,
+ enable_group_swarms=False, # Disable for cost savings
+ enable_lazy_loading=True,
+ enable_caching=True,
+ batch_size=25,
+ budget_limit=50.0, # $50 budget limit
+ verbose=True
+ )
+
+ # Show system statistics
+ stats = template.get_system_stats()
+
+ print(f"\nSYSTEM STATISTICS:")
+ print(f"Total Agents: {stats['total_agents']}")
+ print(f"Loaded Agents: {stats['loaded_agents']} (lazy loading active)")
+ print(f"Total Groups: {stats['total_groups']}")
+
+ print(f"\nCOST OPTIMIZATION:")
+ cost_stats = stats['cost_stats']
+ print(f"Budget Limit: ${cost_stats['budget_remaining'] + cost_stats['total_cost']:.2f}")
+ print(f"Budget Used: ${cost_stats['total_cost']:.2f}")
+ print(f"Budget Remaining: ${cost_stats['budget_remaining']:.2f}")
+ print(f"Cache Hit Rate: {cost_stats['cache_hit_rate']:.1%}")
+
+ print(f"\nCATEGORY BREAKDOWN:")
+ for category, count in stats['categories'].items():
+ print(f" {category}: {count} agents")
+
+ print(f"\nROLE BREAKDOWN:")
+ for role, count in stats['roles'].items():
+ print(f" {role}: {count} agents")
+
+ print(f"\nEXPERIENCE LEVEL BREAKDOWN:")
+ for level, count in stats['experience_levels'].items():
+ print(f" {level}: {count} agents")
+
+ # Demonstrate cost-optimized mass task execution
+ print(f"\nCOST-OPTIMIZED MASS TASK DEMONSTRATION:")
+ print("-" * 40)
+
+ # Small task first (low cost)
+ small_result = template.run_mass_task(
+ "What is the most important skill for a software developer?",
+ agent_count=5
+ )
+
+ print(f"Small Task Results:")
+ print(f" Agents Used: {len(small_result['agents_used'])}")
+ print(f" Cached: {small_result.get('cached', False)}")
+ print(f" Cost: ${small_result['cost_stats']['total_cost']:.2f}")
+
+ # Large task to demonstrate full capability
+ print(f"\nLarge Task Demonstration (Full Capability):")
+ large_result = template.run_mass_task(
+ "Analyze the benefits of cloud computing for small businesses",
+ agent_count=200 # Use more agents to show capability
+ )
+
+ print(f" Agents Used: {len(large_result['agents_used'])}")
+ print(f" Cached: {large_result.get('cached', False)}")
+ print(f" Cost: ${large_result['cost_stats']['total_cost']:.2f}")
+ print(f" Budget Remaining: ${large_result['cost_stats']['budget_remaining']:.2f}")
+
+ # Show what happens with cost limits
+ print(f"\nCost-Limited Task Demonstration:")
+ cost_limited_result = template.run_mass_task_optimized(
+ "What are the key principles of agile development?",
+ agent_count=100,
+ max_cost=2.0 # Show cost limiting in action
+ )
+
+ print(f" Agents Used: {len(cost_limited_result['agents_used'])}")
+ print(f" Cached: {cost_limited_result.get('cached', False)}")
+ print(f" Cost: ${cost_limited_result['cost_stats']['total_cost']:.2f}")
+ print(f" Budget Remaining: ${cost_limited_result['cost_stats']['budget_remaining']:.2f}")
+
+ # Show final cost statistics
+ final_stats = template.get_system_stats()
+ print(f"\nFINAL COST STATISTICS:")
+ print(f"Total Cost: ${final_stats['cost_stats']['total_cost']:.2f}")
+ print(f"Budget Remaining: ${final_stats['cost_stats']['budget_remaining']:.2f}")
+ print(f"Cache Hit Rate: {final_stats['cost_stats']['cache_hit_rate']:.1%}")
+ print(f"Total Requests: {final_stats['cost_stats']['requests_made']}")
+ print(f"Cache Hits: {final_stats['cost_stats']['cache_hits']}")
+
+ print(f"\nDEMONSTRATION COMPLETED SUCCESSFULLY!")
+ print(f"ā
Cost optimization working: ${final_stats['cost_stats']['total_cost']:.2f} spent")
+ print(f"ā
Lazy loading working: {final_stats['loaded_agents']}/{final_stats['total_agents']} agents loaded")
+ print(f"ā
Caching working: {final_stats['cost_stats']['cache_hit_rate']:.1%} hit rate")
+
+
+if __name__ == "__main__":
+ demonstrate_mass_agent_template()
\ No newline at end of file
diff --git a/examples/simulations/euroswarm_parliament/test_mass_agents.py b/examples/simulations/euroswarm_parliament/test_mass_agents.py
new file mode 100644
index 00000000..54ec2223
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/test_mass_agents.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+"""
+Test script to verify mass agent template can process more than 500 agents.
+"""
+
+from mass_agent_template import MassAgentTemplate
+
+def test_mass_agents():
+ print("Testing Mass Agent Template - Processing More Than 50 Agents")
+ print("=" * 60)
+
+ # Initialize template with 200 agents
+ template = MassAgentTemplate(
+ agent_count=200,
+ budget_limit=50.0,
+ batch_size=25,
+ verbose=True
+ )
+
+ print(f"Initialized with {len(template.agents)} agents")
+ print(f"Budget limit: ${template.cost_tracker.budget_limit}")
+
+ # Test processing 100 agents
+ print(f"\nTesting with 100 agents...")
+ result = template.run_mass_task(
+ "What is the most important skill for your role?",
+ agent_count=100
+ )
+
+ print(f"Results:")
+ print(f" Agents processed: {len(result['agents_used'])}")
+ print(f" Cost: ${result['cost_stats']['total_cost']:.4f}")
+ print(f" Budget remaining: ${result['cost_stats']['budget_remaining']:.2f}")
+ print(f" Cached: {result.get('cached', False)}")
+
+ # Test processing 150 agents
+ print(f"\nTesting with 150 agents...")
+ result2 = template.run_mass_task(
+ "Describe your approach to problem-solving",
+ agent_count=150
+ )
+
+ print(f"Results:")
+ print(f" Agents processed: {len(result2['agents_used'])}")
+ print(f" Cost: ${result2['cost_stats']['total_cost']:.4f}")
+ print(f" Budget remaining: ${result2['cost_stats']['budget_remaining']:.2f}")
+ print(f" Cached: {result2.get('cached', False)}")
+
+ # Show final stats
+ final_stats = template.get_system_stats()
+ print(f"\nFinal Statistics:")
+ print(f" Total agents: {final_stats['total_agents']}")
+ print(f" Loaded agents: {final_stats['loaded_agents']}")
+ print(f" Total cost: ${final_stats['cost_stats']['total_cost']:.4f}")
+ print(f" Budget remaining: ${final_stats['cost_stats']['budget_remaining']:.2f}")
+
+ # Success criteria
+ total_processed = len(result['agents_used']) + len(result2['agents_used'])
+ print(f"\nTotal agents processed: {total_processed}")
+
+ if total_processed > 50:
+ print("ā
SUCCESS: Template processed more than 50 agents!")
+ else:
+ print("ā FAILURE: Template still limited to 50 agents")
+
+if __name__ == "__main__":
+ test_mass_agents()
\ No newline at end of file
diff --git a/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py b/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py
new file mode 100644
index 00000000..0ef7cda7
--- /dev/null
+++ b/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py
@@ -0,0 +1,575 @@
+#!/usr/bin/env python3
+"""
+Wikipedia Personality Scraper for EuroSwarm Parliament MEPs
+
+This module scrapes Wikipedia data for each MEP to create realistic, personality-driven
+AI agents based on their real backgrounds, political history, and personal beliefs.
+"""
+
+import json
+import os
+import time
+import re
+from typing import Dict, List, Optional, Any
+from dataclasses import dataclass, asdict
+import requests
+from loguru import logger
+import xml.etree.ElementTree as ET
+
+
+@dataclass
+class MEPPersonalityProfile:
+ """
+ Comprehensive personality profile for an MEP based on Wikipedia data.
+
+ Attributes:
+ full_name: Full name of the MEP
+ mep_id: Unique MEP identifier
+ wikipedia_url: URL of the MEP's Wikipedia page
+ summary: Brief summary of the MEP's background
+ early_life: Early life and education information
+ political_career: Political career and positions held
+ political_views: Key political views and positions
+ policy_focus: Areas of policy expertise and focus
+ achievements: Notable achievements and accomplishments
+ controversies: Any controversies or notable incidents
+ personal_life: Personal background and family information
+ education: Educational background
+ professional_background: Professional experience before politics
+ party_affiliations: Political party history
+ committee_experience: Parliamentary committee experience
+ voting_record: Notable voting patterns or positions
+ public_statements: Key public statements or quotes
+ interests: Personal and professional interests
+ languages: Languages spoken
+ awards: Awards and recognitions
+ publications: Publications or written works
+ social_media: Social media presence
+ last_updated: When the profile was last updated
+ """
+
+ full_name: str
+ mep_id: str
+ wikipedia_url: Optional[str] = None
+ summary: str = ""
+ early_life: str = ""
+ political_career: str = ""
+ political_views: str = ""
+ policy_focus: str = ""
+ achievements: str = ""
+ controversies: str = ""
+ personal_life: str = ""
+ education: str = ""
+ professional_background: str = ""
+ party_affiliations: str = ""
+ committee_experience: str = ""
+ voting_record: str = ""
+ public_statements: str = ""
+ interests: str = ""
+ languages: str = ""
+ awards: str = ""
+ publications: str = ""
+ social_media: str = ""
+ last_updated: str = ""
+
+
+class WikipediaPersonalityScraper:
+ """
+ Scraper for gathering Wikipedia personality data for MEPs.
+ """
+
+ def __init__(self, output_dir: str = "mep_personalities", verbose: bool = True):
+ """
+ Initialize the Wikipedia personality scraper.
+
+ Args:
+ output_dir: Directory to store personality profiles
+ verbose: Enable verbose logging
+ """
+ self.output_dir = output_dir
+ self.verbose = verbose
+ self.session = requests.Session()
+ self.session.headers.update({
+ 'User-Agent': 'EuroSwarm Parliament Personality Scraper/1.0 (https://github.com/swarms-democracy)'
+ })
+
+ # Create output directory
+ os.makedirs(output_dir, exist_ok=True)
+
+ if verbose:
+ logger.info(f"Wikipedia Personality Scraper initialized. Output directory: {output_dir}")
+
+ def extract_mep_data_from_xml(self, xml_file: str = "EU.xml") -> List[Dict[str, str]]:
+ """
+ Extract MEP data from EU.xml file.
+
+ Args:
+ xml_file: Path to EU.xml file
+
+ Returns:
+ List of MEP data dictionaries
+ """
+ meps = []
+
+ try:
+ with open(xml_file, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ # Use regex to extract MEP data
+ mep_pattern = r'\s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s* '
+ mep_matches = re.findall(mep_pattern, content, re.DOTALL)
+
+ for full_name, country, political_group, mep_id, national_party in mep_matches:
+ meps.append({
+ 'full_name': full_name.strip(),
+ 'country': country.strip(),
+ 'political_group': political_group.strip(),
+ 'mep_id': mep_id.strip(),
+ 'national_party': national_party.strip()
+ })
+
+ if self.verbose:
+ logger.info(f"Extracted {len(meps)} MEPs from {xml_file}")
+
+ except Exception as e:
+ logger.error(f"Error extracting MEP data from {xml_file}: {e}")
+
+ return meps
+
+ def search_wikipedia_page(self, mep_name: str, country: str) -> Optional[str]:
+ """
+ Search for a Wikipedia page for an MEP.
+
+ Args:
+ mep_name: Full name of the MEP
+ country: Country of the MEP
+
+ Returns:
+ Wikipedia page title if found, None otherwise
+ """
+ try:
+ # Search for the MEP on Wikipedia
+ search_url = "https://en.wikipedia.org/w/api.php"
+ search_params = {
+ 'action': 'query',
+ 'format': 'json',
+ 'list': 'search',
+ 'srsearch': f'"{mep_name}" {country}',
+ 'srlimit': 5,
+ 'srnamespace': 0
+ }
+
+ response = self.session.get(search_url, params=search_params)
+ response.raise_for_status()
+
+ data = response.json()
+ search_results = data.get('query', {}).get('search', [])
+
+ if search_results:
+ # Return the first result
+ return search_results[0]['title']
+
+ # Try alternative search without quotes
+ search_params['srsearch'] = f'{mep_name} {country}'
+ response = self.session.get(search_url, params=search_params)
+ response.raise_for_status()
+
+ data = response.json()
+ search_results = data.get('query', {}).get('search', [])
+
+ if search_results:
+ return search_results[0]['title']
+
+ except Exception as e:
+ if self.verbose:
+ logger.warning(f"Error searching Wikipedia for {mep_name}: {e}")
+
+ return None
+
+ def get_wikipedia_content(self, page_title: str) -> Optional[Dict[str, Any]]:
+ """
+ Get Wikipedia content for a specific page.
+
+ Args:
+ page_title: Wikipedia page title
+
+ Returns:
+ Dictionary containing page content and metadata
+ """
+ try:
+ # Get page content
+ content_url = "https://en.wikipedia.org/w/api.php"
+ content_params = {
+ 'action': 'query',
+ 'format': 'json',
+ 'titles': page_title,
+ 'prop': 'extracts|info|categories',
+ 'exintro': True,
+ 'explaintext': True,
+ 'inprop': 'url',
+ 'cllimit': 50
+ }
+
+ response = self.session.get(content_url, params=content_params)
+ response.raise_for_status()
+
+ data = response.json()
+ pages = data.get('query', {}).get('pages', {})
+
+ if pages:
+ page_id = list(pages.keys())[0]
+ page_data = pages[page_id]
+
+ return {
+ 'title': page_data.get('title', ''),
+ 'extract': page_data.get('extract', ''),
+ 'url': page_data.get('fullurl', ''),
+ 'categories': [cat['title'] for cat in page_data.get('categories', [])],
+ 'pageid': page_data.get('pageid', ''),
+ 'length': page_data.get('length', 0)
+ }
+
+ except Exception as e:
+ if self.verbose:
+ logger.warning(f"Error getting Wikipedia content for {page_title}: {e}")
+
+ return None
+
+ def parse_wikipedia_content(self, content: str, mep_name: str) -> Dict[str, str]:
+ """
+ Parse Wikipedia content to extract structured personality information.
+
+ Args:
+ content: Raw Wikipedia content
+ mep_name: Name of the MEP
+
+ Returns:
+ Dictionary of parsed personality information
+ """
+ personality_data = {
+ 'summary': '',
+ 'early_life': '',
+ 'political_career': '',
+ 'political_views': '',
+ 'policy_focus': '',
+ 'achievements': '',
+ 'controversies': '',
+ 'personal_life': '',
+ 'education': '',
+ 'professional_background': '',
+ 'party_affiliations': '',
+ 'committee_experience': '',
+ 'voting_record': '',
+ 'public_statements': '',
+ 'interests': '',
+ 'languages': '',
+ 'awards': '',
+ 'publications': '',
+ 'social_media': ''
+ }
+
+ # Extract summary (first paragraph)
+ paragraphs = content.split('\n\n')
+ if paragraphs:
+ personality_data['summary'] = paragraphs[0][:1000] # Limit summary length
+
+ # Look for specific sections
+ content_lower = content.lower()
+
+ # Early life and education
+ early_life_patterns = [
+ r'early life[^.]*\.',
+ r'born[^.]*\.',
+ r'childhood[^.]*\.',
+ r'grew up[^.]*\.',
+ r'education[^.]*\.'
+ ]
+
+ for pattern in early_life_patterns:
+ matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ if matches:
+ personality_data['early_life'] = ' '.join(matches[:3]) # Take first 3 matches
+ break
+
+ # Political career
+ political_patterns = [
+ r'political career[^.]*\.',
+ r'elected[^.]*\.',
+ r'parliament[^.]*\.',
+ r'minister[^.]*\.',
+ r'party[^.]*\.'
+ ]
+
+ for pattern in political_patterns:
+ matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ if matches:
+ personality_data['political_career'] = ' '.join(matches[:5]) # Take first 5 matches
+ break
+
+ # Political views
+ views_patterns = [
+ r'political views[^.]*\.',
+ r'positions[^.]*\.',
+ r'advocates[^.]*\.',
+ r'supports[^.]*\.',
+ r'opposes[^.]*\.'
+ ]
+
+ for pattern in views_patterns:
+ matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ if matches:
+ personality_data['political_views'] = ' '.join(matches[:3])
+ break
+
+ # Policy focus
+ policy_patterns = [
+ r'policy[^.]*\.',
+ r'focus[^.]*\.',
+ r'issues[^.]*\.',
+ r'legislation[^.]*\.'
+ ]
+
+ for pattern in policy_patterns:
+ matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ if matches:
+ personality_data['policy_focus'] = ' '.join(matches[:3])
+ break
+
+ # Achievements
+ achievement_patterns = [
+ r'achievements[^.]*\.',
+ r'accomplishments[^.]*\.',
+ r'success[^.]*\.',
+ r'won[^.]*\.',
+ r'received[^.]*\.'
+ ]
+
+ for pattern in achievement_patterns:
+ matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ if matches:
+ personality_data['achievements'] = ' '.join(matches[:3])
+ break
+
+ return personality_data
+
+ def create_personality_profile(self, mep_data: Dict[str, str]) -> MEPPersonalityProfile:
+ """
+ Create a personality profile for an MEP.
+
+ Args:
+ mep_data: MEP data from XML file
+
+ Returns:
+ MEPPersonalityProfile object
+ """
+ mep_name = mep_data['full_name']
+ country = mep_data['country']
+
+ # Search for Wikipedia page
+ page_title = self.search_wikipedia_page(mep_name, country)
+
+ if page_title:
+ # Get Wikipedia content
+ wiki_content = self.get_wikipedia_content(page_title)
+
+ if wiki_content:
+ # Parse content
+ personality_data = self.parse_wikipedia_content(wiki_content['extract'], mep_name)
+
+ # Create profile
+ profile = MEPPersonalityProfile(
+ full_name=mep_name,
+ mep_id=mep_data['mep_id'],
+ wikipedia_url=wiki_content['url'],
+ summary=personality_data['summary'],
+ early_life=personality_data['early_life'],
+ political_career=personality_data['political_career'],
+ political_views=personality_data['political_views'],
+ policy_focus=personality_data['policy_focus'],
+ achievements=personality_data['achievements'],
+ controversies=personality_data['controversies'],
+ personal_life=personality_data['personal_life'],
+ education=personality_data['education'],
+ professional_background=personality_data['professional_background'],
+ party_affiliations=personality_data['party_affiliations'],
+ committee_experience=personality_data['committee_experience'],
+ voting_record=personality_data['voting_record'],
+ public_statements=personality_data['public_statements'],
+ interests=personality_data['interests'],
+ languages=personality_data['languages'],
+ awards=personality_data['awards'],
+ publications=personality_data['publications'],
+ social_media=personality_data['social_media'],
+ last_updated=time.strftime("%Y-%m-%d %H:%M:%S")
+ )
+
+ if self.verbose:
+ logger.info(f"Created personality profile for {mep_name} from Wikipedia")
+
+ return profile
+
+ # Create minimal profile if no Wikipedia data found
+ profile = MEPPersonalityProfile(
+ full_name=mep_name,
+ mep_id=mep_data['mep_id'],
+ summary=f"{mep_name} is a Member of the European Parliament representing {country}.",
+ political_career=f"Currently serving as MEP for {country}.",
+ political_views=f"Member of {mep_data['political_group']} and {mep_data['national_party']}.",
+ last_updated=time.strftime("%Y-%m-%d %H:%M:%S")
+ )
+
+ if self.verbose:
+ logger.warning(f"No Wikipedia data found for {mep_name}, created minimal profile")
+
+ return profile
+
+ def save_personality_profile(self, profile: MEPPersonalityProfile) -> str:
+ """
+ Save personality profile to JSON file.
+
+ Args:
+ profile: MEPPersonalityProfile object
+
+ Returns:
+ Path to saved file
+ """
+ # Create safe filename
+ safe_name = re.sub(r'[^\w\s-]', '', profile.full_name).strip()
+ safe_name = re.sub(r'[-\s]+', '_', safe_name)
+ filename = f"{safe_name}_{profile.mep_id}.json"
+ filepath = os.path.join(self.output_dir, filename)
+
+ # Convert to dictionary and save
+ profile_dict = asdict(profile)
+
+ with open(filepath, 'w', encoding='utf-8') as f:
+ json.dump(profile_dict, f, indent=2, ensure_ascii=False)
+
+ if self.verbose:
+ logger.info(f"Saved personality profile: {filepath}")
+
+ return filepath
+
+ def scrape_all_mep_personalities(self, xml_file: str = "EU.xml", delay: float = 1.0) -> Dict[str, str]:
+ """
+ Scrape personality data for all MEPs.
+
+ Args:
+ xml_file: Path to EU.xml file
+ delay: Delay between requests to be respectful to Wikipedia
+
+ Returns:
+ Dictionary mapping MEP names to their personality profile file paths
+ """
+ meps = self.extract_mep_data_from_xml(xml_file)
+ profile_files = {}
+
+ if self.verbose:
+ logger.info(f"Starting personality scraping for {len(meps)} MEPs")
+
+ for i, mep_data in enumerate(meps, 1):
+ mep_name = mep_data['full_name']
+
+ if self.verbose:
+ logger.info(f"Processing {i}/{len(meps)}: {mep_name}")
+
+ try:
+ # Create personality profile
+ profile = self.create_personality_profile(mep_data)
+
+ # Save profile
+ filepath = self.save_personality_profile(profile)
+ profile_files[mep_name] = filepath
+
+ # Respectful delay
+ time.sleep(delay)
+
+ except Exception as e:
+ logger.error(f"Error processing {mep_name}: {e}")
+ continue
+
+ if self.verbose:
+ logger.info(f"Completed personality scraping. {len(profile_files)} profiles created.")
+
+ return profile_files
+
+ def load_personality_profile(self, filepath: str) -> MEPPersonalityProfile:
+ """
+ Load personality profile from JSON file.
+
+ Args:
+ filepath: Path to personality profile JSON file
+
+ Returns:
+ MEPPersonalityProfile object
+ """
+ with open(filepath, 'r', encoding='utf-8') as f:
+ data = json.load(f)
+
+ return MEPPersonalityProfile(**data)
+
+ def get_personality_summary(self, profile: MEPPersonalityProfile) -> str:
+ """
+ Generate a personality summary for use in AI agent system prompts.
+
+ Args:
+ profile: MEPPersonalityProfile object
+
+ Returns:
+ Formatted personality summary
+ """
+ summary_parts = []
+
+ if profile.summary:
+ summary_parts.append(f"Background: {profile.summary}")
+
+ if profile.political_career:
+ summary_parts.append(f"Political Career: {profile.political_career}")
+
+ if profile.political_views:
+ summary_parts.append(f"Political Views: {profile.political_views}")
+
+ if profile.policy_focus:
+ summary_parts.append(f"Policy Focus: {profile.policy_focus}")
+
+ if profile.achievements:
+ summary_parts.append(f"Notable Achievements: {profile.achievements}")
+
+ if profile.education:
+ summary_parts.append(f"Education: {profile.education}")
+
+ if profile.professional_background:
+ summary_parts.append(f"Professional Background: {profile.professional_background}")
+
+ return "\n".join(summary_parts)
+
+
+def main():
+ """Main function to run the Wikipedia personality scraper."""
+
+ print("šļø WIKIPEDIA PERSONALITY SCRAPER FOR EUROSWARM PARLIAMENT")
+ print("=" * 70)
+
+ # Initialize scraper
+ scraper = WikipediaPersonalityScraper(output_dir="mep_personalities", verbose=True)
+
+ # Scrape all MEP personalities
+ profile_files = scraper.scrape_all_mep_personalities(delay=1.0)
+
+ print(f"\nā
Scraping completed!")
+ print(f"š Profiles saved to: {scraper.output_dir}")
+ print(f"š Total profiles created: {len(profile_files)}")
+
+ # Show sample profile
+ if profile_files:
+ sample_name = list(profile_files.keys())[0]
+ sample_file = profile_files[sample_name]
+ sample_profile = scraper.load_personality_profile(sample_file)
+
+ print(f"\nš Sample Profile: {sample_name}")
+ print("-" * 50)
+ print(scraper.get_personality_summary(sample_profile))
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
From c31ee1df38f968585b0a5c3de07288f5551747c9 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Fri, 15 Aug 2025 23:02:01 +0300
Subject: [PATCH 50/56] Add files via upload
---
EU.xml | 5027 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 5027 insertions(+)
create mode 100644 EU.xml
diff --git a/EU.xml b/EU.xml
new file mode 100644
index 00000000..32220aaa
--- /dev/null
+++ b/EU.xml
@@ -0,0 +1,5027 @@
+
+Mika AALTOLA
+Finland
+Group of the European People's Party (Christian Democrats)
+256810
+Kansallinen Kokoomus
+
+
+Maravillas ABADĆA JOVER
+Spain
+Group of the European People's Party (Christian Democrats)
+257043
+Partido Popular
+
+
+Magdalena ADAMOWICZ
+Poland
+Group of the European People's Party (Christian Democrats)
+197490
+Independent
+
+
+Georgios AFTIAS
+Greece
+Group of the European People's Party (Christian Democrats)
+256820
+Nea Demokratia
+
+
+Oihane AGIRREGOITIA MARTĆNEZ
+Spain
+Renew Europe Group
+256987
+Partido Nacionalista Vasco
+
+
+Peter AGIUS
+Malta
+Group of the European People's Party (Christian Democrats)
+113523
+Partit Nazzjonalista
+
+
+Alex AGIUS SALIBA
+Malta
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197403
+Partit Laburista
+
+
+Galato ALEXANDRAKI
+Greece
+European Conservatives and Reformists Group
+256956
+Elliniki Lusi-Greek Solution
+
+
+GrƩgory ALLIONE
+France
+Renew Europe Group
+256869
+Renaissance
+
+
+Abir AL-SAHLANI
+Sweden
+Renew Europe Group
+197400
+Centerpartiet
+
+
+Nikolaos ANADIOTIS
+Greece
+Non-attached Members
+256858
+Dimokratikó Patriotikó KĆnima Ā«NIKIĀ»
+
+
+Christine ANDERSON
+Germany
+Europe of Sovereign Nations Group
+197475
+Alternative für Deutschland
+
+
+Li ANDERSSON
+Finland
+The Left group in the European Parliament - GUE/NGL
+256805
+Vasemmistoliitto
+
+
+Rasmus ANDRESEN
+Germany
+Group of the Greens/European Free Alliance
+197448
+Bündnis 90/Die Grünen
+
+
+Barry ANDREWS
+Ireland
+Renew Europe Group
+204332
+Fianna FƔil Party
+
+
+Vytenis Povilas ANDRIUKAITIS
+Lithuania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+119652
+Lietuvos socialdemokratų partija
+
+
+Mathilde ANDROUĆT
+France
+Patriots for Europe Group
+197691
+Rassemblement national
+
+
+Marc ANGEL
+Luxembourg
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+202073
+Parti ouvrier socialiste luxembourgeois
+
+
+Gerolf ANNEMANS
+Belgium
+Patriots for Europe Group
+124973
+Vlaams Belang
+
+
+Lucia ANNUNZIATA
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257123
+Partito Democratico
+
+
+Giuseppe ANTOCI
+Italy
+The Left group in the European Parliament - GUE/NGL
+257138
+Movimento 5 Stelle
+
+
+Pablo ARIAS ECHEVERRĆA
+Spain
+Group of the European People's Party (Christian Democrats)
+96808
+Partido Popular
+
+
+Pascal ARIMONT
+Belgium
+Group of the European People's Party (Christian Democrats)
+24922
+Christlich Soziale Partei
+
+
+Bartosz ARÅUKOWICZ
+Poland
+Group of the European People's Party (Christian Democrats)
+197492
+Platforma Obywatelska
+
+
+Sakis ARNAOUTOGLOU
+Greece
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256829
+PASOK-KINAL
+
+
+Anja ARNDT
+Germany
+Europe of Sovereign Nations Group
+256951
+Alternative für Deutschland
+
+
+Konstantinos ARVANITIS
+Greece
+The Left group in the European Parliament - GUE/NGL
+197701
+Coalition of the Radical Left
+
+
+Jaume ASENS LLODRĆ
+Spain
+Group of the Greens/European Free Alliance
+257015
+Movimiento Sumar
+
+
+Francisco ASSIS
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+28307
+Partido Socialista
+
+
+Daniel ATTARD
+Malta
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256934
+Partit Laburista
+
+
+Manon AUBRY
+France
+The Left group in the European Parliament - GUE/NGL
+197533
+La France Insoumise
+
+
+RenƩ AUST
+Germany
+Europe of Sovereign Nations Group
+256929
+Alternative für Deutschland
+
+
+Petras AUÅ TREVIÄIUS
+Lithuania
+Renew Europe Group
+124766
+Liberalų sÄ
jūdis
+
+
+Adrian-George AXINIA
+Romania
+European Conservatives and Reformists Group
+257117
+AlianČa pentru Unirea RomĆ¢nilor
+
+
+Malik AZMANI
+Netherlands
+Renew Europe Group
+197781
+Volkspartij voor Vrijheid en Democratie
+
+
+Thomas BAJADA
+Malta
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256936
+Partit Laburista
+
+
+Jeannette BALJEU
+Netherlands
+Renew Europe Group
+257003
+Volkspartij voor Vrijheid en Democratie
+
+
+Laura BALLARĆN CEREZA
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+247735
+Partido Socialista Obrero EspaƱol
+
+
+Jordan BARDELLA
+France
+Patriots for Europe Group
+131580
+Rassemblement national
+
+
+Katarina BARLEY
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197433
+Sozialdemokratische Partei Deutschlands
+
+
+Dan BARNA
+Romania
+Renew Europe Group
+257110
+Uniunea SalvaČi RomĆ¢nia
+
+
+Pernando BARRENA ARZA
+Spain
+The Left group in the European Parliament - GUE/NGL
+197684
+EH BILDU
+
+
+Stephen Nikola BARTULICA
+Croatia
+European Conservatives and Reformists Group
+257000
+Dom i nacionalno okupljanje
+
+
+Nikola BARTŮŠEK
+Czechia
+Patriots for Europe Group
+256852
+PÅĆsaha
+
+
+Arno BAUSEMER
+Germany
+Europe of Sovereign Nations Group
+256948
+Alternative für Deutschland
+
+
+Nicolas BAY
+France
+European Conservatives and Reformists Group
+124760
+IdentitƩ LibertƩs
+
+
+Christophe BAY
+France
+Patriots for Europe Group
+261797
+Rassemblement national
+
+
+Wouter BEKE
+Belgium
+Group of the European People's Party (Christian Democrats)
+256887
+Christen-Democratisch & Vlaams
+
+
+Fredis BELERIS
+Greece
+Group of the European People's Party (Christian Democrats)
+256947
+Nea Demokratia
+
+
+FranƧois-Xavier BELLAMY
+France
+Group of the European People's Party (Christian Democrats)
+197534
+Les RƩpublicains
+
+
+DragoÅ BENEA
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197658
+Partidul Social Democrat
+
+
+Brando BENIFEI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124867
+Partito Democratico
+
+
+Isabel BENJUMEA BENJUMEA
+Spain
+Group of the European People's Party (Christian Democrats)
+197679
+Partido Popular
+
+
+Monika BEÅOVĆ
+Slovakia
+Non-attached Members
+23868
+SMER-SociƔlna demokracia
+
+
+Hildegard BENTELE
+Germany
+Group of the European People's Party (Christian Democrats)
+197408
+Christlich Demokratische Union Deutschlands
+
+
+Tom BERENDSEN
+Netherlands
+Group of the European People's Party (Christian Democrats)
+197778
+Christen Democratisch AppĆØl
+
+
+Stefan BERGER
+Germany
+Group of the European People's Party (Christian Democrats)
+197410
+Christlich Demokratische Union Deutschlands
+
+
+Sibylle BERG
+Germany
+Non-attached Members
+256960
+Die PARTEI
+
+
+Sergio BERLATO
+Italy
+European Conservatives and Reformists Group
+4746
+FRATELLI D' ITALIA
+
+
+Alexander BERNHUBER
+Austria
+Group of the European People's Party (Christian Democrats)
+197648
+Ćsterreichische Volkspartei
+
+
+Robert BIEDROÅ
+Poland
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197498
+Nowa Lewica
+
+
+Adam BIELAN
+Poland
+European Conservatives and Reformists Group
+23788
+Prawo i SprawiedliwoÅÄ
+
+
+Gabriele BISCHOFF
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197435
+Sozialdemokratische Partei Deutschlands
+
+
+ĽuboŔ BLAHA
+Slovakia
+Non-attached Members
+257005
+SMER-SociƔlna demokracia
+
+
+Vilija BLINKEVIÄIÅŖTÄ
+Lithuania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+96681
+Lietuvos socialdemokratų partija
+
+
+Rachel BLOM
+Netherlands
+Patriots for Europe Group
+256998
+Partij voor de Vrijheid
+
+
+Michael BLOSS
+Germany
+Group of the Greens/European Free Alliance
+197449
+Bündnis 90/Die Grünen
+
+
+Tobiasz BOCHEÅSKI
+Poland
+European Conservatives and Reformists Group
+257073
+Prawo i SprawiedliwoÅÄ
+
+
+Damian BOESELAGER
+Germany
+Group of the Greens/European Free Alliance
+197439
+Volt
+
+
+Ioan-RareÅ BOGDAN
+Romania
+Group of the European People's Party (Christian Democrats)
+197636
+Partidul Naţional Liberal
+
+
+Stefano BONACCINI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257108
+Partito Democratico
+
+
+Barbara BONTE
+Belgium
+Patriots for Europe Group
+256881
+Vlaams Belang
+
+
+Paolo BORCHIA
+Italy
+Patriots for Europe Group
+101039
+Lega
+
+
+Mireia BORRĆS PABĆN
+Spain
+Patriots for Europe Group
+257024
+VOX
+
+
+Zsuzsanna BORVENDĆG
+Hungary
+Europe of Sovereign Nations Group
+257457
+Mi HazƔnk Mozgalom
+
+
+Biljana BORZAN
+Croatia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+112748
+Socijaldemokratska partija Hrvatske
+
+
+Gordan BOSANAC
+Croatia
+Group of the Greens/European Free Alliance
+256995
+Možemo!
+
+
+Irmhild BOįŗDORF
+Germany
+Europe of Sovereign Nations Group
+256945
+Alternative für Deutschland
+
+
+Stine BOSSE
+Denmark
+Renew Europe Group
+257020
+Moderaterne
+
+
+Marc BOTENGA
+Belgium
+The Left group in the European Parliament - GUE/NGL
+187917
+PVDA-PTB
+
+
+Gilles BOYER
+France
+Renew Europe Group
+197577
+Horizons
+
+
+Lynn BOYLAN
+Ireland
+The Left group in the European Parliament - GUE/NGL
+124984
+Sinn FƩin
+
+
+Helmut BRANDSTĆTTER
+Austria
+Renew Europe Group
+256841
+NEOS ā Das Neue Ćsterreich
+
+
+Marie-Luce BRASIER-CLAIN
+France
+Patriots for Europe Group
+256878
+Rassemblement national
+
+
+Grzegorz BRAUN
+Poland
+Non-attached Members
+257067
+Konfederacja Korony Polskiej
+
+
+Krzysztof BREJZA
+Poland
+Group of the European People's Party (Christian Democrats)
+251324
+Platforma Obywatelska
+
+
+Saskia BRICMONT
+Belgium
+Group of the Greens/European Free Alliance
+197470
+Ecologistes ConfƩdƩrƩs pour l'Organisation de Luttes Originales
+
+
+Nikolina BRNJAC
+Croatia
+Group of the European People's Party (Christian Democrats)
+204129
+Hrvatska demokratska zajednica
+
+
+Joachim StanisÅaw BRUDZIÅSKI
+Poland
+European Conservatives and Reformists Group
+197501
+Prawo i SprawiedliwoÅÄ
+
+
+Anna BRYÅKA
+Poland
+Patriots for Europe Group
+257064
+Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
+
+
+Markus BUCHHEIT
+Germany
+Europe of Sovereign Nations Group
+128483
+Alternative für Deutschland
+
+
+Tomasz BUCZEK
+Poland
+Patriots for Europe Group
+257072
+Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
+
+
+Daniel BUDA
+Romania
+Group of the European People's Party (Christian Democrats)
+125012
+Partidul Naţional Liberal
+
+
+Waldemar BUDA
+Poland
+European Conservatives and Reformists Group
+99878
+Prawo i SprawiedliwoÅÄ
+
+
+Borys BUDKA
+Poland
+Group of the European People's Party (Christian Democrats)
+257047
+Platforma Obywatelska
+
+
+Sebastião BUGALHO
+Portugal
+Group of the European People's Party (Christian Democrats)
+257081
+Partido Social Democrata
+
+
+Andrzej BUÅA
+Poland
+Group of the European People's Party (Christian Democrats)
+257051
+Platforma Obywatelska
+
+
+Udo BULLMANN
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+4267
+Sozialdemokratische Partei Deutschlands
+
+
+Delara BURKHARDT
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197440
+Sozialdemokratische Partei Deutschlands
+
+
+Jorge BUXADĆ VILLALBA
+Spain
+Patriots for Europe Group
+197829
+VOX
+
+
+Petr BYSTRON
+Germany
+Europe of Sovereign Nations Group
+256928
+Alternative für Deutschland
+
+
+Jaroslav BŽOCH
+Czechia
+Patriots for Europe Group
+220840
+ANO 2011
+
+
+MƩlissa CAMARA
+France
+Group of the Greens/European Free Alliance
+256915
+Les Ćcologistes
+
+
+Pascal CANFIN
+France
+Renew Europe Group
+96711
+Renaissance
+
+
+Nina CARBERRY
+Ireland
+Group of the European People's Party (Christian Democrats)
+257296
+Fine Gael Party
+
+
+Gheorghe CĆRCIU
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257100
+Partidul Social Democrat
+
+
+Damien CARĆME
+France
+The Left group in the European Parliament - GUE/NGL
+197574
+La France Insoumise
+
+
+David CASA
+Malta
+Group of the European People's Party (Christian Democrats)
+28122
+Partit Nazzjonalista
+
+
+Daniel CASPARY
+Germany
+Group of the European People's Party (Christian Democrats)
+28219
+Christlich Demokratische Union Deutschlands
+
+
+Benoit CASSART
+Belgium
+Renew Europe Group
+256891
+Mouvement RƩformateur
+
+
+Laurent CASTILLO
+France
+Group of the European People's Party (Christian Democrats)
+256921
+Union des droites pour la RƩpublique
+
+
+Pilar DEL CASTILLO VERA
+Spain
+Group of the European People's Party (Christian Democrats)
+28390
+Partido Popular
+
+
+Anna CAVAZZINI
+Germany
+Group of the Greens/European Free Alliance
+86793
+Bündnis 90/Die Grünen
+
+
+Stefano CAVEDAGNA
+Italy
+European Conservatives and Reformists Group
+257096
+FRATELLI D' ITALIA
+
+
+Susanna CECCARDI
+Italy
+Patriots for Europe Group
+197786
+Lega
+
+
+JosƩ CEPEDA
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257002
+Partido Socialista Obrero EspaƱol
+
+
+Estelle CEULEMANS
+Belgium
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256880
+Parti Socialiste
+
+
+Mohammed CHAHIM
+Netherlands
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197782
+GroenLinks-PvdA
+
+
+Leila CHAIBI
+France
+The Left group in the European Parliament - GUE/NGL
+197529
+La France Insoumise
+
+
+Olivier CHASTEL
+Belgium
+Renew Europe Group
+197463
+Mouvement RƩformateur
+
+
+Caterina CHINNICI
+Italy
+Group of the European People's Party (Christian Democrats)
+124861
+Forza Italia
+
+
+Asger CHRISTENSEN
+Denmark
+Renew Europe Group
+197558
+Venstre, Danmarks Liberale Parti
+
+
+Carlo CICCIOLI
+Italy
+European Conservatives and Reformists Group
+257093
+FRATELLI D' ITALIA
+
+
+Veronika CIFROVĆ OSTRIHOÅOVĆ
+Slovakia
+Renew Europe Group
+257014
+ProgresĆvne Slovensko
+
+
+Alessandro CIRIANI
+Italy
+European Conservatives and Reformists Group
+257147
+FRATELLI D' ITALIA
+
+
+Anna Maria CISINT
+Italy
+Patriots for Europe Group
+257131
+Lega
+
+
+Per CLAUSEN
+Denmark
+The Left group in the European Parliament - GUE/NGL
+257023
+Enhedslisten
+
+
+Christophe CLERGEAU
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+245018
+Parti socialiste
+
+
+David CORMAND
+France
+Group of the Greens/European Free Alliance
+197503
+Les Ćcologistes
+
+
+Annalisa CORRADO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257169
+Partito Democratico
+
+
+Vivien COSTANZO
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256937
+Sozialdemokratische Partei Deutschlands
+
+
+João COTRIM DE FIGUEIREDO
+Portugal
+Renew Europe Group
+257057
+Iniciativa Liberal
+
+
+Barry COWEN
+Ireland
+Renew Europe Group
+257297
+Fianna FƔil Party
+
+
+Tobias CREMER
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256938
+Sozialdemokratische Partei Deutschlands
+
+
+Carmen CRESPO DĆAZ
+Spain
+Group of the European People's Party (Christian Democrats)
+257034
+Partido Popular
+
+
+Andi CRISTEA
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+40224
+Partidul Social Democrat
+
+
+Giovanni CROSETTO
+Italy
+European Conservatives and Reformists Group
+257094
+FRATELLI D' ITALIA
+
+
+Paulo CUNHA
+Portugal
+Group of the European People's Party (Christian Democrats)
+257078
+Partido Social Democrata
+
+
+Henrik DAHL
+Denmark
+Group of the European People's Party (Christian Democrats)
+257028
+Liberal Alliance
+
+
+Johan DANIELSSON
+Sweden
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+38542
+Arbetarepartiet- Socialdemokraterna
+
+
+Marie DAUCHY
+France
+Patriots for Europe Group
+236050
+Rassemblement national
+
+
+Dóra DĆVID
+Hungary
+Group of the European People's Party (Christian Democrats)
+256862
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Ivan DAVID
+Czechia
+Europe of Sovereign Nations Group
+197556
+Svoboda a pÅĆmĆ” demokracie
+
+
+Antonio DECARO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257122
+Partito Democratico
+
+
+RaĆŗl DE LA HOZ QUINTANO
+Spain
+Group of the European People's Party (Christian Democrats)
+257030
+Partido Popular
+
+
+Danilo DELLA VALLE
+Italy
+The Left group in the European Parliament - GUE/NGL
+257155
+Movimento 5 Stelle
+
+
+ValƩrie DELOGE
+France
+Patriots for Europe Group
+256886
+Rassemblement national
+
+
+Fabio DE MASI
+Germany
+Non-attached Members
+124858
+Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
+
+
+Salvatore DE MEO
+Italy
+Group of the European People's Party (Christian Democrats)
+204333
+Forza Italia
+
+
+Ćzlem DEMIREL
+Germany
+The Left group in the European Parliament - GUE/NGL
+197468
+DIE LINKE.
+
+
+TamƔs DEUTSCH
+Hungary
+Patriots for Europe Group
+96826
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+ValƩrie DEVAUX
+France
+Renew Europe Group
+256870
+Union des dƩmocrates et indƩpendants
+
+
+Adnan DIBRANI
+Sweden
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257087
+Arbetarepartiet- Socialdemokraterna
+
+
+Ton DIEPEVEEN
+Netherlands
+Patriots for Europe Group
+256981
+Partij voor de Vrijheid
+
+
+Elisabeth DIERINGER
+Austria
+Patriots for Europe Group
+256834
+Freiheitliche Partei Ćsterreichs
+
+
+Vasile DĆNCU
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+33998
+Partidul Social Democrat
+
+
+Elio DI RUPO
+Belgium
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+1294
+Parti Socialiste
+
+
+MƩlanie DISDIER
+France
+Patriots for Europe Group
+256874
+Rassemblement national
+
+
+KlƔra DOBREV
+Hungary
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197579
+Demokratikus KoalĆció
+
+
+Regina DOHERTY
+Ireland
+Group of the European People's Party (Christian Democrats)
+257237
+Fine Gael Party
+
+
+Christian DOLESCHAL
+Germany
+Group of the European People's Party (Christian Democrats)
+197473
+Christlich-Soziale Union in Bayern e.V.
+
+
+Csaba DĆMĆTĆR
+Hungary
+Patriots for Europe Group
+260724
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Paulo DO NASCIMENTO CABRAL
+Portugal
+Group of the European People's Party (Christian Democrats)
+257048
+AlianƧa DemocrƔtica
+
+
+Elena DONAZZAN
+Italy
+European Conservatives and Reformists Group
+257095
+FRATELLI D' ITALIA
+
+
+Herbert DORFMANN
+Italy
+Group of the European People's Party (Christian Democrats)
+96787
+Südtiroler Volkspartei
+
+
+Klara DOSTALOVA
+Czechia
+Patriots for Europe Group
+256853
+ANO 2011
+
+
+OndÅej DOSTĆL
+Czechia
+Non-attached Members
+256851
+Independent
+
+
+Siegbert Frank DROESE
+Germany
+Europe of Sovereign Nations Group
+256949
+Alternative für Deutschland
+
+
+Lena DĆPONT
+Germany
+Group of the European People's Party (Christian Democrats)
+99945
+Christlich Demokratische Union Deutschlands
+
+
+MichaÅ DWORCZYK
+Poland
+European Conservatives and Reformists Group
+257076
+Prawo i SprawiedliwoÅÄ
+
+
+Matthias ECKE
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+237465
+Sozialdemokratische Partei Deutschlands
+
+
+Christian EHLER
+Germany
+Group of the European People's Party (Christian Democrats)
+28226
+Christlich Demokratische Union Deutschlands
+
+
+Marieke EHLERS
+Netherlands
+Patriots for Europe Group
+192254
+Partij voor de Vrijheid
+
+
+Bas EICKHOUT
+Netherlands
+Group of the Greens/European Free Alliance
+96725
+GroenLinks-PvdA
+
+
+Sofie ERIKSSON
+Sweden
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257088
+Arbetarepartiet- Socialdemokraterna
+
+
+Dick ERIXON
+Sweden
+European Conservatives and Reformists Group
+257091
+Sverigedemokraterna
+
+
+Engin EROGLU
+Germany
+Renew Europe Group
+197430
+Freie WƤhler
+
+
+Rosa ESTARĆS FERRAGUT
+Spain
+Group of the European People's Party (Christian Democrats)
+96811
+Partido Popular
+
+
+Sebastian EVERDING
+Germany
+The Left group in the European Parliament - GUE/NGL
+256961
+Partei Mensch Umwelt Tierschutz
+
+
+Alma EZCURRA ALMANSA
+Spain
+Group of the European People's Party (Christian Democrats)
+257035
+Partido Popular
+
+
+Gheorghe FALCÄ
+Romania
+Group of the European People's Party (Christian Democrats)
+197649
+Partidul Naţional Liberal
+
+
+Marco FALCONE
+Italy
+Group of the European People's Party (Christian Democrats)
+257137
+Forza Italia
+
+
+Nikolas FARANTOURIS
+Greece
+The Left group in the European Parliament - GUE/NGL
+256823
+Coalition of the Radical Left
+
+
+Laurence FARRENG
+France
+Renew Europe Group
+197589
+Mouvement DƩmocrate
+
+
+Jan FARSKĆ
+Czechia
+Group of the European People's Party (Christian Democrats)
+256840
+StarostovƩ a nezƔvisli
+
+
+Markus FERBER
+Germany
+Group of the European People's Party (Christian Democrats)
+1917
+Christlich-Soziale Union in Bayern e.V.
+
+
+Viktória FERENC
+Hungary
+Patriots for Europe Group
+256857
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+JonĆ”s FERNĆNDEZ
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+125046
+Partido Socialista Obrero EspaƱol
+
+
+Carlo FIDANZA
+Italy
+European Conservatives and Reformists Group
+96810
+FRATELLI D' ITALIA
+
+
+Pietro FIOCCHI
+Italy
+European Conservatives and Reformists Group
+197607
+FRATELLI D' ITALIA
+
+
+Gabriela FIREA
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257098
+Partidul Social Democrat
+
+
+Ruth FIRMENICH
+Germany
+Non-attached Members
+25758
+Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
+
+
+Claire FITA
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256906
+Parti socialiste
+
+
+Luke Ming FLANAGAN
+Ireland
+The Left group in the European Parliament - GUE/NGL
+124985
+Independent
+
+
+Loucas FOURLAS
+Cyprus
+Group of the European People's Party (Christian Democrats)
+197414
+Democratic Rally
+
+
+Emma FOURREAU
+France
+The Left group in the European Parliament - GUE/NGL
+256913
+La France Insoumise
+
+
+Emmanouil FRAGKOS
+Greece
+European Conservatives and Reformists Group
+198490
+Elliniki Lusi-Greek Solution
+
+
+Daniel FREUND
+Germany
+Group of the Greens/European Free Alliance
+106936
+Bündnis 90/Die Grünen
+
+
+Anne-Sophie FRIGOUT
+France
+Patriots for Europe Group
+256876
+Rassemblement national
+
+
+Sigrid FRIIS
+Denmark
+Renew Europe Group
+257038
+Det Radikale Venstre
+
+
+HelƩne FRITZON
+Sweden
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197391
+Arbetarepartiet- Socialdemokraterna
+
+
+Tomasz FROELICH
+Germany
+Europe of Sovereign Nations Group
+190574
+Alternative für Deutschland
+
+
+Niels FUGLSANG
+Denmark
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+101585
+Socialdemokratiet
+
+
+Kathleen FUNCHION
+Ireland
+The Left group in the European Parliament - GUE/NGL
+257299
+Sinn FƩin
+
+
+AngƩline FURET
+France
+Patriots for Europe Group
+256896
+Rassemblement national
+
+
+Mario FURORE
+Italy
+The Left group in the European Parliament - GUE/NGL
+197795
+Movimento 5 Stelle
+
+
+Michael GAHLER
+Germany
+Group of the European People's Party (Christian Democrats)
+2341
+Christlich Demokratische Union Deutschlands
+
+
+Kinga GĆL
+Hungary
+Patriots for Europe Group
+28150
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Estrella GALĆN
+Spain
+The Left group in the European Parliament - GUE/NGL
+257012
+Movimiento Sumar
+
+
+Lina GĆLVEZ
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197702
+Partido Socialista Obrero EspaƱol
+
+
+Alberico GAMBINO
+Italy
+European Conservatives and Reformists Group
+257097
+FRATELLI D' ITALIA
+
+
+Iratxe GARCĆA PĆREZ
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+28298
+Partido Socialista Obrero EspaƱol
+
+
+Raquel GARCĆA HERMIDA-VAN DER WALLE
+Netherlands
+Renew Europe Group
+256970
+Democraten 66
+
+
+Jean-Paul GARRAUD
+France
+Patriots for Europe Group
+197628
+Rassemblement national
+
+
+Kamila GASIUK-PIHOWICZ
+Poland
+Group of the European People's Party (Christian Democrats)
+257032
+Platforma Obywatelska
+
+
+Geadis GEADI
+Cyprus
+European Conservatives and Reformists Group
+256986
+ĪĪøĪ½Ī¹ĪŗĻ ĪαĻĪŗĻ ĪĪĻĻĻĪæ
+
+
+Hanna GEDIN
+Sweden
+The Left group in the European Parliament - GUE/NGL
+257092
+VƤnsterpartiet
+
+
+Alexandra GEESE
+Germany
+Group of the Greens/European Free Alliance
+183916
+Bündnis 90/Die Grünen
+
+
+Jens GEIER
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+96833
+Sozialdemokratische Partei Deutschlands
+
+
+Thomas GEISEL
+Germany
+Non-attached Members
+256939
+Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
+
+
+Chiara GEMMA
+Italy
+European Conservatives and Reformists Group
+197794
+FRATELLI D' ITALIA
+
+
+Giorgos GEORGIOU
+Cyprus
+The Left group in the European Parliament - GUE/NGL
+197416
+Progressive Party of Working People - Left - New Forces
+
+
+Gerben-Jan GERBRANDY
+Netherlands
+Renew Europe Group
+96940
+Democraten 66
+
+
+Jean-Marc GERMAIN
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256901
+Parti socialiste
+
+
+Gabriella GERZSENYI
+Hungary
+Group of the European People's Party (Christian Democrats)
+256866
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Niels GEUKING
+Germany
+Group of the European People's Party (Christian Democrats)
+251874
+Familien-Partei Deutschlands
+
+
+Jens GIESEKE
+Germany
+Group of the European People's Party (Christian Democrats)
+124807
+Christlich Demokratische Union Deutschlands
+
+
+Borja GIMĆNEZ LARRAZ
+Spain
+Group of the European People's Party (Christian Democrats)
+125204
+Partido Popular
+
+
+Juan Carlos GIRAUTA VIDAL
+Spain
+Patriots for Europe Group
+125052
+VOX
+
+
+SunÄana GLAVAK
+Croatia
+Group of the European People's Party (Christian Democrats)
+202036
+Hrvatska demokratska zajednica
+
+
+Andreas GLĆCK
+Germany
+Renew Europe Group
+197443
+Freie Demokratische Partei
+
+
+Raphaƫl GLUCKSMANN
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197694
+Place publique
+
+
+Charles GOERENS
+Luxembourg
+Renew Europe Group
+840
+Parti dƩmocratique
+
+
+Christophe GOMART
+France
+Group of the European People's Party (Christian Democrats)
+256919
+Les RƩpublicains
+
+
+Isilda GOMES
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257075
+Partido Socialista
+
+
+Sandra GĆMEZ LĆPEZ
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256997
+Partido Socialista Obrero EspaƱol
+
+
+Bruno GONĆALVES
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257059
+Partido Socialista
+
+
+SĆ©rgio GONĆALVES
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257079
+Partido Socialista
+
+
+NicolĆ”s GONZĆLEZ CASARES
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197718
+Partido Socialista Obrero EspaƱol
+
+
+Esteban GONZĆLEZ PONS
+Spain
+Group of the European People's Party (Christian Democrats)
+125027
+Partido Popular
+
+
+Giorgio GORI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257102
+Partito Democratico
+
+
+MaÅgorzata GOSIEWSKA
+Poland
+European Conservatives and Reformists Group
+257055
+Prawo i SprawiedliwoÅÄ
+
+
+Dirk GOTINK
+Netherlands
+Group of the European People's Party (Christian Democrats)
+97399
+Nieuw Sociaal Contract
+
+
+Sandro GOZI
+France
+Renew Europe Group
+204419
+Mouvement DƩmocrate
+
+
+Maria GRAPINI
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124785
+Partidul Social Democrat
+
+
+Petras GRAŽULIS
+Lithuania
+Europe of Sovereign Nations Group
+256808
+Tautos ir teisingumo sÄ
junga
+
+
+MarkĆ©ta GREGOROVĆ
+Czechia
+Group of the Greens/European Free Alliance
+197549
+PIRĆTI
+
+
+Branko GRIMS
+Slovenia
+Group of the European People's Party (Christian Democrats)
+220908
+Slovenska demokratska stranka
+
+
+Catherine GRISET
+France
+Patriots for Europe Group
+94649
+Rassemblement national
+
+
+Hanna GRONKIEWICZ-WALTZ
+Poland
+Group of the European People's Party (Christian Democrats)
+262021
+Platforma Obywatelska
+
+
+Bart GROOTHUIS
+Netherlands
+Renew Europe Group
+197780
+Volkspartij voor Vrijheid en Democratie
+
+
+Elisabeth GROSSMANN
+Austria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256830
+Sozialdemokratische Partei Ćsterreichs
+
+
+Christophe GRUDLER
+France
+Renew Europe Group
+197557
+Mouvement DƩmocrate
+
+
+Elisabetta GUALMINI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197618
+Partito Democratico
+
+
+Cristina GUARDA
+Italy
+Group of the Greens/European Free Alliance
+257130
+Europa Verde - Verdi
+
+
+Bernard GUETTA
+France
+Renew Europe Group
+197543
+Sans parti
+
+
+Maria GUZENINA
+Finland
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256803
+Suomen Sosialidemokraattinen Puolue/Finlands Socialdemokratiska Parti
+
+
+EnikÅ GYÅRI
+Hungary
+Patriots for Europe Group
+96830
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+AndrĆ”s GYĆRK
+Hungary
+Patriots for Europe Group
+23816
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Michalis HADJIPANTELA
+Cyprus
+Group of the European People's Party (Christian Democrats)
+256985
+Democratic Rally
+
+
+Svenja HAHN
+Germany
+Renew Europe Group
+197444
+Freie Demokratische Partei
+
+
+Roman HAIDER
+Austria
+Patriots for Europe Group
+198176
+Freiheitliche Partei Ćsterreichs
+
+
+Andrzej HALICKI
+Poland
+Group of the European People's Party (Christian Democrats)
+197514
+Platforma Obywatelska
+
+
+Niels Flemming HANSEN
+Denmark
+Group of the European People's Party (Christian Democrats)
+257033
+Det Konservative Folkeparti
+
+
+Rima HASSAN
+France
+The Left group in the European Parliament - GUE/NGL
+256912
+La France Insoumise
+
+
+Gerald HAUSER
+Austria
+Patriots for Europe Group
+256842
+Freiheitliche Partei Ćsterreichs
+
+
+Martin HĆUSLING
+Germany
+Group of the Greens/European Free Alliance
+96752
+Bündnis 90/Die Grünen
+
+
+Mircea-Gheorghe HAVA
+Romania
+Group of the European People's Party (Christian Democrats)
+197646
+Partidul Naţional Liberal
+
+
+ValƩrie HAYER
+France
+Renew Europe Group
+135511
+Renaissance
+
+
+Anja HAZEKAMP
+Netherlands
+The Left group in the European Parliament - GUE/NGL
+125023
+Partij voor de Dieren
+
+
+Hannes HEIDE
+Austria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197682
+Sozialdemokratische Partei Ćsterreichs
+
+
+Eero HEINĆLUOMA
+Finland
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197800
+Suomen Sosialidemokraattinen Puolue/Finlands Socialdemokratiska Parti
+
+
+Anna-Maja HENRIKSSON
+Finland
+Renew Europe Group
+198073
+Svenska folkpartiet
+
+
+Niclas HERBST
+Germany
+Group of the European People's Party (Christian Democrats)
+197412
+Christlich Demokratische Union Deutschlands
+
+
+Esther HERRANZ GARCĆA
+Spain
+Group of the European People's Party (Christian Democrats)
+22418
+Partido Popular
+
+
+Krzysztof HETMAN
+Poland
+Group of the European People's Party (Christian Democrats)
+124895
+Polskie Stronnictwo Ludowe
+
+
+Monika HOHLMEIER
+Germany
+Group of the European People's Party (Christian Democrats)
+96780
+Christlich-Soziale Union in Bayern e.V.
+
+
+Martin HOJSĆK
+Slovakia
+Renew Europe Group
+197770
+ProgresĆvne Slovensko
+
+
+PƤr HOLMGREN
+Sweden
+Group of the Greens/European Free Alliance
+197398
+Miljƶpartiet de grƶna
+
+
+Gyƶrgy HĆLVĆNYI
+Hungary
+Patriots for Europe Group
+124715
+KeresztƩnydemokrata NƩppƔrt
+
+
+Alicia HOMS GINEL
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+122978
+Partido Socialista Obrero EspaƱol
+
+
+SƩrgio HUMBERTO
+Portugal
+Group of the European People's Party (Christian Democrats)
+257065
+AlianƧa DemocrƔtica
+
+
+Ivars IJABS
+Latvia
+Renew Europe Group
+197624
+Latvijas attīstībai
+
+
+CƩline IMART
+France
+Group of the European People's Party (Christian Democrats)
+256918
+Les RƩpublicains
+
+
+Evin INCIR
+Sweden
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197392
+Arbetarepartiet- Socialdemokraterna
+
+
+Paolo INSELVINI
+Italy
+European Conservatives and Reformists Group
+257144
+FRATELLI D' ITALIA
+
+
+Diana IOVANOVICI ÅOÅOACÄ
+Romania
+Non-attached Members
+257120
+S.O.S. România
+
+
+Patryk JAKI
+Poland
+European Conservatives and Reformists Group
+197516
+Solidarna Polska Zbigniewa Ziobro
+
+
+Hana JALLOUL MURO
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256992
+Partido Socialista Obrero EspaƱol
+
+
+France JAMET
+France
+Patriots for Europe Group
+189065
+Rassemblement national
+
+
+Adam JARUBAS
+Poland
+Group of the European People's Party (Christian Democrats)
+197517
+Polskie Stronnictwo Ludowe
+
+
+Romana JERKOVIÄ
+Croatia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+112747
+Socijaldemokratska partija Hrvatske
+
+
+Marc JONGEN
+Germany
+Europe of Sovereign Nations Group
+256942
+Alternative für Deutschland
+
+
+Dariusz JOÅSKI
+Poland
+Group of the European People's Party (Christian Democrats)
+257031
+Inicjatywa Polska
+
+
+Virginie JORON
+France
+Patriots for Europe Group
+197627
+Rassemblement national
+
+
+Pierre JOUVET
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256898
+Parti socialiste
+
+
+Irena JOVEVA
+Slovenia
+Renew Europe Group
+197447
+Gibanje Svoboda
+
+
+Rasa JUKNEVIÄIENÄ
+Lithuania
+Group of the European People's Party (Christian Democrats)
+197840
+TÄvynÄs sÄ
junga-Lietuvos krikÅ”Äionys demokratai
+
+
+Nora JUNCO GARCĆA
+Spain
+European Conservatives and Reformists Group
+257022
+Independiente
+
+
+Alexander JUNGBLUTH
+Germany
+Europe of Sovereign Nations Group
+256941
+Alternative für Deutschland
+
+
+Taner KABILOV
+Bulgaria
+Non-attached Members
+257256
+Movement for Rights and Freedoms
+
+
+FranƧois KALFON
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256908
+Parti socialiste
+
+
+Erik KALIÅĆK
+Slovakia
+Non-attached Members
+257007
+SMER-SociƔlna demokracia
+
+
+Marina KALJURAND
+Estonia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197491
+Sotsiaaldemokraatlik Erakond
+
+
+Sandra KALNIETE
+Latvia
+Group of the European People's Party (Christian Democrats)
+96934
+JaunÄ VienotÄ«ba
+
+
+Mariusz KAMIÅSKI
+Poland
+European Conservatives and Reformists Group
+257056
+Prawo i SprawiedliwoÅÄ
+
+
+Radan KANEV
+Bulgaria
+Group of the European People's Party (Christian Democrats)
+197839
+Democrats for Strong Bulgaria
+
+
+Assita KANKO
+Belgium
+European Conservatives and Reformists Group
+197469
+Nieuw-Vlaamse Alliantie
+
+
+Karin KARLSBRO
+Sweden
+Renew Europe Group
+197401
+Liberalerna
+
+
+Fernand KARTHEISER
+Luxembourg
+Non-attached Members
+256900
+Alternativ Demokratesch Reformpartei
+
+
+Ľubica KARVAÅ OVĆ
+Slovakia
+Renew Europe Group
+257013
+ProgresĆvne Slovensko
+
+
+Elsi KATAINEN
+Finland
+Renew Europe Group
+191693
+Suomen Keskusta
+
+
+Emmanouil KEFALOGIANNIS
+Greece
+Group of the European People's Party (Christian Democrats)
+125068
+Nea Demokratia
+
+
+Billy KELLEHER
+Ireland
+Renew Europe Group
+197818
+Fianna FƔil Party
+
+
+Fabienne KELLER
+France
+Renew Europe Group
+22858
+Renaissance
+
+
+SeƔn KELLY
+Ireland
+Group of the European People's Party (Christian Democrats)
+96668
+Fine Gael Party
+
+
+Martine KEMP
+Luxembourg
+Group of the European People's Party (Christian Democrats)
+249603
+Parti chrƩtien social luxembourgeois
+
+
+Rudi KENNES
+Belgium
+The Left group in the European Parliament - GUE/NGL
+256890
+Independent
+
+
+Mary KHAN
+Germany
+Europe of Sovereign Nations Group
+256957
+Alternative für Deutschland
+
+
+Sophia KIRCHER
+Austria
+Group of the European People's Party (Christian Democrats)
+256831
+Ćsterreichische Volkspartei
+
+
+Sarah KNAFO
+France
+Europe of Sovereign Nations Group
+256924
+ReconquĆŖte!
+
+
+OndÅej KNOTEK
+Czechia
+Patriots for Europe Group
+197528
+ANO 2011
+
+
+MichaÅ KOBOSKO
+Poland
+Renew Europe Group
+257037
+Polska 2050
+
+
+Stefan KĆHLER
+Germany
+Group of the European People's Party (Christian Democrats)
+256973
+Christlich-Soziale Union in Bayern e.V.
+
+
+Åukasz KOHUT
+Poland
+Group of the European People's Party (Christian Democrats)
+197523
+Independent
+
+
+Arba KOKALARI
+Sweden
+Group of the European People's Party (Christian Democrats)
+197406
+Moderaterna
+
+
+OndÅej KOLĆÅ
+Czechia
+Group of the European People's Party (Christian Democrats)
+256846
+TOP 09 a StarostovƩ
+
+
+Kinga KOLLĆR
+Hungary
+Group of the European People's Party (Christian Democrats)
+256861
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Rihards KOLS
+Latvia
+European Conservatives and Reformists Group
+220871
+NacionÄlÄ apvienÄ«ba "Visu Latvijai!" - "TÄvzemei un BrÄ«vÄ«bai/LNNK"
+
+
+KateÅina KONEÄNĆ
+Czechia
+Non-attached Members
+23699
+KomunistickĆ” strana Äech a Moravy
+
+
+Ewa KOPACZ
+Poland
+Group of the European People's Party (Christian Democrats)
+197525
+Platforma Obywatelska
+
+
+Moritz KĆRNER
+Germany
+Renew Europe Group
+197445
+Freie Demokratische Partei
+
+
+Elena KOUNTOURA
+Greece
+The Left group in the European Parliament - GUE/NGL
+197699
+Coalition of the Radical Left
+
+
+Andrey KOVATCHEV
+Bulgaria
+Group of the European People's Party (Christian Democrats)
+97968
+Citizens for European Development of Bulgaria
+
+
+Vilis KRIÅ TOPANS
+Latvia
+Patriots for Europe Group
+256909
+Latvija pirmajÄ vietÄ
+
+
+Sebastian KRUIS
+Netherlands
+Patriots for Europe Group
+256996
+Partij voor de Vrijheid
+
+
+OndÅej KRUTĆLEK
+Czechia
+European Conservatives and Reformists Group
+256845
+ObÄanskĆ” demokratickĆ” strana
+
+
+TomÔŔ KUBĆN
+Czechia
+Patriots for Europe Group
+261038
+ANO 2011
+
+
+Alice KUHNKE
+Sweden
+Group of the Greens/European Free Alliance
+197395
+Miljƶpartiet de grƶna
+
+
+AndrƔs Tivadar KULJA
+Hungary
+Group of the European People's Party (Christian Democrats)
+256864
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Katri KULMUNI
+Finland
+Renew Europe Group
+198084
+Suomen Keskusta
+
+
+Merja KYLLĆNEN
+Finland
+The Left group in the European Parliament - GUE/NGL
+124736
+Vasemmistoliitto
+
+
+Ilhan KYUCHYUK
+Bulgaria
+Renew Europe Group
+124866
+Movement for Rights and Freedoms
+
+
+Sergey LAGODINSKY
+Germany
+Group of the Greens/European Free Alliance
+197460
+Bündnis 90/Die Grünen
+
+
+Eszter LAKOS
+Hungary
+Group of the European People's Party (Christian Democrats)
+256865
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Aurore LALUCQ
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197697
+Place publique
+
+
+Bernd LANGE
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+1909
+Sozialdemokratische Partei Deutschlands
+
+
+Katrin LANGENSIEPEN
+Germany
+Group of the Greens/European Free Alliance
+197461
+Bündnis 90/Die Grünen
+
+
+Judita LAÅ Å ĆKOVĆ
+Slovakia
+Non-attached Members
+198373
+SMER-SociƔlna demokracia
+
+
+AndrĆ”s LĆSZLĆ
+Hungary
+Patriots for Europe Group
+256860
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Afroditi LATINOPOULOU
+Greece
+Patriots for Europe Group
+256954
+FonĆ LoyikĆs
+
+
+Murielle LAURENT
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256899
+Parti socialiste
+
+
+Camilla LAURETI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+230085
+Partito Democratico
+
+
+Rada LAYKOVA
+Bulgaria
+Europe of Sovereign Nations Group
+257262
+Revival
+
+
+Ilia LAZAROV
+Bulgaria
+Group of the European People's Party (Christian Democrats)
+257261
+Union of Democratic Forces
+
+
+Luis-VicenČiu LAZARUS
+Romania
+Non-attached Members
+257118
+S.O.S. România
+
+
+Isabelle LE CALLENNEC
+France
+Group of the European People's Party (Christian Democrats)
+256920
+Les RƩpublicains
+
+
+Fabrice LEGGERI
+France
+Patriots for Europe Group
+256872
+Rassemblement national
+
+
+Jeroen LENAERS
+Netherlands
+Group of the European People's Party (Christian Democrats)
+95074
+Christen Democratisch AppĆØl
+
+
+Julien LEONARDELLI
+France
+Patriots for Europe Group
+256895
+Rassemblement national
+
+
+Janusz LEWANDOWSKI
+Poland
+Group of the European People's Party (Christian Democrats)
+23781
+Platforma Obywatelska
+
+
+Miriam LEXMANN
+Slovakia
+Group of the European People's Party (Christian Democrats)
+204336
+Kresńanskodemokratické hnutie
+
+
+Peter LIESE
+Germany
+Group of the European People's Party (Christian Democrats)
+1927
+Christlich Demokratische Union Deutschlands
+
+
+Norbert LINS
+Germany
+Group of the European People's Party (Christian Democrats)
+124808
+Christlich Demokratische Union Deutschlands
+
+
+Nathalie LOISEAU
+France
+Renew Europe Group
+197494
+Horizons
+
+
+Morten LĆKKEGAARD
+Denmark
+Renew Europe Group
+96709
+Venstre, Danmarks Liberale Parti
+
+
+Reinhold LOPATKA
+Austria
+Group of the European People's Party (Christian Democrats)
+220896
+Ćsterreichische Volkspartei
+
+
+Javi LĆPEZ
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+125042
+Partit dels Socialistes de Catalunya (PSC-PSOE)
+
+
+Juan Fernando LĆPEZ AGUILAR
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+96812
+Partido Socialista Obrero EspaƱol
+
+
+Antonio LĆPEZ-ISTĆRIZ WHITE
+Spain
+Group of the European People's Party (Christian Democrats)
+28399
+Partido Popular
+
+
+Isabella LĆVIN
+Sweden
+Group of the Greens/European Free Alliance
+96675
+Miljƶpartiet de grƶna
+
+
+Mimmo LUCANO
+Italy
+The Left group in the European Parliament - GUE/NGL
+257129
+Alleanza Verdi e Sinistra
+
+
+CƩsar LUENA
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197721
+Partido Socialista Obrero EspaƱol
+
+
+Elżbieta Katarzyna ÅUKACIJEWSKA
+Poland
+Group of the European People's Party (Christian Democrats)
+96791
+Platforma Obywatelska
+
+
+Giuseppe LUPO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257124
+Partito Democratico
+
+
+David MCALLISTER
+Germany
+Group of the European People's Party (Christian Democrats)
+124806
+Christlich Demokratische Union Deutschlands
+
+
+Jaak MADISON
+Estonia
+European Conservatives and Reformists Group
+197493
+Eesti Keskerakond
+
+
+Cristina MAESTRE
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197719
+Partido Socialista Obrero EspaƱol
+
+
+Lara MAGONI
+Italy
+European Conservatives and Reformists Group
+257149
+FRATELLI D' ITALIA
+
+
+PƩter MAGYAR
+Hungary
+Group of the European People's Party (Christian Democrats)
+256868
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Marit MAIJ
+Netherlands
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+91636
+GroenLinks-PvdA
+
+
+Marlena MALÄG
+Poland
+European Conservatives and Reformists Group
+257077
+Prawo i SprawiedliwoÅÄ
+
+
+Claudiu MANDA
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197653
+Partidul Social Democrat
+
+
+Lukas MANDL
+Austria
+Group of the European People's Party (Christian Democrats)
+190713
+Ćsterreichische Volkspartei
+
+
+Yannis MANIATIS
+Greece
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256824
+PASOK-KINAL
+
+
+Mario MANTOVANI
+Italy
+European Conservatives and Reformists Group
+4395
+FRATELLI D' ITALIA
+
+
+Pierfrancesco MARAN
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257727
+Partito Democratico
+
+
+Jagna MARCZUÅAJTIS-WALCZAK
+Poland
+Group of the European People's Party (Christian Democrats)
+257082
+Platforma Obywatelska
+
+
+Marion MARĆCHAL
+France
+European Conservatives and Reformists Group
+256922
+IdentitƩ LibertƩs
+
+
+Thierry MARIANI
+France
+Patriots for Europe Group
+197623
+Rassemblement national
+
+
+Ignazio Roberto MARINO
+Italy
+Group of the Greens/European Free Alliance
+257132
+Independent
+
+
+Erik MARQUARDT
+Germany
+Group of the Greens/European Free Alliance
+197462
+Bündnis 90/Die Grünen
+
+
+Jorge MARTĆN FRĆAS
+Spain
+Patriots for Europe Group
+257029
+VOX
+
+
+Catarina MARTINS
+Portugal
+The Left group in the European Parliament - GUE/NGL
+257063
+Bloco de Esquerda
+
+
+Fulvio MARTUSCIELLO
+Italy
+Group of the European People's Party (Christian Democrats)
+124828
+Forza Italia
+
+
+Vicent MARZĆ IBĆĆEZ
+Spain
+Group of the Greens/European Free Alliance
+257016
+CompromĆs
+
+
+Gabriel MATO
+Spain
+Group of the European People's Party (Christian Democrats)
+96936
+Partido Popular
+
+
+Sara MATTHIEU
+Belgium
+Group of the Greens/European Free Alliance
+208722
+Groen
+
+
+Costas MAVRIDES
+Cyprus
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124691
+Democratic Party
+
+
+Eva MAYDELL
+Bulgaria
+Group of the European People's Party (Christian Democrats)
+98341
+Citizens for European Development of Bulgaria
+
+
+Georg MAYER
+Austria
+Patriots for Europe Group
+38511
+Freiheitliche Partei Ćsterreichs
+
+
+Milan MAZUREK
+Slovakia
+Europe of Sovereign Nations Group
+249982
+Hnutie Republika
+
+
+Liudas MAŽYLIS
+Lithuania
+Group of the European People's Party (Christian Democrats)
+197841
+TÄvynÄs sÄ
junga-Lietuvos krikÅ”Äionys demokratai
+
+
+Michael MCNAMARA
+Ireland
+Renew Europe Group
+257300
+Independent
+
+
+Nora MEBAREK
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+204418
+Parti socialiste
+
+
+Alexandra MEHNERT
+Germany
+Group of the European People's Party (Christian Democrats)
+256980
+Christlich Demokratische Union Deutschlands
+
+
+Vangelis MEIMARAKIS
+Greece
+Group of the European People's Party (Christian Democrats)
+197662
+Nea Demokratia
+
+
+Eleonora MELETI
+Greece
+Group of the European People's Party (Christian Democrats)
+256943
+Nea Demokratia
+
+
+Ana Catarina MENDES
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257053
+Partido Socialista
+
+
+Idoia MENDIA
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256994
+Partido Socialista Obrero EspaƱol
+
+
+Verena MERTENS
+Germany
+Group of the European People's Party (Christian Democrats)
+256974
+Christlich Demokratische Union Deutschlands
+
+
+Marina MESURE
+France
+The Left group in the European Parliament - GUE/NGL
+236053
+La France Insoumise
+
+
+Roberta METSOLA
+Malta
+Group of the European People's Party (Christian Democrats)
+118859
+Partit Nazzjonalista
+
+
+Tilly METZ
+Luxembourg
+Group of the Greens/European Free Alliance
+193292
+DƩi GrƩng - Les Verts
+
+
+Sven MIKSER
+Estonia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197497
+Sotsiaaldemokraatlik Erakond
+
+
+Giuseppe MILAZZO
+Italy
+European Conservatives and Reformists Group
+197824
+FRATELLI D' ITALIA
+
+
+Francisco JosĆ© MILLĆN MON
+Spain
+Group of the European People's Party (Christian Democrats)
+28400
+Partido Popular
+
+
+Nikola MINCHEV
+Bulgaria
+Renew Europe Group
+257259
+We continue the change ā Democratic Bulgaria
+
+
+Ana MIRANDA PAZ
+Spain
+Group of the Greens/European Free Alliance
+24942
+Bloque Nacionalista Galego
+
+
+Csaba MOLNĆR
+Hungary
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124722
+Demokratikus KoalĆció
+
+
+Irene MONTERO
+Spain
+The Left group in the European Parliament - GUE/NGL
+245770
+PODEMOS
+
+
+Dolors MONTSERRAT
+Spain
+Group of the European People's Party (Christian Democrats)
+197711
+Partido Popular
+
+
+Carolina MORACE
+Italy
+The Left group in the European Parliament - GUE/NGL
+257140
+Movimento 5 Stelle
+
+
+Nadine MORANO
+France
+Group of the European People's Party (Christian Democrats)
+72779
+Les RƩpublicains
+
+
+Letizia MORATTI
+Italy
+Group of the European People's Party (Christian Democrats)
+257151
+Forza Italia
+
+
+Tiago MOREIRA DE SĆ
+Portugal
+Patriots for Europe Group
+257054
+Chega
+
+
+Javier MORENO SĆNCHEZ
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+28347
+Partido Socialista Obrero EspaƱol
+
+
+Alessandra MORETTI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124799
+Partito Democratico
+
+
+Dan-Åtefan MOTREANU
+Romania
+Group of the European People's Party (Christian Democrats)
+197647
+Partidul Naţional Liberal
+
+
+Arkadiusz MULARCZYK
+Poland
+European Conservatives and Reformists Group
+257060
+Prawo i SprawiedliwoÅÄ
+
+
+Piotr MĆLLER
+Poland
+European Conservatives and Reformists Group
+257080
+Prawo i SprawiedliwoÅÄ
+
+
+Ciaran MULLOOLY
+Ireland
+Renew Europe Group
+257298
+Independent
+
+
+Siegfried MUREÅAN
+Romania
+Group of the European People's Party (Christian Democrats)
+124802
+Partidul Naţional Liberal
+
+
+Åtefan MUÅOIU
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257103
+Partidul Social Democrat
+
+
+Jana NAGYOVĆ
+Czechia
+Patriots for Europe Group
+256843
+ANO 2011
+
+
+Dario NARDELLA
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257111
+Partito Democratico
+
+
+Fernando NAVARRETE ROJAS
+Spain
+Group of the European People's Party (Christian Democrats)
+257027
+Partido Popular
+
+
+Victor NEGRESCU
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+88882
+Partidul Social Democrat
+
+
+Matjaž NEMEC
+Slovenia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+233862
+Socialni demokrati
+
+
+DanuÅ”e NERUDOVĆ
+Czechia
+Group of the European People's Party (Christian Democrats)
+256847
+StarostovƩ a nezƔvisli
+
+
+Denis NESCI
+Italy
+European Conservatives and Reformists Group
+239260
+FRATELLI D' ITALIA
+
+
+Hans NEUHOFF
+Germany
+Europe of Sovereign Nations Group
+256944
+Alternative für Deutschland
+
+
+Hannah NEUMANN
+Germany
+Group of the Greens/European Free Alliance
+197464
+Bündnis 90/Die Grünen
+
+
+Elena NEVADO DEL CAMPO
+Spain
+Group of the European People's Party (Christian Democrats)
+257039
+Partido Popular
+
+
+Dan NICA
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124784
+Partidul Social Democrat
+
+
+Angelika NIEBLER
+Germany
+Group of the European People's Party (Christian Democrats)
+4289
+Christlich-Soziale Union in Bayern e.V.
+
+
+LudÄk NIEDERMAYER
+Czechia
+Group of the European People's Party (Christian Democrats)
+124701
+TOP 09 a StarostovƩ
+
+
+Ville NIINISTĆ
+Finland
+Group of the Greens/European Free Alliance
+197802
+VihreƤ liitto
+
+
+Lefteris NIKOLAOU-ALAVANOS
+Greece
+Non-attached Members
+197734
+Communist Party of Greece
+
+
+Aleksandar NIKOLIC
+France
+Patriots for Europe Group
+256883
+Rassemblement national
+
+
+Cynthia NĆ MHURCHĆ
+Ireland
+Renew Europe Group
+257301
+Fianna FƔil Party
+
+
+Maria NOICHL
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124836
+Sozialdemokratische Partei Deutschlands
+
+
+Rasmus NORDQVIST
+Denmark
+Group of the Greens/European Free Alliance
+257044
+Socialistisk Folkeparti
+
+
+Andrey NOVAKOV
+Bulgaria
+Group of the European People's Party (Christian Democrats)
+107212
+Citizens for European Development of Bulgaria
+
+
+MirosÅawa NYKIEL
+Poland
+Group of the European People's Party (Christian Democrats)
+257049
+Platforma Obywatelska
+
+
+Daniel OBAJTEK
+Poland
+European Conservatives and Reformists Group
+257058
+Prawo i SprawiedliwoÅÄ
+
+
+ĽudovĆt ĆDOR
+Slovakia
+Renew Europe Group
+257010
+ProgresĆvne Slovensko
+
+
+Jan-Christoph OETJEN
+Germany
+Renew Europe Group
+197432
+Freie Demokratische Partei
+
+
+Maria OHISALO
+Finland
+Group of the Greens/European Free Alliance
+198076
+VihreƤ liitto
+
+
+João OLIVEIRA
+Portugal
+The Left group in the European Parliament - GUE/NGL
+257083
+Partido Comunista PortuguĆŖs
+
+
+Philippe OLIVIER
+France
+Patriots for Europe Group
+197687
+Rassemblement national
+
+
+Younous OMARJEE
+France
+The Left group in the European Parliament - GUE/NGL
+30482
+La France Insoumise
+
+
+Branislav ONDRUÅ
+Slovakia
+Non-attached Members
+257018
+Hlas ā sociĆ”lna demokracia
+
+
+AodhĆ”n Ć RĆORDĆIN
+Ireland
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257238
+Labour Party
+
+
+Leoluca ORLANDO
+Italy
+Group of the Greens/European Free Alliance
+2152
+Independent
+
+
+Jacek OZDOBA
+Poland
+European Conservatives and Reformists Group
+257086
+Prawo i SprawiedliwoÅÄ
+
+
+Urmas PAET
+Estonia
+Renew Europe Group
+129073
+Eesti Reformierakond
+
+
+Leire PAJĆN
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256993
+Partido Socialista Obrero EspaƱol
+
+
+Valentina PALMISANO
+Italy
+The Left group in the European Parliament - GUE/NGL
+257135
+Movimento 5 Stelle
+
+
+Fidias PANAYIOTOU
+Cyprus
+Non-attached Members
+256989
+Independent
+
+
+Kostas PAPADAKIS
+Greece
+Non-attached Members
+125093
+Communist Party of Greece
+
+
+Nikos PAPANDREOU
+Greece
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+244571
+PASOK-KINAL
+
+
+Nikos PAPPAS
+Greece
+The Left group in the European Parliament - GUE/NGL
+256952
+Coalition of the Radical Left
+
+
+NicolƔs PASCUAL DE LA PARTE
+Spain
+Group of the European People's Party (Christian Democrats)
+257040
+Partido Popular
+
+
+Aldo PATRICIELLO
+Italy
+Patriots for Europe Group
+36392
+Lega
+
+
+Jutta PAULUS
+Germany
+Group of the Greens/European Free Alliance
+197466
+Bündnis 90/Die Grünen
+
+
+Ana Miguel PEDRO
+Portugal
+Group of the European People's Party (Christian Democrats)
+110673
+Partido do Centro DemocrƔtico Social-Partido Popular
+
+
+Gaetano PEDULLA'
+Italy
+The Left group in the European Parliament - GUE/NGL
+257126
+Movimento 5 Stelle
+
+
+Thomas PELLERIN-CARLIN
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256903
+Place publique
+
+
+Guillaume PELTIER
+France
+European Conservatives and Reformists Group
+30123
+IdentitƩ LibertƩs
+
+
+Tsvetelina PENKOVA
+Bulgaria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197845
+Bulgarian Socialist Party
+
+
+Gilles PENNELLE
+France
+Patriots for Europe Group
+126699
+Rassemblement national
+
+
+LĆdia PEREIRA
+Portugal
+Group of the European People's Party (Christian Democrats)
+197738
+Partido Social Democrata
+
+
+Alvise PĆREZ
+Spain
+Non-attached Members
+257019
+Se Acabó la Fiesta
+
+
+Kira Marie PETER-HANSEN
+Denmark
+Group of the Greens/European Free Alliance
+197573
+Socialistisk Folkeparti
+
+
+Hristo PETROV
+Bulgaria
+Renew Europe Group
+257257
+We continue the change ā Democratic Bulgaria
+
+
+Michele PICARO
+Italy
+European Conservatives and Reformists Group
+257150
+FRATELLI D' ITALIA
+
+
+Pina PICIERNO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+124846
+Partito Democratico
+
+
+Tonino PICULA
+Croatia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+112744
+Socijaldemokratska partija Hrvatske
+
+
+Pascale PIERA
+France
+Patriots for Europe Group
+256877
+Rassemblement national
+
+
+Sirpa PIETIKĆINEN
+Finland
+Group of the European People's Party (Christian Democrats)
+40599
+Kansallinen Kokoomus
+
+
+Pierre PIMPIE
+France
+Patriots for Europe Group
+256893
+Rassemblement national
+
+
+Gheorghe PIPEREA
+Romania
+European Conservatives and Reformists Group
+257115
+AlianČa pentru Unirea RomĆ¢nilor
+
+
+Margarita DE LA PISA CARRIĆN
+Spain
+Patriots for Europe Group
+204414
+VOX
+
+
+Jaroslava POKORNĆ JERMANOVĆ
+Czechia
+Patriots for Europe Group
+256844
+ANO 2011
+
+
+Daniele POLATO
+Italy
+European Conservatives and Reformists Group
+257145
+FRATELLI D' ITALIA
+
+
+Jessica POLFJĆRD
+Sweden
+Group of the European People's Party (Christian Democrats)
+197404
+Moderaterna
+
+
+Virgil-Daniel POPESCU
+Romania
+Group of the European People's Party (Christian Democrats)
+257107
+Partidul Naţional Liberal
+
+
+Reinis POZÅ
AKS
+Latvia
+European Conservatives and Reformists Group
+256907
+Apvienotais saraksts ā Latvijas ZaÄ¼Ä partija, Latvijas ReÄ£ionu ApvienÄ«ba, LiepÄjas partija
+
+
+Vladimir PREBILIÄ
+Slovenia
+Group of the Greens/European Free Alliance
+256813
+Vesna ā zelena stranka
+
+
+Giusi PRINCI
+Italy
+Group of the European People's Party (Christian Democrats)
+257128
+Forza Italia
+
+
+Nicola PROCACCINI
+Italy
+European Conservatives and Reformists Group
+197820
+FRATELLI D' ITALIA
+
+
+Jacek PROTAS
+Poland
+Group of the European People's Party (Christian Democrats)
+257041
+Platforma Obywatelska
+
+
+Friedrich PĆRNER
+Germany
+Non-attached Members
+256969
+Independent
+
+
+Carola RACKETE
+Germany
+The Left group in the European Parliament - GUE/NGL
+256927
+Independent
+
+
+Emil RADEV
+Bulgaria
+Group of the European People's Party (Christian Democrats)
+124850
+Citizens for European Development of Bulgaria
+
+
+Dennis RADTKE
+Germany
+Group of the European People's Party (Christian Democrats)
+188945
+Christlich Demokratische Union Deutschlands
+
+
+Emma RAFOWICZ
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256902
+Parti socialiste
+
+
+Jüri RATAS
+Estonia
+Group of the European People's Party (Christian Democrats)
+188096
+Isamaa
+
+
+Ruggero RAZZA
+Italy
+European Conservatives and Reformists Group
+257104
+FRATELLI D' ITALIA
+
+
+Julie RECHAGNEUX
+France
+Patriots for Europe Group
+256882
+Rassemblement national
+
+
+Evelyn REGNER
+Austria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+96998
+Sozialdemokratische Partei Ćsterreichs
+
+
+Terry REINTKE
+Germany
+Group of the Greens/European Free Alliance
+103381
+Bündnis 90/Die Grünen
+
+
+RenƩ REPASI
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+229839
+Sozialdemokratische Partei Deutschlands
+
+
+Sabrina REPP
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256935
+Sozialdemokratische Partei Deutschlands
+
+
+Karlo RESSLER
+Croatia
+Group of the European People's Party (Christian Democrats)
+197413
+Hrvatska demokratska zajednica
+
+
+Thijs REUTEN
+Netherlands
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+218347
+GroenLinks-PvdA
+
+
+Diana RIBA I GINER
+Spain
+Group of the Greens/European Free Alliance
+197832
+Esquerra Republicana de Catalunya
+
+
+Matteo RICCI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257121
+Partito Democratico
+
+
+ChloƩ RIDEL
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256904
+Parti socialiste
+
+
+Nela RIEHL
+Germany
+Group of the Greens/European Free Alliance
+256964
+Volt
+
+
+Manuela RIPA
+Germany
+Group of the European People's Party (Christian Democrats)
+206158
+Ćkologisch-Demokratische Partei
+
+
+AndrƩ RODRIGUES
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257066
+Partido Socialista
+
+
+Marcos ROS SEMPERE
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+204413
+Partido Socialista Obrero EspaƱol
+
+
+KatarĆna ROTH NEVEÄALOVĆ
+Slovakia
+Non-attached Members
+96653
+SMER-SociƔlna demokracia
+
+
+AndrĆ© ROUGĆ
+France
+Patriots for Europe Group
+197690
+Rassemblement national
+
+
+Bert-Jan RUISSEN
+Netherlands
+European Conservatives and Reformists Group
+197773
+Staatkundig Gereformeerde Partij
+
+
+Sandro RUOTOLO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257170
+Partito Democratico
+
+
+Bogdan RZOÅCA
+Poland
+European Conservatives and Reformists Group
+197545
+Prawo i SprawiedliwoÅÄ
+
+
+Arash SAEIDI
+France
+The Left group in the European Parliament - GUE/NGL
+256911
+La France Insoumise
+
+
+Massimiliano SALINI
+Italy
+Group of the European People's Party (Christian Democrats)
+125670
+Forza Italia
+
+
+Ilaria SALIS
+Italy
+The Left group in the European Parliament - GUE/NGL
+257127
+Alleanza Verdi e Sinistra
+
+
+Aura SALLA
+Finland
+Group of the European People's Party (Christian Democrats)
+98219
+Kansallinen Kokoomus
+
+
+Nacho SĆNCHEZ AMOR
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197722
+Partido Socialista Obrero EspaƱol
+
+
+Julien SANCHEZ
+France
+Patriots for Europe Group
+88552
+Rassemblement national
+
+
+Elena SANCHO MURILLO
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257001
+Partido Socialista Obrero EspaƱol
+
+
+Jussi SARAMO
+Finland
+The Left group in the European Parliament - GUE/NGL
+127766
+Vasemmistoliitto
+
+
+Silvia SARDONE
+Italy
+Patriots for Europe Group
+197578
+Lega
+
+
+Marjan Å AREC
+Slovenia
+Renew Europe Group
+256815
+Gibanje Svoboda
+
+
+Eric SARGIACOMO
+France
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256905
+Parti socialiste
+
+
+Mounir SATOURI
+France
+Group of the Greens/European Free Alliance
+197500
+Les Ćcologistes
+
+
+Paulius SAUDARGAS
+Lithuania
+Group of the European People's Party (Christian Democrats)
+256809
+TÄvynÄs sÄ
junga-Lietuvos krikÅ”Äionys demokratai
+
+
+Majdouline SBAI
+France
+Group of the Greens/European Free Alliance
+256917
+Les Ćcologistes
+
+
+Antonella SBERNA
+Italy
+European Conservatives and Reformists Group
+257113
+FRATELLI D' ITALIA
+
+
+Christel SCHALDEMOSE
+Denmark
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+37312
+Socialdemokratiet
+
+
+ErnÅ SCHALLER-BAROSS
+Hungary
+Patriots for Europe Group
+213330
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Oliver SCHENK
+Germany
+Group of the European People's Party (Christian Democrats)
+256979
+Christlich Demokratische Union Deutschlands
+
+
+Joanna SCHEURING-WIELGUS
+Poland
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257084
+Nowa Lewica
+
+
+Andreas SCHIEDER
+Austria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197670
+Sozialdemokratische Partei Ćsterreichs
+
+
+Lena SCHILLING
+Austria
+Group of the Greens/European Free Alliance
+256833
+Die Grünen - Die Grüne Alternative
+
+
+Martin SCHIRDEWAN
+Germany
+The Left group in the European Parliament - GUE/NGL
+190517
+DIE LINKE.
+
+
+Christine SCHNEIDER
+Germany
+Group of the European People's Party (Christian Democrats)
+197422
+Christlich Demokratische Union Deutschlands
+
+
+Volker SCHNURRBUSCH
+Germany
+Europe of Sovereign Nations Group
+267485
+Alternative für Deutschland
+
+
+Andreas SCHWAB
+Germany
+Group of the European People's Party (Christian Democrats)
+28223
+Christlich Demokratische Union Deutschlands
+
+
+Benedetta SCUDERI
+Italy
+Group of the Greens/European Free Alliance
+257139
+Europa Verde - Verdi
+
+
+Ralf SEEKATZ
+Germany
+Group of the European People's Party (Christian Democrats)
+197425
+Christlich Demokratische Union Deutschlands
+
+
+Alexander SELL
+Germany
+Europe of Sovereign Nations Group
+256959
+Alternative für Deutschland
+
+
+Rosa SERRANO SIERRA
+Spain
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256999
+Partido Socialista Obrero EspaƱol
+
+
+Isabel SERRA SĆNCHEZ
+Spain
+The Left group in the European Parliament - GUE/NGL
+257009
+PODEMOS
+
+
+Günther SIDL
+Austria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197677
+Sozialdemokratische Partei Ćsterreichs
+
+
+BartÅomiej SIENKIEWICZ
+Poland
+Group of the European People's Party (Christian Democrats)
+86057
+Platforma Obywatelska
+
+
+Lukas SIEPER
+Germany
+Non-attached Members
+256971
+Partei des Fortschritts
+
+
+Sven SIMON
+Germany
+Group of the European People's Party (Christian Democrats)
+197426
+Christlich Demokratische Union Deutschlands
+
+
+Christine SINGER
+Germany
+Renew Europe Group
+256946
+Freie WƤhler
+
+
+Virginijus SINKEVIÄIUS
+Lithuania
+Group of the Greens/European Free Alliance
+201945
+Demokratų sÄ
junga āVardan Lietuvosā
+
+
+Birgit SIPPEL
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+96932
+Sozialdemokratische Partei Deutschlands
+
+
+Jonas SJĆSTEDT
+Sweden
+The Left group in the European Parliament - GUE/NGL
+2268
+VƤnsterpartiet
+
+
+Krzysztof ÅMISZEK
+Poland
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257085
+Nowa Lewica
+
+
+Anthony SMITH
+France
+The Left group in the European Parliament - GUE/NGL
+256910
+La France Insoumise
+
+
+Sander SMIT
+Netherlands
+Group of the European People's Party (Christian Democrats)
+125325
+BoerBurgerBeweging
+
+
+Tomislav SOKOL
+Croatia
+Group of the European People's Party (Christian Democrats)
+197417
+Hrvatska demokratska zajednica
+
+
+Diego SOLIER
+Spain
+European Conservatives and Reformists Group
+257021
+Independiente
+
+
+Susana SOLĆS PĆREZ
+Spain
+Group of the European People's Party (Christian Democrats)
+197784
+Partido Popular
+
+
+Liesbet SOMMEN
+Belgium
+Group of the European People's Party (Christian Democrats)
+256889
+Christen-Democratisch & Vlaams
+
+
+Martin SONNEBORN
+Germany
+Non-attached Members
+124834
+Die PARTEI
+
+
+Malika SOREL
+France
+Non-attached Members
+256871
+Sans parti
+
+
+HƩlder SOUSA SILVA
+Portugal
+Group of the European People's Party (Christian Democrats)
+257068
+Partido Social Democrata
+
+
+Villy SĆVNDAL
+Denmark
+Group of the Greens/European Free Alliance
+111412
+Socialistisk Folkeparti
+
+
+Marco SQUARTA
+Italy
+European Conservatives and Reformists Group
+257109
+FRATELLI D' ITALIA
+
+
+MÄrtiÅÅ” STAĶIS
+Latvia
+Group of the Greens/European Free Alliance
+256916
+Progresīvie
+
+
+Raffaele STANCANELLI
+Italy
+Patriots for Europe Group
+197825
+Lega
+
+
+Nicolae ČTEFÄNUČÄ
+Romania
+Group of the Greens/European Free Alliance
+58766
+Independent
+
+
+Petra STEGER
+Austria
+Patriots for Europe Group
+220897
+Freiheitliche Partei Ćsterreichs
+
+
+Davor Ivo STIER
+Croatia
+Group of the European People's Party (Christian Democrats)
+119435
+Hrvatska demokratska zajednica
+
+
+Kristoffer STORM
+Denmark
+European Conservatives and Reformists Group
+257025
+Danmarksdemokraterne
+
+
+Sebastiaan STĆTELER
+Netherlands
+Patriots for Europe Group
+256991
+Partij voor de Vrijheid
+
+
+Stanislav STOYANOV
+Bulgaria
+Europe of Sovereign Nations Group
+257255
+Revival
+
+
+Marie-Agnes STRACK-ZIMMERMANN
+Germany
+Renew Europe Group
+256926
+Freie Demokratische Partei
+
+
+Cecilia STRADA
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257101
+Partito Democratico
+
+
+Joachim STREIT
+Germany
+Renew Europe Group
+256962
+Freie WƤhler
+
+
+Tineke STRIK
+Netherlands
+Group of the Greens/European Free Alliance
+197772
+GroenLinks-PvdA
+
+
+Anna STROLENBERG
+Netherlands
+Group of the Greens/European Free Alliance
+256990
+Volt
+
+
+Åerban Dimitrie STURDZA
+Romania
+European Conservatives and Reformists Group
+257119
+Partidul AcČiunea Conservatoare
+
+
+Anna STĆRGKH
+Austria
+Renew Europe Group
+256839
+NEOS ā Das Neue Ćsterreich
+
+
+Marcin SYPNIEWSKI
+Poland
+Europe of Sovereign Nations Group
+257070
+Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
+
+
+MichaÅ SZCZERBA
+Poland
+Group of the European People's Party (Christian Democrats)
+257026
+Platforma Obywatelska
+
+
+PƔl SZEKERES
+Hungary
+Patriots for Europe Group
+256855
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Beata SZYDÅO
+Poland
+European Conservatives and Reformists Group
+197553
+Prawo i SprawiedliwoÅÄ
+
+
+Dario TAMBURRANO
+Italy
+The Left group in the European Parliament - GUE/NGL
+124813
+Movimento 5 Stelle
+
+
+António TĆNGER CORRĆA
+Portugal
+Patriots for Europe Group
+257050
+Chega
+
+
+Dominik TARCZYÅSKI
+Poland
+European Conservatives and Reformists Group
+204346
+Prawo i SprawiedliwoÅÄ
+
+
+Marco TARQUINIO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257160
+Partito Democratico
+
+
+ZoltƔn TARR
+Hungary
+Group of the European People's Party (Christian Democrats)
+256863
+Tisztelet Ʃs SzabadsƔg PƔrt
+
+
+Claudiu-Richard TĆRZIU
+Romania
+European Conservatives and Reformists Group
+257114
+Partidul AcČiunea Conservatoare
+
+
+Carla TAVARES
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257071
+Partido Socialista
+
+
+Kai TEGETHOFF
+Germany
+Group of the Greens/European Free Alliance
+256965
+Volt
+
+
+Marta TEMIDO
+Portugal
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+210480
+Partido Socialista
+
+
+Georgiana TEODORESCU
+Romania
+European Conservatives and Reformists Group
+257116
+AlianČa pentru Unirea RomĆ¢nilor
+
+
+Alice TEODORESCU MĆ
WE
+Sweden
+Group of the European People's Party (Christian Democrats)
+257089
+Kristdemokraterna
+
+
+Cristian TERHEÅ
+Romania
+European Conservatives and Reformists Group
+197655
+Partidului NaČional Conservator RomĆ¢n (PNCR)
+
+
+Ingeborg TER LAAK
+Netherlands
+Group of the European People's Party (Christian Democrats)
+256968
+Christen Democratisch AppĆØl
+
+
+Riho TERRAS
+Estonia
+Group of the European People's Party (Christian Democrats)
+204449
+Isamaa
+
+
+Hermann TERTSCH
+Spain
+Patriots for Europe Group
+197831
+VOX
+
+
+Pierre-Romain THIONNET
+France
+Patriots for Europe Group
+200345
+Rassemblement national
+
+
+Beatrice TIMGREN
+Sweden
+European Conservatives and Reformists Group
+257090
+Sverigedemokraterna
+
+
+Irene TINAGLI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197591
+Partito Democratico
+
+
+Bruno TOBBACK
+Belgium
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+256885
+Vooruit
+
+
+Tomas TOBĆ
+Sweden
+Group of the European People's Party (Christian Democrats)
+197402
+Moderaterna
+
+
+Rody TOLASSY
+France
+Patriots for Europe Group
+256888
+Rassemblement national
+
+
+Eugen TOMAC
+Romania
+Renew Europe Group
+197672
+Partidul MiČcarea PopularÄ
+
+
+Zala TOMAÅ IÄ
+Slovenia
+Group of the European People's Party (Christian Democrats)
+256814
+Slovenska demokratska stranka
+
+
+Waldemar TOMASZEWSKI
+Lithuania
+European Conservatives and Reformists Group
+96697
+Lietuvos lenkų rinkimų akcija ā KrikÅ”ÄioniÅ”kų Å”eimų sÄ
junga
+
+
+Romana TOMC
+Slovenia
+Group of the European People's Party (Christian Democrats)
+125104
+Slovenska demokratska stranka
+
+
+Matej TONIN
+Slovenia
+Group of the European People's Party (Christian Democrats)
+219652
+Nova Slovenija ā KrÅ”Äanski demokrati
+
+
+Jana TOOM
+Estonia
+Renew Europe Group
+124700
+Eesti Keskerakond
+
+
+Raffaele TOPO
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257148
+Partito Democratico
+
+
+Francesco TORSELLI
+Italy
+European Conservatives and Reformists Group
+257163
+FRATELLI D' ITALIA
+
+
+Flavio TOSI
+Italy
+Group of the European People's Party (Christian Democrats)
+124795
+Forza Italia
+
+
+Marie TOUSSAINT
+France
+Group of the Greens/European Free Alliance
+97236
+Les Ćcologistes
+
+
+Isabella TOVAGLIERI
+Italy
+Patriots for Europe Group
+197580
+Lega
+
+
+Pekka TOVERI
+Finland
+Group of the European People's Party (Christian Democrats)
+256804
+Kansallinen Kokoomus
+
+
+Pasquale TRIDICO
+Italy
+The Left group in the European Parliament - GUE/NGL
+257133
+Movimento 5 Stelle
+
+
+Laurence TROCHU
+France
+European Conservatives and Reformists Group
+256925
+IdentitƩ LibertƩs
+
+
+Dimitris TSIODRAS
+Greece
+Group of the European People's Party (Christian Democrats)
+256950
+Nea Demokratia
+
+
+Mihai TUDOSE
+Romania
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+198183
+Partidul Social Democrat
+
+
+Filip TUREK
+Czechia
+Patriots for Europe Group
+256850
+MotoristĆ© sobÄ
+
+
+Sebastian TYNKKYNEN
+Finland
+European Conservatives and Reformists Group
+256806
+Perussuomalaiset
+
+
+StanisÅaw TYSZKA
+Poland
+Europe of Sovereign Nations Group
+257062
+Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
+
+
+Milan UHRĆK
+Slovakia
+Europe of Sovereign Nations Group
+197763
+Hnutie Republika
+
+
+Nils UÅ AKOVS
+Latvia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+197810
+"SaskaÅa" sociÄldemokrÄtiskÄ partija
+
+
+Inese VAIDERE
+Latvia
+Group of the European People's Party (Christian Democrats)
+28617
+JaunÄ VienotÄ«ba
+
+
+Ivaylo VALCHEV
+Bulgaria
+European Conservatives and Reformists Group
+257258
+There Is Such a People
+
+
+Adina VÄLEAN
+Romania
+Group of the European People's Party (Christian Democrats)
+37324
+Partidul Naţional Liberal
+
+
+Matthieu VALET
+France
+Patriots for Europe Group
+256875
+Rassemblement national
+
+
+Kathleen VAN BREMPT
+Belgium
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+5729
+Vooruit
+
+
+Anouk VAN BRUG
+Netherlands
+Renew Europe Group
+257438
+Volkspartij voor Vrijheid en Democratie
+
+
+Brigitte VAN DEN BERG
+Netherlands
+Renew Europe Group
+256976
+Democraten 66
+
+
+Tom VANDENDRIESSCHE
+Belgium
+Patriots for Europe Group
+185771
+Vlaams Belang
+
+
+Kris VAN DIJCK
+Belgium
+European Conservatives and Reformists Group
+256884
+Nieuw-Vlaamse Alliantie
+
+
+Reinier VAN LANSCHOT
+Netherlands
+Group of the Greens/European Free Alliance
+256978
+Volt
+
+
+Jessika VAN LEEUWEN
+Netherlands
+Group of the European People's Party (Christian Democrats)
+256983
+BoerBurgerBeweging
+
+
+Roberto VANNACCI
+Italy
+Patriots for Europe Group
+257125
+Lega
+
+
+Johan VAN OVERTVELDT
+Belgium
+European Conservatives and Reformists Group
+125106
+Nieuw-Vlaamse Alliantie
+
+
+Kim VAN SPARRENTAK
+Netherlands
+Group of the Greens/European Free Alliance
+197870
+GroenLinks-PvdA
+
+
+Alexandre VARAUT
+France
+Patriots for Europe Group
+5736
+Rassemblement national
+
+
+Ana VASCONCELOS
+Portugal
+Renew Europe Group
+257061
+Iniciativa Liberal
+
+
+Vlad VASILE-VOICULESCU
+Romania
+Renew Europe Group
+257112
+Uniunea SalvaČi RomĆ¢nia
+
+
+Hilde VAUTMANS
+Belgium
+Renew Europe Group
+130100
+Open Vlaamse Liberalen en Democraten
+
+
+Marie-Pierre VEDRENNE
+France
+Renew Europe Group
+197502
+Mouvement DƩmocrate
+
+
+Francesco VENTOLA
+Italy
+European Conservatives and Reformists Group
+257099
+FRATELLI D' ITALIA
+
+
+Sabine VERHEYEN
+Germany
+Group of the European People's Party (Christian Democrats)
+96756
+Christlich Demokratische Union Deutschlands
+
+
+Yvan VEROUGSTRAETE
+Belgium
+Renew Europe Group
+256879
+Les EngagƩs
+
+
+Aurelijus VERYGA
+Lithuania
+European Conservatives and Reformists Group
+256811
+Lietuvos valstieÄių ir žaliųjų sÄ
junga
+
+
+Marko VEÅ LIGAJ
+Croatia
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+260035
+Socijaldemokratska partija Hrvatske
+
+
+AnnamƔria VICSEK
+Hungary
+Patriots for Europe Group
+256859
+Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
+
+
+Catarina VIEIRA
+Netherlands
+Group of the Greens/European Free Alliance
+257437
+GroenLinks-PvdA
+
+
+Kristian VIGENIN
+Bulgaria
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+34232
+Bulgarian Socialist Party
+
+
+Harald VILIMSKY
+Austria
+Patriots for Europe Group
+125001
+Freiheitliche Partei Ćsterreichs
+
+
+LorƔnt VINCZE
+Romania
+Group of the European People's Party (Christian Democrats)
+98582
+Uniunea DemocratÄ MaghiarÄ din RomĆ¢nia
+
+
+Marianne VIND
+Denmark
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+199941
+Socialdemokratiet
+
+
+Anders VISTISEN
+Denmark
+Patriots for Europe Group
+124875
+Dansk Folkeparti
+
+
+Mariateresa VIVALDINI
+Italy
+European Conservatives and Reformists Group
+257143
+FRATELLI D' ITALIA
+
+
+Petar VOLGIN
+Bulgaria
+Europe of Sovereign Nations Group
+257260
+Revival
+
+
+Michael VON DER SCHULENBURG
+Germany
+Non-attached Members
+256966
+Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
+
+
+Alexandr VONDRA
+Czechia
+European Conservatives and Reformists Group
+197537
+ObÄanskĆ” demokratickĆ” strana
+
+
+Axel VOSS
+Germany
+Group of the European People's Party (Christian Democrats)
+96761
+Christlich Demokratische Union Deutschlands
+
+
+Elissavet VOZEMBERG-VRIONIDI
+Greece
+Group of the European People's Party (Christian Democrats)
+125065
+Nea Demokratia
+
+
+Veronika VRECIONOVĆ
+Czechia
+European Conservatives and Reformists Group
+197552
+ObÄanskĆ” demokratickĆ” strana
+
+
+AdriĆ”n VĆZQUEZ LĆZARA
+Spain
+Group of the European People's Party (Christian Democrats)
+204400
+Partido Popular
+
+
+Thomas WAITZ
+Austria
+Group of the Greens/European Free Alliance
+190464
+Die Grünen - Die Grüne Alternative
+
+
+Maria WALSH
+Ireland
+Group of the European People's Party (Christian Democrats)
+197863
+Fine Gael Party
+
+
+Marion WALSMANN
+Germany
+Group of the European People's Party (Christian Democrats)
+197429
+Christlich Demokratische Union Deutschlands
+
+
+Jƶrgen WARBORN
+Sweden
+Group of the European People's Party (Christian Democrats)
+197405
+Moderaterna
+
+
+Jan-Peter WARNKE
+Germany
+Non-attached Members
+256967
+Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
+
+
+Maciej WÄSIK
+Poland
+European Conservatives and Reformists Group
+257052
+Prawo i SprawiedliwoÅÄ
+
+
+MichaÅ WAWRYKIEWICZ
+Poland
+Group of the European People's Party (Christian Democrats)
+257045
+Independent
+
+
+Marta WCISÅO
+Poland
+Group of the European People's Party (Christian Democrats)
+257046
+Platforma Obywatelska
+
+
+Manfred WEBER
+Germany
+Group of the European People's Party (Christian Democrats)
+28229
+Christlich-Soziale Union in Bayern e.V.
+
+
+Andrea WECHSLER
+Germany
+Group of the European People's Party (Christian Democrats)
+256977
+Christlich Demokratische Union Deutschlands
+
+
+Charlie WEIMERS
+Sweden
+European Conservatives and Reformists Group
+123562
+Sverigedemokraterna
+
+
+SƩverine WERBROUCK
+France
+Patriots for Europe Group
+261796
+Rassemblement national
+
+
+Emma WIESNER
+Sweden
+Renew Europe Group
+214839
+Centerpartiet
+
+
+Michal WIEZIK
+Slovakia
+Renew Europe Group
+197769
+ProgresĆvne Slovensko
+
+
+Sophie WILMĆS
+Belgium
+Renew Europe Group
+220801
+Mouvement RƩformateur
+
+
+Iuliu WINKLER
+Romania
+Group of the European People's Party (Christian Democrats)
+39725
+Uniunea DemocratÄ MaghiarÄ din RomĆ¢nia
+
+
+Angelika WINZIG
+Austria
+Group of the European People's Party (Christian Democrats)
+197652
+Ćsterreichische Volkspartei
+
+
+Isabel WISELER-LIMA
+Luxembourg
+Group of the European People's Party (Christian Democrats)
+197421
+Parti chrƩtien social luxembourgeois
+
+
+Jadwiga WIÅNIEWSKA
+Poland
+European Conservatives and Reformists Group
+124877
+Prawo i SprawiedliwoÅÄ
+
+
+Tiemo WĆLKEN
+Germany
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+185619
+Sozialdemokratische Partei Deutschlands
+
+
+Lara WOLTERS
+Netherlands
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+5392
+GroenLinks-PvdA
+
+
+Lucia YAR
+Slovakia
+Renew Europe Group
+257011
+ProgresĆvne Slovensko
+
+
+StƩphanie YON-COURTIN
+France
+Renew Europe Group
+197581
+Renaissance
+
+
+Elena YONCHEVA
+Bulgaria
+Non-attached Members
+197842
+Movement for Rights and Freedoms
+
+
+Maria ZACHARIA
+Greece
+Non-attached Members
+256955
+Plefsi Eleftherias
+
+
+Ewa ZAJÄCZKOWSKA-HERNIK
+Poland
+Europe of Sovereign Nations Group
+257069
+Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
+
+
+Anna ZALEWSKA
+Poland
+European Conservatives and Reformists Group
+197572
+Prawo i SprawiedliwoÅÄ
+
+
+Dainius ŽALIMAS
+Lithuania
+Renew Europe Group
+256807
+LaisvÄs partija
+
+
+Alessandro ZAN
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+257106
+Partito Democratico
+
+
+Javier ZARZALEJOS
+Spain
+Group of the European People's Party (Christian Democrats)
+197606
+Partido Popular
+
+
+TomÔŔ ZDECHOVSKĆ
+Czechia
+Group of the European People's Party (Christian Democrats)
+124713
+KÅesÅ„anskĆ” a demokratickĆ” unie - ÄeskoslovenskĆ” strana lidovĆ”
+
+
+Bogdan Andrzej ZDROJEWSKI
+Poland
+Group of the European People's Party (Christian Democrats)
+124893
+Platforma Obywatelska
+
+
+Auke ZIJLSTRA
+Netherlands
+Patriots for Europe Group
+103246
+Partij voor de Vrijheid
+
+
+Roberts ZÄŖLE
+Latvia
+European Conservatives and Reformists Group
+28615
+NacionÄlÄ apvienÄ«ba "Visu Latvijai!" - "TÄvzemei un BrÄ«vÄ«bai/LNNK"
+
+
+Nicola ZINGARETTI
+Italy
+Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
+28419
+Partito Democratico
+
+
+Kosma ZÅOTOWSKI
+Poland
+European Conservatives and Reformists Group
+124884
+Prawo i SprawiedliwoÅÄ
+
+
+Juan Ignacio ZOIDO ĆLVAREZ
+Spain
+Group of the European People's Party (Christian Democrats)
+197621
+Partido Popular
+
+
+Željana ZOVKO
+Croatia
+Group of the European People's Party (Christian Democrats)
+185341
+Hrvatska demokratska zajednica
+
+
+Milan ZVER
+Slovenia
+Group of the European People's Party (Christian Democrats)
+96933
+Slovenska demokratska stranka
+
+
\ No newline at end of file
From d35fb71d57868e0fa7bd58b8a11dcda0d591d2ae Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Sat, 16 Aug 2025 01:25:45 +0300
Subject: [PATCH 51/56] Update euroswarm_parliament.py
---
.../euroswarm_parliament.py | 279 ++++++++++++++++--
1 file changed, 254 insertions(+), 25 deletions(-)
diff --git a/examples/simulations/euroswarm_parliament/euroswarm_parliament.py b/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
index 9984ba58..1694277b 100644
--- a/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
+++ b/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
@@ -17,6 +17,8 @@ import random
import xml.etree.ElementTree as ET
import time
import hashlib
+import requests
+import re
from typing import Dict, List, Optional, Union, Any, Set
from dataclasses import dataclass, field
from enum import Enum
@@ -138,6 +140,7 @@ class ParliamentaryMember:
voting_weight: Weight of the MEP's vote (default: 1.0)
agent: The AI agent representing this MEP (lazy loaded)
is_loaded: Whether the agent has been instantiated
+ wikipedia_info: Wikipedia-scraped personality information (optional)
"""
full_name: str
@@ -151,6 +154,7 @@ class ParliamentaryMember:
voting_weight: float = 1.0
agent: Optional[Agent] = None
is_loaded: bool = False
+ wikipedia_info: Optional[Any] = None # Wikipedia personality information
@dataclass
@@ -385,7 +389,158 @@ class EuroSwarmParliament:
def _load_mep_data(self) -> Dict[str, ParliamentaryMember]:
"""
- Load MEP data from EU.xml file and create parliamentary members with lazy loading.
+ Load MEP data from official EU Parliament website and create parliamentary members with lazy loading.
+ Fetches real-time data from https://www.europarl.europa.eu/meps/en/full-list/xml
+ and scrapes Wikipedia information for each MEP.
+
+ Returns:
+ Dict[str, ParliamentaryMember]: Dictionary of MEPs
+ """
+ meps = {}
+
+ try:
+ # Fetch XML data from official EU Parliament website
+ import requests
+ import re
+
+ eu_xml_url = "https://www.europarl.europa.eu/meps/en/full-list/xml"
+
+ logger.info(f"Fetching MEP data from: {eu_xml_url}")
+
+ # Fetch the XML content
+ response = requests.get(eu_xml_url, timeout=30)
+ response.raise_for_status()
+ content = response.text
+
+ logger.info(f"Successfully fetched {len(content)} characters of MEP data")
+
+ # Parse the XML content to extract MEP information
+ # The XML is properly formatted, so we can use ElementTree
+ try:
+ root = ET.fromstring(content)
+ mep_matches = []
+
+ for mep_element in root.findall('mep'):
+ full_name = mep_element.find('fullName').text.strip()
+ country = mep_element.find('country').text.strip()
+ political_group = mep_element.find('politicalGroup').text.strip()
+ mep_id = mep_element.find('id').text.strip()
+ national_party = mep_element.find('nationalPoliticalGroup').text.strip()
+
+ mep_matches.append((full_name, country, political_group, mep_id, national_party))
+
+ logger.info(f"Successfully parsed {len(mep_matches)} MEP entries from XML")
+
+ except ET.ParseError as xml_error:
+ logger.warning(f"XML parsing failed: {xml_error}")
+ # Fallback to regex parsing for malformed XML
+ mep_pattern = r'(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) '
+ mep_matches = re.findall(mep_pattern, content, re.DOTALL)
+ logger.info(f"Fallback regex parsing found {len(mep_matches)} MEP entries")
+
+ # Initialize Wikipedia scraper if available
+ wikipedia_scraper = None
+ if WIKIPEDIA_PERSONALITY_AVAILABLE:
+ try:
+ wikipedia_scraper = WikipediaPersonalityScraper()
+ logger.info("Wikipedia personality scraper initialized")
+ except Exception as e:
+ logger.warning(f"Failed to initialize Wikipedia scraper: {e}")
+
+ # Process each MEP
+ for i, mep_data in enumerate(mep_matches):
+ if len(mep_data) >= 5: # full_name, country, political_group, mep_id, national_party
+ full_name = mep_data[0].strip()
+ country = mep_data[1].strip()
+ political_group = mep_data[2].strip()
+ mep_id = mep_data[3].strip()
+ national_party = mep_data[4].strip()
+
+ # Clean up political group name
+ political_group = self._clean_political_group_name(political_group)
+
+ # Scrape Wikipedia information if scraper is available
+ wikipedia_info = None
+ if wikipedia_scraper:
+ try:
+ # Create MEP data dictionary for the scraper
+ mep_data = {
+ 'full_name': full_name,
+ 'country': country,
+ 'political_group': political_group,
+ 'national_party': national_party,
+ 'mep_id': mep_id
+ }
+
+ # Create personality profile
+ personality_profile = wikipedia_scraper.create_personality_profile(mep_data)
+
+ # Convert to dictionary format for storage
+ wikipedia_info = {
+ 'personality_summary': personality_profile.summary,
+ 'political_views': personality_profile.political_views,
+ 'policy_focus': personality_profile.policy_focus,
+ 'achievements': personality_profile.achievements,
+ 'professional_background': personality_profile.professional_background,
+ 'political_career': personality_profile.political_career,
+ 'education': personality_profile.education,
+ 'wikipedia_url': personality_profile.wikipedia_url
+ }
+
+ if self.verbose:
+ logger.info(f"Scraped Wikipedia info for {full_name}")
+ except Exception as e:
+ if self.verbose:
+ logger.debug(f"Failed to scrape Wikipedia for {full_name}: {e}")
+
+ # Create parliamentary member (without agent for lazy loading)
+ mep = ParliamentaryMember(
+ full_name=full_name,
+ country=country,
+ political_group=political_group,
+ national_party=national_party,
+ mep_id=mep_id,
+ expertise_areas=self._generate_expertise_areas(political_group, country),
+ committees=self._assign_committees(political_group),
+ agent=None, # Will be created on demand
+ is_loaded=False,
+ wikipedia_info=wikipedia_info # Add Wikipedia information
+ )
+
+ meps[full_name] = mep
+
+ # Limit processing for performance (can be adjusted)
+ if len(meps) >= 705: # Standard EU Parliament size
+ break
+
+ # Set parliament size to actual number of MEPs loaded
+ if self.parliament_size is None:
+ self.parliament_size = len(meps)
+
+ logger.info(f"Successfully loaded {len(meps)} MEP profiles from official EU data (lazy loading enabled)")
+ if wikipedia_scraper:
+ logger.info(f"Wikipedia scraping completed for {len([m for m in meps.values() if m.wikipedia_info])} MEPs")
+
+ except Exception as e:
+ logger.error(f"Error loading MEP data from official website: {e}")
+ logger.info("Falling back to local EU.xml file...")
+
+ # Fallback to local file
+ try:
+ meps = self._load_mep_data_from_local_file()
+ except Exception as local_error:
+ logger.error(f"Error loading local MEP data: {local_error}")
+ # Create fallback MEPs if both methods fail
+ meps = self._create_fallback_meps()
+
+ if self.parliament_size is None:
+ self.parliament_size = len(meps)
+
+ return meps
+
+ def _load_mep_data_from_local_file(self) -> Dict[str, ParliamentaryMember]:
+ """
+ Fallback method to load MEP data from local EU.xml file.
Returns:
Dict[str, ParliamentaryMember]: Dictionary of MEPs
@@ -432,21 +587,98 @@ class EuroSwarmParliament:
meps[full_name] = mep
- # Set parliament size to actual number of MEPs loaded if not specified
- if self.parliament_size is None:
- self.parliament_size = len(meps)
-
- logger.info(f"Loaded {len(meps)} MEP profiles from EU data (lazy loading enabled)")
+ logger.info(f"Loaded {len(meps)} MEP profiles from local EU.xml file (lazy loading enabled)")
except Exception as e:
- logger.error(f"Error loading MEP data: {e}")
- # Create fallback MEPs if file loading fails
- meps = self._create_fallback_meps()
- if self.parliament_size is None:
- self.parliament_size = len(meps)
+ logger.error(f"Error loading local MEP data: {e}")
+ raise
return meps
+ def _clean_political_group_name(self, political_group: str) -> str:
+ """
+ Clean and standardize political group names.
+
+ Args:
+ political_group: Raw political group name
+
+ Returns:
+ str: Cleaned political group name
+ """
+ # Map common variations to standard names
+ group_mapping = {
+ 'EPP': 'Group of the European People\'s Party (Christian Democrats)',
+ 'S&D': 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament',
+ 'Renew': 'Renew Europe Group',
+ 'Greens/EFA': 'Group of the Greens/European Free Alliance',
+ 'ECR': 'European Conservatives and Reformists Group',
+ 'ID': 'Identity and Democracy Group',
+ 'GUE/NGL': 'The Left group in the European Parliament - GUE/NGL',
+ 'Non-attached': 'Non-attached Members'
+ }
+
+ # Check for exact matches first
+ for key, value in group_mapping.items():
+ if political_group.strip() == key:
+ return value
+
+ # Check for partial matches
+ political_group_lower = political_group.lower()
+ for key, value in group_mapping.items():
+ if key.lower() in political_group_lower:
+ return value
+
+ # Return original if no match found
+ return political_group.strip()
+
+ def _generate_national_party(self, country: str, political_group: str) -> str:
+ """
+ Generate a realistic national party name based on country and political group.
+
+ Args:
+ country: Country of the MEP
+ political_group: Political group affiliation
+
+ Returns:
+ str: Generated national party name
+ """
+ # Map of countries to common parties for each political group
+ party_mapping = {
+ 'Germany': {
+ 'Group of the European People\'s Party (Christian Democrats)': 'Christlich Demokratische Union Deutschlands',
+ 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament': 'Sozialdemokratische Partei Deutschlands',
+ 'Renew Europe Group': 'Freie Demokratische Partei',
+ 'Group of the Greens/European Free Alliance': 'Bündnis 90/Die Grünen',
+ 'European Conservatives and Reformists Group': 'Alternative für Deutschland',
+ 'Identity and Democracy Group': 'Alternative für Deutschland',
+ 'The Left group in the European Parliament - GUE/NGL': 'Die Linke'
+ },
+ 'France': {
+ 'Group of the European People\'s Party (Christian Democrats)': 'Les RƩpublicains',
+ 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament': 'Parti Socialiste',
+ 'Renew Europe Group': 'Renaissance',
+ 'Group of the Greens/European Free Alliance': 'Europe Ćcologie Les Verts',
+ 'European Conservatives and Reformists Group': 'Rassemblement National',
+ 'Identity and Democracy Group': 'Rassemblement National',
+ 'The Left group in the European Parliament - GUE/NGL': 'La France Insoumise'
+ },
+ 'Italy': {
+ 'Group of the European People\'s Party (Christian Democrats)': 'Forza Italia',
+ 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament': 'Partito Democratico',
+ 'Renew Europe Group': 'Italia Viva',
+ 'Group of the Greens/European Free Alliance': 'Federazione dei Verdi',
+ 'European Conservatives and Reformists Group': 'Fratelli d\'Italia',
+ 'Identity and Democracy Group': 'Lega',
+ 'The Left group in the European Parliament - GUE/NGL': 'Movimento 5 Stelle'
+ }
+ }
+
+ # Return mapped party or generate a generic one
+ if country in party_mapping and political_group in party_mapping[country]:
+ return party_mapping[country][political_group]
+ else:
+ return f"{country} National Party"
+
def _load_mep_agent(self, mep_name: str) -> Optional[Agent]:
"""
Lazy load a single MEP agent on demand.
@@ -684,9 +916,6 @@ class EuroSwarmParliament:
str: System prompt for the MEP agent
"""
- # Get Wikipedia personality profile if available
- personality_profile = self.get_mep_personality_profile(mep.full_name)
-
# Base prompt structure
prompt = f"""You are {mep.full_name}, a Member of the European Parliament (MEP) representing {mep.country}.
@@ -700,16 +929,16 @@ POLITICAL BACKGROUND:
"""
# Add Wikipedia personality data if available
- if personality_profile and self.enable_wikipedia_personalities:
+ if mep.wikipedia_info and self.enable_wikipedia_personalities:
prompt += f"""
REAL PERSONALITY PROFILE (Based on Wikipedia data):
-{self.personality_scraper.get_personality_summary(personality_profile)}
+{mep.wikipedia_info.get('personality_summary', 'Based on parliamentary service and political alignment')}
POLITICAL VIEWS AND POSITIONS:
-- Key Political Views: {personality_profile.political_views if personality_profile.political_views else 'Based on party alignment'}
-- Policy Focus Areas: {personality_profile.policy_focus if personality_profile.policy_focus else ', '.join(mep.expertise_areas)}
-- Notable Achievements: {personality_profile.achievements if personality_profile.achievements else 'Parliamentary service'}
-- Professional Background: {personality_profile.professional_background if personality_profile.professional_background else 'Political career'}
+- Key Political Views: {mep.wikipedia_info.get('political_views', 'Based on party alignment')}
+- Policy Focus Areas: {mep.wikipedia_info.get('policy_focus', ', '.join(mep.expertise_areas))}
+- Notable Achievements: {mep.wikipedia_info.get('achievements', 'Parliamentary service')}
+- Professional Background: {mep.wikipedia_info.get('professional_background', 'Political career')}
"""
else:
@@ -753,11 +982,11 @@ COMMUNICATION STYLE:
When responding to parliamentary matters, consider:
1. How does this affect {mep.country} and your constituents?
2. What is the position of {mep.political_group} on this issue?
-3. What are the implications for your areas of expertise?
-4. How can you contribute constructively to the discussion?
-5. What is the best outcome for European citizens?
+3. How does this align with your areas of expertise?
+4. What are the broader European implications?
+5. How can you best represent your constituents' interests?
-Remember: You are a democratically elected representative working for the benefit of European citizens while representing {mep.country}'s interests within the European Union framework.
+Remember: You are a real MEP with specific political views, expertise, and responsibilities. Act accordingly in all parliamentary interactions.
"""
return prompt
@@ -2595,4 +2824,4 @@ Remember: You are a democratically elected representative working for the benefi
analysis["opposition"] = weighted_opposition
analysis["uncertainty"] = weighted_uncertainty
- return analysis
\ No newline at end of file
+ return analysis
From 385391dd0c992f08b51376641634b2d76c496e53 Mon Sep 17 00:00:00 2001
From: CI-DEV <154627941+IlumCI@users.noreply.github.com>
Date: Sat, 16 Aug 2025 01:25:58 +0300
Subject: [PATCH 52/56] Delete EU.xml
---
EU.xml | 5027 --------------------------------------------------------
1 file changed, 5027 deletions(-)
delete mode 100644 EU.xml
diff --git a/EU.xml b/EU.xml
deleted file mode 100644
index 32220aaa..00000000
--- a/EU.xml
+++ /dev/null
@@ -1,5027 +0,0 @@
-
-Mika AALTOLA
-Finland
-Group of the European People's Party (Christian Democrats)
-256810
-Kansallinen Kokoomus
-
-
-Maravillas ABADĆA JOVER
-Spain
-Group of the European People's Party (Christian Democrats)
-257043
-Partido Popular
-
-
-Magdalena ADAMOWICZ
-Poland
-Group of the European People's Party (Christian Democrats)
-197490
-Independent
-
-
-Georgios AFTIAS
-Greece
-Group of the European People's Party (Christian Democrats)
-256820
-Nea Demokratia
-
-
-Oihane AGIRREGOITIA MARTĆNEZ
-Spain
-Renew Europe Group
-256987
-Partido Nacionalista Vasco
-
-
-Peter AGIUS
-Malta
-Group of the European People's Party (Christian Democrats)
-113523
-Partit Nazzjonalista
-
-
-Alex AGIUS SALIBA
-Malta
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197403
-Partit Laburista
-
-
-Galato ALEXANDRAKI
-Greece
-European Conservatives and Reformists Group
-256956
-Elliniki Lusi-Greek Solution
-
-
-GrƩgory ALLIONE
-France
-Renew Europe Group
-256869
-Renaissance
-
-
-Abir AL-SAHLANI
-Sweden
-Renew Europe Group
-197400
-Centerpartiet
-
-
-Nikolaos ANADIOTIS
-Greece
-Non-attached Members
-256858
-Dimokratikó Patriotikó KĆnima Ā«NIKIĀ»
-
-
-Christine ANDERSON
-Germany
-Europe of Sovereign Nations Group
-197475
-Alternative für Deutschland
-
-
-Li ANDERSSON
-Finland
-The Left group in the European Parliament - GUE/NGL
-256805
-Vasemmistoliitto
-
-
-Rasmus ANDRESEN
-Germany
-Group of the Greens/European Free Alliance
-197448
-Bündnis 90/Die Grünen
-
-
-Barry ANDREWS
-Ireland
-Renew Europe Group
-204332
-Fianna FƔil Party
-
-
-Vytenis Povilas ANDRIUKAITIS
-Lithuania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-119652
-Lietuvos socialdemokratų partija
-
-
-Mathilde ANDROUĆT
-France
-Patriots for Europe Group
-197691
-Rassemblement national
-
-
-Marc ANGEL
-Luxembourg
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-202073
-Parti ouvrier socialiste luxembourgeois
-
-
-Gerolf ANNEMANS
-Belgium
-Patriots for Europe Group
-124973
-Vlaams Belang
-
-
-Lucia ANNUNZIATA
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257123
-Partito Democratico
-
-
-Giuseppe ANTOCI
-Italy
-The Left group in the European Parliament - GUE/NGL
-257138
-Movimento 5 Stelle
-
-
-Pablo ARIAS ECHEVERRĆA
-Spain
-Group of the European People's Party (Christian Democrats)
-96808
-Partido Popular
-
-
-Pascal ARIMONT
-Belgium
-Group of the European People's Party (Christian Democrats)
-24922
-Christlich Soziale Partei
-
-
-Bartosz ARÅUKOWICZ
-Poland
-Group of the European People's Party (Christian Democrats)
-197492
-Platforma Obywatelska
-
-
-Sakis ARNAOUTOGLOU
-Greece
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256829
-PASOK-KINAL
-
-
-Anja ARNDT
-Germany
-Europe of Sovereign Nations Group
-256951
-Alternative für Deutschland
-
-
-Konstantinos ARVANITIS
-Greece
-The Left group in the European Parliament - GUE/NGL
-197701
-Coalition of the Radical Left
-
-
-Jaume ASENS LLODRĆ
-Spain
-Group of the Greens/European Free Alliance
-257015
-Movimiento Sumar
-
-
-Francisco ASSIS
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-28307
-Partido Socialista
-
-
-Daniel ATTARD
-Malta
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256934
-Partit Laburista
-
-
-Manon AUBRY
-France
-The Left group in the European Parliament - GUE/NGL
-197533
-La France Insoumise
-
-
-RenƩ AUST
-Germany
-Europe of Sovereign Nations Group
-256929
-Alternative für Deutschland
-
-
-Petras AUÅ TREVIÄIUS
-Lithuania
-Renew Europe Group
-124766
-Liberalų sÄ
jūdis
-
-
-Adrian-George AXINIA
-Romania
-European Conservatives and Reformists Group
-257117
-AlianČa pentru Unirea RomĆ¢nilor
-
-
-Malik AZMANI
-Netherlands
-Renew Europe Group
-197781
-Volkspartij voor Vrijheid en Democratie
-
-
-Thomas BAJADA
-Malta
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256936
-Partit Laburista
-
-
-Jeannette BALJEU
-Netherlands
-Renew Europe Group
-257003
-Volkspartij voor Vrijheid en Democratie
-
-
-Laura BALLARĆN CEREZA
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-247735
-Partido Socialista Obrero EspaƱol
-
-
-Jordan BARDELLA
-France
-Patriots for Europe Group
-131580
-Rassemblement national
-
-
-Katarina BARLEY
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197433
-Sozialdemokratische Partei Deutschlands
-
-
-Dan BARNA
-Romania
-Renew Europe Group
-257110
-Uniunea SalvaČi RomĆ¢nia
-
-
-Pernando BARRENA ARZA
-Spain
-The Left group in the European Parliament - GUE/NGL
-197684
-EH BILDU
-
-
-Stephen Nikola BARTULICA
-Croatia
-European Conservatives and Reformists Group
-257000
-Dom i nacionalno okupljanje
-
-
-Nikola BARTŮŠEK
-Czechia
-Patriots for Europe Group
-256852
-PÅĆsaha
-
-
-Arno BAUSEMER
-Germany
-Europe of Sovereign Nations Group
-256948
-Alternative für Deutschland
-
-
-Nicolas BAY
-France
-European Conservatives and Reformists Group
-124760
-IdentitƩ LibertƩs
-
-
-Christophe BAY
-France
-Patriots for Europe Group
-261797
-Rassemblement national
-
-
-Wouter BEKE
-Belgium
-Group of the European People's Party (Christian Democrats)
-256887
-Christen-Democratisch & Vlaams
-
-
-Fredis BELERIS
-Greece
-Group of the European People's Party (Christian Democrats)
-256947
-Nea Demokratia
-
-
-FranƧois-Xavier BELLAMY
-France
-Group of the European People's Party (Christian Democrats)
-197534
-Les RƩpublicains
-
-
-DragoÅ BENEA
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197658
-Partidul Social Democrat
-
-
-Brando BENIFEI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124867
-Partito Democratico
-
-
-Isabel BENJUMEA BENJUMEA
-Spain
-Group of the European People's Party (Christian Democrats)
-197679
-Partido Popular
-
-
-Monika BEÅOVĆ
-Slovakia
-Non-attached Members
-23868
-SMER-SociƔlna demokracia
-
-
-Hildegard BENTELE
-Germany
-Group of the European People's Party (Christian Democrats)
-197408
-Christlich Demokratische Union Deutschlands
-
-
-Tom BERENDSEN
-Netherlands
-Group of the European People's Party (Christian Democrats)
-197778
-Christen Democratisch AppĆØl
-
-
-Stefan BERGER
-Germany
-Group of the European People's Party (Christian Democrats)
-197410
-Christlich Demokratische Union Deutschlands
-
-
-Sibylle BERG
-Germany
-Non-attached Members
-256960
-Die PARTEI
-
-
-Sergio BERLATO
-Italy
-European Conservatives and Reformists Group
-4746
-FRATELLI D' ITALIA
-
-
-Alexander BERNHUBER
-Austria
-Group of the European People's Party (Christian Democrats)
-197648
-Ćsterreichische Volkspartei
-
-
-Robert BIEDROÅ
-Poland
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197498
-Nowa Lewica
-
-
-Adam BIELAN
-Poland
-European Conservatives and Reformists Group
-23788
-Prawo i SprawiedliwoÅÄ
-
-
-Gabriele BISCHOFF
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197435
-Sozialdemokratische Partei Deutschlands
-
-
-ĽuboŔ BLAHA
-Slovakia
-Non-attached Members
-257005
-SMER-SociƔlna demokracia
-
-
-Vilija BLINKEVIÄIÅŖTÄ
-Lithuania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-96681
-Lietuvos socialdemokratų partija
-
-
-Rachel BLOM
-Netherlands
-Patriots for Europe Group
-256998
-Partij voor de Vrijheid
-
-
-Michael BLOSS
-Germany
-Group of the Greens/European Free Alliance
-197449
-Bündnis 90/Die Grünen
-
-
-Tobiasz BOCHEÅSKI
-Poland
-European Conservatives and Reformists Group
-257073
-Prawo i SprawiedliwoÅÄ
-
-
-Damian BOESELAGER
-Germany
-Group of the Greens/European Free Alliance
-197439
-Volt
-
-
-Ioan-RareÅ BOGDAN
-Romania
-Group of the European People's Party (Christian Democrats)
-197636
-Partidul Naţional Liberal
-
-
-Stefano BONACCINI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257108
-Partito Democratico
-
-
-Barbara BONTE
-Belgium
-Patriots for Europe Group
-256881
-Vlaams Belang
-
-
-Paolo BORCHIA
-Italy
-Patriots for Europe Group
-101039
-Lega
-
-
-Mireia BORRĆS PABĆN
-Spain
-Patriots for Europe Group
-257024
-VOX
-
-
-Zsuzsanna BORVENDĆG
-Hungary
-Europe of Sovereign Nations Group
-257457
-Mi HazƔnk Mozgalom
-
-
-Biljana BORZAN
-Croatia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-112748
-Socijaldemokratska partija Hrvatske
-
-
-Gordan BOSANAC
-Croatia
-Group of the Greens/European Free Alliance
-256995
-Možemo!
-
-
-Irmhild BOįŗDORF
-Germany
-Europe of Sovereign Nations Group
-256945
-Alternative für Deutschland
-
-
-Stine BOSSE
-Denmark
-Renew Europe Group
-257020
-Moderaterne
-
-
-Marc BOTENGA
-Belgium
-The Left group in the European Parliament - GUE/NGL
-187917
-PVDA-PTB
-
-
-Gilles BOYER
-France
-Renew Europe Group
-197577
-Horizons
-
-
-Lynn BOYLAN
-Ireland
-The Left group in the European Parliament - GUE/NGL
-124984
-Sinn FƩin
-
-
-Helmut BRANDSTĆTTER
-Austria
-Renew Europe Group
-256841
-NEOS ā Das Neue Ćsterreich
-
-
-Marie-Luce BRASIER-CLAIN
-France
-Patriots for Europe Group
-256878
-Rassemblement national
-
-
-Grzegorz BRAUN
-Poland
-Non-attached Members
-257067
-Konfederacja Korony Polskiej
-
-
-Krzysztof BREJZA
-Poland
-Group of the European People's Party (Christian Democrats)
-251324
-Platforma Obywatelska
-
-
-Saskia BRICMONT
-Belgium
-Group of the Greens/European Free Alliance
-197470
-Ecologistes ConfƩdƩrƩs pour l'Organisation de Luttes Originales
-
-
-Nikolina BRNJAC
-Croatia
-Group of the European People's Party (Christian Democrats)
-204129
-Hrvatska demokratska zajednica
-
-
-Joachim StanisÅaw BRUDZIÅSKI
-Poland
-European Conservatives and Reformists Group
-197501
-Prawo i SprawiedliwoÅÄ
-
-
-Anna BRYÅKA
-Poland
-Patriots for Europe Group
-257064
-Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
-
-
-Markus BUCHHEIT
-Germany
-Europe of Sovereign Nations Group
-128483
-Alternative für Deutschland
-
-
-Tomasz BUCZEK
-Poland
-Patriots for Europe Group
-257072
-Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
-
-
-Daniel BUDA
-Romania
-Group of the European People's Party (Christian Democrats)
-125012
-Partidul Naţional Liberal
-
-
-Waldemar BUDA
-Poland
-European Conservatives and Reformists Group
-99878
-Prawo i SprawiedliwoÅÄ
-
-
-Borys BUDKA
-Poland
-Group of the European People's Party (Christian Democrats)
-257047
-Platforma Obywatelska
-
-
-Sebastião BUGALHO
-Portugal
-Group of the European People's Party (Christian Democrats)
-257081
-Partido Social Democrata
-
-
-Andrzej BUÅA
-Poland
-Group of the European People's Party (Christian Democrats)
-257051
-Platforma Obywatelska
-
-
-Udo BULLMANN
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-4267
-Sozialdemokratische Partei Deutschlands
-
-
-Delara BURKHARDT
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197440
-Sozialdemokratische Partei Deutschlands
-
-
-Jorge BUXADĆ VILLALBA
-Spain
-Patriots for Europe Group
-197829
-VOX
-
-
-Petr BYSTRON
-Germany
-Europe of Sovereign Nations Group
-256928
-Alternative für Deutschland
-
-
-Jaroslav BŽOCH
-Czechia
-Patriots for Europe Group
-220840
-ANO 2011
-
-
-MƩlissa CAMARA
-France
-Group of the Greens/European Free Alliance
-256915
-Les Ćcologistes
-
-
-Pascal CANFIN
-France
-Renew Europe Group
-96711
-Renaissance
-
-
-Nina CARBERRY
-Ireland
-Group of the European People's Party (Christian Democrats)
-257296
-Fine Gael Party
-
-
-Gheorghe CĆRCIU
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257100
-Partidul Social Democrat
-
-
-Damien CARĆME
-France
-The Left group in the European Parliament - GUE/NGL
-197574
-La France Insoumise
-
-
-David CASA
-Malta
-Group of the European People's Party (Christian Democrats)
-28122
-Partit Nazzjonalista
-
-
-Daniel CASPARY
-Germany
-Group of the European People's Party (Christian Democrats)
-28219
-Christlich Demokratische Union Deutschlands
-
-
-Benoit CASSART
-Belgium
-Renew Europe Group
-256891
-Mouvement RƩformateur
-
-
-Laurent CASTILLO
-France
-Group of the European People's Party (Christian Democrats)
-256921
-Union des droites pour la RƩpublique
-
-
-Pilar DEL CASTILLO VERA
-Spain
-Group of the European People's Party (Christian Democrats)
-28390
-Partido Popular
-
-
-Anna CAVAZZINI
-Germany
-Group of the Greens/European Free Alliance
-86793
-Bündnis 90/Die Grünen
-
-
-Stefano CAVEDAGNA
-Italy
-European Conservatives and Reformists Group
-257096
-FRATELLI D' ITALIA
-
-
-Susanna CECCARDI
-Italy
-Patriots for Europe Group
-197786
-Lega
-
-
-JosƩ CEPEDA
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257002
-Partido Socialista Obrero EspaƱol
-
-
-Estelle CEULEMANS
-Belgium
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256880
-Parti Socialiste
-
-
-Mohammed CHAHIM
-Netherlands
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197782
-GroenLinks-PvdA
-
-
-Leila CHAIBI
-France
-The Left group in the European Parliament - GUE/NGL
-197529
-La France Insoumise
-
-
-Olivier CHASTEL
-Belgium
-Renew Europe Group
-197463
-Mouvement RƩformateur
-
-
-Caterina CHINNICI
-Italy
-Group of the European People's Party (Christian Democrats)
-124861
-Forza Italia
-
-
-Asger CHRISTENSEN
-Denmark
-Renew Europe Group
-197558
-Venstre, Danmarks Liberale Parti
-
-
-Carlo CICCIOLI
-Italy
-European Conservatives and Reformists Group
-257093
-FRATELLI D' ITALIA
-
-
-Veronika CIFROVĆ OSTRIHOÅOVĆ
-Slovakia
-Renew Europe Group
-257014
-ProgresĆvne Slovensko
-
-
-Alessandro CIRIANI
-Italy
-European Conservatives and Reformists Group
-257147
-FRATELLI D' ITALIA
-
-
-Anna Maria CISINT
-Italy
-Patriots for Europe Group
-257131
-Lega
-
-
-Per CLAUSEN
-Denmark
-The Left group in the European Parliament - GUE/NGL
-257023
-Enhedslisten
-
-
-Christophe CLERGEAU
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-245018
-Parti socialiste
-
-
-David CORMAND
-France
-Group of the Greens/European Free Alliance
-197503
-Les Ćcologistes
-
-
-Annalisa CORRADO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257169
-Partito Democratico
-
-
-Vivien COSTANZO
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256937
-Sozialdemokratische Partei Deutschlands
-
-
-João COTRIM DE FIGUEIREDO
-Portugal
-Renew Europe Group
-257057
-Iniciativa Liberal
-
-
-Barry COWEN
-Ireland
-Renew Europe Group
-257297
-Fianna FƔil Party
-
-
-Tobias CREMER
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256938
-Sozialdemokratische Partei Deutschlands
-
-
-Carmen CRESPO DĆAZ
-Spain
-Group of the European People's Party (Christian Democrats)
-257034
-Partido Popular
-
-
-Andi CRISTEA
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-40224
-Partidul Social Democrat
-
-
-Giovanni CROSETTO
-Italy
-European Conservatives and Reformists Group
-257094
-FRATELLI D' ITALIA
-
-
-Paulo CUNHA
-Portugal
-Group of the European People's Party (Christian Democrats)
-257078
-Partido Social Democrata
-
-
-Henrik DAHL
-Denmark
-Group of the European People's Party (Christian Democrats)
-257028
-Liberal Alliance
-
-
-Johan DANIELSSON
-Sweden
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-38542
-Arbetarepartiet- Socialdemokraterna
-
-
-Marie DAUCHY
-France
-Patriots for Europe Group
-236050
-Rassemblement national
-
-
-Dóra DĆVID
-Hungary
-Group of the European People's Party (Christian Democrats)
-256862
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Ivan DAVID
-Czechia
-Europe of Sovereign Nations Group
-197556
-Svoboda a pÅĆmĆ” demokracie
-
-
-Antonio DECARO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257122
-Partito Democratico
-
-
-RaĆŗl DE LA HOZ QUINTANO
-Spain
-Group of the European People's Party (Christian Democrats)
-257030
-Partido Popular
-
-
-Danilo DELLA VALLE
-Italy
-The Left group in the European Parliament - GUE/NGL
-257155
-Movimento 5 Stelle
-
-
-ValƩrie DELOGE
-France
-Patriots for Europe Group
-256886
-Rassemblement national
-
-
-Fabio DE MASI
-Germany
-Non-attached Members
-124858
-Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
-
-
-Salvatore DE MEO
-Italy
-Group of the European People's Party (Christian Democrats)
-204333
-Forza Italia
-
-
-Ćzlem DEMIREL
-Germany
-The Left group in the European Parliament - GUE/NGL
-197468
-DIE LINKE.
-
-
-TamƔs DEUTSCH
-Hungary
-Patriots for Europe Group
-96826
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-ValƩrie DEVAUX
-France
-Renew Europe Group
-256870
-Union des dƩmocrates et indƩpendants
-
-
-Adnan DIBRANI
-Sweden
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257087
-Arbetarepartiet- Socialdemokraterna
-
-
-Ton DIEPEVEEN
-Netherlands
-Patriots for Europe Group
-256981
-Partij voor de Vrijheid
-
-
-Elisabeth DIERINGER
-Austria
-Patriots for Europe Group
-256834
-Freiheitliche Partei Ćsterreichs
-
-
-Vasile DĆNCU
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-33998
-Partidul Social Democrat
-
-
-Elio DI RUPO
-Belgium
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-1294
-Parti Socialiste
-
-
-MƩlanie DISDIER
-France
-Patriots for Europe Group
-256874
-Rassemblement national
-
-
-KlƔra DOBREV
-Hungary
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197579
-Demokratikus KoalĆció
-
-
-Regina DOHERTY
-Ireland
-Group of the European People's Party (Christian Democrats)
-257237
-Fine Gael Party
-
-
-Christian DOLESCHAL
-Germany
-Group of the European People's Party (Christian Democrats)
-197473
-Christlich-Soziale Union in Bayern e.V.
-
-
-Csaba DĆMĆTĆR
-Hungary
-Patriots for Europe Group
-260724
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Paulo DO NASCIMENTO CABRAL
-Portugal
-Group of the European People's Party (Christian Democrats)
-257048
-AlianƧa DemocrƔtica
-
-
-Elena DONAZZAN
-Italy
-European Conservatives and Reformists Group
-257095
-FRATELLI D' ITALIA
-
-
-Herbert DORFMANN
-Italy
-Group of the European People's Party (Christian Democrats)
-96787
-Südtiroler Volkspartei
-
-
-Klara DOSTALOVA
-Czechia
-Patriots for Europe Group
-256853
-ANO 2011
-
-
-OndÅej DOSTĆL
-Czechia
-Non-attached Members
-256851
-Independent
-
-
-Siegbert Frank DROESE
-Germany
-Europe of Sovereign Nations Group
-256949
-Alternative für Deutschland
-
-
-Lena DĆPONT
-Germany
-Group of the European People's Party (Christian Democrats)
-99945
-Christlich Demokratische Union Deutschlands
-
-
-MichaÅ DWORCZYK
-Poland
-European Conservatives and Reformists Group
-257076
-Prawo i SprawiedliwoÅÄ
-
-
-Matthias ECKE
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-237465
-Sozialdemokratische Partei Deutschlands
-
-
-Christian EHLER
-Germany
-Group of the European People's Party (Christian Democrats)
-28226
-Christlich Demokratische Union Deutschlands
-
-
-Marieke EHLERS
-Netherlands
-Patriots for Europe Group
-192254
-Partij voor de Vrijheid
-
-
-Bas EICKHOUT
-Netherlands
-Group of the Greens/European Free Alliance
-96725
-GroenLinks-PvdA
-
-
-Sofie ERIKSSON
-Sweden
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257088
-Arbetarepartiet- Socialdemokraterna
-
-
-Dick ERIXON
-Sweden
-European Conservatives and Reformists Group
-257091
-Sverigedemokraterna
-
-
-Engin EROGLU
-Germany
-Renew Europe Group
-197430
-Freie WƤhler
-
-
-Rosa ESTARĆS FERRAGUT
-Spain
-Group of the European People's Party (Christian Democrats)
-96811
-Partido Popular
-
-
-Sebastian EVERDING
-Germany
-The Left group in the European Parliament - GUE/NGL
-256961
-Partei Mensch Umwelt Tierschutz
-
-
-Alma EZCURRA ALMANSA
-Spain
-Group of the European People's Party (Christian Democrats)
-257035
-Partido Popular
-
-
-Gheorghe FALCÄ
-Romania
-Group of the European People's Party (Christian Democrats)
-197649
-Partidul Naţional Liberal
-
-
-Marco FALCONE
-Italy
-Group of the European People's Party (Christian Democrats)
-257137
-Forza Italia
-
-
-Nikolas FARANTOURIS
-Greece
-The Left group in the European Parliament - GUE/NGL
-256823
-Coalition of the Radical Left
-
-
-Laurence FARRENG
-France
-Renew Europe Group
-197589
-Mouvement DƩmocrate
-
-
-Jan FARSKĆ
-Czechia
-Group of the European People's Party (Christian Democrats)
-256840
-StarostovƩ a nezƔvisli
-
-
-Markus FERBER
-Germany
-Group of the European People's Party (Christian Democrats)
-1917
-Christlich-Soziale Union in Bayern e.V.
-
-
-Viktória FERENC
-Hungary
-Patriots for Europe Group
-256857
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-JonĆ”s FERNĆNDEZ
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-125046
-Partido Socialista Obrero EspaƱol
-
-
-Carlo FIDANZA
-Italy
-European Conservatives and Reformists Group
-96810
-FRATELLI D' ITALIA
-
-
-Pietro FIOCCHI
-Italy
-European Conservatives and Reformists Group
-197607
-FRATELLI D' ITALIA
-
-
-Gabriela FIREA
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257098
-Partidul Social Democrat
-
-
-Ruth FIRMENICH
-Germany
-Non-attached Members
-25758
-Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
-
-
-Claire FITA
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256906
-Parti socialiste
-
-
-Luke Ming FLANAGAN
-Ireland
-The Left group in the European Parliament - GUE/NGL
-124985
-Independent
-
-
-Loucas FOURLAS
-Cyprus
-Group of the European People's Party (Christian Democrats)
-197414
-Democratic Rally
-
-
-Emma FOURREAU
-France
-The Left group in the European Parliament - GUE/NGL
-256913
-La France Insoumise
-
-
-Emmanouil FRAGKOS
-Greece
-European Conservatives and Reformists Group
-198490
-Elliniki Lusi-Greek Solution
-
-
-Daniel FREUND
-Germany
-Group of the Greens/European Free Alliance
-106936
-Bündnis 90/Die Grünen
-
-
-Anne-Sophie FRIGOUT
-France
-Patriots for Europe Group
-256876
-Rassemblement national
-
-
-Sigrid FRIIS
-Denmark
-Renew Europe Group
-257038
-Det Radikale Venstre
-
-
-HelƩne FRITZON
-Sweden
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197391
-Arbetarepartiet- Socialdemokraterna
-
-
-Tomasz FROELICH
-Germany
-Europe of Sovereign Nations Group
-190574
-Alternative für Deutschland
-
-
-Niels FUGLSANG
-Denmark
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-101585
-Socialdemokratiet
-
-
-Kathleen FUNCHION
-Ireland
-The Left group in the European Parliament - GUE/NGL
-257299
-Sinn FƩin
-
-
-AngƩline FURET
-France
-Patriots for Europe Group
-256896
-Rassemblement national
-
-
-Mario FURORE
-Italy
-The Left group in the European Parliament - GUE/NGL
-197795
-Movimento 5 Stelle
-
-
-Michael GAHLER
-Germany
-Group of the European People's Party (Christian Democrats)
-2341
-Christlich Demokratische Union Deutschlands
-
-
-Kinga GĆL
-Hungary
-Patriots for Europe Group
-28150
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Estrella GALĆN
-Spain
-The Left group in the European Parliament - GUE/NGL
-257012
-Movimiento Sumar
-
-
-Lina GĆLVEZ
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197702
-Partido Socialista Obrero EspaƱol
-
-
-Alberico GAMBINO
-Italy
-European Conservatives and Reformists Group
-257097
-FRATELLI D' ITALIA
-
-
-Iratxe GARCĆA PĆREZ
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-28298
-Partido Socialista Obrero EspaƱol
-
-
-Raquel GARCĆA HERMIDA-VAN DER WALLE
-Netherlands
-Renew Europe Group
-256970
-Democraten 66
-
-
-Jean-Paul GARRAUD
-France
-Patriots for Europe Group
-197628
-Rassemblement national
-
-
-Kamila GASIUK-PIHOWICZ
-Poland
-Group of the European People's Party (Christian Democrats)
-257032
-Platforma Obywatelska
-
-
-Geadis GEADI
-Cyprus
-European Conservatives and Reformists Group
-256986
-ĪĪøĪ½Ī¹ĪŗĻ ĪαĻĪŗĻ ĪĪĻĻĻĪæ
-
-
-Hanna GEDIN
-Sweden
-The Left group in the European Parliament - GUE/NGL
-257092
-VƤnsterpartiet
-
-
-Alexandra GEESE
-Germany
-Group of the Greens/European Free Alliance
-183916
-Bündnis 90/Die Grünen
-
-
-Jens GEIER
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-96833
-Sozialdemokratische Partei Deutschlands
-
-
-Thomas GEISEL
-Germany
-Non-attached Members
-256939
-Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
-
-
-Chiara GEMMA
-Italy
-European Conservatives and Reformists Group
-197794
-FRATELLI D' ITALIA
-
-
-Giorgos GEORGIOU
-Cyprus
-The Left group in the European Parliament - GUE/NGL
-197416
-Progressive Party of Working People - Left - New Forces
-
-
-Gerben-Jan GERBRANDY
-Netherlands
-Renew Europe Group
-96940
-Democraten 66
-
-
-Jean-Marc GERMAIN
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256901
-Parti socialiste
-
-
-Gabriella GERZSENYI
-Hungary
-Group of the European People's Party (Christian Democrats)
-256866
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Niels GEUKING
-Germany
-Group of the European People's Party (Christian Democrats)
-251874
-Familien-Partei Deutschlands
-
-
-Jens GIESEKE
-Germany
-Group of the European People's Party (Christian Democrats)
-124807
-Christlich Demokratische Union Deutschlands
-
-
-Borja GIMĆNEZ LARRAZ
-Spain
-Group of the European People's Party (Christian Democrats)
-125204
-Partido Popular
-
-
-Juan Carlos GIRAUTA VIDAL
-Spain
-Patriots for Europe Group
-125052
-VOX
-
-
-SunÄana GLAVAK
-Croatia
-Group of the European People's Party (Christian Democrats)
-202036
-Hrvatska demokratska zajednica
-
-
-Andreas GLĆCK
-Germany
-Renew Europe Group
-197443
-Freie Demokratische Partei
-
-
-Raphaƫl GLUCKSMANN
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197694
-Place publique
-
-
-Charles GOERENS
-Luxembourg
-Renew Europe Group
-840
-Parti dƩmocratique
-
-
-Christophe GOMART
-France
-Group of the European People's Party (Christian Democrats)
-256919
-Les RƩpublicains
-
-
-Isilda GOMES
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257075
-Partido Socialista
-
-
-Sandra GĆMEZ LĆPEZ
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256997
-Partido Socialista Obrero EspaƱol
-
-
-Bruno GONĆALVES
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257059
-Partido Socialista
-
-
-SĆ©rgio GONĆALVES
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257079
-Partido Socialista
-
-
-NicolĆ”s GONZĆLEZ CASARES
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197718
-Partido Socialista Obrero EspaƱol
-
-
-Esteban GONZĆLEZ PONS
-Spain
-Group of the European People's Party (Christian Democrats)
-125027
-Partido Popular
-
-
-Giorgio GORI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257102
-Partito Democratico
-
-
-MaÅgorzata GOSIEWSKA
-Poland
-European Conservatives and Reformists Group
-257055
-Prawo i SprawiedliwoÅÄ
-
-
-Dirk GOTINK
-Netherlands
-Group of the European People's Party (Christian Democrats)
-97399
-Nieuw Sociaal Contract
-
-
-Sandro GOZI
-France
-Renew Europe Group
-204419
-Mouvement DƩmocrate
-
-
-Maria GRAPINI
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124785
-Partidul Social Democrat
-
-
-Petras GRAŽULIS
-Lithuania
-Europe of Sovereign Nations Group
-256808
-Tautos ir teisingumo sÄ
junga
-
-
-MarkĆ©ta GREGOROVĆ
-Czechia
-Group of the Greens/European Free Alliance
-197549
-PIRĆTI
-
-
-Branko GRIMS
-Slovenia
-Group of the European People's Party (Christian Democrats)
-220908
-Slovenska demokratska stranka
-
-
-Catherine GRISET
-France
-Patriots for Europe Group
-94649
-Rassemblement national
-
-
-Hanna GRONKIEWICZ-WALTZ
-Poland
-Group of the European People's Party (Christian Democrats)
-262021
-Platforma Obywatelska
-
-
-Bart GROOTHUIS
-Netherlands
-Renew Europe Group
-197780
-Volkspartij voor Vrijheid en Democratie
-
-
-Elisabeth GROSSMANN
-Austria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256830
-Sozialdemokratische Partei Ćsterreichs
-
-
-Christophe GRUDLER
-France
-Renew Europe Group
-197557
-Mouvement DƩmocrate
-
-
-Elisabetta GUALMINI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197618
-Partito Democratico
-
-
-Cristina GUARDA
-Italy
-Group of the Greens/European Free Alliance
-257130
-Europa Verde - Verdi
-
-
-Bernard GUETTA
-France
-Renew Europe Group
-197543
-Sans parti
-
-
-Maria GUZENINA
-Finland
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256803
-Suomen Sosialidemokraattinen Puolue/Finlands Socialdemokratiska Parti
-
-
-EnikÅ GYÅRI
-Hungary
-Patriots for Europe Group
-96830
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-AndrĆ”s GYĆRK
-Hungary
-Patriots for Europe Group
-23816
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Michalis HADJIPANTELA
-Cyprus
-Group of the European People's Party (Christian Democrats)
-256985
-Democratic Rally
-
-
-Svenja HAHN
-Germany
-Renew Europe Group
-197444
-Freie Demokratische Partei
-
-
-Roman HAIDER
-Austria
-Patriots for Europe Group
-198176
-Freiheitliche Partei Ćsterreichs
-
-
-Andrzej HALICKI
-Poland
-Group of the European People's Party (Christian Democrats)
-197514
-Platforma Obywatelska
-
-
-Niels Flemming HANSEN
-Denmark
-Group of the European People's Party (Christian Democrats)
-257033
-Det Konservative Folkeparti
-
-
-Rima HASSAN
-France
-The Left group in the European Parliament - GUE/NGL
-256912
-La France Insoumise
-
-
-Gerald HAUSER
-Austria
-Patriots for Europe Group
-256842
-Freiheitliche Partei Ćsterreichs
-
-
-Martin HĆUSLING
-Germany
-Group of the Greens/European Free Alliance
-96752
-Bündnis 90/Die Grünen
-
-
-Mircea-Gheorghe HAVA
-Romania
-Group of the European People's Party (Christian Democrats)
-197646
-Partidul Naţional Liberal
-
-
-ValƩrie HAYER
-France
-Renew Europe Group
-135511
-Renaissance
-
-
-Anja HAZEKAMP
-Netherlands
-The Left group in the European Parliament - GUE/NGL
-125023
-Partij voor de Dieren
-
-
-Hannes HEIDE
-Austria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197682
-Sozialdemokratische Partei Ćsterreichs
-
-
-Eero HEINĆLUOMA
-Finland
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197800
-Suomen Sosialidemokraattinen Puolue/Finlands Socialdemokratiska Parti
-
-
-Anna-Maja HENRIKSSON
-Finland
-Renew Europe Group
-198073
-Svenska folkpartiet
-
-
-Niclas HERBST
-Germany
-Group of the European People's Party (Christian Democrats)
-197412
-Christlich Demokratische Union Deutschlands
-
-
-Esther HERRANZ GARCĆA
-Spain
-Group of the European People's Party (Christian Democrats)
-22418
-Partido Popular
-
-
-Krzysztof HETMAN
-Poland
-Group of the European People's Party (Christian Democrats)
-124895
-Polskie Stronnictwo Ludowe
-
-
-Monika HOHLMEIER
-Germany
-Group of the European People's Party (Christian Democrats)
-96780
-Christlich-Soziale Union in Bayern e.V.
-
-
-Martin HOJSĆK
-Slovakia
-Renew Europe Group
-197770
-ProgresĆvne Slovensko
-
-
-PƤr HOLMGREN
-Sweden
-Group of the Greens/European Free Alliance
-197398
-Miljƶpartiet de grƶna
-
-
-Gyƶrgy HĆLVĆNYI
-Hungary
-Patriots for Europe Group
-124715
-KeresztƩnydemokrata NƩppƔrt
-
-
-Alicia HOMS GINEL
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-122978
-Partido Socialista Obrero EspaƱol
-
-
-SƩrgio HUMBERTO
-Portugal
-Group of the European People's Party (Christian Democrats)
-257065
-AlianƧa DemocrƔtica
-
-
-Ivars IJABS
-Latvia
-Renew Europe Group
-197624
-Latvijas attīstībai
-
-
-CƩline IMART
-France
-Group of the European People's Party (Christian Democrats)
-256918
-Les RƩpublicains
-
-
-Evin INCIR
-Sweden
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197392
-Arbetarepartiet- Socialdemokraterna
-
-
-Paolo INSELVINI
-Italy
-European Conservatives and Reformists Group
-257144
-FRATELLI D' ITALIA
-
-
-Diana IOVANOVICI ÅOÅOACÄ
-Romania
-Non-attached Members
-257120
-S.O.S. România
-
-
-Patryk JAKI
-Poland
-European Conservatives and Reformists Group
-197516
-Solidarna Polska Zbigniewa Ziobro
-
-
-Hana JALLOUL MURO
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256992
-Partido Socialista Obrero EspaƱol
-
-
-France JAMET
-France
-Patriots for Europe Group
-189065
-Rassemblement national
-
-
-Adam JARUBAS
-Poland
-Group of the European People's Party (Christian Democrats)
-197517
-Polskie Stronnictwo Ludowe
-
-
-Romana JERKOVIÄ
-Croatia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-112747
-Socijaldemokratska partija Hrvatske
-
-
-Marc JONGEN
-Germany
-Europe of Sovereign Nations Group
-256942
-Alternative für Deutschland
-
-
-Dariusz JOÅSKI
-Poland
-Group of the European People's Party (Christian Democrats)
-257031
-Inicjatywa Polska
-
-
-Virginie JORON
-France
-Patriots for Europe Group
-197627
-Rassemblement national
-
-
-Pierre JOUVET
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256898
-Parti socialiste
-
-
-Irena JOVEVA
-Slovenia
-Renew Europe Group
-197447
-Gibanje Svoboda
-
-
-Rasa JUKNEVIÄIENÄ
-Lithuania
-Group of the European People's Party (Christian Democrats)
-197840
-TÄvynÄs sÄ
junga-Lietuvos krikÅ”Äionys demokratai
-
-
-Nora JUNCO GARCĆA
-Spain
-European Conservatives and Reformists Group
-257022
-Independiente
-
-
-Alexander JUNGBLUTH
-Germany
-Europe of Sovereign Nations Group
-256941
-Alternative für Deutschland
-
-
-Taner KABILOV
-Bulgaria
-Non-attached Members
-257256
-Movement for Rights and Freedoms
-
-
-FranƧois KALFON
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256908
-Parti socialiste
-
-
-Erik KALIÅĆK
-Slovakia
-Non-attached Members
-257007
-SMER-SociƔlna demokracia
-
-
-Marina KALJURAND
-Estonia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197491
-Sotsiaaldemokraatlik Erakond
-
-
-Sandra KALNIETE
-Latvia
-Group of the European People's Party (Christian Democrats)
-96934
-JaunÄ VienotÄ«ba
-
-
-Mariusz KAMIÅSKI
-Poland
-European Conservatives and Reformists Group
-257056
-Prawo i SprawiedliwoÅÄ
-
-
-Radan KANEV
-Bulgaria
-Group of the European People's Party (Christian Democrats)
-197839
-Democrats for Strong Bulgaria
-
-
-Assita KANKO
-Belgium
-European Conservatives and Reformists Group
-197469
-Nieuw-Vlaamse Alliantie
-
-
-Karin KARLSBRO
-Sweden
-Renew Europe Group
-197401
-Liberalerna
-
-
-Fernand KARTHEISER
-Luxembourg
-Non-attached Members
-256900
-Alternativ Demokratesch Reformpartei
-
-
-Ľubica KARVAÅ OVĆ
-Slovakia
-Renew Europe Group
-257013
-ProgresĆvne Slovensko
-
-
-Elsi KATAINEN
-Finland
-Renew Europe Group
-191693
-Suomen Keskusta
-
-
-Emmanouil KEFALOGIANNIS
-Greece
-Group of the European People's Party (Christian Democrats)
-125068
-Nea Demokratia
-
-
-Billy KELLEHER
-Ireland
-Renew Europe Group
-197818
-Fianna FƔil Party
-
-
-Fabienne KELLER
-France
-Renew Europe Group
-22858
-Renaissance
-
-
-SeƔn KELLY
-Ireland
-Group of the European People's Party (Christian Democrats)
-96668
-Fine Gael Party
-
-
-Martine KEMP
-Luxembourg
-Group of the European People's Party (Christian Democrats)
-249603
-Parti chrƩtien social luxembourgeois
-
-
-Rudi KENNES
-Belgium
-The Left group in the European Parliament - GUE/NGL
-256890
-Independent
-
-
-Mary KHAN
-Germany
-Europe of Sovereign Nations Group
-256957
-Alternative für Deutschland
-
-
-Sophia KIRCHER
-Austria
-Group of the European People's Party (Christian Democrats)
-256831
-Ćsterreichische Volkspartei
-
-
-Sarah KNAFO
-France
-Europe of Sovereign Nations Group
-256924
-ReconquĆŖte!
-
-
-OndÅej KNOTEK
-Czechia
-Patriots for Europe Group
-197528
-ANO 2011
-
-
-MichaÅ KOBOSKO
-Poland
-Renew Europe Group
-257037
-Polska 2050
-
-
-Stefan KĆHLER
-Germany
-Group of the European People's Party (Christian Democrats)
-256973
-Christlich-Soziale Union in Bayern e.V.
-
-
-Åukasz KOHUT
-Poland
-Group of the European People's Party (Christian Democrats)
-197523
-Independent
-
-
-Arba KOKALARI
-Sweden
-Group of the European People's Party (Christian Democrats)
-197406
-Moderaterna
-
-
-OndÅej KOLĆÅ
-Czechia
-Group of the European People's Party (Christian Democrats)
-256846
-TOP 09 a StarostovƩ
-
-
-Kinga KOLLĆR
-Hungary
-Group of the European People's Party (Christian Democrats)
-256861
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Rihards KOLS
-Latvia
-European Conservatives and Reformists Group
-220871
-NacionÄlÄ apvienÄ«ba "Visu Latvijai!" - "TÄvzemei un BrÄ«vÄ«bai/LNNK"
-
-
-KateÅina KONEÄNĆ
-Czechia
-Non-attached Members
-23699
-KomunistickĆ” strana Äech a Moravy
-
-
-Ewa KOPACZ
-Poland
-Group of the European People's Party (Christian Democrats)
-197525
-Platforma Obywatelska
-
-
-Moritz KĆRNER
-Germany
-Renew Europe Group
-197445
-Freie Demokratische Partei
-
-
-Elena KOUNTOURA
-Greece
-The Left group in the European Parliament - GUE/NGL
-197699
-Coalition of the Radical Left
-
-
-Andrey KOVATCHEV
-Bulgaria
-Group of the European People's Party (Christian Democrats)
-97968
-Citizens for European Development of Bulgaria
-
-
-Vilis KRIÅ TOPANS
-Latvia
-Patriots for Europe Group
-256909
-Latvija pirmajÄ vietÄ
-
-
-Sebastian KRUIS
-Netherlands
-Patriots for Europe Group
-256996
-Partij voor de Vrijheid
-
-
-OndÅej KRUTĆLEK
-Czechia
-European Conservatives and Reformists Group
-256845
-ObÄanskĆ” demokratickĆ” strana
-
-
-TomÔŔ KUBĆN
-Czechia
-Patriots for Europe Group
-261038
-ANO 2011
-
-
-Alice KUHNKE
-Sweden
-Group of the Greens/European Free Alliance
-197395
-Miljƶpartiet de grƶna
-
-
-AndrƔs Tivadar KULJA
-Hungary
-Group of the European People's Party (Christian Democrats)
-256864
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Katri KULMUNI
-Finland
-Renew Europe Group
-198084
-Suomen Keskusta
-
-
-Merja KYLLĆNEN
-Finland
-The Left group in the European Parliament - GUE/NGL
-124736
-Vasemmistoliitto
-
-
-Ilhan KYUCHYUK
-Bulgaria
-Renew Europe Group
-124866
-Movement for Rights and Freedoms
-
-
-Sergey LAGODINSKY
-Germany
-Group of the Greens/European Free Alliance
-197460
-Bündnis 90/Die Grünen
-
-
-Eszter LAKOS
-Hungary
-Group of the European People's Party (Christian Democrats)
-256865
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Aurore LALUCQ
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197697
-Place publique
-
-
-Bernd LANGE
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-1909
-Sozialdemokratische Partei Deutschlands
-
-
-Katrin LANGENSIEPEN
-Germany
-Group of the Greens/European Free Alliance
-197461
-Bündnis 90/Die Grünen
-
-
-Judita LAÅ Å ĆKOVĆ
-Slovakia
-Non-attached Members
-198373
-SMER-SociƔlna demokracia
-
-
-AndrĆ”s LĆSZLĆ
-Hungary
-Patriots for Europe Group
-256860
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Afroditi LATINOPOULOU
-Greece
-Patriots for Europe Group
-256954
-FonĆ LoyikĆs
-
-
-Murielle LAURENT
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256899
-Parti socialiste
-
-
-Camilla LAURETI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-230085
-Partito Democratico
-
-
-Rada LAYKOVA
-Bulgaria
-Europe of Sovereign Nations Group
-257262
-Revival
-
-
-Ilia LAZAROV
-Bulgaria
-Group of the European People's Party (Christian Democrats)
-257261
-Union of Democratic Forces
-
-
-Luis-VicenČiu LAZARUS
-Romania
-Non-attached Members
-257118
-S.O.S. România
-
-
-Isabelle LE CALLENNEC
-France
-Group of the European People's Party (Christian Democrats)
-256920
-Les RƩpublicains
-
-
-Fabrice LEGGERI
-France
-Patriots for Europe Group
-256872
-Rassemblement national
-
-
-Jeroen LENAERS
-Netherlands
-Group of the European People's Party (Christian Democrats)
-95074
-Christen Democratisch AppĆØl
-
-
-Julien LEONARDELLI
-France
-Patriots for Europe Group
-256895
-Rassemblement national
-
-
-Janusz LEWANDOWSKI
-Poland
-Group of the European People's Party (Christian Democrats)
-23781
-Platforma Obywatelska
-
-
-Miriam LEXMANN
-Slovakia
-Group of the European People's Party (Christian Democrats)
-204336
-Kresńanskodemokratické hnutie
-
-
-Peter LIESE
-Germany
-Group of the European People's Party (Christian Democrats)
-1927
-Christlich Demokratische Union Deutschlands
-
-
-Norbert LINS
-Germany
-Group of the European People's Party (Christian Democrats)
-124808
-Christlich Demokratische Union Deutschlands
-
-
-Nathalie LOISEAU
-France
-Renew Europe Group
-197494
-Horizons
-
-
-Morten LĆKKEGAARD
-Denmark
-Renew Europe Group
-96709
-Venstre, Danmarks Liberale Parti
-
-
-Reinhold LOPATKA
-Austria
-Group of the European People's Party (Christian Democrats)
-220896
-Ćsterreichische Volkspartei
-
-
-Javi LĆPEZ
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-125042
-Partit dels Socialistes de Catalunya (PSC-PSOE)
-
-
-Juan Fernando LĆPEZ AGUILAR
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-96812
-Partido Socialista Obrero EspaƱol
-
-
-Antonio LĆPEZ-ISTĆRIZ WHITE
-Spain
-Group of the European People's Party (Christian Democrats)
-28399
-Partido Popular
-
-
-Isabella LĆVIN
-Sweden
-Group of the Greens/European Free Alliance
-96675
-Miljƶpartiet de grƶna
-
-
-Mimmo LUCANO
-Italy
-The Left group in the European Parliament - GUE/NGL
-257129
-Alleanza Verdi e Sinistra
-
-
-CƩsar LUENA
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197721
-Partido Socialista Obrero EspaƱol
-
-
-Elżbieta Katarzyna ÅUKACIJEWSKA
-Poland
-Group of the European People's Party (Christian Democrats)
-96791
-Platforma Obywatelska
-
-
-Giuseppe LUPO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257124
-Partito Democratico
-
-
-David MCALLISTER
-Germany
-Group of the European People's Party (Christian Democrats)
-124806
-Christlich Demokratische Union Deutschlands
-
-
-Jaak MADISON
-Estonia
-European Conservatives and Reformists Group
-197493
-Eesti Keskerakond
-
-
-Cristina MAESTRE
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197719
-Partido Socialista Obrero EspaƱol
-
-
-Lara MAGONI
-Italy
-European Conservatives and Reformists Group
-257149
-FRATELLI D' ITALIA
-
-
-PƩter MAGYAR
-Hungary
-Group of the European People's Party (Christian Democrats)
-256868
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Marit MAIJ
-Netherlands
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-91636
-GroenLinks-PvdA
-
-
-Marlena MALÄG
-Poland
-European Conservatives and Reformists Group
-257077
-Prawo i SprawiedliwoÅÄ
-
-
-Claudiu MANDA
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197653
-Partidul Social Democrat
-
-
-Lukas MANDL
-Austria
-Group of the European People's Party (Christian Democrats)
-190713
-Ćsterreichische Volkspartei
-
-
-Yannis MANIATIS
-Greece
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256824
-PASOK-KINAL
-
-
-Mario MANTOVANI
-Italy
-European Conservatives and Reformists Group
-4395
-FRATELLI D' ITALIA
-
-
-Pierfrancesco MARAN
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257727
-Partito Democratico
-
-
-Jagna MARCZUÅAJTIS-WALCZAK
-Poland
-Group of the European People's Party (Christian Democrats)
-257082
-Platforma Obywatelska
-
-
-Marion MARĆCHAL
-France
-European Conservatives and Reformists Group
-256922
-IdentitƩ LibertƩs
-
-
-Thierry MARIANI
-France
-Patriots for Europe Group
-197623
-Rassemblement national
-
-
-Ignazio Roberto MARINO
-Italy
-Group of the Greens/European Free Alliance
-257132
-Independent
-
-
-Erik MARQUARDT
-Germany
-Group of the Greens/European Free Alliance
-197462
-Bündnis 90/Die Grünen
-
-
-Jorge MARTĆN FRĆAS
-Spain
-Patriots for Europe Group
-257029
-VOX
-
-
-Catarina MARTINS
-Portugal
-The Left group in the European Parliament - GUE/NGL
-257063
-Bloco de Esquerda
-
-
-Fulvio MARTUSCIELLO
-Italy
-Group of the European People's Party (Christian Democrats)
-124828
-Forza Italia
-
-
-Vicent MARZĆ IBĆĆEZ
-Spain
-Group of the Greens/European Free Alliance
-257016
-CompromĆs
-
-
-Gabriel MATO
-Spain
-Group of the European People's Party (Christian Democrats)
-96936
-Partido Popular
-
-
-Sara MATTHIEU
-Belgium
-Group of the Greens/European Free Alliance
-208722
-Groen
-
-
-Costas MAVRIDES
-Cyprus
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124691
-Democratic Party
-
-
-Eva MAYDELL
-Bulgaria
-Group of the European People's Party (Christian Democrats)
-98341
-Citizens for European Development of Bulgaria
-
-
-Georg MAYER
-Austria
-Patriots for Europe Group
-38511
-Freiheitliche Partei Ćsterreichs
-
-
-Milan MAZUREK
-Slovakia
-Europe of Sovereign Nations Group
-249982
-Hnutie Republika
-
-
-Liudas MAŽYLIS
-Lithuania
-Group of the European People's Party (Christian Democrats)
-197841
-TÄvynÄs sÄ
junga-Lietuvos krikÅ”Äionys demokratai
-
-
-Michael MCNAMARA
-Ireland
-Renew Europe Group
-257300
-Independent
-
-
-Nora MEBAREK
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-204418
-Parti socialiste
-
-
-Alexandra MEHNERT
-Germany
-Group of the European People's Party (Christian Democrats)
-256980
-Christlich Demokratische Union Deutschlands
-
-
-Vangelis MEIMARAKIS
-Greece
-Group of the European People's Party (Christian Democrats)
-197662
-Nea Demokratia
-
-
-Eleonora MELETI
-Greece
-Group of the European People's Party (Christian Democrats)
-256943
-Nea Demokratia
-
-
-Ana Catarina MENDES
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257053
-Partido Socialista
-
-
-Idoia MENDIA
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256994
-Partido Socialista Obrero EspaƱol
-
-
-Verena MERTENS
-Germany
-Group of the European People's Party (Christian Democrats)
-256974
-Christlich Demokratische Union Deutschlands
-
-
-Marina MESURE
-France
-The Left group in the European Parliament - GUE/NGL
-236053
-La France Insoumise
-
-
-Roberta METSOLA
-Malta
-Group of the European People's Party (Christian Democrats)
-118859
-Partit Nazzjonalista
-
-
-Tilly METZ
-Luxembourg
-Group of the Greens/European Free Alliance
-193292
-DƩi GrƩng - Les Verts
-
-
-Sven MIKSER
-Estonia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197497
-Sotsiaaldemokraatlik Erakond
-
-
-Giuseppe MILAZZO
-Italy
-European Conservatives and Reformists Group
-197824
-FRATELLI D' ITALIA
-
-
-Francisco JosĆ© MILLĆN MON
-Spain
-Group of the European People's Party (Christian Democrats)
-28400
-Partido Popular
-
-
-Nikola MINCHEV
-Bulgaria
-Renew Europe Group
-257259
-We continue the change ā Democratic Bulgaria
-
-
-Ana MIRANDA PAZ
-Spain
-Group of the Greens/European Free Alliance
-24942
-Bloque Nacionalista Galego
-
-
-Csaba MOLNĆR
-Hungary
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124722
-Demokratikus KoalĆció
-
-
-Irene MONTERO
-Spain
-The Left group in the European Parliament - GUE/NGL
-245770
-PODEMOS
-
-
-Dolors MONTSERRAT
-Spain
-Group of the European People's Party (Christian Democrats)
-197711
-Partido Popular
-
-
-Carolina MORACE
-Italy
-The Left group in the European Parliament - GUE/NGL
-257140
-Movimento 5 Stelle
-
-
-Nadine MORANO
-France
-Group of the European People's Party (Christian Democrats)
-72779
-Les RƩpublicains
-
-
-Letizia MORATTI
-Italy
-Group of the European People's Party (Christian Democrats)
-257151
-Forza Italia
-
-
-Tiago MOREIRA DE SĆ
-Portugal
-Patriots for Europe Group
-257054
-Chega
-
-
-Javier MORENO SĆNCHEZ
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-28347
-Partido Socialista Obrero EspaƱol
-
-
-Alessandra MORETTI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124799
-Partito Democratico
-
-
-Dan-Åtefan MOTREANU
-Romania
-Group of the European People's Party (Christian Democrats)
-197647
-Partidul Naţional Liberal
-
-
-Arkadiusz MULARCZYK
-Poland
-European Conservatives and Reformists Group
-257060
-Prawo i SprawiedliwoÅÄ
-
-
-Piotr MĆLLER
-Poland
-European Conservatives and Reformists Group
-257080
-Prawo i SprawiedliwoÅÄ
-
-
-Ciaran MULLOOLY
-Ireland
-Renew Europe Group
-257298
-Independent
-
-
-Siegfried MUREÅAN
-Romania
-Group of the European People's Party (Christian Democrats)
-124802
-Partidul Naţional Liberal
-
-
-Åtefan MUÅOIU
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257103
-Partidul Social Democrat
-
-
-Jana NAGYOVĆ
-Czechia
-Patriots for Europe Group
-256843
-ANO 2011
-
-
-Dario NARDELLA
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257111
-Partito Democratico
-
-
-Fernando NAVARRETE ROJAS
-Spain
-Group of the European People's Party (Christian Democrats)
-257027
-Partido Popular
-
-
-Victor NEGRESCU
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-88882
-Partidul Social Democrat
-
-
-Matjaž NEMEC
-Slovenia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-233862
-Socialni demokrati
-
-
-DanuÅ”e NERUDOVĆ
-Czechia
-Group of the European People's Party (Christian Democrats)
-256847
-StarostovƩ a nezƔvisli
-
-
-Denis NESCI
-Italy
-European Conservatives and Reformists Group
-239260
-FRATELLI D' ITALIA
-
-
-Hans NEUHOFF
-Germany
-Europe of Sovereign Nations Group
-256944
-Alternative für Deutschland
-
-
-Hannah NEUMANN
-Germany
-Group of the Greens/European Free Alliance
-197464
-Bündnis 90/Die Grünen
-
-
-Elena NEVADO DEL CAMPO
-Spain
-Group of the European People's Party (Christian Democrats)
-257039
-Partido Popular
-
-
-Dan NICA
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124784
-Partidul Social Democrat
-
-
-Angelika NIEBLER
-Germany
-Group of the European People's Party (Christian Democrats)
-4289
-Christlich-Soziale Union in Bayern e.V.
-
-
-LudÄk NIEDERMAYER
-Czechia
-Group of the European People's Party (Christian Democrats)
-124701
-TOP 09 a StarostovƩ
-
-
-Ville NIINISTĆ
-Finland
-Group of the Greens/European Free Alliance
-197802
-VihreƤ liitto
-
-
-Lefteris NIKOLAOU-ALAVANOS
-Greece
-Non-attached Members
-197734
-Communist Party of Greece
-
-
-Aleksandar NIKOLIC
-France
-Patriots for Europe Group
-256883
-Rassemblement national
-
-
-Cynthia NĆ MHURCHĆ
-Ireland
-Renew Europe Group
-257301
-Fianna FƔil Party
-
-
-Maria NOICHL
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124836
-Sozialdemokratische Partei Deutschlands
-
-
-Rasmus NORDQVIST
-Denmark
-Group of the Greens/European Free Alliance
-257044
-Socialistisk Folkeparti
-
-
-Andrey NOVAKOV
-Bulgaria
-Group of the European People's Party (Christian Democrats)
-107212
-Citizens for European Development of Bulgaria
-
-
-MirosÅawa NYKIEL
-Poland
-Group of the European People's Party (Christian Democrats)
-257049
-Platforma Obywatelska
-
-
-Daniel OBAJTEK
-Poland
-European Conservatives and Reformists Group
-257058
-Prawo i SprawiedliwoÅÄ
-
-
-ĽudovĆt ĆDOR
-Slovakia
-Renew Europe Group
-257010
-ProgresĆvne Slovensko
-
-
-Jan-Christoph OETJEN
-Germany
-Renew Europe Group
-197432
-Freie Demokratische Partei
-
-
-Maria OHISALO
-Finland
-Group of the Greens/European Free Alliance
-198076
-VihreƤ liitto
-
-
-João OLIVEIRA
-Portugal
-The Left group in the European Parliament - GUE/NGL
-257083
-Partido Comunista PortuguĆŖs
-
-
-Philippe OLIVIER
-France
-Patriots for Europe Group
-197687
-Rassemblement national
-
-
-Younous OMARJEE
-France
-The Left group in the European Parliament - GUE/NGL
-30482
-La France Insoumise
-
-
-Branislav ONDRUÅ
-Slovakia
-Non-attached Members
-257018
-Hlas ā sociĆ”lna demokracia
-
-
-AodhĆ”n Ć RĆORDĆIN
-Ireland
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257238
-Labour Party
-
-
-Leoluca ORLANDO
-Italy
-Group of the Greens/European Free Alliance
-2152
-Independent
-
-
-Jacek OZDOBA
-Poland
-European Conservatives and Reformists Group
-257086
-Prawo i SprawiedliwoÅÄ
-
-
-Urmas PAET
-Estonia
-Renew Europe Group
-129073
-Eesti Reformierakond
-
-
-Leire PAJĆN
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256993
-Partido Socialista Obrero EspaƱol
-
-
-Valentina PALMISANO
-Italy
-The Left group in the European Parliament - GUE/NGL
-257135
-Movimento 5 Stelle
-
-
-Fidias PANAYIOTOU
-Cyprus
-Non-attached Members
-256989
-Independent
-
-
-Kostas PAPADAKIS
-Greece
-Non-attached Members
-125093
-Communist Party of Greece
-
-
-Nikos PAPANDREOU
-Greece
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-244571
-PASOK-KINAL
-
-
-Nikos PAPPAS
-Greece
-The Left group in the European Parliament - GUE/NGL
-256952
-Coalition of the Radical Left
-
-
-NicolƔs PASCUAL DE LA PARTE
-Spain
-Group of the European People's Party (Christian Democrats)
-257040
-Partido Popular
-
-
-Aldo PATRICIELLO
-Italy
-Patriots for Europe Group
-36392
-Lega
-
-
-Jutta PAULUS
-Germany
-Group of the Greens/European Free Alliance
-197466
-Bündnis 90/Die Grünen
-
-
-Ana Miguel PEDRO
-Portugal
-Group of the European People's Party (Christian Democrats)
-110673
-Partido do Centro DemocrƔtico Social-Partido Popular
-
-
-Gaetano PEDULLA'
-Italy
-The Left group in the European Parliament - GUE/NGL
-257126
-Movimento 5 Stelle
-
-
-Thomas PELLERIN-CARLIN
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256903
-Place publique
-
-
-Guillaume PELTIER
-France
-European Conservatives and Reformists Group
-30123
-IdentitƩ LibertƩs
-
-
-Tsvetelina PENKOVA
-Bulgaria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197845
-Bulgarian Socialist Party
-
-
-Gilles PENNELLE
-France
-Patriots for Europe Group
-126699
-Rassemblement national
-
-
-LĆdia PEREIRA
-Portugal
-Group of the European People's Party (Christian Democrats)
-197738
-Partido Social Democrata
-
-
-Alvise PĆREZ
-Spain
-Non-attached Members
-257019
-Se Acabó la Fiesta
-
-
-Kira Marie PETER-HANSEN
-Denmark
-Group of the Greens/European Free Alliance
-197573
-Socialistisk Folkeparti
-
-
-Hristo PETROV
-Bulgaria
-Renew Europe Group
-257257
-We continue the change ā Democratic Bulgaria
-
-
-Michele PICARO
-Italy
-European Conservatives and Reformists Group
-257150
-FRATELLI D' ITALIA
-
-
-Pina PICIERNO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-124846
-Partito Democratico
-
-
-Tonino PICULA
-Croatia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-112744
-Socijaldemokratska partija Hrvatske
-
-
-Pascale PIERA
-France
-Patriots for Europe Group
-256877
-Rassemblement national
-
-
-Sirpa PIETIKĆINEN
-Finland
-Group of the European People's Party (Christian Democrats)
-40599
-Kansallinen Kokoomus
-
-
-Pierre PIMPIE
-France
-Patriots for Europe Group
-256893
-Rassemblement national
-
-
-Gheorghe PIPEREA
-Romania
-European Conservatives and Reformists Group
-257115
-AlianČa pentru Unirea RomĆ¢nilor
-
-
-Margarita DE LA PISA CARRIĆN
-Spain
-Patriots for Europe Group
-204414
-VOX
-
-
-Jaroslava POKORNĆ JERMANOVĆ
-Czechia
-Patriots for Europe Group
-256844
-ANO 2011
-
-
-Daniele POLATO
-Italy
-European Conservatives and Reformists Group
-257145
-FRATELLI D' ITALIA
-
-
-Jessica POLFJĆRD
-Sweden
-Group of the European People's Party (Christian Democrats)
-197404
-Moderaterna
-
-
-Virgil-Daniel POPESCU
-Romania
-Group of the European People's Party (Christian Democrats)
-257107
-Partidul Naţional Liberal
-
-
-Reinis POZÅ
AKS
-Latvia
-European Conservatives and Reformists Group
-256907
-Apvienotais saraksts ā Latvijas ZaÄ¼Ä partija, Latvijas ReÄ£ionu ApvienÄ«ba, LiepÄjas partija
-
-
-Vladimir PREBILIÄ
-Slovenia
-Group of the Greens/European Free Alliance
-256813
-Vesna ā zelena stranka
-
-
-Giusi PRINCI
-Italy
-Group of the European People's Party (Christian Democrats)
-257128
-Forza Italia
-
-
-Nicola PROCACCINI
-Italy
-European Conservatives and Reformists Group
-197820
-FRATELLI D' ITALIA
-
-
-Jacek PROTAS
-Poland
-Group of the European People's Party (Christian Democrats)
-257041
-Platforma Obywatelska
-
-
-Friedrich PĆRNER
-Germany
-Non-attached Members
-256969
-Independent
-
-
-Carola RACKETE
-Germany
-The Left group in the European Parliament - GUE/NGL
-256927
-Independent
-
-
-Emil RADEV
-Bulgaria
-Group of the European People's Party (Christian Democrats)
-124850
-Citizens for European Development of Bulgaria
-
-
-Dennis RADTKE
-Germany
-Group of the European People's Party (Christian Democrats)
-188945
-Christlich Demokratische Union Deutschlands
-
-
-Emma RAFOWICZ
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256902
-Parti socialiste
-
-
-Jüri RATAS
-Estonia
-Group of the European People's Party (Christian Democrats)
-188096
-Isamaa
-
-
-Ruggero RAZZA
-Italy
-European Conservatives and Reformists Group
-257104
-FRATELLI D' ITALIA
-
-
-Julie RECHAGNEUX
-France
-Patriots for Europe Group
-256882
-Rassemblement national
-
-
-Evelyn REGNER
-Austria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-96998
-Sozialdemokratische Partei Ćsterreichs
-
-
-Terry REINTKE
-Germany
-Group of the Greens/European Free Alliance
-103381
-Bündnis 90/Die Grünen
-
-
-RenƩ REPASI
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-229839
-Sozialdemokratische Partei Deutschlands
-
-
-Sabrina REPP
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256935
-Sozialdemokratische Partei Deutschlands
-
-
-Karlo RESSLER
-Croatia
-Group of the European People's Party (Christian Democrats)
-197413
-Hrvatska demokratska zajednica
-
-
-Thijs REUTEN
-Netherlands
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-218347
-GroenLinks-PvdA
-
-
-Diana RIBA I GINER
-Spain
-Group of the Greens/European Free Alliance
-197832
-Esquerra Republicana de Catalunya
-
-
-Matteo RICCI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257121
-Partito Democratico
-
-
-ChloƩ RIDEL
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256904
-Parti socialiste
-
-
-Nela RIEHL
-Germany
-Group of the Greens/European Free Alliance
-256964
-Volt
-
-
-Manuela RIPA
-Germany
-Group of the European People's Party (Christian Democrats)
-206158
-Ćkologisch-Demokratische Partei
-
-
-AndrƩ RODRIGUES
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257066
-Partido Socialista
-
-
-Marcos ROS SEMPERE
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-204413
-Partido Socialista Obrero EspaƱol
-
-
-KatarĆna ROTH NEVEÄALOVĆ
-Slovakia
-Non-attached Members
-96653
-SMER-SociƔlna demokracia
-
-
-AndrĆ© ROUGĆ
-France
-Patriots for Europe Group
-197690
-Rassemblement national
-
-
-Bert-Jan RUISSEN
-Netherlands
-European Conservatives and Reformists Group
-197773
-Staatkundig Gereformeerde Partij
-
-
-Sandro RUOTOLO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257170
-Partito Democratico
-
-
-Bogdan RZOÅCA
-Poland
-European Conservatives and Reformists Group
-197545
-Prawo i SprawiedliwoÅÄ
-
-
-Arash SAEIDI
-France
-The Left group in the European Parliament - GUE/NGL
-256911
-La France Insoumise
-
-
-Massimiliano SALINI
-Italy
-Group of the European People's Party (Christian Democrats)
-125670
-Forza Italia
-
-
-Ilaria SALIS
-Italy
-The Left group in the European Parliament - GUE/NGL
-257127
-Alleanza Verdi e Sinistra
-
-
-Aura SALLA
-Finland
-Group of the European People's Party (Christian Democrats)
-98219
-Kansallinen Kokoomus
-
-
-Nacho SĆNCHEZ AMOR
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197722
-Partido Socialista Obrero EspaƱol
-
-
-Julien SANCHEZ
-France
-Patriots for Europe Group
-88552
-Rassemblement national
-
-
-Elena SANCHO MURILLO
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257001
-Partido Socialista Obrero EspaƱol
-
-
-Jussi SARAMO
-Finland
-The Left group in the European Parliament - GUE/NGL
-127766
-Vasemmistoliitto
-
-
-Silvia SARDONE
-Italy
-Patriots for Europe Group
-197578
-Lega
-
-
-Marjan Å AREC
-Slovenia
-Renew Europe Group
-256815
-Gibanje Svoboda
-
-
-Eric SARGIACOMO
-France
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256905
-Parti socialiste
-
-
-Mounir SATOURI
-France
-Group of the Greens/European Free Alliance
-197500
-Les Ćcologistes
-
-
-Paulius SAUDARGAS
-Lithuania
-Group of the European People's Party (Christian Democrats)
-256809
-TÄvynÄs sÄ
junga-Lietuvos krikÅ”Äionys demokratai
-
-
-Majdouline SBAI
-France
-Group of the Greens/European Free Alliance
-256917
-Les Ćcologistes
-
-
-Antonella SBERNA
-Italy
-European Conservatives and Reformists Group
-257113
-FRATELLI D' ITALIA
-
-
-Christel SCHALDEMOSE
-Denmark
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-37312
-Socialdemokratiet
-
-
-ErnÅ SCHALLER-BAROSS
-Hungary
-Patriots for Europe Group
-213330
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Oliver SCHENK
-Germany
-Group of the European People's Party (Christian Democrats)
-256979
-Christlich Demokratische Union Deutschlands
-
-
-Joanna SCHEURING-WIELGUS
-Poland
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257084
-Nowa Lewica
-
-
-Andreas SCHIEDER
-Austria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197670
-Sozialdemokratische Partei Ćsterreichs
-
-
-Lena SCHILLING
-Austria
-Group of the Greens/European Free Alliance
-256833
-Die Grünen - Die Grüne Alternative
-
-
-Martin SCHIRDEWAN
-Germany
-The Left group in the European Parliament - GUE/NGL
-190517
-DIE LINKE.
-
-
-Christine SCHNEIDER
-Germany
-Group of the European People's Party (Christian Democrats)
-197422
-Christlich Demokratische Union Deutschlands
-
-
-Volker SCHNURRBUSCH
-Germany
-Europe of Sovereign Nations Group
-267485
-Alternative für Deutschland
-
-
-Andreas SCHWAB
-Germany
-Group of the European People's Party (Christian Democrats)
-28223
-Christlich Demokratische Union Deutschlands
-
-
-Benedetta SCUDERI
-Italy
-Group of the Greens/European Free Alliance
-257139
-Europa Verde - Verdi
-
-
-Ralf SEEKATZ
-Germany
-Group of the European People's Party (Christian Democrats)
-197425
-Christlich Demokratische Union Deutschlands
-
-
-Alexander SELL
-Germany
-Europe of Sovereign Nations Group
-256959
-Alternative für Deutschland
-
-
-Rosa SERRANO SIERRA
-Spain
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256999
-Partido Socialista Obrero EspaƱol
-
-
-Isabel SERRA SĆNCHEZ
-Spain
-The Left group in the European Parliament - GUE/NGL
-257009
-PODEMOS
-
-
-Günther SIDL
-Austria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197677
-Sozialdemokratische Partei Ćsterreichs
-
-
-BartÅomiej SIENKIEWICZ
-Poland
-Group of the European People's Party (Christian Democrats)
-86057
-Platforma Obywatelska
-
-
-Lukas SIEPER
-Germany
-Non-attached Members
-256971
-Partei des Fortschritts
-
-
-Sven SIMON
-Germany
-Group of the European People's Party (Christian Democrats)
-197426
-Christlich Demokratische Union Deutschlands
-
-
-Christine SINGER
-Germany
-Renew Europe Group
-256946
-Freie WƤhler
-
-
-Virginijus SINKEVIÄIUS
-Lithuania
-Group of the Greens/European Free Alliance
-201945
-Demokratų sÄ
junga āVardan Lietuvosā
-
-
-Birgit SIPPEL
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-96932
-Sozialdemokratische Partei Deutschlands
-
-
-Jonas SJĆSTEDT
-Sweden
-The Left group in the European Parliament - GUE/NGL
-2268
-VƤnsterpartiet
-
-
-Krzysztof ÅMISZEK
-Poland
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257085
-Nowa Lewica
-
-
-Anthony SMITH
-France
-The Left group in the European Parliament - GUE/NGL
-256910
-La France Insoumise
-
-
-Sander SMIT
-Netherlands
-Group of the European People's Party (Christian Democrats)
-125325
-BoerBurgerBeweging
-
-
-Tomislav SOKOL
-Croatia
-Group of the European People's Party (Christian Democrats)
-197417
-Hrvatska demokratska zajednica
-
-
-Diego SOLIER
-Spain
-European Conservatives and Reformists Group
-257021
-Independiente
-
-
-Susana SOLĆS PĆREZ
-Spain
-Group of the European People's Party (Christian Democrats)
-197784
-Partido Popular
-
-
-Liesbet SOMMEN
-Belgium
-Group of the European People's Party (Christian Democrats)
-256889
-Christen-Democratisch & Vlaams
-
-
-Martin SONNEBORN
-Germany
-Non-attached Members
-124834
-Die PARTEI
-
-
-Malika SOREL
-France
-Non-attached Members
-256871
-Sans parti
-
-
-HƩlder SOUSA SILVA
-Portugal
-Group of the European People's Party (Christian Democrats)
-257068
-Partido Social Democrata
-
-
-Villy SĆVNDAL
-Denmark
-Group of the Greens/European Free Alliance
-111412
-Socialistisk Folkeparti
-
-
-Marco SQUARTA
-Italy
-European Conservatives and Reformists Group
-257109
-FRATELLI D' ITALIA
-
-
-MÄrtiÅÅ” STAĶIS
-Latvia
-Group of the Greens/European Free Alliance
-256916
-Progresīvie
-
-
-Raffaele STANCANELLI
-Italy
-Patriots for Europe Group
-197825
-Lega
-
-
-Nicolae ČTEFÄNUČÄ
-Romania
-Group of the Greens/European Free Alliance
-58766
-Independent
-
-
-Petra STEGER
-Austria
-Patriots for Europe Group
-220897
-Freiheitliche Partei Ćsterreichs
-
-
-Davor Ivo STIER
-Croatia
-Group of the European People's Party (Christian Democrats)
-119435
-Hrvatska demokratska zajednica
-
-
-Kristoffer STORM
-Denmark
-European Conservatives and Reformists Group
-257025
-Danmarksdemokraterne
-
-
-Sebastiaan STĆTELER
-Netherlands
-Patriots for Europe Group
-256991
-Partij voor de Vrijheid
-
-
-Stanislav STOYANOV
-Bulgaria
-Europe of Sovereign Nations Group
-257255
-Revival
-
-
-Marie-Agnes STRACK-ZIMMERMANN
-Germany
-Renew Europe Group
-256926
-Freie Demokratische Partei
-
-
-Cecilia STRADA
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257101
-Partito Democratico
-
-
-Joachim STREIT
-Germany
-Renew Europe Group
-256962
-Freie WƤhler
-
-
-Tineke STRIK
-Netherlands
-Group of the Greens/European Free Alliance
-197772
-GroenLinks-PvdA
-
-
-Anna STROLENBERG
-Netherlands
-Group of the Greens/European Free Alliance
-256990
-Volt
-
-
-Åerban Dimitrie STURDZA
-Romania
-European Conservatives and Reformists Group
-257119
-Partidul AcČiunea Conservatoare
-
-
-Anna STĆRGKH
-Austria
-Renew Europe Group
-256839
-NEOS ā Das Neue Ćsterreich
-
-
-Marcin SYPNIEWSKI
-Poland
-Europe of Sovereign Nations Group
-257070
-Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
-
-
-MichaÅ SZCZERBA
-Poland
-Group of the European People's Party (Christian Democrats)
-257026
-Platforma Obywatelska
-
-
-PƔl SZEKERES
-Hungary
-Patriots for Europe Group
-256855
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Beata SZYDÅO
-Poland
-European Conservatives and Reformists Group
-197553
-Prawo i SprawiedliwoÅÄ
-
-
-Dario TAMBURRANO
-Italy
-The Left group in the European Parliament - GUE/NGL
-124813
-Movimento 5 Stelle
-
-
-António TĆNGER CORRĆA
-Portugal
-Patriots for Europe Group
-257050
-Chega
-
-
-Dominik TARCZYÅSKI
-Poland
-European Conservatives and Reformists Group
-204346
-Prawo i SprawiedliwoÅÄ
-
-
-Marco TARQUINIO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257160
-Partito Democratico
-
-
-ZoltƔn TARR
-Hungary
-Group of the European People's Party (Christian Democrats)
-256863
-Tisztelet Ʃs SzabadsƔg PƔrt
-
-
-Claudiu-Richard TĆRZIU
-Romania
-European Conservatives and Reformists Group
-257114
-Partidul AcČiunea Conservatoare
-
-
-Carla TAVARES
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257071
-Partido Socialista
-
-
-Kai TEGETHOFF
-Germany
-Group of the Greens/European Free Alliance
-256965
-Volt
-
-
-Marta TEMIDO
-Portugal
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-210480
-Partido Socialista
-
-
-Georgiana TEODORESCU
-Romania
-European Conservatives and Reformists Group
-257116
-AlianČa pentru Unirea RomĆ¢nilor
-
-
-Alice TEODORESCU MĆ
WE
-Sweden
-Group of the European People's Party (Christian Democrats)
-257089
-Kristdemokraterna
-
-
-Cristian TERHEÅ
-Romania
-European Conservatives and Reformists Group
-197655
-Partidului NaČional Conservator RomĆ¢n (PNCR)
-
-
-Ingeborg TER LAAK
-Netherlands
-Group of the European People's Party (Christian Democrats)
-256968
-Christen Democratisch AppĆØl
-
-
-Riho TERRAS
-Estonia
-Group of the European People's Party (Christian Democrats)
-204449
-Isamaa
-
-
-Hermann TERTSCH
-Spain
-Patriots for Europe Group
-197831
-VOX
-
-
-Pierre-Romain THIONNET
-France
-Patriots for Europe Group
-200345
-Rassemblement national
-
-
-Beatrice TIMGREN
-Sweden
-European Conservatives and Reformists Group
-257090
-Sverigedemokraterna
-
-
-Irene TINAGLI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197591
-Partito Democratico
-
-
-Bruno TOBBACK
-Belgium
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-256885
-Vooruit
-
-
-Tomas TOBĆ
-Sweden
-Group of the European People's Party (Christian Democrats)
-197402
-Moderaterna
-
-
-Rody TOLASSY
-France
-Patriots for Europe Group
-256888
-Rassemblement national
-
-
-Eugen TOMAC
-Romania
-Renew Europe Group
-197672
-Partidul MiČcarea PopularÄ
-
-
-Zala TOMAÅ IÄ
-Slovenia
-Group of the European People's Party (Christian Democrats)
-256814
-Slovenska demokratska stranka
-
-
-Waldemar TOMASZEWSKI
-Lithuania
-European Conservatives and Reformists Group
-96697
-Lietuvos lenkų rinkimų akcija ā KrikÅ”ÄioniÅ”kų Å”eimų sÄ
junga
-
-
-Romana TOMC
-Slovenia
-Group of the European People's Party (Christian Democrats)
-125104
-Slovenska demokratska stranka
-
-
-Matej TONIN
-Slovenia
-Group of the European People's Party (Christian Democrats)
-219652
-Nova Slovenija ā KrÅ”Äanski demokrati
-
-
-Jana TOOM
-Estonia
-Renew Europe Group
-124700
-Eesti Keskerakond
-
-
-Raffaele TOPO
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257148
-Partito Democratico
-
-
-Francesco TORSELLI
-Italy
-European Conservatives and Reformists Group
-257163
-FRATELLI D' ITALIA
-
-
-Flavio TOSI
-Italy
-Group of the European People's Party (Christian Democrats)
-124795
-Forza Italia
-
-
-Marie TOUSSAINT
-France
-Group of the Greens/European Free Alliance
-97236
-Les Ćcologistes
-
-
-Isabella TOVAGLIERI
-Italy
-Patriots for Europe Group
-197580
-Lega
-
-
-Pekka TOVERI
-Finland
-Group of the European People's Party (Christian Democrats)
-256804
-Kansallinen Kokoomus
-
-
-Pasquale TRIDICO
-Italy
-The Left group in the European Parliament - GUE/NGL
-257133
-Movimento 5 Stelle
-
-
-Laurence TROCHU
-France
-European Conservatives and Reformists Group
-256925
-IdentitƩ LibertƩs
-
-
-Dimitris TSIODRAS
-Greece
-Group of the European People's Party (Christian Democrats)
-256950
-Nea Demokratia
-
-
-Mihai TUDOSE
-Romania
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-198183
-Partidul Social Democrat
-
-
-Filip TUREK
-Czechia
-Patriots for Europe Group
-256850
-MotoristĆ© sobÄ
-
-
-Sebastian TYNKKYNEN
-Finland
-European Conservatives and Reformists Group
-256806
-Perussuomalaiset
-
-
-StanisÅaw TYSZKA
-Poland
-Europe of Sovereign Nations Group
-257062
-Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
-
-
-Milan UHRĆK
-Slovakia
-Europe of Sovereign Nations Group
-197763
-Hnutie Republika
-
-
-Nils UÅ AKOVS
-Latvia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-197810
-"SaskaÅa" sociÄldemokrÄtiskÄ partija
-
-
-Inese VAIDERE
-Latvia
-Group of the European People's Party (Christian Democrats)
-28617
-JaunÄ VienotÄ«ba
-
-
-Ivaylo VALCHEV
-Bulgaria
-European Conservatives and Reformists Group
-257258
-There Is Such a People
-
-
-Adina VÄLEAN
-Romania
-Group of the European People's Party (Christian Democrats)
-37324
-Partidul Naţional Liberal
-
-
-Matthieu VALET
-France
-Patriots for Europe Group
-256875
-Rassemblement national
-
-
-Kathleen VAN BREMPT
-Belgium
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-5729
-Vooruit
-
-
-Anouk VAN BRUG
-Netherlands
-Renew Europe Group
-257438
-Volkspartij voor Vrijheid en Democratie
-
-
-Brigitte VAN DEN BERG
-Netherlands
-Renew Europe Group
-256976
-Democraten 66
-
-
-Tom VANDENDRIESSCHE
-Belgium
-Patriots for Europe Group
-185771
-Vlaams Belang
-
-
-Kris VAN DIJCK
-Belgium
-European Conservatives and Reformists Group
-256884
-Nieuw-Vlaamse Alliantie
-
-
-Reinier VAN LANSCHOT
-Netherlands
-Group of the Greens/European Free Alliance
-256978
-Volt
-
-
-Jessika VAN LEEUWEN
-Netherlands
-Group of the European People's Party (Christian Democrats)
-256983
-BoerBurgerBeweging
-
-
-Roberto VANNACCI
-Italy
-Patriots for Europe Group
-257125
-Lega
-
-
-Johan VAN OVERTVELDT
-Belgium
-European Conservatives and Reformists Group
-125106
-Nieuw-Vlaamse Alliantie
-
-
-Kim VAN SPARRENTAK
-Netherlands
-Group of the Greens/European Free Alliance
-197870
-GroenLinks-PvdA
-
-
-Alexandre VARAUT
-France
-Patriots for Europe Group
-5736
-Rassemblement national
-
-
-Ana VASCONCELOS
-Portugal
-Renew Europe Group
-257061
-Iniciativa Liberal
-
-
-Vlad VASILE-VOICULESCU
-Romania
-Renew Europe Group
-257112
-Uniunea SalvaČi RomĆ¢nia
-
-
-Hilde VAUTMANS
-Belgium
-Renew Europe Group
-130100
-Open Vlaamse Liberalen en Democraten
-
-
-Marie-Pierre VEDRENNE
-France
-Renew Europe Group
-197502
-Mouvement DƩmocrate
-
-
-Francesco VENTOLA
-Italy
-European Conservatives and Reformists Group
-257099
-FRATELLI D' ITALIA
-
-
-Sabine VERHEYEN
-Germany
-Group of the European People's Party (Christian Democrats)
-96756
-Christlich Demokratische Union Deutschlands
-
-
-Yvan VEROUGSTRAETE
-Belgium
-Renew Europe Group
-256879
-Les EngagƩs
-
-
-Aurelijus VERYGA
-Lithuania
-European Conservatives and Reformists Group
-256811
-Lietuvos valstieÄių ir žaliųjų sÄ
junga
-
-
-Marko VEÅ LIGAJ
-Croatia
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-260035
-Socijaldemokratska partija Hrvatske
-
-
-AnnamƔria VICSEK
-Hungary
-Patriots for Europe Group
-256859
-Fidesz-Magyar PolgƔri SzƶvetsƩg-KeresztƩnydemokrata NƩppƔrt
-
-
-Catarina VIEIRA
-Netherlands
-Group of the Greens/European Free Alliance
-257437
-GroenLinks-PvdA
-
-
-Kristian VIGENIN
-Bulgaria
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-34232
-Bulgarian Socialist Party
-
-
-Harald VILIMSKY
-Austria
-Patriots for Europe Group
-125001
-Freiheitliche Partei Ćsterreichs
-
-
-LorƔnt VINCZE
-Romania
-Group of the European People's Party (Christian Democrats)
-98582
-Uniunea DemocratÄ MaghiarÄ din RomĆ¢nia
-
-
-Marianne VIND
-Denmark
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-199941
-Socialdemokratiet
-
-
-Anders VISTISEN
-Denmark
-Patriots for Europe Group
-124875
-Dansk Folkeparti
-
-
-Mariateresa VIVALDINI
-Italy
-European Conservatives and Reformists Group
-257143
-FRATELLI D' ITALIA
-
-
-Petar VOLGIN
-Bulgaria
-Europe of Sovereign Nations Group
-257260
-Revival
-
-
-Michael VON DER SCHULENBURG
-Germany
-Non-attached Members
-256966
-Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
-
-
-Alexandr VONDRA
-Czechia
-European Conservatives and Reformists Group
-197537
-ObÄanskĆ” demokratickĆ” strana
-
-
-Axel VOSS
-Germany
-Group of the European People's Party (Christian Democrats)
-96761
-Christlich Demokratische Union Deutschlands
-
-
-Elissavet VOZEMBERG-VRIONIDI
-Greece
-Group of the European People's Party (Christian Democrats)
-125065
-Nea Demokratia
-
-
-Veronika VRECIONOVĆ
-Czechia
-European Conservatives and Reformists Group
-197552
-ObÄanskĆ” demokratickĆ” strana
-
-
-AdriĆ”n VĆZQUEZ LĆZARA
-Spain
-Group of the European People's Party (Christian Democrats)
-204400
-Partido Popular
-
-
-Thomas WAITZ
-Austria
-Group of the Greens/European Free Alliance
-190464
-Die Grünen - Die Grüne Alternative
-
-
-Maria WALSH
-Ireland
-Group of the European People's Party (Christian Democrats)
-197863
-Fine Gael Party
-
-
-Marion WALSMANN
-Germany
-Group of the European People's Party (Christian Democrats)
-197429
-Christlich Demokratische Union Deutschlands
-
-
-Jƶrgen WARBORN
-Sweden
-Group of the European People's Party (Christian Democrats)
-197405
-Moderaterna
-
-
-Jan-Peter WARNKE
-Germany
-Non-attached Members
-256967
-Bündnis Sahra Wagenknecht ā Vernunft und Gerechtigkeit
-
-
-Maciej WÄSIK
-Poland
-European Conservatives and Reformists Group
-257052
-Prawo i SprawiedliwoÅÄ
-
-
-MichaÅ WAWRYKIEWICZ
-Poland
-Group of the European People's Party (Christian Democrats)
-257045
-Independent
-
-
-Marta WCISÅO
-Poland
-Group of the European People's Party (Christian Democrats)
-257046
-Platforma Obywatelska
-
-
-Manfred WEBER
-Germany
-Group of the European People's Party (Christian Democrats)
-28229
-Christlich-Soziale Union in Bayern e.V.
-
-
-Andrea WECHSLER
-Germany
-Group of the European People's Party (Christian Democrats)
-256977
-Christlich Demokratische Union Deutschlands
-
-
-Charlie WEIMERS
-Sweden
-European Conservatives and Reformists Group
-123562
-Sverigedemokraterna
-
-
-SƩverine WERBROUCK
-France
-Patriots for Europe Group
-261796
-Rassemblement national
-
-
-Emma WIESNER
-Sweden
-Renew Europe Group
-214839
-Centerpartiet
-
-
-Michal WIEZIK
-Slovakia
-Renew Europe Group
-197769
-ProgresĆvne Slovensko
-
-
-Sophie WILMĆS
-Belgium
-Renew Europe Group
-220801
-Mouvement RƩformateur
-
-
-Iuliu WINKLER
-Romania
-Group of the European People's Party (Christian Democrats)
-39725
-Uniunea DemocratÄ MaghiarÄ din RomĆ¢nia
-
-
-Angelika WINZIG
-Austria
-Group of the European People's Party (Christian Democrats)
-197652
-Ćsterreichische Volkspartei
-
-
-Isabel WISELER-LIMA
-Luxembourg
-Group of the European People's Party (Christian Democrats)
-197421
-Parti chrƩtien social luxembourgeois
-
-
-Jadwiga WIÅNIEWSKA
-Poland
-European Conservatives and Reformists Group
-124877
-Prawo i SprawiedliwoÅÄ
-
-
-Tiemo WĆLKEN
-Germany
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-185619
-Sozialdemokratische Partei Deutschlands
-
-
-Lara WOLTERS
-Netherlands
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-5392
-GroenLinks-PvdA
-
-
-Lucia YAR
-Slovakia
-Renew Europe Group
-257011
-ProgresĆvne Slovensko
-
-
-StƩphanie YON-COURTIN
-France
-Renew Europe Group
-197581
-Renaissance
-
-
-Elena YONCHEVA
-Bulgaria
-Non-attached Members
-197842
-Movement for Rights and Freedoms
-
-
-Maria ZACHARIA
-Greece
-Non-attached Members
-256955
-Plefsi Eleftherias
-
-
-Ewa ZAJÄCZKOWSKA-HERNIK
-Poland
-Europe of Sovereign Nations Group
-257069
-Konfederacja WolnoÅÄ i NiepodlegÅoÅÄ
-
-
-Anna ZALEWSKA
-Poland
-European Conservatives and Reformists Group
-197572
-Prawo i SprawiedliwoÅÄ
-
-
-Dainius ŽALIMAS
-Lithuania
-Renew Europe Group
-256807
-LaisvÄs partija
-
-
-Alessandro ZAN
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-257106
-Partito Democratico
-
-
-Javier ZARZALEJOS
-Spain
-Group of the European People's Party (Christian Democrats)
-197606
-Partido Popular
-
-
-TomÔŔ ZDECHOVSKĆ
-Czechia
-Group of the European People's Party (Christian Democrats)
-124713
-KÅesÅ„anskĆ” a demokratickĆ” unie - ÄeskoslovenskĆ” strana lidovĆ”
-
-
-Bogdan Andrzej ZDROJEWSKI
-Poland
-Group of the European People's Party (Christian Democrats)
-124893
-Platforma Obywatelska
-
-
-Auke ZIJLSTRA
-Netherlands
-Patriots for Europe Group
-103246
-Partij voor de Vrijheid
-
-
-Roberts ZÄŖLE
-Latvia
-European Conservatives and Reformists Group
-28615
-NacionÄlÄ apvienÄ«ba "Visu Latvijai!" - "TÄvzemei un BrÄ«vÄ«bai/LNNK"
-
-
-Nicola ZINGARETTI
-Italy
-Group of the Progressive Alliance of Socialists and Democrats in the European Parliament
-28419
-Partito Democratico
-
-
-Kosma ZÅOTOWSKI
-Poland
-European Conservatives and Reformists Group
-124884
-Prawo i SprawiedliwoÅÄ
-
-
-Juan Ignacio ZOIDO ĆLVAREZ
-Spain
-Group of the European People's Party (Christian Democrats)
-197621
-Partido Popular
-
-
-Željana ZOVKO
-Croatia
-Group of the European People's Party (Christian Democrats)
-185341
-Hrvatska demokratska zajednica
-
-
-Milan ZVER
-Slovenia
-Group of the European People's Party (Christian Democrats)
-96933
-Slovenska demokratska stranka
-
-
\ No newline at end of file
From f9ffd102f5b3e46032bf5bdf445b864ed8a0b4e3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 18 Aug 2025 15:00:39 +0000
Subject: [PATCH 53/56] Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-version: '5'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
.github/workflows/RELEASE.yml | 2 +-
.github/workflows/codacy.yml | 2 +-
.github/workflows/code-quality-and-tests.yml | 2 +-
.github/workflows/codeql.yml | 2 +-
.github/workflows/dependency-review.yml | 2 +-
.github/workflows/docs.yml | 2 +-
.github/workflows/lint.yml | 2 +-
.github/workflows/pyre.yml | 2 +-
.github/workflows/pysa.yml | 2 +-
.github/workflows/python-package.yml | 2 +-
.github/workflows/tests.yml | 2 +-
.github/workflows/trivy.yml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/RELEASE.yml b/.github/workflows/RELEASE.yml
index 059ec93e..2c7663af 100644
--- a/.github/workflows/RELEASE.yml
+++ b/.github/workflows/RELEASE.yml
@@ -17,7 +17,7 @@ jobs:
&& ${{ contains(github.event.pull_request.labels.*.name, 'release') }}
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Install poetry
run: pipx install poetry==$POETRY_VERSION
- name: Set up Python 3.9
diff --git a/.github/workflows/codacy.yml b/.github/workflows/codacy.yml
index 23466431..28950171 100644
--- a/.github/workflows/codacy.yml
+++ b/.github/workflows/codacy.yml
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@562ee3e92b8e92df8b67e0a5ff8aa8e261919c08
diff --git a/.github/workflows/code-quality-and-tests.yml b/.github/workflows/code-quality-and-tests.yml
index a6fec774..7e56373e 100644
--- a/.github/workflows/code-quality-and-tests.yml
+++ b/.github/workflows/code-quality-and-tests.yml
@@ -16,7 +16,7 @@ jobs:
steps:
# Step 1: Check out the repository
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
# Step 2: Set up Python
- name: Set up Python ${{ matrix.python-version }}
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index b93db343..0228db1b 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -28,7 +28,7 @@ jobs:
language: ["python"]
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index 9bbf3ba2..507a2882 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout repository'
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4
# Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options.
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 17e8b500..8d2d2d58 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -9,7 +9,7 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: 3.11
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 964a012a..f09618f5 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -6,7 +6,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v5
diff --git a/.github/workflows/pyre.yml b/.github/workflows/pyre.yml
index 53aca44d..336569b5 100644
--- a/.github/workflows/pyre.yml
+++ b/.github/workflows/pyre.yml
@@ -33,7 +33,7 @@ jobs:
security-events: write
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
submodules: true
diff --git a/.github/workflows/pysa.yml b/.github/workflows/pysa.yml
index 6c301e80..5f913465 100644
--- a/.github/workflows/pysa.yml
+++ b/.github/workflows/pysa.yml
@@ -35,7 +35,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
submodules: true
diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml
index c0ad132e..ec58ac6d 100644
--- a/.github/workflows/python-package.yml
+++ b/.github/workflows/python-package.yml
@@ -21,7 +21,7 @@ jobs:
python-version: ["3.10", "3.11", "3.12"]
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index fb6f4c5e..f27c181c 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up Python 3.10
uses: actions/setup-python@v5
diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml
index 54d83af8..1a92d0ee 100644
--- a/.github/workflows/trivy.yml
+++ b/.github/workflows/trivy.yml
@@ -27,7 +27,7 @@ jobs:
runs-on: "ubuntu-20.04"
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Build an image from Dockerfile
run: |
From 20819aae80a0b83ab67c6ea3742fd8aa1fb710e0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 18 Aug 2025 15:42:29 +0000
Subject: [PATCH 54/56] Update asyncio requirement from <4.0,>=3.4.3 to
>=3.4.3,<5.0
Updates the requirements on [asyncio](https://github.com/python/asyncio) to permit the latest version.
- [Commits](https://github.com/python/asyncio/commits)
---
updated-dependencies:
- dependency-name: asyncio
dependency-version: 4.0.0
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index ead3af6e..d920af57 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
torch>=2.1.1,<3.0
transformers>=4.39.0,<4.51.0
-asyncio>=3.4.3,<4.0
+asyncio>=3.4.3,<5.0
toml
pypdf==5.1.0
ratelimit==2.2.1
From bb46bd9f949c4d2187e4f78854a4d27e38db6a2a Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Mon, 18 Aug 2025 15:01:35 -0700
Subject: [PATCH 55/56] [REMOVE UN-USED FILES] [Cleanup Concurrent Dashboard]
[file renaming]
---
docs/examples/smart_database.md | 4 +-
docs/llm.txt | 4 +-
docs/swarms/concept/vision.md | 2 +-
docs/swarms/structs/swarm_rearrange.md | 2 +-
example.py | 5 +
.../smart_database_swarm.py | 7 +-
examples/models/claude_4.py | 2 +-
.../streaming_concurrent_workflow.py | 2 +-
.../council/council_judge_evaluation.py | 2 +-
.../council/council_judge_example.py | 2 +-
.../council/council_of_judges_eval.py | 2 +-
.../council_judge_complex_example.py | 2 +-
.../council_judge_custom_example.py | 2 +-
.../council_judge_example.py | 2 +-
...dation.py => graph_workflow_validation.py} | 0
.../paper_implementations}/long_agent.py | 0
examples/sims/simulation_vote_example.py | 19 -
examples/utils/misc/swarm_eval_deepseek.py | 170 ---------
graph_workflow_basic.py | 51 +++
scripts/docker/test_docker.py | 34 +-
simulation_vote_example.py | 27 ++
swarms/structs/__init__.py | 6 +-
swarms/structs/agent.py | 28 +-
.../{rearrange.py => agent_rearrange.py} | 8 +-
swarms/structs/batch_agent_execution.py | 12 +-
swarms/structs/concurrent_workflow.py | 7 +-
.../{council_judge.py => council_as_judge.py} | 0
swarms/structs/matrix_swarm.py | 306 ----------------
swarms/structs/sequential_workflow.py | 2 +-
swarms/structs/swarm_eval.py | 326 ------------------
swarms/structs/swarm_id_generator.py | 2 +-
.../{swarm_arange.py => swarm_rearrange.py} | 0
swarms/structs/swarm_router.py | 38 +-
swarms/utils/formatter.py | 2 +-
tests/structs/test_agentrearrange.py | 2 +-
tests/structs/test_matrix_swarm.py | 216 ------------
36 files changed, 164 insertions(+), 1132 deletions(-)
rename examples/{guides/smart_database => apps}/smart_database_swarm.py (99%)
rename examples/multi_agent/graphworkflow_examples/{test_graphworlfolw_validation.py => graph_workflow_validation.py} (100%)
rename {swarms/structs => examples/paper_implementations}/long_agent.py (100%)
delete mode 100644 examples/sims/simulation_vote_example.py
delete mode 100644 examples/utils/misc/swarm_eval_deepseek.py
create mode 100644 graph_workflow_basic.py
create mode 100644 simulation_vote_example.py
rename swarms/structs/{rearrange.py => agent_rearrange.py} (99%)
rename swarms/structs/{council_judge.py => council_as_judge.py} (100%)
delete mode 100644 swarms/structs/matrix_swarm.py
delete mode 100644 swarms/structs/swarm_eval.py
rename swarms/structs/{swarm_arange.py => swarm_rearrange.py} (100%)
delete mode 100644 tests/structs/test_matrix_swarm.py
diff --git a/docs/examples/smart_database.md b/docs/examples/smart_database.md
index f8681d55..a49ac22f 100644
--- a/docs/examples/smart_database.md
+++ b/docs/examples/smart_database.md
@@ -1,8 +1,6 @@
# Smart Database Powered by Hierarchical Multi-Agent Workflow
-This module implements a fully autonomous database management system using a hierarchical
-multi-agent architecture. The system includes specialized agents for different database
-operations coordinated by a Database Director agent.
+This module implements a fully autonomous database management system using a hierarchical multi-agent architecture. The system includes specialized agents for different database operations coordinated by a Database Director agent.
## Features
diff --git a/docs/llm.txt b/docs/llm.txt
index 3dc0048a..692944af 100644
--- a/docs/llm.txt
+++ b/docs/llm.txt
@@ -14643,7 +14643,7 @@ The following example showcases how to use the `AgentRearrange` class to manage
```python
from swarms.structs.agent import Agent
-from swarms.structs.rearrange import AgentRearrange
+from swarms.structs.agent_rearrange import AgentRearrange
# Initialize the Director agent using Anthropic model via model_name
director = Agent(
@@ -44327,7 +44327,7 @@ The flow pattern uses arrow notation (`->`) to define execution order:
### Basic Sequential Flow
```python
-from swarms.structs.swarm_arange import SwarmRearrange
+from swarms.structs.swarm_rearrange import SwarmRearrange
import os
from swarms import Agent, AgentRearrange
from swarm_models import OpenAIChat
diff --git a/docs/swarms/concept/vision.md b/docs/swarms/concept/vision.md
index 678b495d..e0ce08be 100644
--- a/docs/swarms/concept/vision.md
+++ b/docs/swarms/concept/vision.md
@@ -49,7 +49,7 @@ The following example showcases how to use the `AgentRearrange` class to manage
```python
from swarms.structs.agent import Agent
-from swarms.structs.rearrange import AgentRearrange
+from swarms.structs.agent_rearrange import AgentRearrange
# Initialize the Director agent using Anthropic model via model_name
director = Agent(
diff --git a/docs/swarms/structs/swarm_rearrange.md b/docs/swarms/structs/swarm_rearrange.md
index c40aa5b5..9297f117 100644
--- a/docs/swarms/structs/swarm_rearrange.md
+++ b/docs/swarms/structs/swarm_rearrange.md
@@ -46,7 +46,7 @@ The flow pattern uses arrow notation (`->`) to define execution order:
### Basic Sequential Flow
```python
-from swarms.structs.swarm_arange import SwarmRearrange
+from swarms.structs.swarm_rearrange import SwarmRearrange
import os
from swarms import Agent, AgentRearrange
from swarm_models import OpenAIChat
diff --git a/example.py b/example.py
index 561f22fc..17398527 100644
--- a/example.py
+++ b/example.py
@@ -1,5 +1,10 @@
from swarms import Agent
+import litellm
+
+litellm._turn_on_debug() # š this is the 1-line change you need to make
+
+
# Initialize the agent
agent = Agent(
agent_name="Quantitative-Trading-Agent",
diff --git a/examples/guides/smart_database/smart_database_swarm.py b/examples/apps/smart_database_swarm.py
similarity index 99%
rename from examples/guides/smart_database/smart_database_swarm.py
rename to examples/apps/smart_database_swarm.py
index b3f07c41..a4b5cb55 100644
--- a/examples/guides/smart_database/smart_database_swarm.py
+++ b/examples/apps/smart_database_swarm.py
@@ -23,6 +23,9 @@ from loguru import logger
from swarms import Agent, HierarchicalSwarm
+from dotenv import load_dotenv
+
+load_dotenv()
# =============================================================================
# DATABASE TOOLS - Core Functions for Database Operations
@@ -901,6 +904,7 @@ smart_database_swarm = HierarchicalSwarm(
description="A comprehensive database management system with specialized agents for creation, schema management, data operations, and querying, coordinated by a database director",
director_model_name="gpt-4.1",
agents=database_specialists,
+ director_reasoning_enabled=False,
max_loops=1,
verbose=True,
)
@@ -917,7 +921,8 @@ if __name__ == "__main__":
print("SMART DATABASE SWARM - E-COMMERCE SYSTEM EXAMPLE")
print("=" * 80)
- task1 = """Create a comprehensive e-commerce database system with the following requirements:
+ task1 = """
+ Create a comprehensive e-commerce database system with the following requirements:
1. Create a database called 'ecommerce_db'
2. Create tables for:
diff --git a/examples/models/claude_4.py b/examples/models/claude_4.py
index 491d5c83..f053e682 100644
--- a/examples/models/claude_4.py
+++ b/examples/models/claude_4.py
@@ -1,5 +1,5 @@
from swarms.structs.agent import Agent
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
# ========== USAGE EXAMPLE ==========
diff --git a/examples/multi_agent/concurrent_examples/streaming_concurrent_workflow.py b/examples/multi_agent/concurrent_examples/streaming_concurrent_workflow.py
index 9a0fc0d5..9318650f 100644
--- a/examples/multi_agent/concurrent_examples/streaming_concurrent_workflow.py
+++ b/examples/multi_agent/concurrent_examples/streaming_concurrent_workflow.py
@@ -46,7 +46,7 @@ technical_analyst = Agent(
)
# Create list of agents
-agents = [market_researcher, financial_analyst, technical_analyst]
+agents = [market_researcher, financial_analyst]
# Initialize the concurrent workflow
workflow = ConcurrentWorkflow(
diff --git a/examples/multi_agent/council/council_judge_evaluation.py b/examples/multi_agent/council/council_judge_evaluation.py
index 8e0694d5..2188c4f8 100644
--- a/examples/multi_agent/council/council_judge_evaluation.py
+++ b/examples/multi_agent/council/council_judge_evaluation.py
@@ -8,7 +8,7 @@ from loguru import logger
from tqdm import tqdm
from swarms.structs.agent import Agent
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
# Dataset configurations
DATASET_CONFIGS = {
diff --git a/examples/multi_agent/council/council_judge_example.py b/examples/multi_agent/council/council_judge_example.py
index 634eba28..f862e274 100644
--- a/examples/multi_agent/council/council_judge_example.py
+++ b/examples/multi_agent/council/council_judge_example.py
@@ -1,5 +1,5 @@
from swarms.structs.agent import Agent
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
if __name__ == "__main__":
diff --git a/examples/multi_agent/council/council_of_judges_eval.py b/examples/multi_agent/council/council_of_judges_eval.py
index ad2e9781..aec19131 100644
--- a/examples/multi_agent/council/council_of_judges_eval.py
+++ b/examples/multi_agent/council/council_of_judges_eval.py
@@ -1,5 +1,5 @@
from swarms.structs.agent import Agent
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
if __name__ == "__main__":
diff --git a/examples/multi_agent/council_of_judges/council_judge_complex_example.py b/examples/multi_agent/council_of_judges/council_judge_complex_example.py
index e072f593..c4654bfb 100644
--- a/examples/multi_agent/council_of_judges/council_judge_complex_example.py
+++ b/examples/multi_agent/council_of_judges/council_judge_complex_example.py
@@ -5,7 +5,7 @@ This example shows how to use the CouncilAsAJudge to evaluate various types
of responses including technical explanations, creative writing, and problem-solving.
"""
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
def evaluate_technical_response():
diff --git a/examples/multi_agent/council_of_judges/council_judge_custom_example.py b/examples/multi_agent/council_of_judges/council_judge_custom_example.py
index f456a824..edf69186 100644
--- a/examples/multi_agent/council_of_judges/council_judge_custom_example.py
+++ b/examples/multi_agent/council_of_judges/council_judge_custom_example.py
@@ -5,7 +5,7 @@ This example shows how to use the CouncilAsAJudge with different output types,
custom worker configurations, and focused evaluation scenarios.
"""
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
def evaluate_with_final_output():
diff --git a/examples/multi_agent/council_of_judges/council_judge_example.py b/examples/multi_agent/council_of_judges/council_judge_example.py
index 64ad1e9a..aa1bf3cd 100644
--- a/examples/multi_agent/council_of_judges/council_judge_example.py
+++ b/examples/multi_agent/council_of_judges/council_judge_example.py
@@ -6,7 +6,7 @@ across multiple dimensions including accuracy, helpfulness, harmlessness,
coherence, conciseness, and instruction adherence.
"""
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
def main():
diff --git a/examples/multi_agent/graphworkflow_examples/test_graphworlfolw_validation.py b/examples/multi_agent/graphworkflow_examples/graph_workflow_validation.py
similarity index 100%
rename from examples/multi_agent/graphworkflow_examples/test_graphworlfolw_validation.py
rename to examples/multi_agent/graphworkflow_examples/graph_workflow_validation.py
diff --git a/swarms/structs/long_agent.py b/examples/paper_implementations/long_agent.py
similarity index 100%
rename from swarms/structs/long_agent.py
rename to examples/paper_implementations/long_agent.py
diff --git a/examples/sims/simulation_vote_example.py b/examples/sims/simulation_vote_example.py
deleted file mode 100644
index 46a99933..00000000
--- a/examples/sims/simulation_vote_example.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from swarms.sims.senator_assembly import SenatorAssembly
-
-
-def main():
- """
- Simulate a Senate vote on a bill to invade Cuba and claim it as the 51st state.
-
- This function initializes the SenatorAssembly and runs a concurrent vote simulation
- on the specified bill.
- """
- senator_simulation = SenatorAssembly()
- senator_simulation.simulate_vote_concurrent(
- "A bill proposing to deregulate the IPO (Initial Public Offering) market in the United States as extensively as possible. The bill seeks to remove or significantly reduce existing regulatory requirements and oversight for companies seeking to go public, with the aim of increasing market efficiency and access to capital. Senators must consider the potential economic, legal, and ethical consequences of such broad deregulation, and cast their votes accordingly.",
- batch_size=10,
- )
-
-
-if __name__ == "__main__":
- main()
diff --git a/examples/utils/misc/swarm_eval_deepseek.py b/examples/utils/misc/swarm_eval_deepseek.py
deleted file mode 100644
index ac4a9408..00000000
--- a/examples/utils/misc/swarm_eval_deepseek.py
+++ /dev/null
@@ -1,170 +0,0 @@
-from loguru import logger
-from swarms.structs.swarm_eval import (
- SwarmEvaluator,
- PRESET_DATASETS,
-)
-
-import os
-from swarms import Agent
-from dotenv import load_dotenv
-
-from swarm_models import OpenAIChat
-
-load_dotenv()
-
-
-model = OpenAIChat(
- model_name="deepseek-ai/DeepSeek-R1-Distill-Llama-70B-free",
- openai_api_key=os.getenv("TOGETHER_API_KEY"),
- base_url="https://api.together.xyz/v1",
-)
-
-# Define system prompts for reasoning agents
-THINKING_AGENT_PROMPT = """You are a sophisticated analytical and strategic thinking agent focused on deep problem analysis and solution design.
-
-Your core capabilities include:
-1. Comprehensive Problem Analysis
- - Break down complex problems into constituent elements
- - Map relationships and dependencies between components
- - Identify root causes and underlying patterns
- - Consider historical context and precedents
-
-2. Multi-Perspective Evaluation
- - Examine issues from multiple stakeholder viewpoints
- - Consider short-term and long-term implications
- - Evaluate social, economic, technical, and ethical dimensions
- - Challenge assumptions and identify potential biases
-
-3. Risk Assessment and Mitigation
- - Conduct thorough risk analysis across scenarios
- - Identify potential failure modes and edge cases
- - Develop contingency plans and mitigation strategies
- - Assess probability and impact of various outcomes
-
-4. Strategic Solution Development
- - Generate multiple solution approaches
- - Evaluate trade-offs between different strategies
- - Consider resource constraints and limitations
- - Design scalable and sustainable solutions
-
-5. Decision Framework Creation
- - Establish clear evaluation criteria
- - Weight competing priorities appropriately
- - Create structured decision matrices
- - Document reasoning and key decision factors
-
-6. Systems Thinking
- - Map interconnections between system elements
- - Identify feedback loops and cascade effects
- - Consider emergent properties and behaviors
- - Account for dynamic system evolution
-
-Your output should always include:
-- Clear articulation of your analytical process
-- Key assumptions and their justification
-- Potential risks and mitigation strategies
-- Multiple solution options with pros/cons
-- Specific recommendations with supporting rationale
-- Areas of uncertainty requiring further investigation
-
-Focus on developing robust, well-reasoned strategies that account for complexity while remaining practical and actionable."""
-
-ACTION_AGENT_PROMPT = """You are an advanced implementation and execution agent focused on turning strategic plans into concrete results.
-
-Your core capabilities include:
-1. Strategic Implementation Planning
- - Break down high-level strategies into specific actions
- - Create detailed project roadmaps and timelines
- - Identify critical path dependencies
- - Establish clear milestones and success metrics
- - Design feedback and monitoring mechanisms
-
-2. Resource Optimization
- - Assess resource requirements and constraints
- - Optimize resource allocation and scheduling
- - Identify efficiency opportunities
- - Plan for scalability and flexibility
- - Manage competing priorities effectively
-
-3. Execution Management
- - Develop detailed implementation procedures
- - Create clear operational guidelines
- - Establish quality control measures
- - Design progress tracking systems
- - Build in review and adjustment points
-
-4. Risk Management
- - Implement specific risk mitigation measures
- - Create early warning systems
- - Develop contingency procedures
- - Establish fallback positions
- - Monitor risk indicators
-
-5. Stakeholder Management
- - Identify key stakeholders and their needs
- - Create communication plans
- - Establish feedback mechanisms
- - Manage expectations effectively
- - Build support and buy-in
-
-6. Continuous Improvement
- - Monitor implementation effectiveness
- - Gather and analyze performance data
- - Identify improvement opportunities
- - Implement iterative enhancements
- - Document lessons learned
-
-Your output should always include:
-- Detailed action plans with specific steps
-- Resource requirements and allocation plans
-- Timeline with key milestones
-- Success metrics and monitoring approach
-- Risk mitigation procedures
-- Communication and stakeholder management plans
-- Quality control measures
-- Feedback and adjustment mechanisms
-
-Focus on practical, efficient, and effective implementation while maintaining high quality standards and achieving desired outcomes."""
-
-# Initialize the thinking agent
-thinking_agent = Agent(
- agent_name="Strategic-Thinker",
- agent_description="Deep analysis and strategic planning agent",
- system_prompt=THINKING_AGENT_PROMPT,
- max_loops=1,
- llm=model,
- dynamic_temperature_enabled=True,
-)
-
-
-class DeepSeekSwarm:
- def __init__(self):
- self.thinking_agent = thinking_agent
-
- def run(self, task: str):
- first_one = self.thinking_agent.run(task)
-
- return self.thinking_agent.run(first_one)
-
-
-if __name__ == "__main__":
- # Initialize the swarm (replace with your actual multi-agent system)
- swarm = DeepSeekSwarm()
-
- # Initialize the evaluator with the swarm instance
- evaluator = SwarmEvaluator(swarm)
-
- logger.info("Starting evaluation for dataset: gsm8k")
-
- # For demonstration, we use 4 concurrent workers, show progress, and save results.
- results = evaluator.evaluate(
- "gsm8k",
- split="train",
- config=PRESET_DATASETS["gsm8k"],
- max_workers=os.cpu_count(),
- max_retries=3,
- show_progress=True,
- output_file="gsm8k_results.txt",
- )
-
- logger.info(f"Results for gsm8k: {results}")
diff --git a/graph_workflow_basic.py b/graph_workflow_basic.py
new file mode 100644
index 00000000..afb3bd92
--- /dev/null
+++ b/graph_workflow_basic.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+"""
+Basic Graph Workflow Example
+
+A minimal example showing how to use GraphWorkflow with backend selection.
+"""
+
+from swarms.structs.graph_workflow import GraphWorkflow
+from swarms.structs.agent import Agent
+
+agent_one = Agent(agent_name="research_agent", model="gpt-4o-mini")
+agent_two = Agent(
+ agent_name="research_agent_two", model="gpt-4o-mini"
+)
+agent_three = Agent(
+ agent_name="research_agent_three", model="gpt-4o-mini"
+)
+
+
+def main():
+ """
+ Run a basic graph workflow example without print statements.
+ """
+ # Create agents
+
+ # Create workflow with backend selection
+ workflow = GraphWorkflow(
+ name="Basic Example",
+ verbose=True,
+ )
+
+ # Add agents to workflow
+ workflow.add_node(agent_one)
+ workflow.add_node(agent_two)
+ workflow.add_node(agent_three)
+
+ # Create simple chain using the actual agent names
+ workflow.add_edge("research_agent", "research_agent_two")
+ workflow.add_edge("research_agent_two", "research_agent_three")
+
+ # Compile the workflow
+ workflow.compile()
+
+ # Run the workflow
+ task = "Complete a simple task"
+ results = workflow.run(task)
+ return results
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/docker/test_docker.py b/scripts/docker/test_docker.py
index 70e9060b..a50a17b9 100644
--- a/scripts/docker/test_docker.py
+++ b/scripts/docker/test_docker.py
@@ -1,4 +1,3 @@
-
#!/usr/bin/env python3
"""
Test script to verify Swarms installation in Docker container.
@@ -7,53 +6,59 @@ Test script to verify Swarms installation in Docker container.
import sys
from typing import Dict, Any
+
def test_swarms_import() -> Dict[str, Any]:
"""
Test that swarms can be imported and basic functionality works.
-
+
Returns:
Dict[str, Any]: Test results
"""
try:
import swarms
- print(f" Swarms imported successfully. Version: {swarms.__version__}")
-
+
+ print(
+ f" Swarms imported successfully. Version: {swarms.__version__}"
+ )
+
# Test basic functionality
from swarms import Agent
+
print(" Agent class imported successfully")
-
+
return {
"status": "success",
"version": swarms.__version__,
- "message": "Swarms package is working correctly"
+ "message": "Swarms package is working correctly",
}
-
+
except ImportError as e:
print(f" Failed to import swarms: {e}")
return {
"status": "error",
"error": str(e),
- "message": "Swarms package import failed"
+ "message": "Swarms package import failed",
}
except Exception as e:
print(f" Unexpected error: {e}")
return {
- "status": "error",
+ "status": "error",
"error": str(e),
- "message": "Unexpected error occurred"
+ "message": "Unexpected error occurred",
}
+
def main() -> None:
"""Main function to run tests."""
print(" Testing Swarms Docker Image...")
print("=" * 50)
-
+
# Test Python version
print(f"Python version: {sys.version}")
-
+
# Test swarms import
result = test_swarms_import()
-
+
print("=" * 50)
if result["status"] == "success":
print(" All tests passed! Docker image is working correctly.")
@@ -62,5 +67,6 @@ def main() -> None:
print(" Tests failed! Please check the Docker image.")
sys.exit(1)
+
if __name__ == "__main__":
- main()
+ main()
diff --git a/simulation_vote_example.py b/simulation_vote_example.py
new file mode 100644
index 00000000..377728c9
--- /dev/null
+++ b/simulation_vote_example.py
@@ -0,0 +1,27 @@
+from swarms.sims.senator_assembly import SenatorAssembly
+
+
+def main():
+ """
+ Runs a simulation of a Senate vote on a bill proposing significant tax cuts for all Americans.
+ The bill is described in realistic legislative terms, and the simulation uses a concurrent voting model.
+ """
+ senator_simulation = SenatorAssembly(
+ model_name="claude-sonnet-4-20250514"
+ )
+ senator_simulation.simulate_vote_concurrent(
+ (
+ "A bill proposing a significant reduction in federal income tax rates for all American citizens. "
+ "The legislation aims to lower tax brackets across the board, increase the standard deduction, "
+ "and provide additional tax relief for middle- and lower-income families. Proponents argue that "
+ "the bill will stimulate economic growth, increase disposable income, and enhance consumer spending. "
+ "Opponents raise concerns about the potential impact on the federal deficit, funding for public services, "
+ "and long-term fiscal responsibility. Senators must weigh the economic, social, and budgetary implications "
+ "before casting their votes."
+ ),
+ batch_size=10,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py
index 9ea95998..8da55bf3 100644
--- a/swarms/structs/__init__.py
+++ b/swarms/structs/__init__.py
@@ -9,7 +9,7 @@ from swarms.structs.board_of_directors_swarm import (
)
from swarms.structs.concurrent_workflow import ConcurrentWorkflow
from swarms.structs.conversation import Conversation
-from swarms.structs.council_judge import CouncilAsAJudge
+from swarms.structs.council_as_judge import CouncilAsAJudge
from swarms.structs.cron_job import CronJob
from swarms.structs.de_hallucination_swarm import DeHallucinationSwarm
from swarms.structs.deep_research_swarm import DeepResearchSwarm
@@ -66,11 +66,11 @@ from swarms.structs.multi_agent_exec import (
run_single_agent,
)
from swarms.structs.multi_agent_router import MultiAgentRouter
-from swarms.structs.rearrange import AgentRearrange, rearrange
+from swarms.structs.agent_rearrange import AgentRearrange, rearrange
from swarms.structs.round_robin import RoundRobinSwarm
from swarms.structs.sequential_workflow import SequentialWorkflow
from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm
-from swarms.structs.swarm_arange import SwarmRearrange
+from swarms.structs.swarm_rearrange import SwarmRearrange
from swarms.structs.swarm_router import (
SwarmRouter,
SwarmType,
diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py
index 73435c30..914c0adb 100644
--- a/swarms/structs/agent.py
+++ b/swarms/structs/agent.py
@@ -660,11 +660,13 @@ class Agent:
# Add agent name, description, and instructions to the prompt
if self.agent_name is not None:
- prompt += f"\n Name: {self.agent_name}"
+ prompt += f"\n Your Name: {self.agent_name} \n"
elif self.agent_description is not None:
- prompt += f"\n Description: {self.agent_description}"
+ prompt += (
+ f"\n Your Description: {self.agent_description} \n"
+ )
elif self.system_prompt is not None:
- prompt += f"\n Instructions: {self.system_prompt}"
+ prompt += f"\n Your Instructions: {self.system_prompt} \n"
else:
prompt = self.system_prompt
@@ -676,26 +678,14 @@ class Agent:
name=f"{self.agent_name}_conversation",
user=self.user_name,
rules=self.rules,
- token_count=(
- self.conversation_schema.count_tokens
- if self.conversation_schema
- else False
- ),
- message_id_on=(
- self.conversation_schema.message_id_on
- if self.conversation_schema
- else False
- ),
- time_enabled=(
- self.conversation_schema.time_enabled
- if self.conversation_schema
- else False
- ),
+ token_count=False,
+ message_id_on=False,
+ time_enabled=True,
)
# Add the system prompt to the conversation
memory.add(
- role="System",
+ role="system",
content=prompt,
)
diff --git a/swarms/structs/rearrange.py b/swarms/structs/agent_rearrange.py
similarity index 99%
rename from swarms/structs/rearrange.py
rename to swarms/structs/agent_rearrange.py
index dd9a65c7..459b1b2e 100644
--- a/swarms/structs/rearrange.py
+++ b/swarms/structs/agent_rearrange.py
@@ -3,19 +3,17 @@ import uuid
from concurrent.futures import ThreadPoolExecutor
from typing import Any, Callable, Dict, List, Optional, Union
-
from swarms.structs.agent import Agent
from swarms.structs.base_swarm import BaseSwarm
-
+from swarms.structs.conversation import Conversation
+from swarms.structs.multi_agent_exec import get_agents_info
+from swarms.telemetry.main import log_agent_data
from swarms.utils.any_to_str import any_to_str
from swarms.utils.history_output_formatter import (
history_output_formatter,
)
from swarms.utils.loguru_logger import initialize_logger
-from swarms.telemetry.main import log_agent_data
-from swarms.structs.conversation import Conversation
from swarms.utils.output_types import OutputType
-from swarms.structs.multi_agent_exec import get_agents_info
logger = initialize_logger(log_folder="rearrange")
diff --git a/swarms/structs/batch_agent_execution.py b/swarms/structs/batch_agent_execution.py
index 7b2a926d..7be9e1f7 100644
--- a/swarms/structs/batch_agent_execution.py
+++ b/swarms/structs/batch_agent_execution.py
@@ -7,10 +7,15 @@ from loguru import logger
import traceback
+class BatchAgentExecutionError(Exception):
+ pass
+
+
def batch_agent_execution(
agents: List[Union[Agent, Callable]],
tasks: List[str] = None,
imgs: List[str] = None,
+ max_workers: int = max(1, int(os.cpu_count() * 0.9)),
):
"""
Execute a batch of agents on a list of tasks concurrently.
@@ -38,9 +43,6 @@ def batch_agent_execution(
results = []
- # Calculate max workers as 90% of available CPU cores
- max_workers = max(1, int(os.cpu_count() * 0.9))
-
formatter.print_panel(
f"Executing {len(agents)} agents on {len(tasks)} tasks using {max_workers} workers"
)
@@ -78,5 +80,7 @@ def batch_agent_execution(
return results
except Exception as e:
log = f"Batch agent execution failed Error: {str(e)} Traceback: {traceback.format_exc()}"
+
logger.error(log)
- raise e
+
+ raise BatchAgentExecutionError(log)
diff --git a/swarms/structs/concurrent_workflow.py b/swarms/structs/concurrent_workflow.py
index 4ceb62e0..57b77f9b 100644
--- a/swarms/structs/concurrent_workflow.py
+++ b/swarms/structs/concurrent_workflow.py
@@ -295,7 +295,7 @@ class ConcurrentWorkflow(BaseSwarm):
def display_agent_dashboard(
self,
- title: str = "š¤ Agent Dashboard",
+ title: str = "ConcurrentWorkflow Dashboard",
is_final: bool = False,
) -> None:
"""
@@ -307,7 +307,7 @@ class ConcurrentWorkflow(BaseSwarm):
Args:
title (str, optional): The dashboard title to display at the top.
- Defaults to "š¤ Agent Dashboard".
+ Defaults to "š¤ ConcurrentWorkflow Dashboard".
is_final (bool, optional): Whether this is the final dashboard display
after all agents have completed. Changes formatting and styling.
Defaults to False.
@@ -543,7 +543,8 @@ class ConcurrentWorkflow(BaseSwarm):
# Display final dashboard if enabled
if self.show_dashboard:
self.display_agent_dashboard(
- "š Final Agent Dashboard", is_final=True
+ "Final ConcurrentWorkflow Dashboard",
+ is_final=True,
)
return history_output_formatter(
diff --git a/swarms/structs/council_judge.py b/swarms/structs/council_as_judge.py
similarity index 100%
rename from swarms/structs/council_judge.py
rename to swarms/structs/council_as_judge.py
diff --git a/swarms/structs/matrix_swarm.py b/swarms/structs/matrix_swarm.py
deleted file mode 100644
index 179e88b5..00000000
--- a/swarms/structs/matrix_swarm.py
+++ /dev/null
@@ -1,306 +0,0 @@
-import json
-from typing import Any, List
-
-from loguru import logger
-from pydantic import BaseModel, Field
-
-from swarms import Agent
-
-
-class AgentOutput(BaseModel):
- """
- Schema for capturing metadata and results of an agent run.
- """
-
- agent_name: str = Field(..., description="Name of the agent.")
- input_query: str = Field(
- ..., description="Input query provided to the agent."
- )
- output_result: Any = Field(
- ..., description="Result produced by the agent."
- )
- metadata: dict = Field(
- ..., description="Additional metadata about the agent run."
- )
-
-
-class MatrixSwarm:
- """
- A class to manage a matrix of agents and perform matrix operations similar to linear algebra.
- """
-
- def __init__(self, agents: List[List[Agent]]):
- """
- Initializes the MatrixSwarm with a 2D list of agents.
- Args:
- agents (List[List[Agent]]): 2D list of agents representing the matrix.
- """
- if not agents or not all(
- isinstance(row, list) for row in agents
- ):
- raise ValueError("Agents must be provided as a 2D list.")
- if not all(
- isinstance(agent, Agent)
- for row in agents
- for agent in row
- ):
- raise ValueError(
- "All elements of the matrix must be instances of `Agent`."
- )
- self.agents = agents
- self.outputs = [] # List to store outputs as AgentOutput
-
- def validate_dimensions(self, other: "MatrixSwarm") -> None:
- """
- Validates that two matrices have compatible dimensions for operations.
-
- Args:
- other (MatrixSwarm): Another MatrixSwarm.
-
- Raises:
- ValueError: If dimensions are incompatible.
- """
- if len(self.agents) != len(other.agents) or len(
- self.agents[0]
- ) != len(other.agents[0]):
- raise ValueError(
- "Matrix dimensions are incompatible for this operation."
- )
-
- def transpose(self) -> "MatrixSwarm":
- """
- Transposes the matrix of agents (swap rows and columns).
-
- Returns:
- MatrixSwarm: A new transposed MatrixSwarm.
- """
- transposed_agents = [
- [self.agents[j][i] for j in range(len(self.agents))]
- for i in range(len(self.agents[0]))
- ]
- return MatrixSwarm(transposed_agents)
-
- def add(self, other: "MatrixSwarm") -> "MatrixSwarm":
- """
- Adds two matrices element-wise.
-
- Args:
- other (MatrixSwarm): Another MatrixSwarm to add.
-
- Returns:
- MatrixSwarm: A new MatrixSwarm resulting from the addition.
- """
- self.validate_dimensions(other)
- added_agents = [
- [self.agents[i][j] for j in range(len(self.agents[i]))]
- for i in range(len(self.agents))
- ]
- return MatrixSwarm(added_agents)
-
- def scalar_multiply(self, scalar: int) -> "MatrixSwarm":
- """
- Scales the agents by duplicating them scalar times along the row.
-
- Args:
- scalar (int): The scalar multiplier.
-
- Returns:
- MatrixSwarm: A new MatrixSwarm where each agent is repeated scalar times along the row.
- """
- scaled_agents = [
- [agent for _ in range(scalar) for agent in row]
- for row in self.agents
- ]
- return MatrixSwarm(scaled_agents)
-
- def multiply(
- self, other: "MatrixSwarm", inputs: List[str]
- ) -> List[List[AgentOutput]]:
- """
- Multiplies two matrices (dot product between rows and columns).
-
- Args:
- other (MatrixSwarm): Another MatrixSwarm for multiplication.
- inputs (List[str]): A list of input queries for the agents.
-
- Returns:
- List[List[AgentOutput]]: A resulting matrix of outputs after multiplication.
- """
- if len(self.agents[0]) != len(other.agents):
- raise ValueError(
- "Matrix dimensions are incompatible for multiplication."
- )
-
- results = []
- for i, row in enumerate(self.agents):
- row_results = []
- for col_idx in range(len(other.agents[0])):
- col = [
- other.agents[row_idx][col_idx]
- for row_idx in range(len(other.agents))
- ]
- query = inputs[
- i
- ] # Input query for the corresponding row
- intermediate_result = []
-
- for agent_r, agent_c in zip(row, col):
- try:
- result = agent_r.run(query)
- intermediate_result.append(result)
- except Exception as e:
- intermediate_result.append(f"Error: {e}")
-
- # Aggregate outputs from dot product
- combined_result = " ".join(
- intermediate_result
- ) # Example aggregation
- row_results.append(
- AgentOutput(
- agent_name=f"DotProduct-{i}-{col_idx}",
- input_query=query,
- output_result=combined_result,
- metadata={"row": i, "col": col_idx},
- )
- )
- results.append(row_results)
- return results
-
- def subtract(self, other: "MatrixSwarm") -> "MatrixSwarm":
- """
- Subtracts two matrices element-wise.
-
- Args:
- other (MatrixSwarm): Another MatrixSwarm to subtract.
-
- Returns:
- MatrixSwarm: A new MatrixSwarm resulting from the subtraction.
- """
- self.validate_dimensions(other)
- subtracted_agents = [
- [self.agents[i][j] for j in range(len(self.agents[i]))]
- for i in range(len(self.agents))
- ]
- return MatrixSwarm(subtracted_agents)
-
- def identity(self, size: int) -> "MatrixSwarm":
- """
- Creates an identity matrix of agents with size `size`.
-
- Args:
- size (int): Size of the identity matrix (NxN).
-
- Returns:
- MatrixSwarm: An identity MatrixSwarm.
- """
- identity_agents = [
- [
- (
- self.agents[i][j]
- if i == j
- else Agent(
- agent_name=f"Zero-Agent-{i}-{j}",
- system_prompt="",
- )
- )
- for j in range(size)
- ]
- for i in range(size)
- ]
- return MatrixSwarm(identity_agents)
-
- def determinant(self) -> Any:
- """
- Computes the determinant of a square MatrixSwarm.
-
- Returns:
- Any: Determinant of the matrix (as agent outputs).
- """
- if len(self.agents) != len(self.agents[0]):
- raise ValueError(
- "Determinant can only be computed for square matrices."
- )
-
- # Recursive determinant calculation (example using placeholder logic)
- if len(self.agents) == 1:
- return self.agents[0][0].run("Compute determinant")
-
- det_result = 0
- for i in range(len(self.agents)):
- submatrix = MatrixSwarm(
- [row[:i] + row[i + 1 :] for row in self.agents[1:]]
- )
- cofactor = ((-1) ** i) * self.agents[0][i].run(
- "Compute determinant"
- )
- det_result += cofactor * submatrix.determinant()
- return det_result
-
- def save_to_file(self, path: str) -> None:
- """
- Saves the agent matrix structure and metadata to a file.
-
- Args:
- path (str): File path to save the matrix.
- """
- try:
- matrix_data = {
- "agents": [
- [agent.agent_name for agent in row]
- for row in self.agents
- ],
- "outputs": [output.dict() for output in self.outputs],
- }
- with open(path, "w") as f:
- json.dump(matrix_data, f, indent=4)
- logger.info(f"MatrixSwarm saved to {path}")
- except Exception as e:
- logger.error(f"Error saving MatrixSwarm: {e}")
-
-
-# # Example usage
-# if __name__ == "__main__":
-# from swarms.prompts.finance_agent_sys_prompt import (
-# FINANCIAL_AGENT_SYS_PROMPT,
-# )
-
-# # Create a 3x3 matrix of agents
-# agents = [
-# [
-# Agent(
-# agent_name=f"Agent-{i}-{j}",
-# system_prompt=FINANCIAL_AGENT_SYS_PROMPT,
-# model_name="gpt-4o-mini",
-# max_loops=1,
-# autosave=True,
-# dashboard=False,
-# verbose=True,
-# dynamic_temperature_enabled=True,
-# saved_state_path=f"agent_{i}_{j}.json",
-# user_name="swarms_corp",
-# retry_attempts=1,
-# context_length=200000,
-# return_step_meta=False,
-# output_type="string",
-# streaming_on=False,
-# )
-# for j in range(3)
-# ]
-# for i in range(3)
-# ]
-
-# # Initialize the matrix
-# agent_matrix = MatrixSwarm(agents)
-
-# # Example queries
-# inputs = [
-# "Explain Roth IRA benefits",
-# "Differences between ETFs and mutual funds",
-# "How to create a diversified portfolio",
-# ]
-
-# # Run agents
-# outputs = agent_matrix.multiply(agent_matrix.transpose(), inputs)
-
-# # Save results
-# agent_matrix.save_to_file("agent_matrix_results.json")
diff --git a/swarms/structs/sequential_workflow.py b/swarms/structs/sequential_workflow.py
index c845d508..32036f7f 100644
--- a/swarms/structs/sequential_workflow.py
+++ b/swarms/structs/sequential_workflow.py
@@ -2,7 +2,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Callable, List, Optional, Union
from swarms.structs.agent import Agent
-from swarms.structs.rearrange import AgentRearrange
+from swarms.structs.agent_rearrange import AgentRearrange
from swarms.utils.loguru_logger import initialize_logger
from swarms.utils.output_types import OutputType
diff --git a/swarms/structs/swarm_eval.py b/swarms/structs/swarm_eval.py
deleted file mode 100644
index ac47b291..00000000
--- a/swarms/structs/swarm_eval.py
+++ /dev/null
@@ -1,326 +0,0 @@
-import math
-import time
-from concurrent.futures import ThreadPoolExecutor, as_completed
-from typing import Any, Callable, Dict, Optional, Tuple
-
-from datasets import Dataset, load_dataset
-from loguru import logger
-from tqdm import tqdm
-
-# -----------------------------------------------------------------------------
-# Logging configuration: log to console and file (rotating by size)
-# -----------------------------------------------------------------------------
-
-# -----------------------------------------------------------------------------
-# Swarm interface example
-# -----------------------------------------------------------------------------
-
-
-# -----------------------------------------------------------------------------
-# Benchmark configuration
-# -----------------------------------------------------------------------------
-class BenchmarkConfig:
- """
- Configuration for a benchmark dataset.
-
- Attributes:
- input_column (str): The column containing the task prompt.
- answer_column (str): The column containing the expected answer.
- answer_extractor (Optional[Callable[[Any], str]]): Function to extract
- a string answer from the dataset's raw answer format.
- answer_matcher (Optional[Callable[[str, str], bool]]): Function to compare
- the expected answer and the swarm output. If None, a simple substring
- containment is used.
- """
-
- def __init__(
- self,
- input_column: str,
- answer_column: str,
- answer_extractor: Optional[Callable[[Any], str]] = None,
- answer_matcher: Optional[Callable[[str, str], bool]] = None,
- ):
- self.input_column = input_column
- self.answer_column = answer_column
- self.answer_extractor = answer_extractor
- self.answer_matcher = answer_matcher
-
-
-# -----------------------------------------------------------------------------
-# Preset dataset configurations for popular benchmarks
-# -----------------------------------------------------------------------------
-PRESET_DATASETS: Dict[str, BenchmarkConfig] = {
- "gsm8k": BenchmarkConfig(
- input_column="question",
- answer_column="answer",
- ),
- "squad": BenchmarkConfig(
- input_column="question",
- answer_column="answers",
- answer_extractor=lambda ans: (
- ans["text"][0]
- if isinstance(ans, dict)
- and "text" in ans
- and isinstance(ans["text"], list)
- and ans["text"]
- else str(ans)
- ),
- ),
- "winogrande": BenchmarkConfig(
- input_column="sentence",
- answer_column="answer",
- ),
- "commonsense_qa": BenchmarkConfig(
- input_column="question",
- answer_column="answerKey",
- ),
- # Add additional presets here.
-}
-
-
-# -----------------------------------------------------------------------------
-# SwarmEvaluator with extended features
-# -----------------------------------------------------------------------------
-class SwarmEvaluator:
- """
- Evaluator that uses a swarm of agents to process benchmark datasets
- from Hugging Face, with concurrency, retries, progress display, performance timing,
- and customizable answer matching.
-
- Example:
- swarm = Swarm()
- evaluator = SwarmEvaluator(swarm)
- results = evaluator.evaluate("gsm8k", split="test", max_workers=4)
- print(results)
- """
-
- def __init__(self, swarm: callable) -> None:
- """
- Initialize the evaluator with a given swarm.
-
- Args:
- swarm (Swarm): A swarm instance with a callable run(task: str) method.
- """
- self.swarm = swarm
-
- def evaluate(
- self,
- dataset_name: str,
- split: str = "test",
- config: Optional[BenchmarkConfig] = None,
- max_workers: int = 1,
- max_retries: int = 3,
- show_progress: bool = True,
- output_file: Optional[str] = None,
- ) -> Dict[str, Any]:
- """
- Evaluate the specified benchmark dataset using the swarm.
-
- Args:
- dataset_name (str): The dataset name (from Hugging Face).
- split (str): The dataset split (e.g., "test", "validation").
- config (Optional[BenchmarkConfig]): Benchmark configuration. If None,
- a preset config is used.
- max_workers (int): Number of concurrent workers.
- max_retries (int): Number of retries for swarm tasks on failure.
- show_progress (bool): If True, display a progress bar.
- output_file (Optional[str]): Path to a file to write the results.
-
- Returns:
- Dict[str, Any]: Evaluation metrics including total examples, correct answers,
- accuracy, and total evaluation time.
- """
- if config is None:
- config = PRESET_DATASETS.get(dataset_name)
- if config is None:
- raise ValueError(
- f"No preset config for dataset '{dataset_name}'. Provide a BenchmarkConfig."
- )
-
- logger.info(
- f"Loading dataset '{dataset_name}' (split: {split})..."
- )
- dataset: Dataset = load_dataset(dataset_name, split=split)
- total_examples = len(dataset)
- logger.info(f"Total examples to evaluate: {total_examples}")
-
- start_time = time.time()
- correct = 0
-
- # Function to process a single example.
- def _process_example(
- example: Dict[str, Any], idx: int
- ) -> Tuple[bool, float]:
- task_start = time.time()
- task_text = example.get(config.input_column)
- expected_answer = example.get(config.answer_column)
-
- if task_text is None or expected_answer is None:
- logger.warning(
- f"Example {idx}: Missing '{config.input_column}' or '{config.answer_column}', skipping."
- )
- return (False, 0.0)
-
- # Use answer_extractor if provided.
- if config.answer_extractor:
- try:
- expected_answer = config.answer_extractor(
- expected_answer
- )
- except Exception as e:
- logger.error(
- f"Example {idx}: Error extracting answer: {e}"
- )
- return (False, 0.0)
-
- logger.debug(f"Example {idx} - Task: {task_text}")
- logger.debug(
- f"Example {idx} - Expected Answer: {expected_answer}"
- )
-
- try:
- swarm_output = self._run_with_retry(
- task_text, max_retries
- )
- except Exception as e:
- logger.error(
- f"Example {idx}: Failed after retries. Error: {e}"
- )
- return (False, time.time() - task_start)
-
- logger.debug(
- f"Example {idx} - Swarm Output: {swarm_output}"
- )
-
- # Use custom matcher if provided; otherwise, default matching.
- if config.answer_matcher:
- is_correct = config.answer_matcher(
- expected_answer, swarm_output
- )
- else:
- is_correct = self._default_matcher(
- expected_answer, swarm_output
- )
-
- task_time = time.time() - task_start
- logger.info(
- f"Example {idx}: {'Correct' if is_correct else 'Incorrect'} in {task_time:.2f}s"
- )
- return (is_correct, task_time)
-
- # Use ThreadPoolExecutor for concurrency.
- futures = []
- total_time = 0.0
- with ThreadPoolExecutor(max_workers=max_workers) as executor:
- # Optionally wrap the dataset with tqdm for a progress bar.
- examples_iter = enumerate(dataset, start=1)
- if show_progress:
- examples_iter = tqdm(
- list(examples_iter),
- total=total_examples,
- desc="Evaluating",
- )
-
- for idx, example in examples_iter:
- futures.append(
- executor.submit(_process_example, example, idx)
- )
-
- for future in as_completed(futures):
- try:
- is_correct, elapsed = future.result()
- total_time += elapsed
- if is_correct:
- correct += 1
- except Exception as e:
- logger.error(f"Error processing an example: {e}")
-
- overall_time = time.time() - start_time
- accuracy = (
- correct / total_examples if total_examples > 0 else 0.0
- )
-
- logger.info(
- f"Evaluation complete. Total examples: {total_examples}, Correct: {correct}, "
- f"Accuracy: {accuracy:.2%}, Overall Time: {overall_time:.2f}s, "
- f"Average per-example time: {total_time/total_examples if total_examples else 0:.2f}s"
- )
-
- results = {
- "total": total_examples,
- "correct": correct,
- "accuracy": accuracy,
- "overall_time": overall_time,
- "average_example_time": (
- total_time / total_examples
- if total_examples
- else math.nan
- ),
- }
-
- # Optionally save results to a file.
- if output_file:
- try:
- with open(output_file, "w") as f:
- for key, value in results.items():
- f.write(f"{key}: {value}\n")
- logger.info(f"Results saved to {output_file}")
- except Exception as e:
- logger.error(
- f"Error saving results to {output_file}: {e}"
- )
-
- return results
-
- def _run_with_retry(self, task: str, max_retries: int) -> str:
- """
- Runs the swarm task with a retry mechanism.
-
- Args:
- task (str): The task string.
- max_retries (int): Maximum number of retries.
-
- Returns:
- str: Swarm output.
-
- Raises:
- Exception: If all retries fail.
- """
- attempt = 0
- while attempt <= max_retries:
- try:
- start = time.time()
- result = self.swarm.run(task)
- elapsed = time.time() - start
- logger.debug(
- f"Task succeeded in {elapsed:.2f}s on attempt {attempt + 1}"
- )
- return result
- except Exception as e:
- logger.warning(
- f"Task failed on attempt {attempt + 1}: {e}"
- )
- attempt += 1
- time.sleep(0.5 * attempt) # Exponential backoff
- raise Exception("Max retries exceeded for task.")
-
- @staticmethod
- def _default_matcher(expected: str, output: str) -> bool:
- """
- Default answer matching using a normalized substring check.
-
- Args:
- expected (str): The expected answer.
- output (str): The swarm output.
-
- Returns:
- bool: True if expected is found in output; otherwise, False.
- """
- expected_norm = " ".join(expected.strip().split())
- output_norm = " ".join(output.strip().split())
- return expected_norm in output_norm
-
-
-# -----------------------------------------------------------------------------
-# Example usage
-# -----------------------------------------------------------------------------
diff --git a/swarms/structs/swarm_id_generator.py b/swarms/structs/swarm_id_generator.py
index c05e039d..aeaa5999 100644
--- a/swarms/structs/swarm_id_generator.py
+++ b/swarms/structs/swarm_id_generator.py
@@ -2,4 +2,4 @@ import uuid
def generate_swarm_id():
- return str(uuid.uuid4())
+ return f"swarm-{uuid.uuid4().hex}"
diff --git a/swarms/structs/swarm_arange.py b/swarms/structs/swarm_rearrange.py
similarity index 100%
rename from swarms/structs/swarm_arange.py
rename to swarms/structs/swarm_rearrange.py
diff --git a/swarms/structs/swarm_router.py b/swarms/structs/swarm_router.py
index 5edf3b13..cae43b9c 100644
--- a/swarms/structs/swarm_router.py
+++ b/swarms/structs/swarm_router.py
@@ -11,33 +11,31 @@ from swarms.prompts.multi_agent_collab_prompt import (
)
from swarms.structs.agent import Agent
from swarms.structs.concurrent_workflow import ConcurrentWorkflow
+from swarms.structs.council_as_judge import CouncilAsAJudge
from swarms.structs.csv_to_agent import AgentLoader
+from swarms.structs.deep_research_swarm import DeepResearchSwarm
from swarms.structs.groupchat import GroupChat
+from swarms.structs.heavy_swarm import HeavySwarm
from swarms.structs.hiearchical_swarm import HierarchicalSwarm
+from swarms.structs.interactive_groupchat import InteractiveGroupChat
+from swarms.structs.ma_utils import list_all_agents
from swarms.structs.majority_voting import MajorityVoting
+from swarms.structs.malt import MALT
from swarms.structs.mixture_of_agents import MixtureOfAgents
from swarms.structs.multi_agent_router import MultiAgentRouter
-from swarms.structs.rearrange import AgentRearrange
+from swarms.structs.agent_rearrange import AgentRearrange
from swarms.structs.sequential_workflow import SequentialWorkflow
-from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm
from swarms.structs.swarm_matcher import swarm_matcher
from swarms.telemetry.log_executions import log_execution
-from swarms.utils.output_types import OutputType
-from swarms.utils.loguru_logger import initialize_logger
-from swarms.structs.malt import MALT
-from swarms.structs.deep_research_swarm import DeepResearchSwarm
-from swarms.structs.council_judge import CouncilAsAJudge
-from swarms.structs.interactive_groupchat import InteractiveGroupChat
-from swarms.structs.heavy_swarm import HeavySwarm
-from swarms.structs.ma_utils import list_all_agents
from swarms.utils.generate_keys import generate_api_key
+from swarms.utils.loguru_logger import initialize_logger
+from swarms.utils.output_types import OutputType
logger = initialize_logger(log_folder="swarm_router")
SwarmType = Literal[
"AgentRearrange",
"MixtureOfAgents",
- "SpreadSheetSwarm",
"SequentialWorkflow",
"ConcurrentWorkflow",
"GroupChat",
@@ -146,7 +144,6 @@ class SwarmRouter:
Available Swarm Types:
- AgentRearrange: Optimizes agent arrangement for task execution
- MixtureOfAgents: Combines multiple agent types for diverse tasks
- - SpreadSheetSwarm: Uses spreadsheet-like operations for task management
- SequentialWorkflow: Executes tasks sequentially
- ConcurrentWorkflow: Executes tasks in parallel
- "auto": Automatically selects best swarm type via embedding search
@@ -179,7 +176,7 @@ class SwarmRouter:
description: str = "Routes your task to the desired swarm",
max_loops: int = 1,
agents: List[Union[Agent, Callable]] = [],
- swarm_type: SwarmType = "SequentialWorkflow", # "SpreadSheetSwarm" # "auto"
+ swarm_type: SwarmType = "SequentialWorkflow", # "ConcurrentWorkflow" # "auto"
autosave: bool = False,
rearrange_flow: str = None,
return_json: bool = False,
@@ -396,7 +393,6 @@ class SwarmRouter:
"MajorityVoting": self._create_majority_voting,
"GroupChat": self._create_group_chat,
"MultiAgentRouter": self._create_multi_agent_router,
- "SpreadSheetSwarm": self._create_spreadsheet_swarm,
"SequentialWorkflow": self._create_sequential_workflow,
"ConcurrentWorkflow": self._create_concurrent_workflow,
}
@@ -528,18 +524,6 @@ class SwarmRouter:
output_type=self.output_type,
)
- def _create_spreadsheet_swarm(self, *args, **kwargs):
- """Factory function for SpreadSheetSwarm."""
- return SpreadSheetSwarm(
- name=self.name,
- description=self.description,
- agents=self.agents,
- max_loops=self.max_loops,
- autosave_on=self.autosave,
- *args,
- **kwargs,
- )
-
def _create_sequential_workflow(self, *args, **kwargs):
"""Factory function for SequentialWorkflow."""
return SequentialWorkflow(
@@ -580,7 +564,7 @@ class SwarmRouter:
**kwargs: Arbitrary keyword arguments.
Returns:
- Union[AgentRearrange, MixtureOfAgents, SpreadSheetSwarm, SequentialWorkflow, ConcurrentWorkflow]:
+ Union[AgentRearrange, MixtureOfAgents, SequentialWorkflow, ConcurrentWorkflow]:
The instantiated swarm object.
Raises:
diff --git a/swarms/utils/formatter.py b/swarms/utils/formatter.py
index 0b546be5..0fb3f4f0 100644
--- a/swarms/utils/formatter.py
+++ b/swarms/utils/formatter.py
@@ -397,7 +397,7 @@ class Formatter:
def print_agent_dashboard(
self,
agents_data: List[Dict[str, Any]],
- title: str = "š¤ Agent Dashboard",
+ title: str = "ConcurrentWorkflow Dashboard",
is_final: bool = False,
) -> None:
"""
diff --git a/tests/structs/test_agentrearrange.py b/tests/structs/test_agentrearrange.py
index abb23dd2..2110cf60 100644
--- a/tests/structs/test_agentrearrange.py
+++ b/tests/structs/test_agentrearrange.py
@@ -7,7 +7,7 @@ from loguru import logger
from swarm_models import OpenAIChat
from swarms.structs.agent import Agent
-from swarms.structs.rearrange import AgentRearrange
+from swarms.structs.agent_rearrange import AgentRearrange
class TestResult:
diff --git a/tests/structs/test_matrix_swarm.py b/tests/structs/test_matrix_swarm.py
deleted file mode 100644
index 4556c693..00000000
--- a/tests/structs/test_matrix_swarm.py
+++ /dev/null
@@ -1,216 +0,0 @@
-from swarms.structs.matrix_swarm import AgentMatrix, AgentOutput
-from swarms import Agent
-
-
-def create_test_matrix(rows: int, cols: int) -> AgentMatrix:
- """Helper function to create a test agent matrix"""
- agents = [
- [
- Agent(
- agent_name=f"TestAgent-{i}-{j}",
- system_prompt="Test prompt",
- )
- for j in range(cols)
- ]
- for i in range(rows)
- ]
- return AgentMatrix(agents)
-
-
-def test_init():
- """Test AgentMatrix initialization"""
- # Test valid initialization
- matrix = create_test_matrix(2, 2)
- assert isinstance(matrix, AgentMatrix)
- assert len(matrix.agents) == 2
- assert len(matrix.agents[0]) == 2
-
- # Test invalid initialization
- try:
- AgentMatrix([[1, 2], [3, 4]]) # Non-agent elements
- assert False, "Should raise ValueError"
- except ValueError:
- pass
-
- try:
- AgentMatrix([]) # Empty matrix
- assert False, "Should raise ValueError"
- except ValueError:
- pass
-
-
-def test_transpose():
- """Test matrix transpose operation"""
- matrix = create_test_matrix(2, 3)
- transposed = matrix.transpose()
-
- assert len(transposed.agents) == 3 # Original cols become rows
- assert len(transposed.agents[0]) == 2 # Original rows become cols
-
- # Verify agent positions
- for i in range(2):
- for j in range(3):
- assert (
- matrix.agents[i][j].agent_name
- == transposed.agents[j][i].agent_name
- )
-
-
-def test_add():
- """Test matrix addition"""
- matrix1 = create_test_matrix(2, 2)
- matrix2 = create_test_matrix(2, 2)
-
- result = matrix1.add(matrix2)
- assert len(result.agents) == 2
- assert len(result.agents[0]) == 2
-
- # Test incompatible dimensions
- matrix3 = create_test_matrix(2, 3)
- try:
- matrix1.add(matrix3)
- assert False, "Should raise ValueError"
- except ValueError:
- pass
-
-
-def test_scalar_multiply():
- """Test scalar multiplication"""
- matrix = create_test_matrix(2, 2)
- scalar = 3
- result = matrix.scalar_multiply(scalar)
-
- assert len(result.agents) == 2
- assert len(result.agents[0]) == 2 * scalar
-
- # Verify agent duplication
- for i in range(len(result.agents)):
- for j in range(0, len(result.agents[0]), scalar):
- original_agent = matrix.agents[i][j // scalar]
- for k in range(scalar):
- assert (
- result.agents[i][j + k].agent_name
- == original_agent.agent_name
- )
-
-
-def test_multiply():
- """Test matrix multiplication"""
- matrix1 = create_test_matrix(2, 3)
- matrix2 = create_test_matrix(3, 2)
- inputs = ["test query 1", "test query 2"]
-
- result = matrix1.multiply(matrix2, inputs)
- assert len(result) == 2 # Number of rows in first matrix
- assert len(result[0]) == 2 # Number of columns in second matrix
-
- # Verify output structure
- for row in result:
- for output in row:
- assert isinstance(output, AgentOutput)
- assert isinstance(output.input_query, str)
- assert isinstance(output.metadata, dict)
-
-
-def test_subtract():
- """Test matrix subtraction"""
- matrix1 = create_test_matrix(2, 2)
- matrix2 = create_test_matrix(2, 2)
-
- result = matrix1.subtract(matrix2)
- assert len(result.agents) == 2
- assert len(result.agents[0]) == 2
-
-
-def test_identity():
- """Test identity matrix creation"""
- matrix = create_test_matrix(3, 3)
- identity = matrix.identity(3)
-
- assert len(identity.agents) == 3
- assert len(identity.agents[0]) == 3
-
- # Verify diagonal elements are from original matrix
- for i in range(3):
- assert (
- identity.agents[i][i].agent_name
- == matrix.agents[i][i].agent_name
- )
-
- # Verify non-diagonal elements are zero agents
- for j in range(3):
- if i != j:
- assert identity.agents[i][j].agent_name.startswith(
- "Zero-Agent"
- )
-
-
-def test_determinant():
- """Test determinant calculation"""
- # Test 1x1 matrix
- matrix1 = create_test_matrix(1, 1)
- det1 = matrix1.determinant()
- assert det1 is not None
-
- # Test 2x2 matrix
- matrix2 = create_test_matrix(2, 2)
- det2 = matrix2.determinant()
- assert det2 is not None
-
- # Test non-square matrix
- matrix3 = create_test_matrix(2, 3)
- try:
- matrix3.determinant()
- assert False, "Should raise ValueError"
- except ValueError:
- pass
-
-
-def test_save_to_file(tmp_path):
- """Test saving matrix to file"""
- import os
-
- matrix = create_test_matrix(2, 2)
- file_path = os.path.join(tmp_path, "test_matrix.json")
-
- matrix.save_to_file(file_path)
- assert os.path.exists(file_path)
-
- # Verify file contents
- import json
-
- with open(file_path, "r") as f:
- data = json.load(f)
- assert "agents" in data
- assert "outputs" in data
- assert len(data["agents"]) == 2
- assert len(data["agents"][0]) == 2
-
-
-def run_all_tests():
- """Run all test functions"""
- test_functions = [
- test_init,
- test_transpose,
- test_add,
- test_scalar_multiply,
- test_multiply,
- test_subtract,
- test_identity,
- test_determinant,
- ]
-
- for test_func in test_functions:
- try:
- test_func()
- print(f"ā
{test_func.__name__} passed")
- except AssertionError as e:
- print(f"ā {test_func.__name__} failed: {str(e)}")
- except Exception as e:
- print(
- f"ā {test_func.__name__} failed with exception: {str(e)}"
- )
-
-
-if __name__ == "__main__":
- run_all_tests()
From 67b380dc8a36c66f6a843c796ad46281dfe8c124 Mon Sep 17 00:00:00 2001
From: Kye Gomez
Date: Mon, 18 Aug 2025 15:26:47 -0700
Subject: [PATCH 56/56] remove-unused-params from agent.py
---
.../graph_workflow_basic.py | 0
.../euroswarm_parliament/__init__.py | 3 +-
.../euroswarm_parliament.py | 2461 +++++++++++------
.../euroswarm_parliament_example.py | 553 ++--
.../mass_agent_template.py | 736 +++--
.../euroswarm_parliament/test_mass_agents.py | 63 +-
.../wikipedia_personality_scraper.py | 608 ++--
swarms/structs/__init__.py | 2 +-
swarms/structs/agent.py | 37 +-
swarms/structs/conversation.py | 86 +-
10 files changed, 2893 insertions(+), 1656 deletions(-)
rename graph_workflow_basic.py => examples/multi_agent/graphworkflow_examples/graph_workflow_basic.py (100%)
diff --git a/graph_workflow_basic.py b/examples/multi_agent/graphworkflow_examples/graph_workflow_basic.py
similarity index 100%
rename from graph_workflow_basic.py
rename to examples/multi_agent/graphworkflow_examples/graph_workflow_basic.py
diff --git a/examples/simulations/euroswarm_parliament/__init__.py b/examples/simulations/euroswarm_parliament/__init__.py
index 381233f0..863b6d26 100644
--- a/examples/simulations/euroswarm_parliament/__init__.py
+++ b/examples/simulations/euroswarm_parliament/__init__.py
@@ -30,6 +30,7 @@ try:
WikipediaPersonalityScraper,
MEPPersonalityProfile,
)
+
WIKIPEDIA_PERSONALITY_AVAILABLE = True
except ImportError:
WIKIPEDIA_PERSONALITY_AVAILABLE = False
@@ -52,4 +53,4 @@ __all__ = [
"WikipediaPersonalityScraper",
"MEPPersonalityProfile",
"WIKIPEDIA_PERSONALITY_AVAILABLE",
-]
\ No newline at end of file
+]
diff --git a/examples/simulations/euroswarm_parliament/euroswarm_parliament.py b/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
index 1694277b..0707ec28 100644
--- a/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
+++ b/examples/simulations/euroswarm_parliament/euroswarm_parliament.py
@@ -15,15 +15,11 @@ ENHANCED WITH COST OPTIMIZATION:
import os
import random
import xml.etree.ElementTree as ET
-import time
import hashlib
-import requests
-import re
-from typing import Dict, List, Optional, Union, Any, Set
+from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field
from enum import Enum
-from datetime import datetime, timedelta
-from functools import lru_cache
+from datetime import datetime
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_concurrently
@@ -31,10 +27,6 @@ from swarms.structs.board_of_directors_swarm import (
BoardOfDirectorsSwarm,
BoardMember,
BoardMemberRole,
- BoardDecisionType,
- BoardSpec,
- BoardOrder,
- BoardDecision,
enable_board_feature,
)
from swarms.utils.loguru_logger import initialize_logger
@@ -47,38 +39,46 @@ enable_board_feature()
# Import Wikipedia personality system
try:
- from wikipedia_personality_scraper import WikipediaPersonalityScraper, MEPPersonalityProfile
+ from wikipedia_personality_scraper import (
+ WikipediaPersonalityScraper,
+ MEPPersonalityProfile,
+ )
+
WIKIPEDIA_PERSONALITY_AVAILABLE = True
except ImportError:
WIKIPEDIA_PERSONALITY_AVAILABLE = False
- logger.warning("Wikipedia personality system not available. Using basic personality generation.")
+ logger.warning(
+ "Wikipedia personality system not available. Using basic personality generation."
+ )
@dataclass
class CostTracker:
"""Track costs and usage for budget management in parliamentary operations."""
-
+
total_tokens_used: int = 0
total_cost_estimate: float = 0.0
budget_limit: float = 200.0 # Default $200 budget for parliament
token_cost_per_1m: float = 0.15 # GPT-4o-mini cost
requests_made: int = 0
cache_hits: int = 0
-
+
def add_tokens(self, tokens: int):
"""Add tokens used and calculate cost."""
self.total_tokens_used += tokens
- self.total_cost_estimate = (self.total_tokens_used / 1_000_000) * self.token_cost_per_1m
+ self.total_cost_estimate = (
+ self.total_tokens_used / 1_000_000
+ ) * self.token_cost_per_1m
self.requests_made += 1
-
+
def add_cache_hit(self):
"""Record a cache hit."""
self.cache_hits += 1
-
+
def check_budget(self) -> bool:
"""Check if within budget."""
return self.total_cost_estimate <= self.budget_limit
-
+
def get_stats(self) -> Dict[str, Any]:
"""Get cost statistics."""
return {
@@ -86,14 +86,17 @@ class CostTracker:
"total_cost": self.total_cost_estimate,
"requests_made": self.requests_made,
"cache_hits": self.cache_hits,
- "cache_hit_rate": self.cache_hits / max(1, self.requests_made + self.cache_hits),
- "budget_remaining": max(0, self.budget_limit - self.total_cost_estimate)
+ "cache_hit_rate": self.cache_hits
+ / max(1, self.requests_made + self.cache_hits),
+ "budget_remaining": max(
+ 0, self.budget_limit - self.total_cost_estimate
+ ),
}
class ParliamentaryRole(str, Enum):
"""Enumeration of parliamentary roles and positions."""
-
+
PRESIDENT = "president"
VICE_PRESIDENT = "vice_president"
QUAESTOR = "quaestor"
@@ -105,7 +108,7 @@ class ParliamentaryRole(str, Enum):
class VoteType(str, Enum):
"""Enumeration of voting types in the European Parliament."""
-
+
ORDINARY_LEGISLATIVE_PROCEDURE = "ordinary_legislative_procedure"
CONSENT_PROCEDURE = "consent_procedure"
CONSULTATION_PROCEDURE = "consultation_procedure"
@@ -116,7 +119,7 @@ class VoteType(str, Enum):
class VoteResult(str, Enum):
"""Enumeration of possible vote results."""
-
+
PASSED = "passed"
FAILED = "failed"
TIED = "tied"
@@ -127,7 +130,7 @@ class VoteResult(str, Enum):
class ParliamentaryMember:
"""
Represents a Member of the European Parliament (MEP).
-
+
Attributes:
full_name: Full name of the MEP
country: Country the MEP represents
@@ -142,7 +145,7 @@ class ParliamentaryMember:
is_loaded: Whether the agent has been instantiated
wikipedia_info: Wikipedia-scraped personality information (optional)
"""
-
+
full_name: str
country: str
political_group: str
@@ -154,14 +157,16 @@ class ParliamentaryMember:
voting_weight: float = 1.0
agent: Optional[Agent] = None
is_loaded: bool = False
- wikipedia_info: Optional[Any] = None # Wikipedia personality information
+ wikipedia_info: Optional[Any] = (
+ None # Wikipedia personality information
+ )
@dataclass
class ParliamentaryBill:
"""
Represents a bill or legislative proposal in the European Parliament.
-
+
Attributes:
title: Title of the bill
description: Detailed description of the bill
@@ -173,7 +178,7 @@ class ParliamentaryBill:
status: Current status of the bill
amendments: List of proposed amendments
"""
-
+
title: str
description: str
bill_type: VoteType
@@ -189,7 +194,7 @@ class ParliamentaryBill:
class ParliamentaryVote:
"""
Represents a parliamentary vote on a bill or resolution.
-
+
Attributes:
bill: The bill being voted on
vote_type: Type of vote being conducted
@@ -202,7 +207,7 @@ class ParliamentaryVote:
individual_votes: Dictionary of individual MEP votes
reasoning: Dictionary of MEP reasoning for votes
"""
-
+
bill: ParliamentaryBill
vote_type: VoteType
date: datetime = field(default_factory=datetime.now)
@@ -219,7 +224,7 @@ class ParliamentaryVote:
class ParliamentaryCommittee:
"""
Represents a parliamentary committee.
-
+
Attributes:
name: Name of the committee
chair: Committee chairperson
@@ -228,20 +233,22 @@ class ParliamentaryCommittee:
responsibilities: Committee responsibilities
current_bills: Bills currently under consideration
"""
-
+
name: str
chair: str
vice_chair: str
members: List[str] = field(default_factory=list)
responsibilities: List[str] = field(default_factory=list)
- current_bills: List[ParliamentaryBill] = field(default_factory=list)
+ current_bills: List[ParliamentaryBill] = field(
+ default_factory=list
+ )
@dataclass
class PoliticalGroupBoard:
"""
Represents a political group as a Board of Directors with specialized expertise.
-
+
Attributes:
group_name: Name of the political group
members: List of MEPs in this group
@@ -252,7 +259,7 @@ class PoliticalGroupBoard:
total_meps: Total number of MEPs in this group
board_member_percentages: Dictionary mapping board members to their internal percentages
"""
-
+
group_name: str
members: List[str] = field(default_factory=list)
board_members: List[BoardMember] = field(default_factory=list)
@@ -260,14 +267,19 @@ class PoliticalGroupBoard:
voting_weight: float = 0.0
group_speaker: Optional[str] = None
total_meps: int = 0
- board_swarm: Optional[Any] = None # BoardOfDirectorsSwarm instance
- board_member_percentages: Dict[str, float] = field(default_factory=dict) # Internal percentages within group
+ board_swarm: Optional[Any] = (
+ None # BoardOfDirectorsSwarm instance
+ )
+ board_member_percentages: Dict[str, float] = field(
+ default_factory=dict
+ ) # Internal percentages within group
+
@dataclass
class ParliamentSpeaker:
"""
Represents the Parliament Speaker who aggregates decisions from all political groups.
-
+
Attributes:
name: Name of the speaker
agent: AI agent representing the speaker
@@ -275,10 +287,12 @@ class ParliamentSpeaker:
total_meps: Total number of MEPs in parliament
majority_threshold: Number of votes needed for majority
"""
-
+
name: str
agent: Optional[Agent] = None
- political_groups: Dict[str, PoliticalGroupBoard] = field(default_factory=dict)
+ political_groups: Dict[str, PoliticalGroupBoard] = field(
+ default_factory=dict
+ )
total_meps: int = 0
majority_threshold: int = 0
@@ -286,7 +300,7 @@ class ParliamentSpeaker:
class EuroSwarmParliament:
"""
A comprehensive simulation of the European Parliament with 700 MEPs.
-
+
This simulation provides democratic functionality including:
- Bill introduction and analysis
- Committee work and hearings
@@ -295,7 +309,7 @@ class EuroSwarmParliament:
- Political group coordination
- Amendment processes
"""
-
+
def __init__(
self,
eu_data_file: str = "EU.xml",
@@ -311,7 +325,7 @@ class EuroSwarmParliament:
):
"""
Initialize the EuroSwarm Parliament with cost optimization.
-
+
Args:
eu_data_file: Path to EU.xml file containing MEP data
parliament_size: Target size of the parliament (default: None = use all MEPs from EU.xml)
@@ -325,18 +339,22 @@ class EuroSwarmParliament:
verbose: Enable verbose logging
"""
self.eu_data_file = eu_data_file
- self.parliament_size = parliament_size # Will be set to actual MEP count if None
- self.enable_democratic_discussion = enable_democratic_discussion
+ self.parliament_size = (
+ parliament_size # Will be set to actual MEP count if None
+ )
+ self.enable_democratic_discussion = (
+ enable_democratic_discussion
+ )
self.enable_committee_work = enable_committee_work
self.enable_amendment_process = enable_amendment_process
self.enable_lazy_loading = enable_lazy_loading
self.enable_caching = enable_caching
self.batch_size = batch_size
self.verbose = verbose
-
+
# Initialize cost tracking
self.cost_tracker = CostTracker(budget_limit=budget_limit)
-
+
# Initialize parliamentary structures
self.meps: Dict[str, ParliamentaryMember] = {}
self.committees: Dict[str, ParliamentaryCommittee] = {}
@@ -344,155 +362,209 @@ class EuroSwarmParliament:
self.bills: List[ParliamentaryBill] = []
self.votes: List[ParliamentaryVote] = []
self.debates: List[Dict[str, Any]] = []
-
+
# Enhanced democratic structures
- self.political_group_boards: Dict[str, PoliticalGroupBoard] = {}
+ self.political_group_boards: Dict[
+ str, PoliticalGroupBoard
+ ] = {}
self.parliament_speaker: Optional[ParliamentSpeaker] = None
self.enable_hierarchical_democracy: bool = True
-
+
# Wikipedia personality system
- self.enable_wikipedia_personalities: bool = WIKIPEDIA_PERSONALITY_AVAILABLE
- self.personality_profiles: Dict[str, MEPPersonalityProfile] = {}
- self.personality_scraper: Optional[WikipediaPersonalityScraper] = None
-
+ self.enable_wikipedia_personalities: bool = (
+ WIKIPEDIA_PERSONALITY_AVAILABLE
+ )
+ self.personality_profiles: Dict[
+ str, MEPPersonalityProfile
+ ] = {}
+ self.personality_scraper: Optional[
+ WikipediaPersonalityScraper
+ ] = None
+
# Initialize caching
self.response_cache: Dict[str, str] = {}
-
+
# Load MEP data and initialize structures
self.meps = self._load_mep_data()
self.parliament_size = len(self.meps)
-
+
if self.verbose:
- logger.info(f"EuroSwarm Parliament initialized with {self.parliament_size} MEPs")
- logger.info(f"Lazy loading: {self.enable_lazy_loading}, Caching: {self.enable_caching}")
- logger.info(f"Budget limit: ${budget_limit}, Batch size: {batch_size}")
-
+ logger.info(
+ f"EuroSwarm Parliament initialized with {self.parliament_size} MEPs"
+ )
+ logger.info(
+ f"Lazy loading: {self.enable_lazy_loading}, Caching: {self.enable_caching}"
+ )
+ logger.info(
+ f"Budget limit: ${budget_limit}, Batch size: {batch_size}"
+ )
+
# Load Wikipedia personalities if enabled
if self.enable_wikipedia_personalities:
self._load_wikipedia_personalities()
-
+
# Initialize parliamentary structures
self.committees = self._create_committees()
self.political_groups = self._organize_political_groups()
-
+
# Initialize enhanced democratic structures
if self.enable_hierarchical_democracy:
self._create_political_group_boards()
self._create_parliament_speaker()
-
+
# Initialize leadership and democratic decision-making
self._create_parliamentary_leadership()
self._assign_committee_leadership()
-
+
if self.enable_democratic_discussion:
self._init_democratic_decision_making()
-
+
def _load_mep_data(self) -> Dict[str, ParliamentaryMember]:
"""
Load MEP data from official EU Parliament website and create parliamentary members with lazy loading.
Fetches real-time data from https://www.europarl.europa.eu/meps/en/full-list/xml
and scrapes Wikipedia information for each MEP.
-
+
Returns:
Dict[str, ParliamentaryMember]: Dictionary of MEPs
"""
meps = {}
-
+
try:
# Fetch XML data from official EU Parliament website
import requests
import re
-
- eu_xml_url = "https://www.europarl.europa.eu/meps/en/full-list/xml"
-
+
+ eu_xml_url = (
+ "https://www.europarl.europa.eu/meps/en/full-list/xml"
+ )
+
logger.info(f"Fetching MEP data from: {eu_xml_url}")
-
+
# Fetch the XML content
response = requests.get(eu_xml_url, timeout=30)
response.raise_for_status()
content = response.text
-
- logger.info(f"Successfully fetched {len(content)} characters of MEP data")
-
+
+ logger.info(
+ f"Successfully fetched {len(content)} characters of MEP data"
+ )
+
# Parse the XML content to extract MEP information
# The XML is properly formatted, so we can use ElementTree
try:
root = ET.fromstring(content)
mep_matches = []
-
- for mep_element in root.findall('mep'):
- full_name = mep_element.find('fullName').text.strip()
- country = mep_element.find('country').text.strip()
- political_group = mep_element.find('politicalGroup').text.strip()
- mep_id = mep_element.find('id').text.strip()
- national_party = mep_element.find('nationalPoliticalGroup').text.strip()
-
- mep_matches.append((full_name, country, political_group, mep_id, national_party))
-
- logger.info(f"Successfully parsed {len(mep_matches)} MEP entries from XML")
-
+
+ for mep_element in root.findall("mep"):
+ full_name = mep_element.find(
+ "fullName"
+ ).text.strip()
+ country = mep_element.find("country").text.strip()
+ political_group = mep_element.find(
+ "politicalGroup"
+ ).text.strip()
+ mep_id = mep_element.find("id").text.strip()
+ national_party = mep_element.find(
+ "nationalPoliticalGroup"
+ ).text.strip()
+
+ mep_matches.append(
+ (
+ full_name,
+ country,
+ political_group,
+ mep_id,
+ national_party,
+ )
+ )
+
+ logger.info(
+ f"Successfully parsed {len(mep_matches)} MEP entries from XML"
+ )
+
except ET.ParseError as xml_error:
logger.warning(f"XML parsing failed: {xml_error}")
# Fallback to regex parsing for malformed XML
- mep_pattern = r'(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) '
- mep_matches = re.findall(mep_pattern, content, re.DOTALL)
- logger.info(f"Fallback regex parsing found {len(mep_matches)} MEP entries")
-
+ mep_pattern = r"(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) "
+ mep_matches = re.findall(
+ mep_pattern, content, re.DOTALL
+ )
+ logger.info(
+ f"Fallback regex parsing found {len(mep_matches)} MEP entries"
+ )
+
# Initialize Wikipedia scraper if available
wikipedia_scraper = None
if WIKIPEDIA_PERSONALITY_AVAILABLE:
try:
wikipedia_scraper = WikipediaPersonalityScraper()
- logger.info("Wikipedia personality scraper initialized")
+ logger.info(
+ "Wikipedia personality scraper initialized"
+ )
except Exception as e:
- logger.warning(f"Failed to initialize Wikipedia scraper: {e}")
-
+ logger.warning(
+ f"Failed to initialize Wikipedia scraper: {e}"
+ )
+
# Process each MEP
for i, mep_data in enumerate(mep_matches):
- if len(mep_data) >= 5: # full_name, country, political_group, mep_id, national_party
+ if (
+ len(mep_data) >= 5
+ ): # full_name, country, political_group, mep_id, national_party
full_name = mep_data[0].strip()
country = mep_data[1].strip()
political_group = mep_data[2].strip()
mep_id = mep_data[3].strip()
national_party = mep_data[4].strip()
-
+
# Clean up political group name
- political_group = self._clean_political_group_name(political_group)
-
+ political_group = (
+ self._clean_political_group_name(
+ political_group
+ )
+ )
+
# Scrape Wikipedia information if scraper is available
wikipedia_info = None
if wikipedia_scraper:
try:
# Create MEP data dictionary for the scraper
mep_data = {
- 'full_name': full_name,
- 'country': country,
- 'political_group': political_group,
- 'national_party': national_party,
- 'mep_id': mep_id
+ "full_name": full_name,
+ "country": country,
+ "political_group": political_group,
+ "national_party": national_party,
+ "mep_id": mep_id,
}
-
+
# Create personality profile
- personality_profile = wikipedia_scraper.create_personality_profile(mep_data)
-
+ personality_profile = wikipedia_scraper.create_personality_profile(
+ mep_data
+ )
+
# Convert to dictionary format for storage
wikipedia_info = {
- 'personality_summary': personality_profile.summary,
- 'political_views': personality_profile.political_views,
- 'policy_focus': personality_profile.policy_focus,
- 'achievements': personality_profile.achievements,
- 'professional_background': personality_profile.professional_background,
- 'political_career': personality_profile.political_career,
- 'education': personality_profile.education,
- 'wikipedia_url': personality_profile.wikipedia_url
+ "personality_summary": personality_profile.summary,
+ "political_views": personality_profile.political_views,
+ "policy_focus": personality_profile.policy_focus,
+ "achievements": personality_profile.achievements,
+ "professional_background": personality_profile.professional_background,
+ "political_career": personality_profile.political_career,
+ "education": personality_profile.education,
+ "wikipedia_url": personality_profile.wikipedia_url,
}
-
+
if self.verbose:
- logger.info(f"Scraped Wikipedia info for {full_name}")
+ logger.info(
+ f"Scraped Wikipedia info for {full_name}"
+ )
except Exception as e:
if self.verbose:
- logger.debug(f"Failed to scrape Wikipedia for {full_name}: {e}")
-
+ logger.debug(
+ f"Failed to scrape Wikipedia for {full_name}: {e}"
+ )
+
# Create parliamentary member (without agent for lazy loading)
mep = ParliamentaryMember(
full_name=full_name,
@@ -500,78 +572,107 @@ class EuroSwarmParliament:
political_group=political_group,
national_party=national_party,
mep_id=mep_id,
- expertise_areas=self._generate_expertise_areas(political_group, country),
- committees=self._assign_committees(political_group),
+ expertise_areas=self._generate_expertise_areas(
+ political_group, country
+ ),
+ committees=self._assign_committees(
+ political_group
+ ),
agent=None, # Will be created on demand
is_loaded=False,
- wikipedia_info=wikipedia_info # Add Wikipedia information
+ wikipedia_info=wikipedia_info, # Add Wikipedia information
)
-
+
meps[full_name] = mep
-
+
# Limit processing for performance (can be adjusted)
- if len(meps) >= 705: # Standard EU Parliament size
+ if (
+ len(meps) >= 705
+ ): # Standard EU Parliament size
break
-
+
# Set parliament size to actual number of MEPs loaded
if self.parliament_size is None:
self.parliament_size = len(meps)
-
- logger.info(f"Successfully loaded {len(meps)} MEP profiles from official EU data (lazy loading enabled)")
+
+ logger.info(
+ f"Successfully loaded {len(meps)} MEP profiles from official EU data (lazy loading enabled)"
+ )
if wikipedia_scraper:
- logger.info(f"Wikipedia scraping completed for {len([m for m in meps.values() if m.wikipedia_info])} MEPs")
-
+ logger.info(
+ f"Wikipedia scraping completed for {len([m for m in meps.values() if m.wikipedia_info])} MEPs"
+ )
+
except Exception as e:
- logger.error(f"Error loading MEP data from official website: {e}")
+ logger.error(
+ f"Error loading MEP data from official website: {e}"
+ )
logger.info("Falling back to local EU.xml file...")
-
+
# Fallback to local file
try:
meps = self._load_mep_data_from_local_file()
except Exception as local_error:
- logger.error(f"Error loading local MEP data: {local_error}")
+ logger.error(
+ f"Error loading local MEP data: {local_error}"
+ )
# Create fallback MEPs if both methods fail
meps = self._create_fallback_meps()
-
+
if self.parliament_size is None:
self.parliament_size = len(meps)
-
+
return meps
-
- def _load_mep_data_from_local_file(self) -> Dict[str, ParliamentaryMember]:
+
+ def _load_mep_data_from_local_file(
+ self,
+ ) -> Dict[str, ParliamentaryMember]:
"""
Fallback method to load MEP data from local EU.xml file.
-
+
Returns:
Dict[str, ParliamentaryMember]: Dictionary of MEPs
"""
meps = {}
-
+
try:
# Construct the full path to EU.xml relative to project root
import os
- project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
- eu_data_path = os.path.join(project_root, self.eu_data_file)
-
+
+ project_root = os.path.dirname(
+ os.path.dirname(
+ os.path.dirname(os.path.abspath(__file__))
+ )
+ )
+ eu_data_path = os.path.join(
+ project_root, self.eu_data_file
+ )
+
# Read the XML file content
- with open(eu_data_path, 'r', encoding='utf-8') as f:
+ with open(eu_data_path, "r", encoding="utf-8") as f:
content = f.read()
-
+
# Use regex to extract MEP data since the XML is malformed
import re
-
+
# Find all MEP blocks
- mep_pattern = r'\s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s* '
+ mep_pattern = r"\s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s* "
mep_matches = re.findall(mep_pattern, content, re.DOTALL)
-
- for full_name, country, political_group, mep_id, national_party in mep_matches:
+
+ for (
+ full_name,
+ country,
+ political_group,
+ mep_id,
+ national_party,
+ ) in mep_matches:
# Clean up the data
full_name = full_name.strip()
country = country.strip()
political_group = political_group.strip()
mep_id = mep_id.strip()
national_party = national_party.strip()
-
+
# Create parliamentary member (without agent for lazy loading)
mep = ParliamentaryMember(
full_name=full_name,
@@ -579,166 +680,183 @@ class EuroSwarmParliament:
political_group=political_group,
national_party=national_party,
mep_id=mep_id,
- expertise_areas=self._generate_expertise_areas(political_group, country),
- committees=self._assign_committees(political_group),
+ expertise_areas=self._generate_expertise_areas(
+ political_group, country
+ ),
+ committees=self._assign_committees(
+ political_group
+ ),
agent=None, # Will be created on demand
- is_loaded=False
+ is_loaded=False,
)
-
+
meps[full_name] = mep
-
- logger.info(f"Loaded {len(meps)} MEP profiles from local EU.xml file (lazy loading enabled)")
-
+
+ logger.info(
+ f"Loaded {len(meps)} MEP profiles from local EU.xml file (lazy loading enabled)"
+ )
+
except Exception as e:
logger.error(f"Error loading local MEP data: {e}")
raise
-
+
return meps
-
- def _clean_political_group_name(self, political_group: str) -> str:
+
+ def _clean_political_group_name(
+ self, political_group: str
+ ) -> str:
"""
Clean and standardize political group names.
-
+
Args:
political_group: Raw political group name
-
+
Returns:
str: Cleaned political group name
"""
# Map common variations to standard names
group_mapping = {
- 'EPP': 'Group of the European People\'s Party (Christian Democrats)',
- 'S&D': 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament',
- 'Renew': 'Renew Europe Group',
- 'Greens/EFA': 'Group of the Greens/European Free Alliance',
- 'ECR': 'European Conservatives and Reformists Group',
- 'ID': 'Identity and Democracy Group',
- 'GUE/NGL': 'The Left group in the European Parliament - GUE/NGL',
- 'Non-attached': 'Non-attached Members'
+ "EPP": "Group of the European People's Party (Christian Democrats)",
+ "S&D": "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament",
+ "Renew": "Renew Europe Group",
+ "Greens/EFA": "Group of the Greens/European Free Alliance",
+ "ECR": "European Conservatives and Reformists Group",
+ "ID": "Identity and Democracy Group",
+ "GUE/NGL": "The Left group in the European Parliament - GUE/NGL",
+ "Non-attached": "Non-attached Members",
}
-
+
# Check for exact matches first
for key, value in group_mapping.items():
if political_group.strip() == key:
return value
-
+
# Check for partial matches
political_group_lower = political_group.lower()
for key, value in group_mapping.items():
if key.lower() in political_group_lower:
return value
-
+
# Return original if no match found
return political_group.strip()
-
- def _generate_national_party(self, country: str, political_group: str) -> str:
+
+ def _generate_national_party(
+ self, country: str, political_group: str
+ ) -> str:
"""
Generate a realistic national party name based on country and political group.
-
+
Args:
country: Country of the MEP
political_group: Political group affiliation
-
+
Returns:
str: Generated national party name
"""
# Map of countries to common parties for each political group
party_mapping = {
- 'Germany': {
- 'Group of the European People\'s Party (Christian Democrats)': 'Christlich Demokratische Union Deutschlands',
- 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament': 'Sozialdemokratische Partei Deutschlands',
- 'Renew Europe Group': 'Freie Demokratische Partei',
- 'Group of the Greens/European Free Alliance': 'Bündnis 90/Die Grünen',
- 'European Conservatives and Reformists Group': 'Alternative für Deutschland',
- 'Identity and Democracy Group': 'Alternative für Deutschland',
- 'The Left group in the European Parliament - GUE/NGL': 'Die Linke'
+ "Germany": {
+ "Group of the European People's Party (Christian Democrats)": "Christlich Demokratische Union Deutschlands",
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": "Sozialdemokratische Partei Deutschlands",
+ "Renew Europe Group": "Freie Demokratische Partei",
+ "Group of the Greens/European Free Alliance": "Bündnis 90/Die Grünen",
+ "European Conservatives and Reformists Group": "Alternative für Deutschland",
+ "Identity and Democracy Group": "Alternative für Deutschland",
+ "The Left group in the European Parliament - GUE/NGL": "Die Linke",
},
- 'France': {
- 'Group of the European People\'s Party (Christian Democrats)': 'Les RƩpublicains',
- 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament': 'Parti Socialiste',
- 'Renew Europe Group': 'Renaissance',
- 'Group of the Greens/European Free Alliance': 'Europe Ćcologie Les Verts',
- 'European Conservatives and Reformists Group': 'Rassemblement National',
- 'Identity and Democracy Group': 'Rassemblement National',
- 'The Left group in the European Parliament - GUE/NGL': 'La France Insoumise'
+ "France": {
+ "Group of the European People's Party (Christian Democrats)": "Les RƩpublicains",
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": "Parti Socialiste",
+ "Renew Europe Group": "Renaissance",
+ "Group of the Greens/European Free Alliance": "Europe Ćcologie Les Verts",
+ "European Conservatives and Reformists Group": "Rassemblement National",
+ "Identity and Democracy Group": "Rassemblement National",
+ "The Left group in the European Parliament - GUE/NGL": "La France Insoumise",
+ },
+ "Italy": {
+ "Group of the European People's Party (Christian Democrats)": "Forza Italia",
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": "Partito Democratico",
+ "Renew Europe Group": "Italia Viva",
+ "Group of the Greens/European Free Alliance": "Federazione dei Verdi",
+ "European Conservatives and Reformists Group": "Fratelli d'Italia",
+ "Identity and Democracy Group": "Lega",
+ "The Left group in the European Parliament - GUE/NGL": "Movimento 5 Stelle",
},
- 'Italy': {
- 'Group of the European People\'s Party (Christian Democrats)': 'Forza Italia',
- 'Group of the Progressive Alliance of Socialists and Democrats in the European Parliament': 'Partito Democratico',
- 'Renew Europe Group': 'Italia Viva',
- 'Group of the Greens/European Free Alliance': 'Federazione dei Verdi',
- 'European Conservatives and Reformists Group': 'Fratelli d\'Italia',
- 'Identity and Democracy Group': 'Lega',
- 'The Left group in the European Parliament - GUE/NGL': 'Movimento 5 Stelle'
- }
}
-
+
# Return mapped party or generate a generic one
- if country in party_mapping and political_group in party_mapping[country]:
+ if (
+ country in party_mapping
+ and political_group in party_mapping[country]
+ ):
return party_mapping[country][political_group]
else:
return f"{country} National Party"
-
+
def _load_mep_agent(self, mep_name: str) -> Optional[Agent]:
"""
Lazy load a single MEP agent on demand.
-
+
Args:
mep_name: Name of the MEP to load
-
+
Returns:
Optional[Agent]: Loaded agent or None if not found
"""
if mep_name not in self.meps:
return None
-
+
mep = self.meps[mep_name]
-
+
# Check if already loaded
if mep.is_loaded and mep.agent:
return mep.agent
-
+
# Check budget before creating agent
if not self.cost_tracker.check_budget():
- logger.warning(f"Budget exceeded. Cannot load MEP agent {mep_name}")
+ logger.warning(
+ f"Budget exceeded. Cannot load MEP agent {mep_name}"
+ )
return None
-
+
# Create agent
mep.agent = self._create_mep_agent(mep)
mep.is_loaded = True
-
+
if self.verbose:
logger.info(f"Loaded MEP agent: {mep_name}")
-
+
return mep.agent
-
- def _load_mep_agents_batch(self, mep_names: List[str]) -> List[Agent]:
+
+ def _load_mep_agents_batch(
+ self, mep_names: List[str]
+ ) -> List[Agent]:
"""
Load multiple MEP agents in a batch.
-
+
Args:
mep_names: List of MEP names to load
-
+
Returns:
List[Agent]: List of loaded agents
"""
loaded_agents = []
-
+
for mep_name in mep_names:
agent = self._load_mep_agent(mep_name)
if agent:
loaded_agents.append(agent)
-
+
return loaded_agents
-
+
def _get_cache_key(self, task: str, mep_names: List[str]) -> str:
"""
Generate a cache key for a task and MEP combination.
-
+
Args:
task: Task to execute
mep_names: List of MEP names
-
+
Returns:
str: Cache key
"""
@@ -746,32 +864,32 @@ class EuroSwarmParliament:
sorted_meps = sorted(mep_names)
content = f"{task}:{':'.join(sorted_meps)}"
return hashlib.md5(content.encode()).hexdigest()
-
+
def _check_cache(self, cache_key: str) -> Optional[str]:
"""
Check if a response is cached.
-
+
Args:
cache_key: Cache key to check
-
+
Returns:
Optional[str]: Cached response or None
"""
if not self.enable_caching:
return None
-
+
cached_response = self.response_cache.get(cache_key)
if cached_response:
self.cost_tracker.add_cache_hit()
if self.verbose:
logger.info(f"Cache hit for key: {cache_key[:20]}...")
-
+
return cached_response
-
+
def _cache_response(self, cache_key: str, response: str):
"""
Cache a response.
-
+
Args:
cache_key: Cache key
response: Response to cache
@@ -779,51 +897,83 @@ class EuroSwarmParliament:
if self.enable_caching:
self.response_cache[cache_key] = response
if self.verbose:
- logger.info(f"Cached response for key: {cache_key[:20]}...")
-
- def _generate_expertise_areas(self, political_group: str, country: str) -> List[str]:
+ logger.info(
+ f"Cached response for key: {cache_key[:20]}..."
+ )
+
+ def _generate_expertise_areas(
+ self, political_group: str, country: str
+ ) -> List[str]:
"""
Generate expertise areas based on political group and country.
-
+
Args:
political_group: MEP's political group
country: MEP's country
-
+
Returns:
List[str]: List of expertise areas
"""
expertise_mapping = {
"Group of the European People's Party (Christian Democrats)": [
- "Economic Policy", "Agriculture", "Regional Development", "Christian Values"
+ "Economic Policy",
+ "Agriculture",
+ "Regional Development",
+ "Christian Values",
],
"Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
- "Social Policy", "Labor Rights", "Healthcare", "Education"
+ "Social Policy",
+ "Labor Rights",
+ "Healthcare",
+ "Education",
],
"Renew Europe Group": [
- "Digital Policy", "Innovation", "Trade", "Liberal Values"
+ "Digital Policy",
+ "Innovation",
+ "Trade",
+ "Liberal Values",
],
"Group of the Greens/European Free Alliance": [
- "Environmental Policy", "Climate Change", "Renewable Energy", "Human Rights"
+ "Environmental Policy",
+ "Climate Change",
+ "Renewable Energy",
+ "Human Rights",
],
"European Conservatives and Reformists Group": [
- "Sovereignty", "Defense", "Traditional Values", "Economic Freedom"
+ "Sovereignty",
+ "Defense",
+ "Traditional Values",
+ "Economic Freedom",
],
"The Left group in the European Parliament - GUE/NGL": [
- "Workers' Rights", "Social Justice", "Anti-Austerity", "Public Services"
+ "Workers' Rights",
+ "Social Justice",
+ "Anti-Austerity",
+ "Public Services",
],
"Patriots for Europe Group": [
- "National Sovereignty", "Border Security", "Cultural Identity", "Law and Order"
+ "National Sovereignty",
+ "Border Security",
+ "Cultural Identity",
+ "Law and Order",
],
"Europe of Sovereign Nations Group": [
- "National Independence", "Sovereignty", "Traditional Values", "Security"
+ "National Independence",
+ "Sovereignty",
+ "Traditional Values",
+ "Security",
],
"Non-attached Members": [
- "Independent Policy", "Cross-cutting Issues", "Specialized Topics"
- ]
+ "Independent Policy",
+ "Cross-cutting Issues",
+ "Specialized Topics",
+ ],
}
-
- base_expertise = expertise_mapping.get(political_group, ["General Policy"])
-
+
+ base_expertise = expertise_mapping.get(
+ political_group, ["General Policy"]
+ )
+
# Add country-specific expertise
country_expertise = {
"Germany": ["Industrial Policy", "Manufacturing"],
@@ -837,66 +987,84 @@ class EuroSwarmParliament:
"Sweden": ["Environmental Policy", "Social Welfare"],
"Denmark": ["Green Technology", "Welfare State"],
}
-
+
if country in country_expertise:
base_expertise.extend(country_expertise[country])
-
+
return base_expertise[:5] # Limit to 5 expertise areas
-
+
def _assign_committees(self, political_group: str) -> List[str]:
"""
Assign committees based on political group preferences.
-
+
Args:
political_group: MEP's political group
-
+
Returns:
List[str]: List of committee assignments
"""
committee_mapping = {
"Group of the European People's Party (Christian Democrats)": [
- "Agriculture and Rural Development", "Economic and Monetary Affairs", "Regional Development"
+ "Agriculture and Rural Development",
+ "Economic and Monetary Affairs",
+ "Regional Development",
],
"Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
- "Employment and Social Affairs", "Environment, Public Health and Food Safety", "Civil Liberties"
+ "Employment and Social Affairs",
+ "Environment, Public Health and Food Safety",
+ "Civil Liberties",
],
"Renew Europe Group": [
- "Industry, Research and Energy", "Internal Market and Consumer Protection", "Legal Affairs"
+ "Industry, Research and Energy",
+ "Internal Market and Consumer Protection",
+ "Legal Affairs",
],
"Group of the Greens/European Free Alliance": [
- "Environment, Public Health and Food Safety", "Transport and Tourism", "Development"
+ "Environment, Public Health and Food Safety",
+ "Transport and Tourism",
+ "Development",
],
"European Conservatives and Reformists Group": [
- "Foreign Affairs", "Security and Defence", "Budgetary Control"
+ "Foreign Affairs",
+ "Security and Defence",
+ "Budgetary Control",
],
"The Left group in the European Parliament - GUE/NGL": [
- "International Trade", "Development", "Civil Liberties"
+ "International Trade",
+ "Development",
+ "Civil Liberties",
],
"Patriots for Europe Group": [
- "Civil Liberties", "Security and Defence", "Budgetary Control"
+ "Civil Liberties",
+ "Security and Defence",
+ "Budgetary Control",
],
"Europe of Sovereign Nations Group": [
- "Foreign Affairs", "Security and Defence", "Civil Liberties"
+ "Foreign Affairs",
+ "Security and Defence",
+ "Civil Liberties",
],
"Non-attached Members": [
- "Petitions", "Budgetary Control", "Legal Affairs"
- ]
+ "Petitions",
+ "Budgetary Control",
+ "Legal Affairs",
+ ],
}
-
+
return committee_mapping.get(political_group, ["Petitions"])
-
+
def _create_mep_agent(self, mep: ParliamentaryMember) -> Agent:
"""
Create an AI agent representing an MEP.
-
+
Args:
mep: Parliamentary member data
-
+
Returns:
Agent: AI agent representing the MEP
"""
system_prompt = self._generate_mep_system_prompt(mep)
-
+
return Agent(
agent_name=f"MEP_{mep.full_name.replace(' ', '_')}",
system_prompt=system_prompt,
@@ -904,18 +1072,20 @@ class EuroSwarmParliament:
max_loops=3,
verbose=self.verbose,
)
-
- def _generate_mep_system_prompt(self, mep: ParliamentaryMember) -> str:
+
+ def _generate_mep_system_prompt(
+ self, mep: ParliamentaryMember
+ ) -> str:
"""
Generate a comprehensive system prompt for an MEP agent with Wikipedia personality data.
-
+
Args:
mep: Parliamentary member data
-
+
Returns:
str: System prompt for the MEP agent
"""
-
+
# Base prompt structure
prompt = f"""You are {mep.full_name}, a Member of the European Parliament (MEP) representing {mep.country}.
@@ -927,7 +1097,7 @@ POLITICAL BACKGROUND:
- Areas of Expertise: {', '.join(mep.expertise_areas)}
"""
-
+
# Add Wikipedia personality data if available
if mep.wikipedia_info and self.enable_wikipedia_personalities:
prompt += f"""
@@ -948,7 +1118,7 @@ POLITICAL VIEWS AND POSITIONS:
- Policy Focus Areas: {', '.join(mep.expertise_areas)}
- Professional Background: Parliamentary service
"""
-
+
# Add core principles
prompt += f"""
CORE PRINCIPLES:
@@ -988,50 +1158,94 @@ When responding to parliamentary matters, consider:
Remember: You are a real MEP with specific political views, expertise, and responsibilities. Act accordingly in all parliamentary interactions.
"""
-
+
return prompt
-
+
def _create_fallback_meps(self) -> Dict[str, ParliamentaryMember]:
"""
Create fallback MEPs if EU.xml file cannot be loaded.
-
+
Returns:
Dict[str, ParliamentaryMember]: Dictionary of fallback MEPs
"""
fallback_meps = {}
-
+
# Create a representative sample of MEPs
sample_data = [
- ("Jean-Claude Juncker", "Luxembourg", "Group of the European People's Party (Christian Democrats)", "Parti chrƩtien social luxembourgeois"),
- ("Ursula von der Leyen", "Germany", "Group of the European People's Party (Christian Democrats)", "Christlich Demokratische Union Deutschlands"),
- ("Roberta Metsola", "Malta", "Group of the European People's Party (Christian Democrats)", "Partit Nazzjonalista"),
- ("Iratxe GarcĆa PĆ©rez", "Spain", "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament", "Partido Socialista Obrero EspaƱol"),
- ("ValƩrie Hayer", "France", "Renew Europe Group", "Renaissance"),
- ("Philippe Lamberts", "Belgium", "Group of the Greens/European Free Alliance", "Ecolo"),
- ("Raffaele Fitto", "Italy", "European Conservatives and Reformists Group", "Fratelli d'Italia"),
- ("Manon Aubry", "France", "The Left group in the European Parliament - GUE/NGL", "La France Insoumise"),
+ (
+ "Jean-Claude Juncker",
+ "Luxembourg",
+ "Group of the European People's Party (Christian Democrats)",
+ "Parti chrƩtien social luxembourgeois",
+ ),
+ (
+ "Ursula von der Leyen",
+ "Germany",
+ "Group of the European People's Party (Christian Democrats)",
+ "Christlich Demokratische Union Deutschlands",
+ ),
+ (
+ "Roberta Metsola",
+ "Malta",
+ "Group of the European People's Party (Christian Democrats)",
+ "Partit Nazzjonalista",
+ ),
+ (
+ "Iratxe GarcĆa PĆ©rez",
+ "Spain",
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament",
+ "Partido Socialista Obrero EspaƱol",
+ ),
+ (
+ "ValƩrie Hayer",
+ "France",
+ "Renew Europe Group",
+ "Renaissance",
+ ),
+ (
+ "Philippe Lamberts",
+ "Belgium",
+ "Group of the Greens/European Free Alliance",
+ "Ecolo",
+ ),
+ (
+ "Raffaele Fitto",
+ "Italy",
+ "European Conservatives and Reformists Group",
+ "Fratelli d'Italia",
+ ),
+ (
+ "Manon Aubry",
+ "France",
+ "The Left group in the European Parliament - GUE/NGL",
+ "La France Insoumise",
+ ),
]
-
- for i, (name, country, group, party) in enumerate(sample_data):
+
+ for i, (name, country, group, party) in enumerate(
+ sample_data
+ ):
mep = ParliamentaryMember(
full_name=name,
country=country,
political_group=group,
national_party=party,
mep_id=f"fallback_{i}",
- expertise_areas=self._generate_expertise_areas(group, country),
+ expertise_areas=self._generate_expertise_areas(
+ group, country
+ ),
committees=self._assign_committees(group),
agent=None, # Will be created on demand
- is_loaded=False
+ is_loaded=False,
)
fallback_meps[name] = mep
-
+
return fallback_meps
-
+
def _create_committees(self) -> Dict[str, ParliamentaryCommittee]:
"""
Create parliamentary committees.
-
+
Returns:
Dict[str, ParliamentaryCommittee]: Dictionary of committees
"""
@@ -1040,106 +1254,171 @@ Remember: You are a real MEP with specific political views, expertise, and respo
name="Agriculture and Rural Development",
chair="",
vice_chair="",
- responsibilities=["Agricultural policy", "Rural development", "Food safety"]
+ responsibilities=[
+ "Agricultural policy",
+ "Rural development",
+ "Food safety",
+ ],
),
"Budgetary Control": ParliamentaryCommittee(
name="Budgetary Control",
chair="",
vice_chair="",
- responsibilities=["Budget oversight", "Financial control", "Audit reports"]
+ responsibilities=[
+ "Budget oversight",
+ "Financial control",
+ "Audit reports",
+ ],
),
"Civil Liberties, Justice and Home Affairs": ParliamentaryCommittee(
name="Civil Liberties, Justice and Home Affairs",
chair="",
vice_chair="",
- responsibilities=["Civil rights", "Justice", "Home affairs", "Immigration"]
+ responsibilities=[
+ "Civil rights",
+ "Justice",
+ "Home affairs",
+ "Immigration",
+ ],
),
"Development": ParliamentaryCommittee(
name="Development",
chair="",
vice_chair="",
- responsibilities=["Development cooperation", "Humanitarian aid", "International relations"]
+ responsibilities=[
+ "Development cooperation",
+ "Humanitarian aid",
+ "International relations",
+ ],
),
"Economic and Monetary Affairs": ParliamentaryCommittee(
name="Economic and Monetary Affairs",
chair="",
vice_chair="",
- responsibilities=["Economic policy", "Monetary policy", "Financial services"]
+ responsibilities=[
+ "Economic policy",
+ "Monetary policy",
+ "Financial services",
+ ],
),
"Employment and Social Affairs": ParliamentaryCommittee(
name="Employment and Social Affairs",
chair="",
vice_chair="",
- responsibilities=["Employment policy", "Social policy", "Working conditions"]
+ responsibilities=[
+ "Employment policy",
+ "Social policy",
+ "Working conditions",
+ ],
),
"Environment, Public Health and Food Safety": ParliamentaryCommittee(
name="Environment, Public Health and Food Safety",
chair="",
vice_chair="",
- responsibilities=["Environmental policy", "Public health", "Food safety"]
+ responsibilities=[
+ "Environmental policy",
+ "Public health",
+ "Food safety",
+ ],
),
"Foreign Affairs": ParliamentaryCommittee(
name="Foreign Affairs",
chair="",
vice_chair="",
- responsibilities=["Foreign policy", "International relations", "Security policy"]
+ responsibilities=[
+ "Foreign policy",
+ "International relations",
+ "Security policy",
+ ],
),
"Industry, Research and Energy": ParliamentaryCommittee(
name="Industry, Research and Energy",
chair="",
vice_chair="",
- responsibilities=["Industrial policy", "Research", "Energy policy"]
+ responsibilities=[
+ "Industrial policy",
+ "Research",
+ "Energy policy",
+ ],
),
"Internal Market and Consumer Protection": ParliamentaryCommittee(
name="Internal Market and Consumer Protection",
chair="",
vice_chair="",
- responsibilities=["Internal market", "Consumer protection", "Digital policy"]
+ responsibilities=[
+ "Internal market",
+ "Consumer protection",
+ "Digital policy",
+ ],
),
"International Trade": ParliamentaryCommittee(
name="International Trade",
chair="",
vice_chair="",
- responsibilities=["Trade policy", "International agreements", "Market access"]
+ responsibilities=[
+ "Trade policy",
+ "International agreements",
+ "Market access",
+ ],
),
"Legal Affairs": ParliamentaryCommittee(
name="Legal Affairs",
chair="",
vice_chair="",
- responsibilities=["Legal matters", "Institutional affairs", "Constitutional issues"]
+ responsibilities=[
+ "Legal matters",
+ "Institutional affairs",
+ "Constitutional issues",
+ ],
),
"Petitions": ParliamentaryCommittee(
name="Petitions",
chair="",
vice_chair="",
- responsibilities=["Citizen petitions", "Ombudsman", "Citizen rights"]
+ responsibilities=[
+ "Citizen petitions",
+ "Ombudsman",
+ "Citizen rights",
+ ],
),
"Regional Development": ParliamentaryCommittee(
name="Regional Development",
chair="",
vice_chair="",
- responsibilities=["Regional policy", "Cohesion policy", "Urban development"]
+ responsibilities=[
+ "Regional policy",
+ "Cohesion policy",
+ "Urban development",
+ ],
),
"Security and Defence": ParliamentaryCommittee(
name="Security and Defence",
chair="",
vice_chair="",
- responsibilities=["Security policy", "Defence", "Military cooperation"]
+ responsibilities=[
+ "Security policy",
+ "Defence",
+ "Military cooperation",
+ ],
),
"Transport and Tourism": ParliamentaryCommittee(
name="Transport and Tourism",
chair="",
vice_chair="",
- responsibilities=["Transport policy", "Tourism", "Infrastructure"]
+ responsibilities=[
+ "Transport policy",
+ "Tourism",
+ "Infrastructure",
+ ],
),
}
-
+
return committees
-
+
def _organize_political_groups(self) -> Dict[str, List[str]]:
"""
Organize MEPs by political groups.
-
+
Returns:
Dict[str, List[str]]: Dictionary mapping political groups to MEP names
"""
@@ -1150,75 +1429,91 @@ Remember: You are a real MEP with specific political views, expertise, and respo
groups[group] = []
groups[group].append(mep_name)
return groups
-
+
def _create_parliamentary_leadership(self):
"""Create parliamentary leadership positions."""
# Assign President (from largest political group)
- largest_group = max(self.political_groups.items(), key=lambda x: len(x[1]))
+ largest_group = max(
+ self.political_groups.items(), key=lambda x: len(x[1])
+ )
president_candidate = largest_group[1][0]
- self.meps[president_candidate].role = ParliamentaryRole.PRESIDENT
-
+ self.meps[president_candidate].role = (
+ ParliamentaryRole.PRESIDENT
+ )
+
# Assign Vice Presidents
vice_presidents = []
for group_name, meps in self.political_groups.items():
if group_name != largest_group[0] and len(meps) > 0:
vice_presidents.append(meps[0])
- if len(vice_presidents) >= 14: # EP has 14 Vice Presidents
+ if (
+ len(vice_presidents) >= 14
+ ): # EP has 14 Vice Presidents
break
-
+
for vp in vice_presidents:
self.meps[vp].role = ParliamentaryRole.VICE_PRESIDENT
-
+
# Assign Committee Chairs
self._assign_committee_leadership()
-
+
def _assign_committee_leadership(self):
"""Assign committee chairs and vice-chairs based on political group representation."""
committee_names = list(self.committees.keys())
-
+
# Distribute committee leadership among political groups
group_assignments = {}
for group_name, meps in self.political_groups.items():
if len(meps) > 0:
group_assignments[group_name] = meps
-
+
committee_index = 0
for group_name, meps in group_assignments.items():
if committee_index >= len(committee_names):
break
-
+
committee_name = committee_names[committee_index]
chair = meps[0]
vice_chair = meps[1] if len(meps) > 1 else ""
-
+
self.committees[committee_name].chair = chair
self.committees[committee_name].vice_chair = vice_chair
-
+
# Update MEP roles
self.meps[chair].role = ParliamentaryRole.COMMITTEE_CHAIR
if vice_chair:
- self.meps[vice_chair].role = ParliamentaryRole.COMMITTEE_VICE_CHAIR
-
+ self.meps[vice_chair].role = (
+ ParliamentaryRole.COMMITTEE_VICE_CHAIR
+ )
+
committee_index += 1
-
+
def _init_democratic_decision_making(self):
"""Initialize democratic decision-making using Board of Directors pattern."""
# Create parliamentary board members for democratic decision-making
board_members = []
-
+
# Add political group leaders
for group_name, meps in self.political_groups.items():
if len(meps) > 0:
leader = meps[0]
- if leader in self.meps and self.meps[leader].agent is not None:
+ if (
+ leader in self.meps
+ and self.meps[leader].agent is not None
+ ):
board_member = BoardMember(
agent=self.meps[leader].agent,
role=BoardMemberRole.EXECUTIVE_DIRECTOR,
- voting_weight=len(meps) / len(self.meps), # Weight based on group size
- expertise_areas=self.meps[leader].expertise_areas
+ voting_weight=len(meps)
+ / len(
+ self.meps
+ ), # Weight based on group size
+ expertise_areas=self.meps[
+ leader
+ ].expertise_areas,
)
board_members.append(board_member)
-
+
# Ensure we have at least one board member
if not board_members and len(self.meps) > 0:
# Use the first available MEP as a fallback
@@ -1229,15 +1524,19 @@ Remember: You are a real MEP with specific political views, expertise, and respo
agent=first_mep.agent,
role=BoardMemberRole.EXECUTIVE_DIRECTOR,
voting_weight=1.0,
- expertise_areas=first_mep.expertise_areas
+ expertise_areas=first_mep.expertise_areas,
)
board_members.append(board_member)
-
+
# Create the democratic decision-making swarm
if board_members:
# Extract agents from board members for the parent class
- agents = [member.agent for member in board_members if member.agent is not None]
-
+ agents = [
+ member.agent
+ for member in board_members
+ if member.agent is not None
+ ]
+
self.democratic_swarm = BoardOfDirectorsSwarm(
name="EuroSwarm Parliament Democratic Council",
description="Democratic decision-making body for the European Parliament",
@@ -1250,87 +1549,147 @@ Remember: You are a real MEP with specific political views, expertise, and respo
enable_consensus=True,
)
else:
- logger.warning("No valid board members found for democratic decision-making")
+ logger.warning(
+ "No valid board members found for democratic decision-making"
+ )
self.democratic_swarm = None
-
+
def _create_political_group_boards(self):
"""Create Board of Directors for each political group with specialized expertise and individual percentages."""
-
+
# Define specialized expertise areas for governance
expertise_areas = {
- "economics": ["Economic Policy", "Trade", "Budget", "Taxation", "Financial Services"],
- "law": ["Legal Affairs", "Justice", "Civil Liberties", "Constitutional Affairs"],
- "environment": ["Environment", "Climate Action", "Energy", "Transport"],
- "social": ["Employment", "Social Affairs", "Health", "Education", "Culture"],
- "foreign": ["Foreign Affairs", "Security", "Defense", "International Trade"],
- "agriculture": ["Agriculture", "Rural Development", "Food Safety"],
- "technology": ["Digital Affairs", "Industry", "Research", "Innovation"],
- "regional": ["Regional Development", "Cohesion Policy", "Urban Planning"]
+ "economics": [
+ "Economic Policy",
+ "Trade",
+ "Budget",
+ "Taxation",
+ "Financial Services",
+ ],
+ "law": [
+ "Legal Affairs",
+ "Justice",
+ "Civil Liberties",
+ "Constitutional Affairs",
+ ],
+ "environment": [
+ "Environment",
+ "Climate Action",
+ "Energy",
+ "Transport",
+ ],
+ "social": [
+ "Employment",
+ "Social Affairs",
+ "Health",
+ "Education",
+ "Culture",
+ ],
+ "foreign": [
+ "Foreign Affairs",
+ "Security",
+ "Defense",
+ "International Trade",
+ ],
+ "agriculture": [
+ "Agriculture",
+ "Rural Development",
+ "Food Safety",
+ ],
+ "technology": [
+ "Digital Affairs",
+ "Industry",
+ "Research",
+ "Innovation",
+ ],
+ "regional": [
+ "Regional Development",
+ "Cohesion Policy",
+ "Urban Planning",
+ ],
}
-
+
total_meps = len(self.meps)
-
+
for group_name, mep_list in self.political_groups.items():
if not mep_list:
continue
-
+
# Calculate voting weight (percentage of parliament)
voting_weight = len(mep_list) / total_meps
-
+
# Assign specialized expertise areas based on political group
- group_expertise = self._assign_group_expertise(group_name, expertise_areas)
-
+ group_expertise = self._assign_group_expertise(
+ group_name, expertise_areas
+ )
+
# Create board members with specialized roles and individual percentages
board_members = []
group_speaker = None
board_member_percentages = {}
-
+
# Select group speaker (CEO) - usually the first MEP in the group
if mep_list and mep_list[0] in self.meps:
group_speaker = mep_list[0]
speaker_mep = self.meps[group_speaker]
-
+
# Create group speaker board member with highest percentage
if speaker_mep.agent:
speaker_board_member = BoardMember(
agent=speaker_mep.agent,
role=BoardMemberRole.CHAIRMAN,
voting_weight=1.0,
- expertise_areas=group_expertise
+ expertise_areas=group_expertise,
)
board_members.append(speaker_board_member)
# Group speaker gets 35% of the group's internal voting power
board_member_percentages[group_speaker] = 0.35
-
+
# Create specialized board members for each expertise area with weighted percentages
- expertise_percentages = self._calculate_expertise_percentages(group_name, len(group_expertise))
-
- for i, expertise_area in enumerate(group_expertise[:5]): # Limit to 5 main areas
+ expertise_percentages = (
+ self._calculate_expertise_percentages(
+ group_name, len(group_expertise)
+ )
+ )
+
+ for i, expertise_area in enumerate(
+ group_expertise[:5]
+ ): # Limit to 5 main areas
# Find MEPs with relevant expertise
specialized_meps = [
- mep_name for mep_name in mep_list
- if mep_name in self.meps and
- any(exp.lower() in expertise_area.lower() for exp in self.meps[mep_name].expertise_areas)
+ mep_name
+ for mep_name in mep_list
+ if mep_name in self.meps
+ and any(
+ exp.lower() in expertise_area.lower()
+ for exp in self.meps[mep_name].expertise_areas
+ )
]
-
- if specialized_meps and i < len(expertise_percentages):
+
+ if specialized_meps and i < len(
+ expertise_percentages
+ ):
# Select the first specialized MEP
specialized_mep_name = specialized_meps[0]
specialized_mep = self.meps[specialized_mep_name]
-
+
if specialized_mep.agent:
# Assign percentage based on expertise importance
- expertise_percentage = expertise_percentages[i]
-
+ expertise_percentage = expertise_percentages[
+ i
+ ]
+
board_member = BoardMember(
agent=specialized_mep.agent,
role=BoardMemberRole.EXECUTIVE_DIRECTOR,
voting_weight=expertise_percentage,
- expertise_areas=[expertise_area]
+ expertise_areas=[expertise_area],
)
board_members.append(board_member)
- board_member_percentages[specialized_mep_name] = expertise_percentage
-
+ board_member_percentages[
+ specialized_mep_name
+ ] = expertise_percentage
+
# Create the political group board with individual percentages
political_group_board = PoliticalGroupBoard(
group_name=group_name,
@@ -1340,13 +1699,17 @@ Remember: You are a real MEP with specific political views, expertise, and respo
voting_weight=voting_weight,
group_speaker=group_speaker,
total_meps=len(mep_list),
- board_member_percentages=board_member_percentages
+ board_member_percentages=board_member_percentages,
)
-
+
# Create BoardOfDirectorsSwarm for this political group
if board_members:
- agents = [member.agent for member in board_members if member.agent is not None]
-
+ agents = [
+ member.agent
+ for member in board_members
+ if member.agent is not None
+ ]
+
political_group_board.board_swarm = BoardOfDirectorsSwarm(
name=f"{group_name} Board",
description=f"Specialized board for {group_name} with expertise in {', '.join(group_expertise)}",
@@ -1356,111 +1719,194 @@ Remember: You are a real MEP with specific political views, expertise, and respo
verbose=self.verbose,
decision_threshold=0.6,
enable_voting=True,
- enable_consensus=True
+ enable_consensus=True,
)
-
- self.political_group_boards[group_name] = political_group_board
-
+
+ self.political_group_boards[group_name] = (
+ political_group_board
+ )
+
if self.verbose:
- logger.info(f"Created {group_name} board with {len(board_members)} members, "
- f"voting weight: {voting_weight:.1%}, expertise: {', '.join(group_expertise[:3])}")
- logger.info(f"Board member percentages: {board_member_percentages}")
+ logger.info(
+ f"Created {group_name} board with {len(board_members)} members, "
+ f"voting weight: {voting_weight:.1%}, expertise: {', '.join(group_expertise[:3])}"
+ )
+ logger.info(
+ f"Board member percentages: {board_member_percentages}"
+ )
- def _assign_group_expertise(self, group_name: str, expertise_areas: Dict[str, List[str]]) -> List[str]:
+ def _assign_group_expertise(
+ self, group_name: str, expertise_areas: Dict[str, List[str]]
+ ) -> List[str]:
"""Assign specialized expertise areas based on political group ideology."""
-
+
# Map political groups to their primary expertise areas
group_expertise_mapping = {
"Group of the European People's Party (Christian Democrats)": [
- "economics", "law", "foreign", "social"
+ "economics",
+ "law",
+ "foreign",
+ "social",
],
"Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
- "social", "economics", "environment", "law"
+ "social",
+ "economics",
+ "environment",
+ "law",
],
"Renew Europe Group": [
- "economics", "technology", "environment", "foreign"
+ "economics",
+ "technology",
+ "environment",
+ "foreign",
],
"European Conservatives and Reformists Group": [
- "law", "foreign", "economics", "regional"
+ "law",
+ "foreign",
+ "economics",
+ "regional",
],
"Group of the Greens/European Free Alliance": [
- "environment", "social", "technology", "agriculture"
+ "environment",
+ "social",
+ "technology",
+ "agriculture",
],
"The Left group in the European Parliament - GUE/NGL": [
- "social", "economics", "environment", "law"
+ "social",
+ "economics",
+ "environment",
+ "law",
],
"Patriots for Europe Group": [
- "foreign", "law", "regional", "social"
+ "foreign",
+ "law",
+ "regional",
+ "social",
],
"Europe of Sovereign Nations Group": [
- "foreign", "law", "regional", "economics"
+ "foreign",
+ "law",
+ "regional",
+ "economics",
],
"Non-attached Members": [
- "law", "foreign", "economics", "social"
- ]
+ "law",
+ "foreign",
+ "economics",
+ "social",
+ ],
}
-
+
# Get primary expertise areas for this group
- primary_areas = group_expertise_mapping.get(group_name, ["economics", "law", "social"])
-
+ primary_areas = group_expertise_mapping.get(
+ group_name, ["economics", "law", "social"]
+ )
+
# Expand to specific expertise topics
specific_expertise = []
for area in primary_areas:
if area in expertise_areas:
specific_expertise.extend(expertise_areas[area])
-
+
return specific_expertise[:8] # Limit to 8 areas
- def _calculate_expertise_percentages(self, group_name: str, num_expertise_areas: int) -> List[float]:
+ def _calculate_expertise_percentages(
+ self, group_name: str, num_expertise_areas: int
+ ) -> List[float]:
"""Calculate individual percentages for board members based on political group and expertise areas."""
-
+
# Define percentage distributions based on political group characteristics
percentage_distributions = {
- "Group of the European People's Party (Christian Democrats)": [0.25, 0.20, 0.15, 0.05], # CEO gets 35%
- "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [0.25, 0.20, 0.15, 0.05],
- "Renew Europe Group": [0.30, 0.20, 0.10, 0.05], # More emphasis on first expertise
- "Group of the Greens/European Free Alliance": [0.30, 0.20, 0.10, 0.05],
- "European Conservatives and Reformists Group": [0.25, 0.20, 0.15, 0.05],
- "The Left group in the European Parliament - GUE/NGL": [0.25, 0.20, 0.15, 0.05],
+ "Group of the European People's Party (Christian Democrats)": [
+ 0.25,
+ 0.20,
+ 0.15,
+ 0.05,
+ ], # CEO gets 35%
+ "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament": [
+ 0.25,
+ 0.20,
+ 0.15,
+ 0.05,
+ ],
+ "Renew Europe Group": [
+ 0.30,
+ 0.20,
+ 0.10,
+ 0.05,
+ ], # More emphasis on first expertise
+ "Group of the Greens/European Free Alliance": [
+ 0.30,
+ 0.20,
+ 0.10,
+ 0.05,
+ ],
+ "European Conservatives and Reformists Group": [
+ 0.25,
+ 0.20,
+ 0.15,
+ 0.05,
+ ],
+ "The Left group in the European Parliament - GUE/NGL": [
+ 0.25,
+ 0.20,
+ 0.15,
+ 0.05,
+ ],
"Patriots for Europe Group": [0.30, 0.20, 0.10, 0.05],
- "Europe of Sovereign Nations Group": [0.30, 0.20, 0.10, 0.05],
- "Non-attached Members": [0.40, 0.20, 0.05, 0.00] # More concentrated power
+ "Europe of Sovereign Nations Group": [
+ 0.30,
+ 0.20,
+ 0.10,
+ 0.05,
+ ],
+ "Non-attached Members": [
+ 0.40,
+ 0.20,
+ 0.05,
+ 0.00,
+ ], # More concentrated power
}
-
+
# Get the distribution for this group
- distribution = percentage_distributions.get(group_name, [0.25, 0.20, 0.15, 0.05])
-
+ distribution = percentage_distributions.get(
+ group_name, [0.25, 0.20, 0.15, 0.05]
+ )
+
# Return the appropriate number of percentages
return distribution[:num_expertise_areas]
def _create_parliament_speaker(self):
"""Create the Parliament Speaker who aggregates decisions from all political groups."""
-
+
# Create parliament speaker agent
speaker_agent = Agent(
name="Parliament Speaker",
system_prompt=self._generate_speaker_system_prompt(),
llm="gpt-4",
- verbose=self.verbose
+ verbose=self.verbose,
)
-
+
# Calculate majority threshold
majority_threshold = (len(self.meps) // 2) + 1
-
+
self.parliament_speaker = ParliamentSpeaker(
name="Parliament Speaker",
agent=speaker_agent,
political_groups=self.political_group_boards,
total_meps=len(self.meps),
- majority_threshold=majority_threshold
+ majority_threshold=majority_threshold,
)
-
+
if self.verbose:
- logger.info(f"Created Parliament Speaker with majority threshold: {majority_threshold}")
+ logger.info(
+ f"Created Parliament Speaker with majority threshold: {majority_threshold}"
+ )
def _generate_speaker_system_prompt(self) -> str:
"""Generate system prompt for the Parliament Speaker."""
-
+
return f"""You are the Parliament Speaker of the European Parliament, responsible for:
1. **Aggregating Political Group Decisions**: Collect and analyze decisions from all political groups
@@ -1483,17 +1929,19 @@ Remember: You are a real MEP with specific political views, expertise, and respo
def _format_political_group_distribution(self) -> str:
"""Format political group distribution for the speaker prompt."""
-
+
if not self.political_group_boards:
return "No political groups available"
-
+
lines = []
for group_name, board in self.political_group_boards.items():
percentage = board.voting_weight * 100
- lines.append(f"- {group_name}: {board.total_meps} MEPs ({percentage:.1f}%)")
-
+ lines.append(
+ f"- {group_name}: {board.total_meps} MEPs ({percentage:.1f}%)"
+ )
+
return "\n".join(lines)
-
+
def introduce_bill(
self,
title: str,
@@ -1501,11 +1949,11 @@ Remember: You are a real MEP with specific political views, expertise, and respo
bill_type: VoteType,
committee: str,
sponsor: str,
- co_sponsors: List[str] = None
+ co_sponsors: List[str] = None,
) -> ParliamentaryBill:
"""
Introduce a new bill to the parliament.
-
+
Args:
title: Bill title
description: Bill description
@@ -1513,61 +1961,71 @@ Remember: You are a real MEP with specific political views, expertise, and respo
committee: Primary committee
sponsor: Sponsoring MEP
co_sponsors: List of co-sponsoring MEPs
-
+
Returns:
ParliamentaryBill: The introduced bill
"""
if sponsor not in self.meps:
raise ValueError(f"Sponsor {sponsor} is not a valid MEP")
-
+
if committee not in self.committees:
raise ValueError(f"Committee {committee} does not exist")
-
+
bill = ParliamentaryBill(
title=title,
description=description,
bill_type=bill_type,
committee=committee,
sponsor=sponsor,
- co_sponsors=co_sponsors or []
+ co_sponsors=co_sponsors or [],
)
-
+
self.bills.append(bill)
self.committees[committee].current_bills.append(bill)
-
- logger.info(f"Bill '{title}' introduced by {sponsor} in {committee} committee")
+
+ logger.info(
+ f"Bill '{title}' introduced by {sponsor} in {committee} committee"
+ )
return bill
-
+
def conduct_committee_hearing(
self,
committee: str,
bill: ParliamentaryBill,
- participants: List[str] = None
+ participants: List[str] = None,
) -> Dict[str, Any]:
"""
Conduct a committee hearing on a bill with cost optimization.
-
+
Args:
committee: Committee name
bill: Bill under consideration
participants: List of MEPs to participate
-
+
Returns:
Dict[str, Any]: Hearing results and transcript
"""
if committee not in self.committees:
raise ValueError(f"Committee {committee} does not exist")
-
+
# Check budget before starting
if not self.cost_tracker.check_budget():
- return {"error": "Budget exceeded", "cost_stats": self.cost_tracker.get_stats()}
-
+ return {
+ "error": "Budget exceeded",
+ "cost_stats": self.cost_tracker.get_stats(),
+ }
+
committee_meps = self.committees[committee].members
if not participants:
- participants = committee_meps[:10] # Limit to 10 participants
-
+ participants = committee_meps[
+ :10
+ ] # Limit to 10 participants
+
# Check cache first
- cache_key = self._get_cache_key(f"committee_hearing_{committee}_{bill.title}", participants)
+ cache_key = self._get_cache_key(
+ f"committee_hearing_{committee}_{bill.title}",
+ participants,
+ )
cached_result = self._check_cache(cache_key)
if cached_result:
return {
@@ -1577,9 +2035,9 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"responses": cached_result,
"date": datetime.now(),
"cached": True,
- "cost_stats": self.cost_tracker.get_stats()
+ "cost_stats": self.cost_tracker.get_stats(),
}
-
+
hearing_prompt = f"""
Committee Hearing: {committee}
Bill: {bill.title}
@@ -1595,51 +2053,65 @@ Remember: You are a real MEP with specific political views, expertise, and respo
Provide a detailed analysis with specific recommendations.
"""
-
+
# Load MEP agents in batches
all_responses = {}
total_processed = 0
-
+
for i in range(0, len(participants), self.batch_size):
- batch_participants = participants[i:i + self.batch_size]
-
+ batch_participants = participants[i : i + self.batch_size]
+
# Check budget for this batch
if not self.cost_tracker.check_budget():
- logger.warning(f"Budget exceeded after processing {total_processed} participants")
+ logger.warning(
+ f"Budget exceeded after processing {total_processed} participants"
+ )
break
-
+
# Load agents for this batch
- batch_agents = self._load_mep_agents_batch(batch_participants)
-
+ batch_agents = self._load_mep_agents_batch(
+ batch_participants
+ )
+
if not batch_agents:
continue
-
+
# Run batch
try:
- batch_results = run_agents_concurrently(batch_agents, hearing_prompt)
-
+ batch_results = run_agents_concurrently(
+ batch_agents, hearing_prompt
+ )
+
# Map results back to participant names
for j, agent in enumerate(batch_agents):
if j < len(batch_results):
participant_name = batch_participants[j]
- all_responses[participant_name] = batch_results[j]
+ all_responses[participant_name] = (
+ batch_results[j]
+ )
total_processed += 1
-
+
# Estimate tokens used
- estimated_tokens = len(batch_agents) * 500 # ~500 tokens per response
+ estimated_tokens = (
+ len(batch_agents) * 500
+ ) # ~500 tokens per response
self.cost_tracker.add_tokens(estimated_tokens)
-
+
if self.verbose:
- logger.info(f"Processed committee hearing batch {i//self.batch_size + 1}: {len(batch_agents)} participants")
-
+ logger.info(
+ f"Processed committee hearing batch {i//self.batch_size + 1}: {len(batch_agents)} participants"
+ )
+
except Exception as e:
- logger.error(f"Error processing committee hearing batch: {e}")
+ logger.error(
+ f"Error processing committee hearing batch: {e}"
+ )
continue
-
+
# Cache the results
if all_responses:
self._cache_response(cache_key, str(all_responses))
-
+
hearing_result = {
"committee": committee,
"bill": bill.title,
@@ -1648,19 +2120,25 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"date": datetime.now(),
"cached": False,
"cost_stats": self.cost_tracker.get_stats(),
- "recommendations": self._synthesize_committee_recommendations(all_responses)
+ "recommendations": self._synthesize_committee_recommendations(
+ all_responses
+ ),
}
-
- logger.info(f"Committee hearing completed for {bill.title} in {committee}")
+
+ logger.info(
+ f"Committee hearing completed for {bill.title} in {committee}"
+ )
return hearing_result
-
- def _synthesize_committee_recommendations(self, responses: Dict[str, str]) -> Dict[str, Any]:
+
+ def _synthesize_committee_recommendations(
+ self, responses: Dict[str, str]
+ ) -> Dict[str, Any]:
"""
Synthesize committee recommendations from individual responses.
-
+
Args:
responses: Dictionary of MEP responses
-
+
Returns:
Dict[str, Any]: Synthesized recommendations
"""
@@ -1668,46 +2146,82 @@ Remember: You are a real MEP with specific political views, expertise, and respo
support_count = 0
oppose_count = 0
amend_count = 0
-
+
for response in responses.values():
response_lower = response.lower()
- if any(word in response_lower for word in ["support", "approve", "recommend", "favorable"]):
+ if any(
+ word in response_lower
+ for word in [
+ "support",
+ "approve",
+ "recommend",
+ "favorable",
+ ]
+ ):
support_count += 1
- elif any(word in response_lower for word in ["oppose", "reject", "against", "unfavorable"]):
+ elif any(
+ word in response_lower
+ for word in [
+ "oppose",
+ "reject",
+ "against",
+ "unfavorable",
+ ]
+ ):
oppose_count += 1
- elif any(word in response_lower for word in ["amend", "modify", "improve", "revise"]):
+ elif any(
+ word in response_lower
+ for word in ["amend", "modify", "improve", "revise"]
+ ):
amend_count += 1
-
+
total = len(responses)
-
+
return {
- "support_percentage": (support_count / total) * 100 if total > 0 else 0,
- "oppose_percentage": (oppose_count / total) * 100 if total > 0 else 0,
- "amend_percentage": (amend_count / total) * 100 if total > 0 else 0,
- "recommendation": "support" if support_count > oppose_count else "oppose" if oppose_count > support_count else "amend"
+ "support_percentage": (
+ (support_count / total) * 100 if total > 0 else 0
+ ),
+ "oppose_percentage": (
+ (oppose_count / total) * 100 if total > 0 else 0
+ ),
+ "amend_percentage": (
+ (amend_count / total) * 100 if total > 0 else 0
+ ),
+ "recommendation": (
+ "support"
+ if support_count > oppose_count
+ else (
+ "oppose"
+ if oppose_count > support_count
+ else "amend"
+ )
+ ),
}
-
+
def conduct_parliamentary_debate(
self,
bill: ParliamentaryBill,
participants: List[str] = None,
- max_speakers: int = 20
+ max_speakers: int = 20,
) -> Dict[str, Any]:
"""
Conduct a parliamentary debate on a bill with cost optimization.
-
+
Args:
bill: Bill under debate
participants: List of MEPs to participate
max_speakers: Maximum number of speakers
-
+
Returns:
Dict[str, Any]: Debate transcript and analysis
"""
# Check budget before starting
if not self.cost_tracker.check_budget():
- return {"error": "Budget exceeded", "cost_stats": self.cost_tracker.get_stats()}
-
+ return {
+ "error": "Budget exceeded",
+ "cost_stats": self.cost_tracker.get_stats(),
+ }
+
if not participants:
# Select diverse participants from different political groups
participants = []
@@ -1716,11 +2230,13 @@ Remember: You are a real MEP with specific political views, expertise, and respo
participants.extend(meps[:3]) # 3 MEPs per group
if len(participants) >= max_speakers:
break
-
+
participants = participants[:max_speakers]
-
+
# Check cache first
- cache_key = self._get_cache_key(f"parliamentary_debate_{bill.title}", participants)
+ cache_key = self._get_cache_key(
+ f"parliamentary_debate_{bill.title}", participants
+ )
cached_result = self._check_cache(cache_key)
if cached_result:
return {
@@ -1729,9 +2245,9 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"transcript": cached_result,
"date": datetime.now(),
"cached": True,
- "cost_stats": self.cost_tracker.get_stats()
+ "cost_stats": self.cost_tracker.get_stats(),
}
-
+
debate_prompt = f"""
Parliamentary Debate: {bill.title}
@@ -1749,60 +2265,70 @@ Remember: You are a real MEP with specific political views, expertise, and respo
Provide a clear, reasoned argument for your position.
"""
-
+
# Conduct debate with batching
debate_transcript = []
total_processed = 0
-
+
for i in range(0, len(participants), self.batch_size):
- batch_participants = participants[i:i + self.batch_size]
-
+ batch_participants = participants[i : i + self.batch_size]
+
# Check budget for this batch
if not self.cost_tracker.check_budget():
- logger.warning(f"Budget exceeded after processing {total_processed} speakers")
+ logger.warning(
+ f"Budget exceeded after processing {total_processed} speakers"
+ )
break
-
+
# Load agents for this batch
- batch_agents = self._load_mep_agents_batch(batch_participants)
-
+ batch_agents = self._load_mep_agents_batch(
+ batch_participants
+ )
+
if not batch_agents:
continue
-
+
# Run batch
try:
- batch_results = run_agents_concurrently(batch_agents, debate_prompt)
-
+ batch_results = run_agents_concurrently(
+ batch_agents, debate_prompt
+ )
+
# Create debate entries
for j, agent in enumerate(batch_agents):
if j < len(batch_results):
participant_name = batch_participants[j]
mep = self.meps[participant_name]
-
+
debate_entry = {
"speaker": participant_name,
"political_group": mep.political_group,
"country": mep.country,
"position": batch_results[j],
- "timestamp": datetime.now()
+ "timestamp": datetime.now(),
}
debate_transcript.append(debate_entry)
total_processed += 1
-
+
# Estimate tokens used
- estimated_tokens = len(batch_agents) * 500 # ~500 tokens per response
+ estimated_tokens = (
+ len(batch_agents) * 500
+ ) # ~500 tokens per response
self.cost_tracker.add_tokens(estimated_tokens)
-
+
if self.verbose:
- logger.info(f"Processed debate batch {i//self.batch_size + 1}: {len(batch_agents)} speakers")
-
+ logger.info(
+ f"Processed debate batch {i//self.batch_size + 1}: {len(batch_agents)} speakers"
+ )
+
except Exception as e:
logger.error(f"Error processing debate batch: {e}")
continue
-
+
# Cache the results
if debate_transcript:
self._cache_response(cache_key, str(debate_transcript))
-
+
debate_result = {
"bill": bill.title,
"participants": participants[:total_processed],
@@ -1810,20 +2336,24 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"date": datetime.now(),
"cached": False,
"cost_stats": self.cost_tracker.get_stats(),
- "analysis": self._analyze_debate(debate_transcript)
+ "analysis": self._analyze_debate(debate_transcript),
}
-
+
self.debates.append(debate_result)
- logger.info(f"Parliamentary debate completed for {bill.title} with {total_processed} speakers")
+ logger.info(
+ f"Parliamentary debate completed for {bill.title} with {total_processed} speakers"
+ )
return debate_result
-
- def _analyze_debate(self, transcript: List[Dict[str, Any]]) -> Dict[str, Any]:
+
+ def _analyze_debate(
+ self, transcript: List[Dict[str, Any]]
+ ) -> Dict[str, Any]:
"""
Analyze debate transcript for key themes and positions.
-
+
Args:
transcript: Debate transcript
-
+
Returns:
Dict[str, Any]: Debate analysis
"""
@@ -1831,39 +2361,49 @@ Remember: You are a real MEP with specific political views, expertise, and respo
support_count = 0
oppose_count = 0
neutral_count = 0
-
+
for entry in transcript:
position = entry["position"].lower()
- if any(word in position for word in ["support", "approve", "favorable", "yes"]):
+ if any(
+ word in position
+ for word in ["support", "approve", "favorable", "yes"]
+ ):
support_count += 1
- elif any(word in position for word in ["oppose", "reject", "against", "no"]):
+ elif any(
+ word in position
+ for word in ["oppose", "reject", "against", "no"]
+ ):
oppose_count += 1
else:
neutral_count += 1
-
+
total = len(transcript)
-
+
return {
"support_count": support_count,
"oppose_count": oppose_count,
"neutral_count": neutral_count,
- "support_percentage": (support_count / total) * 100 if total > 0 else 0,
- "oppose_percentage": (oppose_count / total) * 100 if total > 0 else 0,
- "neutral_percentage": (neutral_count / total) * 100 if total > 0 else 0
+ "support_percentage": (
+ (support_count / total) * 100 if total > 0 else 0
+ ),
+ "oppose_percentage": (
+ (oppose_count / total) * 100 if total > 0 else 0
+ ),
+ "neutral_percentage": (
+ (neutral_count / total) * 100 if total > 0 else 0
+ ),
}
-
+
def conduct_democratic_vote(
- self,
- bill: ParliamentaryBill,
- participants: List[str] = None
+ self, bill: ParliamentaryBill, participants: List[str] = None
) -> ParliamentaryVote:
"""
Conduct a democratic vote on a bill using the Board of Directors pattern with lazy loading.
-
+
Args:
bill: Bill to vote on
participants: List of MEPs to participate
-
+
Returns:
ParliamentaryVote: Vote results
"""
@@ -1872,12 +2412,12 @@ Remember: You are a real MEP with specific political views, expertise, and respo
return ParliamentaryVote(
bill=bill,
vote_type=bill.bill_type,
- result=VoteResult.FAILED
+ result=VoteResult.FAILED,
)
-
+
if not participants:
participants = list(self.meps.keys())
-
+
# Use democratic swarm for decision-making if available
democratic_result = None
if self.democratic_swarm is not None:
@@ -1896,30 +2436,36 @@ Remember: You are a real MEP with specific political views, expertise, and respo
This is a critical legislative decision that will affect all EU citizens.
"""
-
+
# Get democratic decision
- democratic_result = self.democratic_swarm.run_board_meeting(decision_task)
-
+ democratic_result = (
+ self.democratic_swarm.run_board_meeting(decision_task)
+ )
+
# Conduct individual MEP votes with lazy loading
individual_votes = {}
reasoning = {}
total_processed = 0
-
+
# Process participants in batches
for i in range(0, len(participants), self.batch_size):
- batch_participants = participants[i:i + self.batch_size]
-
+ batch_participants = participants[i : i + self.batch_size]
+
# Check budget for this batch
if not self.cost_tracker.check_budget():
- logger.warning(f"Budget exceeded after processing {total_processed} voters")
+ logger.warning(
+ f"Budget exceeded after processing {total_processed} voters"
+ )
break
-
+
# Load agents for this batch
- batch_agents = self._load_mep_agents_batch(batch_participants)
-
+ batch_agents = self._load_mep_agents_batch(
+ batch_participants
+ )
+
if not batch_agents:
continue
-
+
# Create voting prompt
vote_prompt = f"""
Vote on Bill: {bill.title}
@@ -1936,47 +2482,79 @@ Remember: You are a real MEP with specific political views, expertise, and respo
Respond with 'FOR', 'AGAINST', or 'ABSTAIN' and explain your reasoning.
"""
-
+
# Run batch voting
try:
- batch_results = run_agents_concurrently(batch_agents, vote_prompt)
-
+ batch_results = run_agents_concurrently(
+ batch_agents, vote_prompt
+ )
+
# Process results
for j, agent in enumerate(batch_agents):
if j < len(batch_results):
participant_name = batch_participants[j]
response = batch_results[j]
-
+
# Parse vote
response_lower = response.lower()
- if any(word in response_lower for word in ["for", "support", "yes", "approve"]):
+ if any(
+ word in response_lower
+ for word in [
+ "for",
+ "support",
+ "yes",
+ "approve",
+ ]
+ ):
vote = "FOR"
- elif any(word in response_lower for word in ["against", "oppose", "no", "reject"]):
+ elif any(
+ word in response_lower
+ for word in [
+ "against",
+ "oppose",
+ "no",
+ "reject",
+ ]
+ ):
vote = "AGAINST"
else:
vote = "ABSTAIN"
-
+
individual_votes[participant_name] = vote
reasoning[participant_name] = response
total_processed += 1
-
+
# Estimate tokens used
- estimated_tokens = len(batch_agents) * 500 # ~500 tokens per response
+ estimated_tokens = (
+ len(batch_agents) * 500
+ ) # ~500 tokens per response
self.cost_tracker.add_tokens(estimated_tokens)
-
+
if self.verbose:
- logger.info(f"Processed voting batch {i//self.batch_size + 1}: {len(batch_agents)} voters")
-
+ logger.info(
+ f"Processed voting batch {i//self.batch_size + 1}: {len(batch_agents)} voters"
+ )
+
except Exception as e:
logger.error(f"Error processing voting batch: {e}")
continue
-
+
# Calculate results
- votes_for = sum(1 for vote in individual_votes.values() if vote == "FOR")
- votes_against = sum(1 for vote in individual_votes.values() if vote == "AGAINST")
- abstentions = sum(1 for vote in individual_votes.values() if vote == "ABSTAIN")
+ votes_for = sum(
+ 1 for vote in individual_votes.values() if vote == "FOR"
+ )
+ votes_against = sum(
+ 1
+ for vote in individual_votes.values()
+ if vote == "AGAINST"
+ )
+ abstentions = sum(
+ 1
+ for vote in individual_votes.values()
+ if vote == "ABSTAIN"
+ )
absent = len(participants) - len(individual_votes)
-
+
# Determine result
if votes_for > votes_against:
result = VoteResult.PASSED
@@ -1984,7 +2562,7 @@ Remember: You are a real MEP with specific political views, expertise, and respo
result = VoteResult.FAILED
else:
result = VoteResult.TIED
-
+
vote_result = ParliamentaryVote(
bill=bill,
vote_type=bill.bill_type,
@@ -1994,60 +2572,65 @@ Remember: You are a real MEP with specific political views, expertise, and respo
absent=absent,
result=result,
individual_votes=individual_votes,
- reasoning=reasoning
+ reasoning=reasoning,
)
-
+
self.votes.append(vote_result)
bill.status = "voted"
-
- logger.info(f"Democratic vote completed for {bill.title}: {result.value} ({total_processed} voters processed)")
+
+ logger.info(
+ f"Democratic vote completed for {bill.title}: {result.value} ({total_processed} voters processed)"
+ )
return vote_result
-
+
def conduct_hierarchical_democratic_vote(
- self,
- bill: ParliamentaryBill,
- participants: List[str] = None
+ self, bill: ParliamentaryBill, participants: List[str] = None
) -> ParliamentaryVote:
"""
Conduct a hierarchical democratic vote using political group boards and parliament speaker.
-
+
This enhanced voting system:
1. Each political group votes internally as a specialized board
2. Group speakers (CEOs) synthesize their group's position
3. Parliament Speaker aggregates all group decisions based on percentage representation
4. Final result calculated using weighted voting
-
+
Args:
bill: Bill to vote on
participants: List of MEPs to participate (optional, uses all by default)
-
+
Returns:
ParliamentaryVote: Enhanced vote results with group-level analysis
"""
-
+
if not self.enable_hierarchical_democracy:
- logger.warning("Hierarchical democracy not enabled, falling back to standard voting")
+ logger.warning(
+ "Hierarchical democracy not enabled, falling back to standard voting"
+ )
return self.conduct_democratic_vote(bill, participants)
-
- logger.info(f"Conducting hierarchical democratic vote on: {bill.title}")
-
+
+ logger.info(
+ f"Conducting hierarchical democratic vote on: {bill.title}"
+ )
+
# Initialize vote tracking
vote = ParliamentaryVote(
- bill=bill,
- vote_type=bill.bill_type,
- date=datetime.now()
+ bill=bill, vote_type=bill.bill_type, date=datetime.now()
)
-
+
# Step 1: Each political group votes internally
group_decisions = {}
group_reasoning = {}
-
- for group_name, group_board in self.political_group_boards.items():
+
+ for (
+ group_name,
+ group_board,
+ ) in self.political_group_boards.items():
if not group_board.board_swarm:
continue
-
+
logger.info(f"Conducting internal vote for {group_name}")
-
+
# Create voting task for this group
voting_task = f"""
Parliamentary Vote: {bill.title}
@@ -2069,27 +2652,37 @@ Remember: You are a real MEP with specific political views, expertise, and respo
Provide your group's decision: POSITIVE, NEGATIVE, or ABSTAIN
Include detailed reasoning for your position.
"""
-
+
try:
# Get group decision using their specialized board
- group_result = group_board.board_swarm.run(voting_task)
-
+ group_result = group_board.board_swarm.run(
+ voting_task
+ )
+
# Parse the group decision
- group_decision = self._parse_group_decision(group_result)
+ group_decision = self._parse_group_decision(
+ group_result
+ )
group_decisions[group_name] = group_decision
group_reasoning[group_name] = group_result
-
- logger.info(f"{group_name} decision: {group_decision}")
-
+
+ logger.info(
+ f"{group_name} decision: {group_decision}"
+ )
+
except Exception as e:
logger.error(f"Error in {group_name} vote: {e}")
group_decisions[group_name] = "ABSTAIN"
- group_reasoning[group_name] = f"Error during voting: {str(e)}"
-
+ group_reasoning[group_name] = (
+ f"Error during voting: {str(e)}"
+ )
+
# Step 2: Parliament Speaker aggregates group decisions
if self.parliament_speaker and self.parliament_speaker.agent:
- logger.info("Parliament Speaker aggregating group decisions")
-
+ logger.info(
+ "Parliament Speaker aggregating group decisions"
+ )
+
aggregation_task = f"""
Parliamentary Vote Aggregation: {bill.title}
@@ -2110,75 +2703,115 @@ Remember: You are a real MEP with specific political views, expertise, and respo
3. Weighted analysis of each group's contribution
4. Summary of the democratic process
"""
-
+
try:
- speaker_result = self.parliament_speaker.agent.run(aggregation_task)
-
+ speaker_result = self.parliament_speaker.agent.run(
+ aggregation_task
+ )
+
# Parse speaker's analysis
- final_result = self._parse_speaker_analysis(speaker_result, group_decisions)
-
+ final_result = self._parse_speaker_analysis(
+ speaker_result, group_decisions
+ )
+
# Update vote with results
- vote.result = final_result['result']
- vote.votes_for = final_result['votes_for']
- vote.votes_against = final_result['votes_against']
- vote.abstentions = final_result['abstentions']
+ vote.result = final_result["result"]
+ vote.votes_for = final_result["votes_for"]
+ vote.votes_against = final_result["votes_against"]
+ vote.abstentions = final_result["abstentions"]
vote.individual_votes = group_decisions
vote.reasoning = group_reasoning
-
+
logger.info(f"Final result: {vote.result.value}")
- logger.info(f"Votes - For: {vote.votes_for}, Against: {vote.votes_against}, Abstain: {vote.abstentions}")
-
+ logger.info(
+ f"Votes - For: {vote.votes_for}, Against: {vote.votes_against}, Abstain: {vote.abstentions}"
+ )
+
except Exception as e:
logger.error(f"Error in speaker aggregation: {e}")
# Fallback to simple counting
- vote = self._fallback_vote_calculation(vote, group_decisions)
-
+ vote = self._fallback_vote_calculation(
+ vote, group_decisions
+ )
+
# Store the vote
self.votes.append(vote)
-
+
return vote
def _parse_group_decision(self, group_result: str) -> str:
"""Parse the decision from a political group's voting result."""
-
+
result_lower = group_result.lower()
-
- if any(word in result_lower for word in ['positive', 'for', 'support', 'approve', 'pass']):
+
+ if any(
+ word in result_lower
+ for word in [
+ "positive",
+ "for",
+ "support",
+ "approve",
+ "pass",
+ ]
+ ):
return "POSITIVE"
- elif any(word in result_lower for word in ['negative', 'against', 'oppose', 'reject', 'fail']):
+ elif any(
+ word in result_lower
+ for word in [
+ "negative",
+ "against",
+ "oppose",
+ "reject",
+ "fail",
+ ]
+ ):
return "NEGATIVE"
else:
return "ABSTAIN"
- def _format_group_decisions(self, group_decisions: Dict[str, str], group_reasoning: Dict[str, str]) -> str:
+ def _format_group_decisions(
+ self,
+ group_decisions: Dict[str, str],
+ group_reasoning: Dict[str, str],
+ ) -> str:
"""Format group decisions for the speaker's analysis."""
-
+
lines = []
for group_name, decision in group_decisions.items():
board = self.political_group_boards.get(group_name)
if board:
percentage = board.voting_weight * 100
- reasoning = group_reasoning.get(group_name, "No reasoning provided")
- lines.append(f"- {group_name} ({board.total_meps} MEPs, {percentage:.1f}%): {decision}")
+ reasoning = group_reasoning.get(
+ group_name, "No reasoning provided"
+ )
+ lines.append(
+ f"- {group_name} ({board.total_meps} MEPs, {percentage:.1f}%): {decision}"
+ )
lines.append(f" Reasoning: {reasoning[:200]}...")
-
+
return "\n".join(lines)
- def _parse_speaker_analysis(self, speaker_result: str, group_decisions: Dict[str, str]) -> Dict[str, Any]:
+ def _parse_speaker_analysis(
+ self, speaker_result: str, group_decisions: Dict[str, str]
+ ) -> Dict[str, Any]:
"""Parse the Parliament Speaker's analysis to extract final vote results using dual-layer percentage system."""
-
+
# Initialize counters
votes_for = 0
votes_against = 0
abstentions = 0
-
+
# Calculate weighted votes using dual-layer percentage system
for group_name, decision in group_decisions.items():
board = self.political_group_boards.get(group_name)
if board and board.board_member_percentages:
# Calculate weighted votes using individual board member percentages
- group_weighted_votes = self._calculate_group_weighted_votes(board, decision)
-
+ group_weighted_votes = (
+ self._calculate_group_weighted_votes(
+ board, decision
+ )
+ )
+
if decision == "POSITIVE":
votes_for += group_weighted_votes
elif decision == "NEGATIVE":
@@ -2188,15 +2821,17 @@ Remember: You are a real MEP with specific political views, expertise, and respo
else:
# Fallback to simple calculation if no individual percentages available
if board:
- weighted_votes = int(board.total_meps * board.voting_weight)
-
+ weighted_votes = int(
+ board.total_meps * board.voting_weight
+ )
+
if decision == "POSITIVE":
votes_for += weighted_votes
elif decision == "NEGATIVE":
votes_against += weighted_votes
else: # ABSTAIN
abstentions += weighted_votes
-
+
# Determine result
if votes_for > votes_against:
result = VoteResult.PASSED
@@ -2204,44 +2839,57 @@ Remember: You are a real MEP with specific political views, expertise, and respo
result = VoteResult.FAILED
else:
result = VoteResult.TIED
-
+
return {
- 'result': result,
- 'votes_for': votes_for,
- 'votes_against': votes_against,
- 'abstentions': abstentions
+ "result": result,
+ "votes_for": votes_for,
+ "votes_against": votes_against,
+ "abstentions": abstentions,
}
- def _calculate_group_weighted_votes(self, board: PoliticalGroupBoard, decision: str) -> int:
+ def _calculate_group_weighted_votes(
+ self, board: PoliticalGroupBoard, decision: str
+ ) -> int:
"""Calculate weighted votes for a political group using individual board member percentages."""
-
+
total_weighted_votes = 0
-
+
# Calculate votes based on individual board member percentages
- for member_name, internal_percentage in board.board_member_percentages.items():
+ for (
+ member_name,
+ internal_percentage,
+ ) in board.board_member_percentages.items():
# Convert internal percentage to parliament percentage
# internal_percentage is percentage within the group
# board.voting_weight is group's percentage of parliament
- parliament_percentage = internal_percentage * board.voting_weight
-
+ parliament_percentage = (
+ internal_percentage * board.voting_weight
+ )
+
# Calculate weighted votes for this member
- member_weighted_votes = int(board.total_meps * parliament_percentage)
+ member_weighted_votes = int(
+ board.total_meps * parliament_percentage
+ )
total_weighted_votes += member_weighted_votes
-
+
if self.verbose:
- logger.debug(f"{member_name}: {internal_percentage:.1%} of {board.group_name} "
- f"({board.voting_weight:.1%} of parliament) = {parliament_percentage:.3%} "
- f"= {member_weighted_votes} weighted votes")
-
+ logger.debug(
+ f"{member_name}: {internal_percentage:.1%} of {board.group_name} "
+ f"({board.voting_weight:.1%} of parliament) = {parliament_percentage:.3%} "
+ f"= {member_weighted_votes} weighted votes"
+ )
+
return total_weighted_votes
- def _fallback_vote_calculation(self, vote: ParliamentaryVote, group_decisions: Dict[str, str]) -> ParliamentaryVote:
+ def _fallback_vote_calculation(
+ self, vote: ParliamentaryVote, group_decisions: Dict[str, str]
+ ) -> ParliamentaryVote:
"""Fallback vote calculation if speaker analysis fails."""
-
+
votes_for = 0
votes_against = 0
abstentions = 0
-
+
for group_name, decision in group_decisions.items():
board = self.political_group_boards.get(group_name)
if board:
@@ -2251,30 +2899,32 @@ Remember: You are a real MEP with specific political views, expertise, and respo
votes_against += board.total_meps
else:
abstentions += board.total_meps
-
+
vote.votes_for = votes_for
vote.votes_against = votes_against
vote.abstentions = abstentions
-
+
if votes_for > votes_against:
vote.result = VoteResult.PASSED
elif votes_against > votes_for:
vote.result = VoteResult.FAILED
else:
vote.result = VoteResult.TIED
-
+
return vote
-
+
def get_parliament_composition(self) -> Dict[str, Any]:
"""
Get the current composition of the parliament including cost statistics.
-
+
Returns:
Dict[str, Any]: Parliament composition statistics
"""
composition = {
"total_meps": len(self.meps),
- "loaded_meps": len([mep for mep in self.meps.values() if mep.is_loaded]),
+ "loaded_meps": len(
+ [mep for mep in self.meps.values() if mep.is_loaded]
+ ),
"political_groups": {},
"countries": {},
"leadership": {},
@@ -2284,25 +2934,27 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"lazy_loading": self.enable_lazy_loading,
"caching": self.enable_caching,
"batch_size": self.batch_size,
- "budget_limit": self.cost_tracker.budget_limit
- }
+ "budget_limit": self.cost_tracker.budget_limit,
+ },
}
-
+
# Political group breakdown
for group_name, meps in self.political_groups.items():
composition["political_groups"][group_name] = {
"count": len(meps),
- "percentage": (len(meps) / len(self.meps)) * 100
+ "percentage": (len(meps) / len(self.meps)) * 100,
}
-
+
# Country breakdown
country_counts = {}
for mep in self.meps.values():
country = mep.country
- country_counts[country] = country_counts.get(country, 0) + 1
-
+ country_counts[country] = (
+ country_counts.get(country, 0) + 1
+ )
+
composition["countries"] = country_counts
-
+
# Leadership positions
leadership = {}
for mep in self.meps.values():
@@ -2311,44 +2963,63 @@ Remember: You are a real MEP with specific political views, expertise, and respo
if role not in leadership:
leadership[role] = []
leadership[role].append(mep.full_name)
-
+
composition["leadership"] = leadership
-
+
# Committee composition
for committee_name, committee in self.committees.items():
composition["committees"][committee_name] = {
"chair": committee.chair,
"vice_chair": committee.vice_chair,
"member_count": len(committee.members),
- "current_bills": len(committee.current_bills)
+ "current_bills": len(committee.current_bills),
}
-
+
return composition
-
+
def get_cost_statistics(self) -> Dict[str, Any]:
"""
Get detailed cost statistics for the parliamentary operations.
-
+
Returns:
Dict[str, Any]: Cost statistics and optimization metrics
"""
stats = self.cost_tracker.get_stats()
-
+
# Add additional metrics
- stats.update({
- "total_meps": len(self.meps),
- "loaded_meps": len([mep for mep in self.meps.values() if mep.is_loaded]),
- "loading_efficiency": len([mep for mep in self.meps.values() if mep.is_loaded]) / len(self.meps) if self.meps else 0,
- "cache_size": len(self.response_cache),
- "optimization_enabled": {
- "lazy_loading": self.enable_lazy_loading,
- "caching": self.enable_caching,
- "batching": self.batch_size > 1
+ stats.update(
+ {
+ "total_meps": len(self.meps),
+ "loaded_meps": len(
+ [
+ mep
+ for mep in self.meps.values()
+ if mep.is_loaded
+ ]
+ ),
+ "loading_efficiency": (
+ len(
+ [
+ mep
+ for mep in self.meps.values()
+ if mep.is_loaded
+ ]
+ )
+ / len(self.meps)
+ if self.meps
+ else 0
+ ),
+ "cache_size": len(self.response_cache),
+ "optimization_enabled": {
+ "lazy_loading": self.enable_lazy_loading,
+ "caching": self.enable_caching,
+ "batching": self.batch_size > 1,
+ },
}
- })
-
+ )
+
return stats
-
+
def run_optimized_parliamentary_session(
self,
bill_title: str,
@@ -2356,11 +3027,11 @@ Remember: You are a real MEP with specific political views, expertise, and respo
bill_type: VoteType = VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee: str = "Legal Affairs",
sponsor: str = None,
- max_cost: float = 50.0
+ max_cost: float = 50.0,
) -> Dict[str, Any]:
"""
Run a complete parliamentary session with cost optimization.
-
+
Args:
bill_title: Title of the bill
bill_description: Description of the bill
@@ -2368,37 +3039,39 @@ Remember: You are a real MEP with specific political views, expertise, and respo
committee: Primary committee
sponsor: Sponsoring MEP (random if not specified)
max_cost: Maximum cost for this session
-
+
Returns:
Dict[str, Any]: Complete session results with cost tracking
"""
# Set temporary budget for this session
original_budget = self.cost_tracker.budget_limit
- self.cost_tracker.budget_limit = min(original_budget, max_cost)
-
+ self.cost_tracker.budget_limit = min(
+ original_budget, max_cost
+ )
+
try:
# Select sponsor if not provided
if not sponsor:
sponsor = random.choice(list(self.meps.keys()))
-
+
# Introduce bill
bill = self.introduce_bill(
title=bill_title,
description=bill_description,
bill_type=bill_type,
committee=committee,
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
# Conduct committee hearing
hearing = self.conduct_committee_hearing(committee, bill)
-
+
# Conduct parliamentary debate
debate = self.conduct_parliamentary_debate(bill)
-
+
# Conduct democratic vote
vote = self.conduct_democratic_vote(bill)
-
+
session_result = {
"bill": bill,
"hearing": hearing,
@@ -2409,66 +3082,78 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"bill_title": bill_title,
"sponsor": sponsor,
"committee": committee,
- "hearing_recommendation": hearing.get("recommendations", {}).get("recommendation", "unknown"),
- "debate_support_percentage": debate.get("analysis", {}).get("support_percentage", 0),
+ "hearing_recommendation": hearing.get(
+ "recommendations", {}
+ ).get("recommendation", "unknown"),
+ "debate_support_percentage": debate.get(
+ "analysis", {}
+ ).get("support_percentage", 0),
"vote_result": vote.result.value,
- "final_outcome": "PASSED" if vote.result == VoteResult.PASSED else "FAILED",
- "total_cost": self.cost_tracker.total_cost_estimate
- }
+ "final_outcome": (
+ "PASSED"
+ if vote.result == VoteResult.PASSED
+ else "FAILED"
+ ),
+ "total_cost": self.cost_tracker.total_cost_estimate,
+ },
}
-
- logger.info(f"Optimized parliamentary session completed for {bill_title}: {session_result['session_summary']['final_outcome']}")
- logger.info(f"Session cost: ${self.cost_tracker.total_cost_estimate:.2f}")
-
+
+ logger.info(
+ f"Optimized parliamentary session completed for {bill_title}: {session_result['session_summary']['final_outcome']}"
+ )
+ logger.info(
+ f"Session cost: ${self.cost_tracker.total_cost_estimate:.2f}"
+ )
+
return session_result
-
+
finally:
# Restore original budget
self.cost_tracker.budget_limit = original_budget
-
+
def run_democratic_session(
self,
bill_title: str,
bill_description: str,
bill_type: VoteType = VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee: str = "Legal Affairs",
- sponsor: str = None
+ sponsor: str = None,
) -> Dict[str, Any]:
"""
Run a complete democratic parliamentary session on a bill.
-
+
Args:
bill_title: Title of the bill
bill_description: Description of the bill
bill_type: Type of legislative procedure
committee: Primary committee
sponsor: Sponsoring MEP (random if not specified)
-
+
Returns:
Dict[str, Any]: Complete session results
"""
# Select sponsor if not provided
if not sponsor:
sponsor = random.choice(list(self.meps.keys()))
-
+
# Introduce bill
bill = self.introduce_bill(
title=bill_title,
description=bill_description,
bill_type=bill_type,
committee=committee,
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
# Conduct committee hearing
hearing = self.conduct_committee_hearing(committee, bill)
-
+
# Conduct parliamentary debate
debate = self.conduct_parliamentary_debate(bill)
-
+
# Conduct democratic vote
vote = self.conduct_democratic_vote(bill)
-
+
session_result = {
"bill": bill,
"hearing": hearing,
@@ -2478,78 +3163,104 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"bill_title": bill_title,
"sponsor": sponsor,
"committee": committee,
- "hearing_recommendation": hearing["recommendations"]["recommendation"],
- "debate_support_percentage": debate["analysis"]["support_percentage"],
+ "hearing_recommendation": hearing["recommendations"][
+ "recommendation"
+ ],
+ "debate_support_percentage": debate["analysis"][
+ "support_percentage"
+ ],
"vote_result": vote.result.value,
- "final_outcome": "PASSED" if vote.result == VoteResult.PASSED else "FAILED"
- }
+ "final_outcome": (
+ "PASSED"
+ if vote.result == VoteResult.PASSED
+ else "FAILED"
+ ),
+ },
}
-
- logger.info(f"Democratic session completed for {bill_title}: {session_result['session_summary']['final_outcome']}")
+
+ logger.info(
+ f"Democratic session completed for {bill_title}: {session_result['session_summary']['final_outcome']}"
+ )
return session_result
-
+
def run_hierarchical_democratic_session(
self,
bill_title: str,
bill_description: str,
bill_type: VoteType = VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee: str = "Legal Affairs",
- sponsor: str = None
+ sponsor: str = None,
) -> Dict[str, Any]:
"""
Run a complete hierarchical democratic session from bill introduction to final vote.
-
+
This enhanced session uses:
1. Political group boards with specialized expertise
2. Group-level internal voting and discussion
3. Parliament Speaker aggregation of group decisions
4. Weighted voting based on political group percentages
-
+
Args:
bill_title: Title of the bill
bill_description: Description of the bill
bill_type: Type of legislative procedure
committee: Committee responsible for the bill
sponsor: MEP sponsoring the bill
-
+
Returns:
Dict[str, Any]: Complete session results including group decisions and final vote
"""
-
+
if not self.enable_hierarchical_democracy:
- logger.warning("Hierarchical democracy not enabled, falling back to standard session")
- return self.run_democratic_session(bill_title, bill_description, bill_type, committee, sponsor)
-
- logger.info(f"Starting hierarchical democratic session: {bill_title}")
-
+ logger.warning(
+ "Hierarchical democracy not enabled, falling back to standard session"
+ )
+ return self.run_democratic_session(
+ bill_title,
+ bill_description,
+ bill_type,
+ committee,
+ sponsor,
+ )
+
+ logger.info(
+ f"Starting hierarchical democratic session: {bill_title}"
+ )
+
# Step 1: Introduce the bill
if not sponsor:
- sponsor = list(self.meps.keys())[0] # Use first MEP as sponsor
-
+ sponsor = list(self.meps.keys())[
+ 0
+ ] # Use first MEP as sponsor
+
bill = self.introduce_bill(
title=bill_title,
description=bill_description,
bill_type=bill_type,
committee=committee,
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
# Step 2: Conduct committee hearing (if enabled)
committee_result = None
if self.enable_committee_work:
- logger.info(f"Conducting committee hearing in {committee}")
- committee_result = self.conduct_committee_hearing(committee, bill)
-
+ logger.info(
+ f"Conducting committee hearing in {committee}"
+ )
+ committee_result = self.conduct_committee_hearing(
+ committee, bill
+ )
+
# Step 3: Conduct parliamentary debate (if enabled)
debate_result = None
if self.enable_democratic_discussion:
logger.info("Conducting parliamentary debate")
debate_result = self.conduct_parliamentary_debate(bill)
-
+
# Step 4: Conduct hierarchical democratic vote
logger.info("Conducting hierarchical democratic vote")
vote_result = self.conduct_hierarchical_democratic_vote(bill)
-
+
# Step 5: Compile comprehensive session report
session_report = {
"session_type": "hierarchical_democratic",
@@ -2559,7 +3270,7 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"type": bill.bill_type.value,
"committee": bill.committee,
"sponsor": bill.sponsor,
- "status": bill.status
+ "status": bill.status,
},
"committee_work": committee_result,
"parliamentary_debate": debate_result,
@@ -2568,24 +3279,36 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"votes_for": vote_result.votes_for,
"votes_against": vote_result.votes_against,
"abstentions": vote_result.abstentions,
- "total_votes": vote_result.votes_for + vote_result.votes_against + vote_result.abstentions
+ "total_votes": vote_result.votes_for
+ + vote_result.votes_against
+ + vote_result.abstentions,
},
"political_group_decisions": vote_result.individual_votes,
"group_reasoning": vote_result.reasoning,
"parliament_composition": self.get_parliament_composition(),
- "session_summary": self._generate_hierarchical_session_summary(bill, vote_result)
+ "session_summary": self._generate_hierarchical_session_summary(
+ bill, vote_result
+ ),
}
-
- logger.info(f"Hierarchical democratic session completed. Final result: {vote_result.result.value}")
-
+
+ logger.info(
+ f"Hierarchical democratic session completed. Final result: {vote_result.result.value}"
+ )
+
return session_report
- def _generate_hierarchical_session_summary(self, bill: ParliamentaryBill, vote: ParliamentaryVote) -> str:
+ def _generate_hierarchical_session_summary(
+ self, bill: ParliamentaryBill, vote: ParliamentaryVote
+ ) -> str:
"""Generate a summary of the hierarchical democratic session with dual-layer percentage breakdown."""
-
- total_votes = vote.votes_for + vote.votes_against + vote.abstentions
- participation_rate = (total_votes / len(self.meps)) * 100 if self.meps else 0
-
+
+ total_votes = (
+ vote.votes_for + vote.votes_against + vote.abstentions
+ )
+ participation_rate = (
+ (total_votes / len(self.meps)) * 100 if self.meps else 0
+ )
+
summary = f"""
šļø HIERARCHICAL DEMOCRATIC SESSION SUMMARY
@@ -2600,168 +3323,212 @@ Remember: You are a real MEP with specific political views, expertise, and respo
šļø POLITICAL GROUP DECISIONS (Dual-Layer Percentage System):
"""
-
+
for group_name, decision in vote.individual_votes.items():
board = self.political_group_boards.get(group_name)
if board:
group_percentage = board.voting_weight * 100
summary += f"\n⢠{group_name}: {decision} ({board.total_meps} MEPs, {group_percentage:.1f}% of parliament)"
-
+
# Show individual board member percentages
if board.board_member_percentages:
- summary += f"\n š Board Member Breakdown:"
- for member_name, internal_percentage in board.board_member_percentages.items():
- parliament_percentage = internal_percentage * board.voting_weight * 100
+ summary += "\n š Board Member Breakdown:"
+ for (
+ member_name,
+ internal_percentage,
+ ) in board.board_member_percentages.items():
+ parliament_percentage = (
+ internal_percentage
+ * board.voting_weight
+ * 100
+ )
summary += f"\n - {member_name}: {internal_percentage:.1%} of group = {parliament_percentage:.3f}% of parliament"
-
- summary += f"\n\nšÆ DUAL-LAYER DEMOCRATIC PROCESS:"
- summary += f"\n⢠Each political group operates as a specialized board"
- summary += f"\n⢠Board members have individual percentages within their group"
- summary += f"\n⢠Individual percentages à Group percentage = Parliament percentage"
- summary += f"\n⢠Parliament Speaker aggregates all weighted decisions"
+
+ summary += "\n\nšÆ DUAL-LAYER DEMOCRATIC PROCESS:"
+ summary += (
+ "\n⢠Each political group operates as a specialized board"
+ )
+ summary += "\n⢠Board members have individual percentages within their group"
+ summary += "\n⢠Individual percentages à Group percentage = Parliament percentage"
+ summary += (
+ "\n⢠Parliament Speaker aggregates all weighted decisions"
+ )
summary += f"\n⢠Final result based on {len(self.political_group_boards)} political groups with {sum(len(board.board_member_percentages) for board in self.political_group_boards.values())} board members"
-
+
return summary
-
+
def get_mep(self, mep_name: str) -> Optional[ParliamentaryMember]:
"""
Get a specific MEP by name.
-
+
Args:
mep_name: Name of the MEP
-
+
Returns:
Optional[ParliamentaryMember]: MEP if found, None otherwise
"""
return self.meps.get(mep_name)
-
- def get_committee(self, committee_name: str) -> Optional[ParliamentaryCommittee]:
+
+ def get_committee(
+ self, committee_name: str
+ ) -> Optional[ParliamentaryCommittee]:
"""
Get a specific committee by name.
-
+
Args:
committee_name: Name of the committee
-
+
Returns:
Optional[ParliamentaryCommittee]: Committee if found, None otherwise
"""
return self.committees.get(committee_name)
-
- def get_political_group_members(self, group_name: str) -> List[str]:
+
+ def get_political_group_members(
+ self, group_name: str
+ ) -> List[str]:
"""
Get all MEPs in a specific political group.
-
+
Args:
group_name: Name of the political group
-
+
Returns:
List[str]: List of MEP names in the group
"""
return self.political_groups.get(group_name, [])
-
+
def get_country_members(self, country: str) -> List[str]:
"""
Get all MEPs from a specific country.
-
+
Args:
country: Name of the country
-
+
Returns:
List[str]: List of MEP names from the country
"""
- return [mep_name for mep_name, mep in self.meps.items() if mep.country == country]
+ return [
+ mep_name
+ for mep_name, mep in self.meps.items()
+ if mep.country == country
+ ]
def _load_wikipedia_personalities(self):
"""Load Wikipedia personality profiles for MEPs."""
-
+
if not self.enable_wikipedia_personalities:
return
-
+
try:
# Initialize personality scraper
self.personality_scraper = WikipediaPersonalityScraper(
- output_dir="mep_personalities",
- verbose=self.verbose
+ output_dir="mep_personalities", verbose=self.verbose
)
-
+
# Load existing personality profiles
personality_dir = "mep_personalities"
if os.path.exists(personality_dir):
- profile_files = [f for f in os.listdir(personality_dir) if f.endswith('.json')]
-
+ profile_files = [
+ f
+ for f in os.listdir(personality_dir)
+ if f.endswith(".json")
+ ]
+
for filename in profile_files:
filepath = os.path.join(personality_dir, filename)
try:
- profile = self.personality_scraper.load_personality_profile(filepath)
- self.personality_profiles[profile.full_name] = profile
-
+ profile = self.personality_scraper.load_personality_profile(
+ filepath
+ )
+ self.personality_profiles[
+ profile.full_name
+ ] = profile
+
if self.verbose:
- logger.debug(f"Loaded personality profile: {profile.full_name}")
-
+ logger.debug(
+ f"Loaded personality profile: {profile.full_name}"
+ )
+
except Exception as e:
- logger.warning(f"Error loading personality profile {filename}: {e}")
-
+ logger.warning(
+ f"Error loading personality profile {filename}: {e}"
+ )
+
if self.verbose:
- logger.info(f"Loaded {len(self.personality_profiles)} Wikipedia personality profiles")
+ logger.info(
+ f"Loaded {len(self.personality_profiles)} Wikipedia personality profiles"
+ )
else:
if self.verbose:
- logger.info("No existing personality profiles found. Run Wikipedia scraper to create profiles.")
-
+ logger.info(
+ "No existing personality profiles found. Run Wikipedia scraper to create profiles."
+ )
+
except Exception as e:
- logger.error(f"Error loading Wikipedia personalities: {e}")
+ logger.error(
+ f"Error loading Wikipedia personalities: {e}"
+ )
self.enable_wikipedia_personalities = False
- def scrape_wikipedia_personalities(self, delay: float = 1.0) -> Dict[str, str]:
+ def scrape_wikipedia_personalities(
+ self, delay: float = 1.0
+ ) -> Dict[str, str]:
"""
Scrape Wikipedia personality data for all MEPs.
-
+
Args:
delay: Delay between requests to be respectful to Wikipedia
-
+
Returns:
Dictionary mapping MEP names to their personality profile file paths
"""
-
+
if not self.enable_wikipedia_personalities:
logger.error("Wikipedia personality system not available")
return {}
-
+
if not self.personality_scraper:
self.personality_scraper = WikipediaPersonalityScraper(
- output_dir="mep_personalities",
- verbose=self.verbose
+ output_dir="mep_personalities", verbose=self.verbose
)
-
- logger.info("Starting Wikipedia personality scraping for all MEPs...")
- profile_files = self.personality_scraper.scrape_all_mep_personalities(
- xml_file=self.eu_data_file,
- delay=delay
+
+ logger.info(
+ "Starting Wikipedia personality scraping for all MEPs..."
)
-
+ profile_files = (
+ self.personality_scraper.scrape_all_mep_personalities(
+ xml_file=self.eu_data_file, delay=delay
+ )
+ )
+
# Reload personality profiles
self._load_wikipedia_personalities()
-
+
return profile_files
- def get_mep_personality_profile(self, mep_name: str) -> Optional[MEPPersonalityProfile]:
+ def get_mep_personality_profile(
+ self, mep_name: str
+ ) -> Optional[MEPPersonalityProfile]:
"""
Get personality profile for a specific MEP.
-
+
Args:
mep_name: Name of the MEP
-
+
Returns:
MEPPersonalityProfile if found, None otherwise
"""
return self.personality_profiles.get(mep_name)
- def analyze_political_landscape(self, bill: ParliamentaryBill) -> Dict[str, Any]:
+ def analyze_political_landscape(
+ self, bill: ParliamentaryBill
+ ) -> Dict[str, Any]:
"""
Analyze the political landscape for a bill to predict voting outcomes.
-
+
Args:
bill: Bill to analyze
-
+
Returns:
Dict[str, Any]: Political analysis results
"""
@@ -2769,59 +3536,79 @@ Remember: You are a real MEP with specific political views, expertise, and respo
"overall_support": 0.0,
"opposition": 0.0,
"uncertainty": 0.0,
- "group_analysis": {}
+ "group_analysis": {},
}
-
+
# Analyze by political group
for group_name, meps in self.political_groups.items():
if not meps:
continue
-
+
# Simple analysis based on political group alignment
group_support = 0.0
group_opposition = 0.0
-
+
# Assign support based on political group characteristics
- if "Green" in group_name or "Environment" in bill.description:
+ if (
+ "Green" in group_name
+ or "Environment" in bill.description
+ ):
group_support = 75.0
group_opposition = 15.0
- elif "Socialist" in group_name or "Social" in bill.description:
+ elif (
+ "Socialist" in group_name
+ or "Social" in bill.description
+ ):
group_support = 70.0
group_opposition = 20.0
- elif "Conservative" in group_name or "Economic" in bill.description:
+ elif (
+ "Conservative" in group_name
+ or "Economic" in bill.description
+ ):
group_support = 60.0
group_opposition = 30.0
- elif "Liberal" in group_name or "Digital" in bill.description:
+ elif (
+ "Liberal" in group_name
+ or "Digital" in bill.description
+ ):
group_support = 65.0
group_opposition = 25.0
else:
group_support = 50.0
group_opposition = 30.0
-
- group_uncertainty = 100.0 - group_support - group_opposition
-
+
+ group_uncertainty = (
+ 100.0 - group_support - group_opposition
+ )
+
analysis["group_analysis"][group_name] = {
"support": group_support,
"opposition": group_opposition,
"uncertainty": group_uncertainty,
- "mep_count": len(meps)
+ "mep_count": len(meps),
}
-
+
# Calculate overall support weighted by group size
total_meps = len(self.meps)
if total_meps > 0:
weighted_support = 0.0
weighted_opposition = 0.0
weighted_uncertainty = 0.0
-
- for group_name, group_data in analysis["group_analysis"].items():
+
+ for group_name, group_data in analysis[
+ "group_analysis"
+ ].items():
weight = group_data["mep_count"] / total_meps
weighted_support += group_data["support"] * weight
- weighted_opposition += group_data["opposition"] * weight
- weighted_uncertainty += group_data["uncertainty"] * weight
-
+ weighted_opposition += (
+ group_data["opposition"] * weight
+ )
+ weighted_uncertainty += (
+ group_data["uncertainty"] * weight
+ )
+
analysis["overall_support"] = weighted_support
analysis["opposition"] = weighted_opposition
analysis["uncertainty"] = weighted_uncertainty
-
+
return analysis
diff --git a/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py b/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py
index 7dc60d02..b2ccf858 100644
--- a/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py
+++ b/examples/simulations/euroswarm_parliament/euroswarm_parliament_example.py
@@ -5,25 +5,21 @@ This script demonstrates the comprehensive democratic functionality of the EuroS
including bill introduction, committee work, parliamentary debates, and democratic voting.
"""
-import json
-import time
-from datetime import datetime
-
# Import directly from the file
from euroswarm_parliament import (
EuroSwarmParliament,
VoteType,
- ParliamentaryRole,
- ParliamentaryMember
)
def demonstrate_parliament_initialization():
"""Demonstrate parliament initialization and basic functionality with cost optimization."""
-
- print("\nEUROSWARM PARLIAMENT INITIALIZATION DEMONSTRATION (COST OPTIMIZED)")
+
+ print(
+ "\nEUROSWARM PARLIAMENT INITIALIZATION DEMONSTRATION (COST OPTIMIZED)"
+ )
print("=" * 60)
-
+
# Initialize the parliament with cost optimization
parliament = EuroSwarmParliament(
eu_data_file="EU.xml",
@@ -35,487 +31,632 @@ def demonstrate_parliament_initialization():
enable_caching=True, # NEW: Enable response caching
batch_size=25, # NEW: Batch size for concurrent execution
budget_limit=100.0, # NEW: Budget limit in dollars
- verbose=True
+ verbose=True,
)
-
+
print(f"Parliament initialized with {len(parliament.meps)} MEPs")
-
+
# Show parliament composition with cost stats
composition = parliament.get_parliament_composition()
-
- print(f"\nPARLIAMENT COMPOSITION:")
+
+ print("\nPARLIAMENT COMPOSITION:")
print(f"Total MEPs: {composition['total_meps']}")
- print(f"Loaded MEPs: {composition['loaded_meps']} (lazy loading active)")
-
- print(f"\nCOST OPTIMIZATION:")
- cost_stats = composition['cost_stats']
- print(f"Budget Limit: ${cost_stats['budget_remaining'] + cost_stats['total_cost']:.2f}")
+ print(
+ f"Loaded MEPs: {composition['loaded_meps']} (lazy loading active)"
+ )
+
+ print("\nCOST OPTIMIZATION:")
+ cost_stats = composition["cost_stats"]
+ print(
+ f"Budget Limit: ${cost_stats['budget_remaining'] + cost_stats['total_cost']:.2f}"
+ )
print(f"Budget Used: ${cost_stats['total_cost']:.2f}")
print(f"Budget Remaining: ${cost_stats['budget_remaining']:.2f}")
print(f"Cache Hit Rate: {cost_stats['cache_hit_rate']:.1%}")
-
- print(f"\nPOLITICAL GROUP DISTRIBUTION:")
- for group, data in composition['political_groups'].items():
- count = data['count']
- percentage = data['percentage']
+
+ print("\nPOLITICAL GROUP DISTRIBUTION:")
+ for group, data in composition["political_groups"].items():
+ count = data["count"]
+ percentage = data["percentage"]
print(f" {group}: {count} MEPs ({percentage:.1f}%)")
-
- print(f"\nCOMMITTEE LEADERSHIP:")
- for committee_name, committee_data in composition['committees'].items():
- chair = committee_data['chair']
+
+ print("\nCOMMITTEE LEADERSHIP:")
+ for committee_name, committee_data in composition[
+ "committees"
+ ].items():
+ chair = committee_data["chair"]
if chair:
print(f" {committee_name}: {chair}")
-
+
return parliament
def demonstrate_individual_mep_interaction(parliament):
"""Demonstrate individual MEP interaction and personality."""
-
+
print("\nINDIVIDUAL MEP INTERACTION DEMONSTRATION")
print("=" * 60)
-
+
# Get a sample MEP
sample_mep_name = list(parliament.meps.keys())[0]
sample_mep = parliament.meps[sample_mep_name]
-
+
print(f"Sample MEP: {sample_mep.full_name}")
print(f"Country: {sample_mep.country}")
print(f"Political Group: {sample_mep.political_group}")
print(f"National Party: {sample_mep.national_party}")
print(f"Committees: {', '.join(sample_mep.committees)}")
print(f"Expertise Areas: {', '.join(sample_mep.expertise_areas)}")
-
+
# Test MEP agent interaction
if sample_mep.agent:
test_prompt = "What are your views on European integration and how do you approach cross-border cooperation?"
-
+
print(f"\nMEP Response to: '{test_prompt}'")
print("-" * 50)
-
+
try:
response = sample_mep.agent.run(test_prompt)
- print(response[:500] + "..." if len(response) > 500 else response)
+ print(
+ response[:500] + "..."
+ if len(response) > 500
+ else response
+ )
except Exception as e:
print(f"Error getting MEP response: {e}")
def demonstrate_committee_work(parliament):
"""Demonstrate committee work and hearings."""
-
+
print("\nCOMMITTEE WORK DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[0]
-
+
# Create a test bill
bill = parliament.introduce_bill(
title="European Digital Rights and Privacy Protection Act",
description="Comprehensive legislation to strengthen digital rights, enhance privacy protection, and establish clear guidelines for data handling across the European Union.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Legal Affairs",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
print(f"Bill: {bill.title}")
print(f"Committee: {bill.committee}")
print(f"Sponsor: {bill.sponsor}")
-
+
# Conduct committee hearing
- print(f"\nCONDUCTING COMMITTEE HEARING...")
- hearing_result = parliament.conduct_committee_hearing(bill.committee, bill)
-
+ print("\nCONDUCTING COMMITTEE HEARING...")
+ hearing_result = parliament.conduct_committee_hearing(
+ bill.committee, bill
+ )
+
print(f"Committee: {hearing_result['committee']}")
print(f"Participants: {len(hearing_result['participants'])} MEPs")
- print(f"Recommendation: {hearing_result['recommendations']['recommendation']}")
- print(f"Support: {hearing_result['recommendations']['support_percentage']:.1f}%")
- print(f"Oppose: {hearing_result['recommendations']['oppose_percentage']:.1f}%")
- print(f"Amend: {hearing_result['recommendations']['amend_percentage']:.1f}%")
+ print(
+ f"Recommendation: {hearing_result['recommendations']['recommendation']}"
+ )
+ print(
+ f"Support: {hearing_result['recommendations']['support_percentage']:.1f}%"
+ )
+ print(
+ f"Oppose: {hearing_result['recommendations']['oppose_percentage']:.1f}%"
+ )
+ print(
+ f"Amend: {hearing_result['recommendations']['amend_percentage']:.1f}%"
+ )
def demonstrate_parliamentary_debate(parliament):
"""Demonstrate parliamentary debate functionality."""
-
+
print("\nPARLIAMENTARY DEBATE DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[1]
-
+
# Create a test bill
bill = parliament.introduce_bill(
title="European Green Deal Implementation Act",
description="Legislation to implement the European Green Deal, including carbon neutrality targets, renewable energy investments, and sustainable development measures.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Environment, Public Health and Food Safety",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
print(f"Bill: {bill.title}")
print(f"Description: {bill.description}")
-
+
# Conduct parliamentary debate
- print(f"\nCONDUCTING PARLIAMENTARY DEBATE...")
- debate_result = parliament.conduct_parliamentary_debate(bill, max_speakers=10)
-
- print(f"Debate Participants: {len(debate_result['participants'])} MEPs")
- print(f"Debate Analysis:")
- print(f" Support: {debate_result['analysis']['support_count']} speakers ({debate_result['analysis']['support_percentage']:.1f}%)")
- print(f" Oppose: {debate_result['analysis']['oppose_count']} speakers ({debate_result['analysis']['oppose_percentage']:.1f}%)")
- print(f" Neutral: {debate_result['analysis']['neutral_count']} speakers ({debate_result['analysis']['neutral_percentage']:.1f}%)")
+ print("\nCONDUCTING PARLIAMENTARY DEBATE...")
+ debate_result = parliament.conduct_parliamentary_debate(
+ bill, max_speakers=10
+ )
+
+ print(
+ f"Debate Participants: {len(debate_result['participants'])} MEPs"
+ )
+ print("Debate Analysis:")
+ print(
+ f" Support: {debate_result['analysis']['support_count']} speakers ({debate_result['analysis']['support_percentage']:.1f}%)"
+ )
+ print(
+ f" Oppose: {debate_result['analysis']['oppose_count']} speakers ({debate_result['analysis']['oppose_percentage']:.1f}%)"
+ )
+ print(
+ f" Neutral: {debate_result['analysis']['neutral_count']} speakers ({debate_result['analysis']['neutral_percentage']:.1f}%)"
+ )
def demonstrate_democratic_voting(parliament):
"""Demonstrate democratic voting functionality."""
-
+
print("\nDEMOCRATIC VOTING DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[2]
-
+
# Create a test bill
bill = parliament.introduce_bill(
title="European Social Rights and Labor Protection Act",
description="Legislation to strengthen social rights, improve labor conditions, and ensure fair treatment of workers across the European Union.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Employment and Social Affairs",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
print(f"Bill: {bill.title}")
print(f"Sponsor: {bill.sponsor}")
-
+
# Conduct democratic vote
- print(f"\nCONDUCTING DEMOCRATIC VOTE...")
+ print("\nCONDUCTING DEMOCRATIC VOTE...")
vote_result = parliament.conduct_democratic_vote(bill)
-
+
# Calculate percentages
- total_votes = vote_result.votes_for + vote_result.votes_against + vote_result.abstentions
- in_favor_percentage = (vote_result.votes_for / total_votes * 100) if total_votes > 0 else 0
- against_percentage = (vote_result.votes_against / total_votes * 100) if total_votes > 0 else 0
- abstentions_percentage = (vote_result.abstentions / total_votes * 100) if total_votes > 0 else 0
-
- print(f"Vote Results:")
+ total_votes = (
+ vote_result.votes_for
+ + vote_result.votes_against
+ + vote_result.abstentions
+ )
+ in_favor_percentage = (
+ (vote_result.votes_for / total_votes * 100)
+ if total_votes > 0
+ else 0
+ )
+ against_percentage = (
+ (vote_result.votes_against / total_votes * 100)
+ if total_votes > 0
+ else 0
+ )
+ abstentions_percentage = (
+ (vote_result.abstentions / total_votes * 100)
+ if total_votes > 0
+ else 0
+ )
+
+ print("Vote Results:")
print(f" Total Votes: {total_votes}")
- print(f" In Favor: {vote_result.votes_for} ({in_favor_percentage:.1f}%)")
- print(f" Against: {vote_result.votes_against} ({against_percentage:.1f}%)")
- print(f" Abstentions: {vote_result.abstentions} ({abstentions_percentage:.1f}%)")
+ print(
+ f" In Favor: {vote_result.votes_for} ({in_favor_percentage:.1f}%)"
+ )
+ print(
+ f" Against: {vote_result.votes_against} ({against_percentage:.1f}%)"
+ )
+ print(
+ f" Abstentions: {vote_result.abstentions} ({abstentions_percentage:.1f}%)"
+ )
print(f" Result: {vote_result.result.value}")
-
+
# Show political group breakdown if available
- if hasattr(vote_result, 'group_votes') and vote_result.group_votes:
- print(f"\nPOLITICAL GROUP BREAKDOWN:")
+ if (
+ hasattr(vote_result, "group_votes")
+ and vote_result.group_votes
+ ):
+ print("\nPOLITICAL GROUP BREAKDOWN:")
for group, votes in vote_result.group_votes.items():
- print(f" {group}: {votes['in_favor']}/{votes['total']} in favor ({votes['percentage']:.1f}%)")
+ print(
+ f" {group}: {votes['in_favor']}/{votes['total']} in favor ({votes['percentage']:.1f}%)"
+ )
else:
- print(f"\nIndividual votes recorded: {len(vote_result.individual_votes)} MEPs")
+ print(
+ f"\nIndividual votes recorded: {len(vote_result.individual_votes)} MEPs"
+ )
def demonstrate_complete_democratic_session(parliament):
"""Demonstrate a complete democratic parliamentary session."""
-
+
print("\nCOMPLETE DEMOCRATIC SESSION DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[3]
-
+
# Run complete session
session_result = parliament.run_democratic_session(
bill_title="European Innovation and Technology Advancement Act",
bill_description="Comprehensive legislation to promote innovation, support technology startups, and establish Europe as a global leader in digital transformation and technological advancement.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Industry, Research and Energy",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
- print(f"Session Results:")
+
+ print("Session Results:")
print(f" Bill: {session_result['bill'].title}")
- print(f" Committee Hearing: {session_result['hearing']['recommendations']['recommendation']}")
- print(f" Debate Participants: {len(session_result['debate']['participants'])} MEPs")
+ print(
+ f" Committee Hearing: {session_result['hearing']['recommendations']['recommendation']}"
+ )
+ print(
+ f" Debate Participants: {len(session_result['debate']['participants'])} MEPs"
+ )
print(f" Final Vote: {session_result['vote']['result']}")
- print(f" Vote Margin: {session_result['vote']['in_favor_percentage']:.1f}% in favor")
+ print(
+ f" Vote Margin: {session_result['vote']['in_favor_percentage']:.1f}% in favor"
+ )
def demonstrate_political_analysis(parliament):
"""Demonstrate political analysis and voting prediction."""
-
+
print("\nPOLITICAL ANALYSIS DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[4]
-
+
# Create a test bill
bill = parliament.introduce_bill(
title="European Climate Action and Sustainability Act",
description="Comprehensive climate action legislation including carbon pricing, renewable energy targets, and sustainable development measures.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Environment, Public Health and Food Safety",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
print(f"Bill: {bill.title}")
print(f"Sponsor: {bill.sponsor}")
-
+
# Analyze political landscape
analysis = parliament.analyze_political_landscape(bill)
-
- print(f"\nPOLITICAL LANDSCAPE ANALYSIS:")
+
+ print("\nPOLITICAL LANDSCAPE ANALYSIS:")
print(f" Overall Support: {analysis['overall_support']:.1f}%")
print(f" Opposition: {analysis['opposition']:.1f}%")
print(f" Uncertainty: {analysis['uncertainty']:.1f}%")
-
- print(f"\nPOLITICAL GROUP ANALYSIS:")
- for group, data in analysis['group_analysis'].items():
- print(f" {group}: {data['support']:.1f}% support, {data['opposition']:.1f}% opposition")
+
+ print("\nPOLITICAL GROUP ANALYSIS:")
+ for group, data in analysis["group_analysis"].items():
+ print(
+ f" {group}: {data['support']:.1f}% support, {data['opposition']:.1f}% opposition"
+ )
def demonstrate_hierarchical_democratic_voting(parliament):
"""Demonstrate hierarchical democratic voting with political group boards."""
-
+
print("\nHIERARCHICAL DEMOCRATIC VOTING DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[5]
-
+
# Create a test bill
bill = parliament.introduce_bill(
title="European Climate Action and Sustainability Act",
description="Comprehensive climate action legislation including carbon pricing, renewable energy targets, and sustainable development measures.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Environment, Public Health and Food Safety",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
+
print(f"Bill: {bill.title}")
print(f"Sponsor: {bill.sponsor}")
-
+
# Conduct hierarchical vote
- print(f"\nCONDUCTING HIERARCHICAL DEMOCRATIC VOTE...")
- hierarchical_result = parliament.conduct_hierarchical_democratic_vote(bill)
-
- print(f"Hierarchical Vote Results:")
+ print("\nCONDUCTING HIERARCHICAL DEMOCRATIC VOTE...")
+ hierarchical_result = (
+ parliament.conduct_hierarchical_democratic_vote(bill)
+ )
+
+ print("Hierarchical Vote Results:")
print(f" Total Votes: {hierarchical_result['total_votes']}")
- print(f" In Favor: {hierarchical_result['in_favor']} ({hierarchical_result['in_favor_percentage']:.1f}%)")
- print(f" Against: {hierarchical_result['against']} ({hierarchical_result['against_percentage']:.1f}%)")
+ print(
+ f" In Favor: {hierarchical_result['in_favor']} ({hierarchical_result['in_favor_percentage']:.1f}%)"
+ )
+ print(
+ f" Against: {hierarchical_result['against']} ({hierarchical_result['against_percentage']:.1f}%)"
+ )
print(f" Result: {hierarchical_result['result']}")
-
- print(f"\nPOLITICAL GROUP BOARD DECISIONS:")
- for group, decision in hierarchical_result['group_decisions'].items():
- print(f" {group}: {decision['decision']} ({decision['confidence']:.1f}% confidence)")
+
+ print("\nPOLITICAL GROUP BOARD DECISIONS:")
+ for group, decision in hierarchical_result[
+ "group_decisions"
+ ].items():
+ print(
+ f" {group}: {decision['decision']} ({decision['confidence']:.1f}% confidence)"
+ )
def demonstrate_complete_hierarchical_session(parliament):
"""Demonstrate a complete hierarchical democratic session."""
-
+
print("\nCOMPLETE HIERARCHICAL DEMOCRATIC SESSION DEMONSTRATION")
print("=" * 60)
-
+
# Get a real MEP as sponsor
sponsor = list(parliament.meps.keys())[6]
-
+
# Run complete hierarchical session
session_result = parliament.run_hierarchical_democratic_session(
bill_title="European Climate Action and Sustainability Act",
bill_description="Comprehensive climate action legislation including carbon pricing, renewable energy targets, and sustainable development measures.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Environment, Public Health and Food Safety",
- sponsor=sponsor
+ sponsor=sponsor,
)
-
- print(f"Hierarchical Session Results:")
+
+ print("Hierarchical Session Results:")
print(f" Bill: {session_result['bill'].title}")
- print(f" Committee Hearing: {session_result['hearing']['recommendations']['recommendation']}")
- print(f" Debate Participants: {len(session_result['debate']['participants'])} MEPs")
+ print(
+ f" Committee Hearing: {session_result['hearing']['recommendations']['recommendation']}"
+ )
+ print(
+ f" Debate Participants: {len(session_result['debate']['participants'])} MEPs"
+ )
print(f" Final Vote: {session_result['vote']['result']}")
- print(f" Vote Margin: {session_result['vote']['in_favor_percentage']:.1f}% in favor")
+ print(
+ f" Vote Margin: {session_result['vote']['in_favor_percentage']:.1f}% in favor"
+ )
def demonstrate_wikipedia_personalities(parliament):
"""Demonstrate the Wikipedia personality system for realistic MEP behavior."""
-
+
print("\nWIKIPEDIA PERSONALITY SYSTEM DEMONSTRATION")
print("=" * 60)
-
+
# Check if Wikipedia personalities are available
if not parliament.enable_wikipedia_personalities:
print("Wikipedia personality system not available")
- print("To enable: Install required dependencies and run Wikipedia scraper")
+ print(
+ "To enable: Install required dependencies and run Wikipedia scraper"
+ )
return
-
- print(f"Wikipedia personality system enabled")
- print(f"Loaded {len(parliament.personality_profiles)} personality profiles")
-
+
+ print("Wikipedia personality system enabled")
+ print(
+ f"Loaded {len(parliament.personality_profiles)} personality profiles"
+ )
+
# Show sample personality profiles
- print(f"\nSAMPLE PERSONALITY PROFILES:")
+ print("\nSAMPLE PERSONALITY PROFILES:")
print("-" * 40)
-
+
sample_count = 0
for mep_name, profile in parliament.personality_profiles.items():
if sample_count >= 3: # Show only 3 samples
break
-
+
print(f"\n{mep_name}")
- print(f" Wikipedia URL: {profile.wikipedia_url if profile.wikipedia_url else 'Not available'}")
- print(f" Summary: {profile.summary[:200]}..." if profile.summary else "No summary available")
- print(f" Political Views: {profile.political_views[:150]}..." if profile.political_views else "Based on party alignment")
- print(f" Policy Focus: {profile.policy_focus[:150]}..." if profile.policy_focus else "General parliamentary work")
- print(f" Achievements: {profile.achievements[:150]}..." if profile.achievements else "Parliamentary service")
+ print(
+ f" Wikipedia URL: {profile.wikipedia_url if profile.wikipedia_url else 'Not available'}"
+ )
+ print(
+ f" Summary: {profile.summary[:200]}..."
+ if profile.summary
+ else "No summary available"
+ )
+ print(
+ f" Political Views: {profile.political_views[:150]}..."
+ if profile.political_views
+ else "Based on party alignment"
+ )
+ print(
+ f" Policy Focus: {profile.policy_focus[:150]}..."
+ if profile.policy_focus
+ else "General parliamentary work"
+ )
+ print(
+ f" Achievements: {profile.achievements[:150]}..."
+ if profile.achievements
+ else "Parliamentary service"
+ )
print(f" Last Updated: {profile.last_updated}")
-
+
sample_count += 1
-
+
# Demonstrate personality-driven voting
- print(f"\nPERSONALITY-DRIVEN VOTING DEMONSTRATION:")
+ print("\nPERSONALITY-DRIVEN VOTING DEMONSTRATION:")
print("-" * 50)
-
+
# Create a test bill that would trigger different personality responses
bill = parliament.introduce_bill(
title="European Climate Action and Green Technology Investment Act",
description="Comprehensive legislation to accelerate Europe's transition to renewable energy, including massive investments in green technology, carbon pricing mechanisms, and support for affected industries and workers.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Environment",
- sponsor="Climate Action Leader"
+ sponsor="Climate Action Leader",
)
-
+
print(f"Bill: {bill.title}")
print(f"Description: {bill.description}")
-
+
# Show how different MEPs with Wikipedia personalities would respond
- print(f"\nPERSONALITY-BASED RESPONSES:")
+ print("\nPERSONALITY-BASED RESPONSES:")
print("-" * 40)
-
+
sample_meps = list(parliament.personality_profiles.keys())[:3]
-
+
for mep_name in sample_meps:
mep = parliament.meps.get(mep_name)
profile = parliament.personality_profiles.get(mep_name)
-
+
if mep and profile:
print(f"\n{mep_name} ({mep.political_group})")
-
+
# Show personality influence
if profile.political_views:
- print(f" Political Views: {profile.political_views[:100]}...")
-
+ print(
+ f" Political Views: {profile.political_views[:100]}..."
+ )
+
if profile.policy_focus:
- print(f" Policy Focus: {profile.policy_focus[:100]}...")
-
+ print(
+ f" Policy Focus: {profile.policy_focus[:100]}..."
+ )
+
# Predict voting behavior based on personality
- if "environment" in profile.policy_focus.lower() or "climate" in profile.political_views.lower():
+ if (
+ "environment" in profile.policy_focus.lower()
+ or "climate" in profile.political_views.lower()
+ ):
predicted_vote = "LIKELY SUPPORT"
- reasoning = "Environmental policy focus and climate advocacy"
- elif "economic" in profile.policy_focus.lower() or "business" in profile.political_views.lower():
+ reasoning = (
+ "Environmental policy focus and climate advocacy"
+ )
+ elif (
+ "economic" in profile.policy_focus.lower()
+ or "business" in profile.political_views.lower()
+ ):
predicted_vote = "LIKELY OPPOSE"
reasoning = "Economic concerns about investment costs"
else:
predicted_vote = "UNCERTAIN"
- reasoning = "Mixed considerations based on party alignment"
-
+ reasoning = (
+ "Mixed considerations based on party alignment"
+ )
+
print(f" Predicted Vote: {predicted_vote}")
print(f" Reasoning: {reasoning}")
-
+
# Demonstrate scraping functionality
- print(f"\nWIKIPEDIA SCRAPING CAPABILITIES:")
+ print("\nWIKIPEDIA SCRAPING CAPABILITIES:")
print("-" * 50)
print("Can scrape Wikipedia data for all 717 MEPs")
- print("Extracts political views, career history, and achievements")
+ print(
+ "Extracts political views, career history, and achievements"
+ )
print("Creates detailed personality profiles in JSON format")
- print("Integrates real personality data into AI agent system prompts")
+ print(
+ "Integrates real personality data into AI agent system prompts"
+ )
print("Enables realistic, personality-driven voting behavior")
print("Respectful API usage with configurable delays")
-
- print(f"\nTo scrape all MEP personalities:")
+
+ print("\nTo scrape all MEP personalities:")
print(" parliament.scrape_wikipedia_personalities(delay=1.0)")
- print(" # This will create personality profiles for all 717 MEPs")
+ print(
+ " # This will create personality profiles for all 717 MEPs"
+ )
print(" # Profiles are saved in 'mep_personalities/' directory")
def demonstrate_optimized_parliamentary_session(parliament):
"""Demonstrate cost-optimized parliamentary session."""
-
+
print("\nCOST-OPTIMIZED PARLIAMENTARY SESSION DEMONSTRATION")
print("=" * 60)
-
+
# Run optimized session with cost limit
session_result = parliament.run_optimized_parliamentary_session(
bill_title="European Digital Rights and Privacy Protection Act",
bill_description="Comprehensive legislation to strengthen digital rights, enhance privacy protection, and establish clear guidelines for data handling across the European Union.",
bill_type=VoteType.ORDINARY_LEGISLATIVE_PROCEDURE,
committee="Legal Affairs",
- max_cost=25.0 # Max $25 for this session
- )
-
- print(f"Session Results:")
- print(f" Bill: {session_result['session_summary']['bill_title']}")
- print(f" Final Outcome: {session_result['session_summary']['final_outcome']}")
- print(f" Total Cost: ${session_result['session_summary']['total_cost']:.2f}")
- print(f" Budget Remaining: ${session_result['cost_stats']['budget_remaining']:.2f}")
-
+ max_cost=25.0, # Max $25 for this session
+ )
+
+ print("Session Results:")
+ print(
+ f" Bill: {session_result['session_summary']['bill_title']}"
+ )
+ print(
+ f" Final Outcome: {session_result['session_summary']['final_outcome']}"
+ )
+ print(
+ f" Total Cost: ${session_result['session_summary']['total_cost']:.2f}"
+ )
+ print(
+ f" Budget Remaining: ${session_result['cost_stats']['budget_remaining']:.2f}"
+ )
+
# Show detailed cost statistics
cost_stats = parliament.get_cost_statistics()
- print(f"\nDETAILED COST STATISTICS:")
+ print("\nDETAILED COST STATISTICS:")
print(f" Total Tokens Used: {cost_stats['total_tokens']:,}")
print(f" Requests Made: {cost_stats['requests_made']}")
print(f" Cache Hits: {cost_stats['cache_hits']}")
print(f" Cache Hit Rate: {cost_stats['cache_hit_rate']:.1%}")
- print(f" Loading Efficiency: {cost_stats['loading_efficiency']:.1%}")
+ print(
+ f" Loading Efficiency: {cost_stats['loading_efficiency']:.1%}"
+ )
print(f" Cache Size: {cost_stats['cache_size']} entries")
-
+
return session_result
def main():
"""Main demonstration function."""
-
+
print("EUROSWARM PARLIAMENT - COST OPTIMIZED DEMONSTRATION")
print("=" * 60)
- print("This demonstration shows the EuroSwarm Parliament with cost optimization features:")
+ print(
+ "This demonstration shows the EuroSwarm Parliament with cost optimization features:"
+ )
print("⢠Lazy loading of MEP agents (only create when needed)")
print("⢠Response caching (avoid repeated API calls)")
print("⢠Batch processing (control memory and cost)")
print("⢠Budget controls (hard limits on spending)")
print("⢠Cost tracking (real-time monitoring)")
-
+
# Initialize parliament with cost optimization
parliament = demonstrate_parliament_initialization()
-
+
# Demonstrate individual MEP interaction (will trigger lazy loading)
demonstrate_individual_mep_interaction(parliament)
-
+
# Demonstrate committee work with cost optimization
demonstrate_committee_work(parliament)
-
+
# Demonstrate parliamentary debate with cost optimization
demonstrate_parliamentary_debate(parliament)
-
+
# Demonstrate democratic voting with cost optimization
demonstrate_democratic_voting(parliament)
-
+
# Demonstrate political analysis with cost optimization
demonstrate_political_analysis(parliament)
-
+
# Demonstrate optimized parliamentary session
demonstrate_optimized_parliamentary_session(parliament)
-
+
# Show final cost statistics
final_stats = parliament.get_cost_statistics()
- print(f"\nFINAL COST STATISTICS:")
+ print("\nFINAL COST STATISTICS:")
print(f"Total Cost: ${final_stats['total_cost']:.2f}")
print(f"Budget Remaining: ${final_stats['budget_remaining']:.2f}")
print(f"Cache Hit Rate: {final_stats['cache_hit_rate']:.1%}")
- print(f"Loading Efficiency: {final_stats['loading_efficiency']:.1%}")
-
- print(f"\nā
COST OPTIMIZATION DEMONSTRATION COMPLETED!")
- print(f"ā
EuroSwarm Parliament now supports cost-effective large-scale simulations")
- print(f"ā
Lazy loading: {final_stats['loaded_meps']}/{final_stats['total_meps']} MEPs loaded")
+ print(
+ f"Loading Efficiency: {final_stats['loading_efficiency']:.1%}"
+ )
+
+ print("\nā
COST OPTIMIZATION DEMONSTRATION COMPLETED!")
+ print(
+ "ā
EuroSwarm Parliament now supports cost-effective large-scale simulations"
+ )
+ print(
+ f"ā
Lazy loading: {final_stats['loaded_meps']}/{final_stats['total_meps']} MEPs loaded"
+ )
print(f"ā
Caching: {final_stats['cache_hit_rate']:.1%} hit rate")
- print(f"ā
Budget control: ${final_stats['total_cost']:.2f} spent of ${final_stats['budget_remaining'] + final_stats['total_cost']:.2f} budget")
+ print(
+ f"ā
Budget control: ${final_stats['total_cost']:.2f} spent of ${final_stats['budget_remaining'] + final_stats['total_cost']:.2f} budget"
+ )
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff --git a/examples/simulations/euroswarm_parliament/mass_agent_template.py b/examples/simulations/euroswarm_parliament/mass_agent_template.py
index a6e29d8c..fc42e3f9 100644
--- a/examples/simulations/euroswarm_parliament/mass_agent_template.py
+++ b/examples/simulations/euroswarm_parliament/mass_agent_template.py
@@ -17,13 +17,10 @@ Key Features:
import os
import random
import json
-import time
import hashlib
-from typing import Dict, List, Optional, Union, Any, Set
+from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field
from enum import Enum
-from datetime import datetime
-from functools import lru_cache
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_concurrently
@@ -31,10 +28,6 @@ from swarms.structs.board_of_directors_swarm import (
BoardOfDirectorsSwarm,
BoardMember,
BoardMemberRole,
- BoardDecisionType,
- BoardSpec,
- BoardOrder,
- BoardDecision,
enable_board_feature,
)
from swarms.utils.loguru_logger import initialize_logger
@@ -48,7 +41,7 @@ enable_board_feature()
class AgentRole(str, Enum):
"""Enumeration of agent roles and specializations."""
-
+
WORKER = "worker"
MANAGER = "manager"
SPECIALIST = "specialist"
@@ -61,7 +54,7 @@ class AgentRole(str, Enum):
class AgentCategory(str, Enum):
"""Enumeration of agent categories for organization."""
-
+
TECHNICAL = "technical"
CREATIVE = "creative"
ANALYTICAL = "analytical"
@@ -74,7 +67,7 @@ class AgentCategory(str, Enum):
class AgentProfile:
"""
Represents a single agent in the mass agent system.
-
+
Attributes:
name: Unique name of the agent
role: Primary role of the agent
@@ -86,7 +79,7 @@ class AgentProfile:
agent: The AI agent instance (lazy loaded)
is_loaded: Whether the agent has been instantiated
"""
-
+
name: str
role: AgentRole
category: AgentCategory
@@ -102,7 +95,7 @@ class AgentProfile:
class AgentGroup:
"""
Represents a group of agents with similar roles or categories.
-
+
Attributes:
name: Name of the group
category: Category of the group
@@ -112,7 +105,7 @@ class AgentGroup:
group_swarm: Board of Directors swarm for this group
is_swarm_loaded: Whether the swarm has been instantiated
"""
-
+
name: str
category: AgentCategory
agents: List[str] = field(default_factory=list)
@@ -125,28 +118,30 @@ class AgentGroup:
@dataclass
class CostTracker:
"""Track costs and usage for budget management."""
-
+
total_tokens_used: int = 0
total_cost_estimate: float = 0.0
budget_limit: float = 100.0 # Default $100 budget
token_cost_per_1m: float = 0.15 # GPT-4o-mini cost
requests_made: int = 0
cache_hits: int = 0
-
+
def add_tokens(self, tokens: int):
"""Add tokens used and calculate cost."""
self.total_tokens_used += tokens
- self.total_cost_estimate = (self.total_tokens_used / 1_000_000) * self.token_cost_per_1m
+ self.total_cost_estimate = (
+ self.total_tokens_used / 1_000_000
+ ) * self.token_cost_per_1m
self.requests_made += 1
-
+
def add_cache_hit(self):
"""Record a cache hit."""
self.cache_hits += 1
-
+
def check_budget(self) -> bool:
"""Check if within budget."""
return self.total_cost_estimate <= self.budget_limit
-
+
def get_stats(self) -> Dict[str, Any]:
"""Get cost statistics."""
return {
@@ -154,19 +149,22 @@ class CostTracker:
"total_cost": self.total_cost_estimate,
"requests_made": self.requests_made,
"cache_hits": self.cache_hits,
- "cache_hit_rate": self.cache_hits / max(1, self.requests_made + self.cache_hits),
- "budget_remaining": max(0, self.budget_limit - self.total_cost_estimate)
+ "cache_hit_rate": self.cache_hits
+ / max(1, self.requests_made + self.cache_hits),
+ "budget_remaining": max(
+ 0, self.budget_limit - self.total_cost_estimate
+ ),
}
class MassAgentTemplate:
"""
Template for creating large-scale multi-agent systems with cost optimization.
-
+
This class provides a framework for generating hundreds of agents on the fly,
organizing them into groups, and managing their interactions with cost controls.
"""
-
+
def __init__(
self,
data_source: str = None, # Path to data file (CSV, JSON, XML, etc.)
@@ -181,7 +179,7 @@ class MassAgentTemplate:
):
"""
Initialize the Mass Agent Template with cost optimization.
-
+
Args:
data_source: Path to data file containing agent information
agent_count: Target number of agents to generate
@@ -195,65 +193,78 @@ class MassAgentTemplate:
"""
self.data_source = data_source
self.agent_count = agent_count
- self.enable_hierarchical_organization = enable_hierarchical_organization
+ self.enable_hierarchical_organization = (
+ enable_hierarchical_organization
+ )
self.enable_group_swarms = enable_group_swarms
self.enable_lazy_loading = enable_lazy_loading
self.enable_caching = enable_caching
self.batch_size = batch_size
self.verbose = verbose
-
+
# Initialize cost tracking
self.cost_tracker = CostTracker(budget_limit=budget_limit)
-
+
# Initialize agent storage
self.agents: Dict[str, AgentProfile] = {}
self.groups: Dict[str, AgentGroup] = {}
self.categories: Dict[AgentCategory, List[str]] = {}
-
+
# Initialize caching
self.response_cache: Dict[str, str] = {}
-
+
# Load agent profiles (without creating agents)
self._load_agent_profiles()
-
+
if self.enable_hierarchical_organization:
self._organize_agents()
-
+
if self.verbose:
- logger.info(f"Mass Agent Template initialized with {len(self.agents)} agent profiles")
- logger.info(f"Lazy loading: {self.enable_lazy_loading}, Caching: {self.enable_caching}")
- logger.info(f"Budget limit: ${budget_limit}, Batch size: {batch_size}")
-
+ logger.info(
+ f"Mass Agent Template initialized with {len(self.agents)} agent profiles"
+ )
+ logger.info(
+ f"Lazy loading: {self.enable_lazy_loading}, Caching: {self.enable_caching}"
+ )
+ logger.info(
+ f"Budget limit: ${budget_limit}, Batch size: {batch_size}"
+ )
+
def _load_agent_profiles(self) -> List[Dict[str, Any]]:
"""
Load agent profiles from the specified data source.
-
+
This method loads agent data but doesn't create AI agents yet (lazy loading).
-
+
Returns:
List[Dict[str, Any]]: List of agent data dictionaries
"""
agent_data = []
-
+
if self.data_source and os.path.exists(self.data_source):
# Load from file - customize based on your data format
try:
- if self.data_source.endswith('.json'):
- with open(self.data_source, 'r', encoding='utf-8') as f:
+ if self.data_source.endswith(".json"):
+ with open(
+ self.data_source, "r", encoding="utf-8"
+ ) as f:
agent_data = json.load(f)
- elif self.data_source.endswith('.csv'):
+ elif self.data_source.endswith(".csv"):
import pandas as pd
+
df = pd.read_csv(self.data_source)
- agent_data = df.to_dict('records')
+ agent_data = df.to_dict("records")
else:
- logger.warning(f"Unsupported data format: {self.data_source}")
+ logger.warning(
+ f"Unsupported data format: {self.data_source}"
+ )
except Exception as e:
logger.error(f"Error loading agent data: {e}")
-
+
# If no data loaded, generate synthetic data
if not agent_data:
agent_data = self._generate_synthetic_data()
-
+
# Create agent profiles (without instantiating agents)
for data in agent_data:
agent_profile = AgentProfile(
@@ -265,68 +276,72 @@ class MassAgentTemplate:
skills=data["skills"],
experience_level=data["experience_level"],
agent=None, # Will be created on demand
- is_loaded=False
+ is_loaded=False,
)
-
+
self.agents[data["name"]] = agent_profile
-
+
return agent_data
-
+
def _load_agent(self, agent_name: str) -> Optional[Agent]:
"""
Lazy load a single agent on demand.
-
+
Args:
agent_name: Name of the agent to load
-
+
Returns:
Optional[Agent]: Loaded agent or None if not found
"""
if agent_name not in self.agents:
return None
-
+
profile = self.agents[agent_name]
-
+
# Check if already loaded
if profile.is_loaded and profile.agent:
return profile.agent
-
+
# Create agent (no cost for creation, only for running)
profile.agent = self._create_agent(profile)
profile.is_loaded = True
-
+
if self.verbose:
logger.info(f"Loaded agent: {agent_name}")
-
+
return profile.agent
-
- def _load_agents_batch(self, agent_names: List[str]) -> List[Agent]:
+
+ def _load_agents_batch(
+ self, agent_names: List[str]
+ ) -> List[Agent]:
"""
Load multiple agents in a batch.
-
+
Args:
agent_names: List of agent names to load
-
+
Returns:
List[Agent]: List of loaded agents
"""
loaded_agents = []
-
+
for agent_name in agent_names:
agent = self._load_agent(agent_name)
if agent:
loaded_agents.append(agent)
-
+
return loaded_agents
-
- def _get_cache_key(self, task: str, agent_names: List[str]) -> str:
+
+ def _get_cache_key(
+ self, task: str, agent_names: List[str]
+ ) -> str:
"""
Generate a cache key for a task and agent combination.
-
+
Args:
task: Task to execute
agent_names: List of agent names
-
+
Returns:
str: Cache key
"""
@@ -334,32 +349,32 @@ class MassAgentTemplate:
sorted_agents = sorted(agent_names)
content = f"{task}:{':'.join(sorted_agents)}"
return hashlib.md5(content.encode()).hexdigest()
-
+
def _check_cache(self, cache_key: str) -> Optional[str]:
"""
Check if a response is cached.
-
+
Args:
cache_key: Cache key to check
-
+
Returns:
Optional[str]: Cached response or None
"""
if not self.enable_caching:
return None
-
+
cached_response = self.response_cache.get(cache_key)
if cached_response:
self.cost_tracker.add_cache_hit()
if self.verbose:
logger.info(f"Cache hit for key: {cache_key[:20]}...")
-
+
return cached_response
-
+
def _cache_response(self, cache_key: str, response: str):
"""
Cache a response.
-
+
Args:
cache_key: Cache key
response: Response to cache
@@ -367,101 +382,167 @@ class MassAgentTemplate:
if self.enable_caching:
self.response_cache[cache_key] = response
if self.verbose:
- logger.info(f"Cached response for key: {cache_key[:20]}...")
-
+ logger.info(
+ f"Cached response for key: {cache_key[:20]}..."
+ )
+
def _generate_synthetic_data(self) -> List[Dict[str, Any]]:
"""
Generate synthetic agent data for demonstration purposes.
-
+
Returns:
List[Dict[str, Any]]: List of synthetic agent data
"""
synthetic_data = []
-
+
# Define sample data for different agent types
sample_agents = [
{
"name": "Alex_Developer",
"role": AgentRole.SPECIALIST,
"category": AgentCategory.TECHNICAL,
- "specialization": ["Python", "Machine Learning", "API Development"],
- "personality_traits": ["analytical", "detail-oriented", "problem-solver"],
- "skills": ["Python", "TensorFlow", "FastAPI", "Docker"],
- "experience_level": "senior"
+ "specialization": [
+ "Python",
+ "Machine Learning",
+ "API Development",
+ ],
+ "personality_traits": [
+ "analytical",
+ "detail-oriented",
+ "problem-solver",
+ ],
+ "skills": [
+ "Python",
+ "TensorFlow",
+ "FastAPI",
+ "Docker",
+ ],
+ "experience_level": "senior",
},
{
"name": "Sarah_Designer",
"role": AgentRole.CREATOR,
"category": AgentCategory.CREATIVE,
- "specialization": ["UI/UX Design", "Visual Design", "Brand Identity"],
- "personality_traits": ["creative", "user-focused", "aesthetic"],
- "skills": ["Figma", "Adobe Creative Suite", "User Research", "Prototyping"],
- "experience_level": "senior"
+ "specialization": [
+ "UI/UX Design",
+ "Visual Design",
+ "Brand Identity",
+ ],
+ "personality_traits": [
+ "creative",
+ "user-focused",
+ "aesthetic",
+ ],
+ "skills": [
+ "Figma",
+ "Adobe Creative Suite",
+ "User Research",
+ "Prototyping",
+ ],
+ "experience_level": "senior",
},
{
"name": "Mike_Analyst",
"role": AgentRole.ANALYST,
"category": AgentCategory.ANALYTICAL,
- "specialization": ["Data Analysis", "Business Intelligence", "Market Research"],
- "personality_traits": ["data-driven", "curious", "insightful"],
+ "specialization": [
+ "Data Analysis",
+ "Business Intelligence",
+ "Market Research",
+ ],
+ "personality_traits": [
+ "data-driven",
+ "curious",
+ "insightful",
+ ],
"skills": ["SQL", "Python", "Tableau", "Statistics"],
- "experience_level": "expert"
+ "experience_level": "expert",
},
{
"name": "Lisa_Manager",
"role": AgentRole.MANAGER,
"category": AgentCategory.STRATEGIC,
- "specialization": ["Project Management", "Team Leadership", "Strategic Planning"],
- "personality_traits": ["organized", "leadership", "strategic"],
- "skills": ["Agile", "Scrum", "Risk Management", "Stakeholder Communication"],
- "experience_level": "senior"
+ "specialization": [
+ "Project Management",
+ "Team Leadership",
+ "Strategic Planning",
+ ],
+ "personality_traits": [
+ "organized",
+ "leadership",
+ "strategic",
+ ],
+ "skills": [
+ "Agile",
+ "Scrum",
+ "Risk Management",
+ "Stakeholder Communication",
+ ],
+ "experience_level": "senior",
},
{
"name": "Tom_Coordinator",
"role": AgentRole.COORDINATOR,
"category": AgentCategory.OPERATIONAL,
- "specialization": ["Process Optimization", "Workflow Management", "Resource Allocation"],
- "personality_traits": ["efficient", "coordinated", "systematic"],
- "skills": ["Process Mapping", "Automation", "Resource Planning", "Quality Assurance"],
- "experience_level": "senior"
- }
+ "specialization": [
+ "Process Optimization",
+ "Workflow Management",
+ "Resource Allocation",
+ ],
+ "personality_traits": [
+ "efficient",
+ "coordinated",
+ "systematic",
+ ],
+ "skills": [
+ "Process Mapping",
+ "Automation",
+ "Resource Planning",
+ "Quality Assurance",
+ ],
+ "experience_level": "senior",
+ },
]
-
+
# Generate the specified number of agents
for i in range(self.agent_count):
# Use sample data as template and create variations
template = random.choice(sample_agents)
-
+
agent_data = {
"name": f"{template['name']}_{i:04d}",
"role": template["role"],
"category": template["category"],
"specialization": template["specialization"].copy(),
- "personality_traits": template["personality_traits"].copy(),
+ "personality_traits": template[
+ "personality_traits"
+ ].copy(),
"skills": template["skills"].copy(),
- "experience_level": template["experience_level"]
+ "experience_level": template["experience_level"],
}
-
+
# Add some randomization for variety
if random.random() < 0.3:
- agent_data["experience_level"] = random.choice(["junior", "senior", "expert"])
-
+ agent_data["experience_level"] = random.choice(
+ ["junior", "senior", "expert"]
+ )
+
synthetic_data.append(agent_data)
-
+
return synthetic_data
-
+
def _create_agent(self, profile: AgentProfile) -> Agent:
"""
Create an AI agent for the given profile.
-
+
Args:
profile: Agent profile data
-
+
Returns:
Agent: AI agent instance
"""
system_prompt = self._generate_agent_system_prompt(profile)
-
+
return Agent(
agent_name=profile.name,
system_prompt=system_prompt,
@@ -469,14 +550,16 @@ class MassAgentTemplate:
max_loops=3,
verbose=self.verbose,
)
-
- def _generate_agent_system_prompt(self, profile: AgentProfile) -> str:
+
+ def _generate_agent_system_prompt(
+ self, profile: AgentProfile
+ ) -> str:
"""
Generate a comprehensive system prompt for an agent.
-
+
Args:
profile: Agent profile data
-
+
Returns:
str: System prompt for the agent
"""
@@ -513,12 +596,12 @@ When working on tasks:
Remember: You are part of a large multi-agent system. Your unique combination of role, skills, and personality makes you valuable to the team.
"""
-
+
return prompt
-
+
def _get_role_responsibilities(self, role: AgentRole) -> str:
"""Get responsibilities for a specific role."""
-
+
responsibilities = {
AgentRole.WORKER: """
- Execute assigned tasks efficiently and accurately
@@ -526,126 +609,137 @@ Remember: You are part of a large multi-agent system. Your unique combination of
- Report progress and any issues encountered
- Maintain quality standards in all work
- Collaborate with team members as needed""",
-
AgentRole.MANAGER: """
- Oversee team activities and coordinate efforts
- Set priorities and allocate resources
- Monitor progress and ensure deadlines are met
- Provide guidance and support to team members
- Make strategic decisions for the team""",
-
AgentRole.SPECIALIST: """
- Provide expert knowledge in specific domains
- Solve complex technical problems
- Mentor other agents in your area of expertise
- Stay updated on latest developments in your field
- Contribute specialized insights to projects""",
-
AgentRole.COORDINATOR: """
- Facilitate communication between different groups
- Ensure smooth workflow and process optimization
- Manage dependencies and resource allocation
- Track project timelines and milestones
- Resolve conflicts and bottlenecks""",
-
AgentRole.ANALYST: """
- Analyze data and extract meaningful insights
- Identify patterns and trends
- Provide evidence-based recommendations
- Create reports and visualizations
- Support decision-making with data""",
-
AgentRole.CREATOR: """
- Generate innovative ideas and solutions
- Design and develop new content or products
- Think creatively and outside the box
- Prototype and iterate on concepts
- Inspire and motivate other team members""",
-
AgentRole.VALIDATOR: """
- Review and validate work quality
- Ensure compliance with standards and requirements
- Provide constructive feedback
- Identify potential issues and risks
- Maintain quality assurance processes""",
-
AgentRole.EXECUTOR: """
- Implement plans and strategies
- Execute tasks with precision and efficiency
- Adapt to changing circumstances
- Ensure successful completion of objectives
-- Maintain focus on results and outcomes"""
+- Maintain focus on results and outcomes""",
}
-
- return responsibilities.get(role, "Execute tasks according to your role and expertise.")
-
+
+ return responsibilities.get(
+ role,
+ "Execute tasks according to your role and expertise.",
+ )
+
def _organize_agents(self):
"""Organize agents into groups and categories."""
-
+
# Organize by category
for agent_name, profile in self.agents.items():
category = profile.category
if category not in self.categories:
self.categories[category] = []
self.categories[category].append(agent_name)
-
+
# Create groups for each category
for category, agent_names in self.categories.items():
group_name = f"{category.value.capitalize()}_Group"
-
+
# Select a leader (first agent in the category)
leader = agent_names[0] if agent_names else None
-
+
group = AgentGroup(
name=group_name,
category=category,
agents=agent_names,
leader=leader,
- total_agents=len(agent_names)
+ total_agents=len(agent_names),
)
-
+
self.groups[group_name] = group
-
+
if self.verbose:
- logger.info(f"Organized agents into {len(self.groups)} groups")
-
+ logger.info(
+ f"Organized agents into {len(self.groups)} groups"
+ )
+
def _create_group_swarms(self):
"""Create Board of Directors swarms for each group."""
-
+
for group_name, group in self.groups.items():
if not group.agents:
continue
-
+
# Create board members from group agents
board_members = []
-
+
# Add group leader as chairman
if group.leader and group.leader in self.agents:
leader_profile = self.agents[group.leader]
if leader_profile.agent:
- board_members.append(BoardMember(
- agent=leader_profile.agent,
- role=BoardMemberRole.CHAIRMAN,
- voting_weight=1.0,
- expertise_areas=leader_profile.specialization
- ))
-
+ board_members.append(
+ BoardMember(
+ agent=leader_profile.agent,
+ role=BoardMemberRole.CHAIRMAN,
+ voting_weight=1.0,
+ expertise_areas=leader_profile.specialization,
+ )
+ )
+
# Add other agents as board members
- for agent_name in group.agents[:5]: # Limit to 5 board members
- if agent_name != group.leader and agent_name in self.agents:
+ for agent_name in group.agents[
+ :5
+ ]: # Limit to 5 board members
+ if (
+ agent_name != group.leader
+ and agent_name in self.agents
+ ):
profile = self.agents[agent_name]
if profile.agent:
- board_members.append(BoardMember(
- agent=profile.agent,
- role=BoardMemberRole.EXECUTIVE_DIRECTOR,
- voting_weight=0.8,
- expertise_areas=profile.specialization
- ))
-
+ board_members.append(
+ BoardMember(
+ agent=profile.agent,
+ role=BoardMemberRole.EXECUTIVE_DIRECTOR,
+ voting_weight=0.8,
+ expertise_areas=profile.specialization,
+ )
+ )
+
# Create Board of Directors swarm
if board_members:
- agents = [member.agent for member in board_members if member.agent is not None]
-
+ agents = [
+ member.agent
+ for member in board_members
+ if member.agent is not None
+ ]
+
group.group_swarm = BoardOfDirectorsSwarm(
name=group_name,
description=f"Specialized swarm for {group_name} with expertise in {group.category.value}",
@@ -655,78 +749,94 @@ Remember: You are part of a large multi-agent system. Your unique combination of
verbose=self.verbose,
decision_threshold=0.6,
enable_voting=True,
- enable_consensus=True
+ enable_consensus=True,
)
-
+
if self.verbose:
- logger.info(f"Created {len([g for g in self.groups.values() if g.group_swarm])} group swarms")
-
+ logger.info(
+ f"Created {len([g for g in self.groups.values() if g.group_swarm])} group swarms"
+ )
+
def get_agent(self, agent_name: str) -> Optional[AgentProfile]:
"""
Get a specific agent by name.
-
+
Args:
agent_name: Name of the agent
-
+
Returns:
Optional[AgentProfile]: Agent profile if found, None otherwise
"""
return self.agents.get(agent_name)
-
+
def get_group(self, group_name: str) -> Optional[AgentGroup]:
"""
Get a specific group by name.
-
+
Args:
group_name: Name of the group
-
+
Returns:
Optional[AgentGroup]: Group if found, None otherwise
"""
return self.groups.get(group_name)
-
- def get_agents_by_category(self, category: AgentCategory) -> List[str]:
+
+ def get_agents_by_category(
+ self, category: AgentCategory
+ ) -> List[str]:
"""
Get all agents in a specific category.
-
+
Args:
category: Agent category
-
+
Returns:
List[str]: List of agent names in the category
"""
return self.categories.get(category, [])
-
+
def get_agents_by_role(self, role: AgentRole) -> List[str]:
"""
Get all agents with a specific role.
-
+
Args:
role: Agent role
-
+
Returns:
List[str]: List of agent names with the role
"""
- return [name for name, profile in self.agents.items() if profile.role == role]
-
- def run_mass_task(self, task: str, agent_count: int = 10) -> Dict[str, Any]:
+ return [
+ name
+ for name, profile in self.agents.items()
+ if profile.role == role
+ ]
+
+ def run_mass_task(
+ self, task: str, agent_count: int = 10
+ ) -> Dict[str, Any]:
"""
Run a task with multiple agents working in parallel with cost optimization.
-
+
Args:
task: Task to execute
agent_count: Number of agents to use
-
+
Returns:
Dict[str, Any]: Results from the mass task execution
"""
# Check budget before starting
if not self.cost_tracker.check_budget():
- return {"error": "Budget exceeded", "cost_stats": self.cost_tracker.get_stats()}
-
+ return {
+ "error": "Budget exceeded",
+ "cost_stats": self.cost_tracker.get_stats(),
+ }
+
# Select random agents
- selected_agent_names = random.sample(list(self.agents.keys()), min(agent_count, len(self.agents)))
-
+ selected_agent_names = random.sample(
+ list(self.agents.keys()),
+ min(agent_count, len(self.agents)),
+ )
+
# Check cache first
cache_key = self._get_cache_key(task, selected_agent_names)
cached_result = self._check_cache(cache_key)
@@ -737,132 +847,160 @@ Remember: You are part of a large multi-agent system. Your unique combination of
"results": cached_result,
"total_agents": len(selected_agent_names),
"cached": True,
- "cost_stats": self.cost_tracker.get_stats()
+ "cost_stats": self.cost_tracker.get_stats(),
}
-
+
# Process in batches to control memory and cost
all_results = []
total_processed = 0
-
+
for i in range(0, len(selected_agent_names), self.batch_size):
- batch_names = selected_agent_names[i:i + self.batch_size]
-
+ batch_names = selected_agent_names[
+ i : i + self.batch_size
+ ]
+
# Check budget for this batch
if not self.cost_tracker.check_budget():
- logger.warning(f"Budget exceeded after processing {total_processed} agents")
- logger.warning(f"Current cost: ${self.cost_tracker.total_cost_estimate:.4f}, Budget: ${self.cost_tracker.budget_limit:.2f}")
+ logger.warning(
+ f"Budget exceeded after processing {total_processed} agents"
+ )
+ logger.warning(
+ f"Current cost: ${self.cost_tracker.total_cost_estimate:.4f}, Budget: ${self.cost_tracker.budget_limit:.2f}"
+ )
break
-
+
# Load agents for this batch
batch_agents = self._load_agents_batch(batch_names)
-
+
if not batch_agents:
continue
-
+
# Run batch
try:
- batch_results = run_agents_concurrently(batch_agents, task)
+ batch_results = run_agents_concurrently(
+ batch_agents, task
+ )
all_results.extend(batch_results)
total_processed += len(batch_agents)
-
+
# Estimate tokens used (more realistic approximation)
# Include both input tokens (task) and output tokens (response)
- task_tokens = len(task.split()) * 1.3 # ~1.3 tokens per word
- response_tokens = len(batch_agents) * 200 # ~200 tokens per response
+ task_tokens = (
+ len(task.split()) * 1.3
+ ) # ~1.3 tokens per word
+ response_tokens = (
+ len(batch_agents) * 200
+ ) # ~200 tokens per response
total_tokens = int(task_tokens + response_tokens)
self.cost_tracker.add_tokens(total_tokens)
-
+
if self.verbose:
- logger.info(f"Processed batch {i//self.batch_size + 1}: {len(batch_agents)} agents")
- logger.info(f"Current cost: ${self.cost_tracker.total_cost_estimate:.4f}, Budget remaining: ${self.cost_tracker.budget_limit - self.cost_tracker.total_cost_estimate:.2f}")
-
+ logger.info(
+ f"Processed batch {i//self.batch_size + 1}: {len(batch_agents)} agents"
+ )
+ logger.info(
+ f"Current cost: ${self.cost_tracker.total_cost_estimate:.4f}, Budget remaining: ${self.cost_tracker.budget_limit - self.cost_tracker.total_cost_estimate:.2f}"
+ )
+
except Exception as e:
logger.error(f"Error processing batch: {e}")
continue
-
+
# Cache the results
if all_results:
self._cache_response(cache_key, str(all_results))
-
+
return {
"task": task,
"agents_used": selected_agent_names[:total_processed],
"results": all_results,
"total_agents": total_processed,
"cached": False,
- "cost_stats": self.cost_tracker.get_stats()
+ "cost_stats": self.cost_tracker.get_stats(),
}
-
- def run_mass_task_optimized(self, task: str, agent_count: int = 1000,
- max_cost: float = 10.0) -> Dict[str, Any]:
+
+ def run_mass_task_optimized(
+ self,
+ task: str,
+ agent_count: int = 1000,
+ max_cost: float = 10.0,
+ ) -> Dict[str, Any]:
"""
Run a task with cost-optimized mass execution for large-scale operations.
-
+
Args:
task: Task to execute
agent_count: Target number of agents to use
max_cost: Maximum cost for this task in dollars
-
+
Returns:
Dict[str, Any]: Results from the optimized mass task execution
"""
# Store original settings
original_budget = self.cost_tracker.budget_limit
original_batch_size = self.batch_size
-
+
try:
# Set temporary budget for this task (don't reduce if max_cost is higher)
if max_cost < original_budget:
self.cost_tracker.budget_limit = max_cost
-
+
# Use smaller batches for better cost control
- self.batch_size = min(25, self.batch_size) # Smaller batches for cost control
-
+ self.batch_size = min(
+ 25, self.batch_size
+ ) # Smaller batches for cost control
+
result = self.run_mass_task(task, agent_count)
-
+
return result
-
+
finally:
# Restore original settings
self.cost_tracker.budget_limit = original_budget
self.batch_size = original_batch_size
-
- def run_group_task(self, group_name: str, task: str) -> Dict[str, Any]:
+
+ def run_group_task(
+ self, group_name: str, task: str
+ ) -> Dict[str, Any]:
"""
Run a task with a specific group using their Board of Directors swarm.
-
+
Args:
group_name: Name of the group
task: Task to execute
-
+
Returns:
Dict[str, Any]: Results from the group task execution
"""
group = self.groups.get(group_name)
if not group or not group.group_swarm:
- return {"error": f"Group {group_name} not found or no swarm available"}
-
+ return {
+ "error": f"Group {group_name} not found or no swarm available"
+ }
+
# Run task with group swarm
result = group.group_swarm.run(task)
-
+
return {
"group": group_name,
"task": task,
"result": result,
- "agents_involved": group.agents
+ "agents_involved": group.agents,
}
-
+
def get_system_stats(self) -> Dict[str, Any]:
"""
Get statistics about the mass agent system including cost tracking.
-
+
Returns:
Dict[str, Any]: System statistics
"""
stats = {
"total_agents": len(self.agents),
"total_groups": len(self.groups),
- "loaded_agents": len([a for a in self.agents.values() if a.is_loaded]),
+ "loaded_agents": len(
+ [a for a in self.agents.values() if a.is_loaded]
+ ),
"categories": {},
"roles": {},
"experience_levels": {},
@@ -871,35 +1009,41 @@ Remember: You are part of a large multi-agent system. Your unique combination of
"lazy_loading": self.enable_lazy_loading,
"caching": self.enable_caching,
"batch_size": self.batch_size,
- "budget_limit": self.cost_tracker.budget_limit
- }
+ "budget_limit": self.cost_tracker.budget_limit,
+ },
}
-
+
# Category breakdown
for category in AgentCategory:
- stats["categories"][category.value] = len(self.get_agents_by_category(category))
-
+ stats["categories"][category.value] = len(
+ self.get_agents_by_category(category)
+ )
+
# Role breakdown
for role in AgentRole:
- stats["roles"][role.value] = len(self.get_agents_by_role(role))
-
+ stats["roles"][role.value] = len(
+ self.get_agents_by_role(role)
+ )
+
# Experience level breakdown
experience_counts = {}
for profile in self.agents.values():
level = profile.experience_level
- experience_counts[level] = experience_counts.get(level, 0) + 1
+ experience_counts[level] = (
+ experience_counts.get(level, 0) + 1
+ )
stats["experience_levels"] = experience_counts
-
+
return stats
# Example usage and demonstration
def demonstrate_mass_agent_template():
"""Demonstrate the Mass Agent Template functionality with cost optimization."""
-
+
print("MASS AGENT TEMPLATE DEMONSTRATION (COST OPTIMIZED)")
print("=" * 60)
-
+
# Initialize the template with 1000 agents and cost optimization
template = MassAgentTemplate(
agent_count=1000,
@@ -909,90 +1053,114 @@ def demonstrate_mass_agent_template():
enable_caching=True,
batch_size=25,
budget_limit=50.0, # $50 budget limit
- verbose=True
+ verbose=True,
)
-
+
# Show system statistics
stats = template.get_system_stats()
-
- print(f"\nSYSTEM STATISTICS:")
+
+ print("\nSYSTEM STATISTICS:")
print(f"Total Agents: {stats['total_agents']}")
- print(f"Loaded Agents: {stats['loaded_agents']} (lazy loading active)")
+ print(
+ f"Loaded Agents: {stats['loaded_agents']} (lazy loading active)"
+ )
print(f"Total Groups: {stats['total_groups']}")
-
- print(f"\nCOST OPTIMIZATION:")
- cost_stats = stats['cost_stats']
- print(f"Budget Limit: ${cost_stats['budget_remaining'] + cost_stats['total_cost']:.2f}")
+
+ print("\nCOST OPTIMIZATION:")
+ cost_stats = stats["cost_stats"]
+ print(
+ f"Budget Limit: ${cost_stats['budget_remaining'] + cost_stats['total_cost']:.2f}"
+ )
print(f"Budget Used: ${cost_stats['total_cost']:.2f}")
print(f"Budget Remaining: ${cost_stats['budget_remaining']:.2f}")
print(f"Cache Hit Rate: {cost_stats['cache_hit_rate']:.1%}")
-
- print(f"\nCATEGORY BREAKDOWN:")
- for category, count in stats['categories'].items():
+
+ print("\nCATEGORY BREAKDOWN:")
+ for category, count in stats["categories"].items():
print(f" {category}: {count} agents")
-
- print(f"\nROLE BREAKDOWN:")
- for role, count in stats['roles'].items():
+
+ print("\nROLE BREAKDOWN:")
+ for role, count in stats["roles"].items():
print(f" {role}: {count} agents")
-
- print(f"\nEXPERIENCE LEVEL BREAKDOWN:")
- for level, count in stats['experience_levels'].items():
+
+ print("\nEXPERIENCE LEVEL BREAKDOWN:")
+ for level, count in stats["experience_levels"].items():
print(f" {level}: {count} agents")
-
+
# Demonstrate cost-optimized mass task execution
- print(f"\nCOST-OPTIMIZED MASS TASK DEMONSTRATION:")
+ print("\nCOST-OPTIMIZED MASS TASK DEMONSTRATION:")
print("-" * 40)
-
+
# Small task first (low cost)
small_result = template.run_mass_task(
"What is the most important skill for a software developer?",
- agent_count=5
+ agent_count=5,
)
-
- print(f"Small Task Results:")
+
+ print("Small Task Results:")
print(f" Agents Used: {len(small_result['agents_used'])}")
print(f" Cached: {small_result.get('cached', False)}")
print(f" Cost: ${small_result['cost_stats']['total_cost']:.2f}")
-
+
# Large task to demonstrate full capability
- print(f"\nLarge Task Demonstration (Full Capability):")
+ print("\nLarge Task Demonstration (Full Capability):")
large_result = template.run_mass_task(
"Analyze the benefits of cloud computing for small businesses",
- agent_count=200 # Use more agents to show capability
+ agent_count=200, # Use more agents to show capability
)
-
+
print(f" Agents Used: {len(large_result['agents_used'])}")
print(f" Cached: {large_result.get('cached', False)}")
print(f" Cost: ${large_result['cost_stats']['total_cost']:.2f}")
- print(f" Budget Remaining: ${large_result['cost_stats']['budget_remaining']:.2f}")
-
+ print(
+ f" Budget Remaining: ${large_result['cost_stats']['budget_remaining']:.2f}"
+ )
+
# Show what happens with cost limits
- print(f"\nCost-Limited Task Demonstration:")
+ print("\nCost-Limited Task Demonstration:")
cost_limited_result = template.run_mass_task_optimized(
"What are the key principles of agile development?",
agent_count=100,
- max_cost=2.0 # Show cost limiting in action
+ max_cost=2.0, # Show cost limiting in action
)
-
+
print(f" Agents Used: {len(cost_limited_result['agents_used'])}")
print(f" Cached: {cost_limited_result.get('cached', False)}")
- print(f" Cost: ${cost_limited_result['cost_stats']['total_cost']:.2f}")
- print(f" Budget Remaining: ${cost_limited_result['cost_stats']['budget_remaining']:.2f}")
-
+ print(
+ f" Cost: ${cost_limited_result['cost_stats']['total_cost']:.2f}"
+ )
+ print(
+ f" Budget Remaining: ${cost_limited_result['cost_stats']['budget_remaining']:.2f}"
+ )
+
# Show final cost statistics
final_stats = template.get_system_stats()
- print(f"\nFINAL COST STATISTICS:")
- print(f"Total Cost: ${final_stats['cost_stats']['total_cost']:.2f}")
- print(f"Budget Remaining: ${final_stats['cost_stats']['budget_remaining']:.2f}")
- print(f"Cache Hit Rate: {final_stats['cost_stats']['cache_hit_rate']:.1%}")
- print(f"Total Requests: {final_stats['cost_stats']['requests_made']}")
+ print("\nFINAL COST STATISTICS:")
+ print(
+ f"Total Cost: ${final_stats['cost_stats']['total_cost']:.2f}"
+ )
+ print(
+ f"Budget Remaining: ${final_stats['cost_stats']['budget_remaining']:.2f}"
+ )
+ print(
+ f"Cache Hit Rate: {final_stats['cost_stats']['cache_hit_rate']:.1%}"
+ )
+ print(
+ f"Total Requests: {final_stats['cost_stats']['requests_made']}"
+ )
print(f"Cache Hits: {final_stats['cost_stats']['cache_hits']}")
-
- print(f"\nDEMONSTRATION COMPLETED SUCCESSFULLY!")
- print(f"ā
Cost optimization working: ${final_stats['cost_stats']['total_cost']:.2f} spent")
- print(f"ā
Lazy loading working: {final_stats['loaded_agents']}/{final_stats['total_agents']} agents loaded")
- print(f"ā
Caching working: {final_stats['cost_stats']['cache_hit_rate']:.1%} hit rate")
+
+ print("\nDEMONSTRATION COMPLETED SUCCESSFULLY!")
+ print(
+ f"ā
Cost optimization working: ${final_stats['cost_stats']['total_cost']:.2f} spent"
+ )
+ print(
+ f"ā
Lazy loading working: {final_stats['loaded_agents']}/{final_stats['total_agents']} agents loaded"
+ )
+ print(
+ f"ā
Caching working: {final_stats['cost_stats']['cache_hit_rate']:.1%} hit rate"
+ )
if __name__ == "__main__":
- demonstrate_mass_agent_template()
\ No newline at end of file
+ demonstrate_mass_agent_template()
diff --git a/examples/simulations/euroswarm_parliament/test_mass_agents.py b/examples/simulations/euroswarm_parliament/test_mass_agents.py
index 54ec2223..c747b0a0 100644
--- a/examples/simulations/euroswarm_parliament/test_mass_agents.py
+++ b/examples/simulations/euroswarm_parliament/test_mass_agents.py
@@ -5,63 +5,76 @@ Test script to verify mass agent template can process more than 500 agents.
from mass_agent_template import MassAgentTemplate
+
def test_mass_agents():
- print("Testing Mass Agent Template - Processing More Than 50 Agents")
+ print(
+ "Testing Mass Agent Template - Processing More Than 50 Agents"
+ )
print("=" * 60)
-
+
# Initialize template with 200 agents
template = MassAgentTemplate(
agent_count=200,
budget_limit=50.0,
batch_size=25,
- verbose=True
+ verbose=True,
)
-
+
print(f"Initialized with {len(template.agents)} agents")
print(f"Budget limit: ${template.cost_tracker.budget_limit}")
-
+
# Test processing 100 agents
- print(f"\nTesting with 100 agents...")
+ print("\nTesting with 100 agents...")
result = template.run_mass_task(
"What is the most important skill for your role?",
- agent_count=100
+ agent_count=100,
)
-
- print(f"Results:")
+
+ print("Results:")
print(f" Agents processed: {len(result['agents_used'])}")
print(f" Cost: ${result['cost_stats']['total_cost']:.4f}")
- print(f" Budget remaining: ${result['cost_stats']['budget_remaining']:.2f}")
+ print(
+ f" Budget remaining: ${result['cost_stats']['budget_remaining']:.2f}"
+ )
print(f" Cached: {result.get('cached', False)}")
-
+
# Test processing 150 agents
- print(f"\nTesting with 150 agents...")
+ print("\nTesting with 150 agents...")
result2 = template.run_mass_task(
- "Describe your approach to problem-solving",
- agent_count=150
+ "Describe your approach to problem-solving", agent_count=150
)
-
- print(f"Results:")
+
+ print("Results:")
print(f" Agents processed: {len(result2['agents_used'])}")
print(f" Cost: ${result2['cost_stats']['total_cost']:.4f}")
- print(f" Budget remaining: ${result2['cost_stats']['budget_remaining']:.2f}")
+ print(
+ f" Budget remaining: ${result2['cost_stats']['budget_remaining']:.2f}"
+ )
print(f" Cached: {result2.get('cached', False)}")
-
+
# Show final stats
final_stats = template.get_system_stats()
- print(f"\nFinal Statistics:")
+ print("\nFinal Statistics:")
print(f" Total agents: {final_stats['total_agents']}")
print(f" Loaded agents: {final_stats['loaded_agents']}")
- print(f" Total cost: ${final_stats['cost_stats']['total_cost']:.4f}")
- print(f" Budget remaining: ${final_stats['cost_stats']['budget_remaining']:.2f}")
-
+ print(
+ f" Total cost: ${final_stats['cost_stats']['total_cost']:.4f}"
+ )
+ print(
+ f" Budget remaining: ${final_stats['cost_stats']['budget_remaining']:.2f}"
+ )
+
# Success criteria
- total_processed = len(result['agents_used']) + len(result2['agents_used'])
+ total_processed = len(result["agents_used"]) + len(
+ result2["agents_used"]
+ )
print(f"\nTotal agents processed: {total_processed}")
-
+
if total_processed > 50:
print("ā
SUCCESS: Template processed more than 50 agents!")
else:
print("ā FAILURE: Template still limited to 50 agents")
+
if __name__ == "__main__":
- test_mass_agents()
\ No newline at end of file
+ test_mass_agents()
diff --git a/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py b/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py
index 0ef7cda7..e7c555cf 100644
--- a/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py
+++ b/examples/simulations/euroswarm_parliament/wikipedia_personality_scraper.py
@@ -14,14 +14,13 @@ from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
import requests
from loguru import logger
-import xml.etree.ElementTree as ET
@dataclass
class MEPPersonalityProfile:
"""
Comprehensive personality profile for an MEP based on Wikipedia data.
-
+
Attributes:
full_name: Full name of the MEP
mep_id: Unique MEP identifier
@@ -47,7 +46,7 @@ class MEPPersonalityProfile:
social_media: Social media presence
last_updated: When the profile was last updated
"""
-
+
full_name: str
mep_id: str
wikipedia_url: Optional[str] = None
@@ -77,11 +76,15 @@ class WikipediaPersonalityScraper:
"""
Scraper for gathering Wikipedia personality data for MEPs.
"""
-
- def __init__(self, output_dir: str = "mep_personalities", verbose: bool = True):
+
+ def __init__(
+ self,
+ output_dir: str = "mep_personalities",
+ verbose: bool = True,
+ ):
"""
Initialize the Wikipedia personality scraper.
-
+
Args:
output_dir: Directory to store personality profiles
verbose: Enable verbose logging
@@ -89,61 +92,81 @@ class WikipediaPersonalityScraper:
self.output_dir = output_dir
self.verbose = verbose
self.session = requests.Session()
- self.session.headers.update({
- 'User-Agent': 'EuroSwarm Parliament Personality Scraper/1.0 (https://github.com/swarms-democracy)'
- })
-
+ self.session.headers.update(
+ {
+ "User-Agent": "EuroSwarm Parliament Personality Scraper/1.0 (https://github.com/swarms-democracy)"
+ }
+ )
+
# Create output directory
os.makedirs(output_dir, exist_ok=True)
-
+
if verbose:
- logger.info(f"Wikipedia Personality Scraper initialized. Output directory: {output_dir}")
+ logger.info(
+ f"Wikipedia Personality Scraper initialized. Output directory: {output_dir}"
+ )
- def extract_mep_data_from_xml(self, xml_file: str = "EU.xml") -> List[Dict[str, str]]:
+ def extract_mep_data_from_xml(
+ self, xml_file: str = "EU.xml"
+ ) -> List[Dict[str, str]]:
"""
Extract MEP data from EU.xml file.
-
+
Args:
xml_file: Path to EU.xml file
-
+
Returns:
List of MEP data dictionaries
"""
meps = []
-
+
try:
- with open(xml_file, 'r', encoding='utf-8') as f:
+ with open(xml_file, "r", encoding="utf-8") as f:
content = f.read()
-
+
# Use regex to extract MEP data
- mep_pattern = r'\s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s* '
+ mep_pattern = r"\s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s*(.*?) \s* "
mep_matches = re.findall(mep_pattern, content, re.DOTALL)
-
- for full_name, country, political_group, mep_id, national_party in mep_matches:
- meps.append({
- 'full_name': full_name.strip(),
- 'country': country.strip(),
- 'political_group': political_group.strip(),
- 'mep_id': mep_id.strip(),
- 'national_party': national_party.strip()
- })
-
+
+ for (
+ full_name,
+ country,
+ political_group,
+ mep_id,
+ national_party,
+ ) in mep_matches:
+ meps.append(
+ {
+ "full_name": full_name.strip(),
+ "country": country.strip(),
+ "political_group": political_group.strip(),
+ "mep_id": mep_id.strip(),
+ "national_party": national_party.strip(),
+ }
+ )
+
if self.verbose:
- logger.info(f"Extracted {len(meps)} MEPs from {xml_file}")
-
+ logger.info(
+ f"Extracted {len(meps)} MEPs from {xml_file}"
+ )
+
except Exception as e:
- logger.error(f"Error extracting MEP data from {xml_file}: {e}")
-
+ logger.error(
+ f"Error extracting MEP data from {xml_file}: {e}"
+ )
+
return meps
- def search_wikipedia_page(self, mep_name: str, country: str) -> Optional[str]:
+ def search_wikipedia_page(
+ self, mep_name: str, country: str
+ ) -> Optional[str]:
"""
Search for a Wikipedia page for an MEP.
-
+
Args:
mep_name: Full name of the MEP
country: Country of the MEP
-
+
Returns:
Wikipedia page title if found, None otherwise
"""
@@ -151,48 +174,56 @@ class WikipediaPersonalityScraper:
# Search for the MEP on Wikipedia
search_url = "https://en.wikipedia.org/w/api.php"
search_params = {
- 'action': 'query',
- 'format': 'json',
- 'list': 'search',
- 'srsearch': f'"{mep_name}" {country}',
- 'srlimit': 5,
- 'srnamespace': 0
+ "action": "query",
+ "format": "json",
+ "list": "search",
+ "srsearch": f'"{mep_name}" {country}',
+ "srlimit": 5,
+ "srnamespace": 0,
}
-
- response = self.session.get(search_url, params=search_params)
+
+ response = self.session.get(
+ search_url, params=search_params
+ )
response.raise_for_status()
-
+
data = response.json()
- search_results = data.get('query', {}).get('search', [])
-
+ search_results = data.get("query", {}).get("search", [])
+
if search_results:
# Return the first result
- return search_results[0]['title']
-
+ return search_results[0]["title"]
+
# Try alternative search without quotes
- search_params['srsearch'] = f'{mep_name} {country}'
- response = self.session.get(search_url, params=search_params)
+ search_params["srsearch"] = f"{mep_name} {country}"
+ response = self.session.get(
+ search_url, params=search_params
+ )
response.raise_for_status()
-
+
data = response.json()
- search_results = data.get('query', {}).get('search', [])
-
+ search_results = data.get("query", {}).get("search", [])
+
if search_results:
- return search_results[0]['title']
-
+ return search_results[0]["title"]
+
except Exception as e:
if self.verbose:
- logger.warning(f"Error searching Wikipedia for {mep_name}: {e}")
-
+ logger.warning(
+ f"Error searching Wikipedia for {mep_name}: {e}"
+ )
+
return None
- def get_wikipedia_content(self, page_title: str) -> Optional[Dict[str, Any]]:
+ def get_wikipedia_content(
+ self, page_title: str
+ ) -> Optional[Dict[str, Any]]:
"""
Get Wikipedia content for a specific page.
-
+
Args:
page_title: Wikipedia page title
-
+
Returns:
Dictionary containing page content and metadata
"""
@@ -200,376 +231,451 @@ class WikipediaPersonalityScraper:
# Get page content
content_url = "https://en.wikipedia.org/w/api.php"
content_params = {
- 'action': 'query',
- 'format': 'json',
- 'titles': page_title,
- 'prop': 'extracts|info|categories',
- 'exintro': True,
- 'explaintext': True,
- 'inprop': 'url',
- 'cllimit': 50
+ "action": "query",
+ "format": "json",
+ "titles": page_title,
+ "prop": "extracts|info|categories",
+ "exintro": True,
+ "explaintext": True,
+ "inprop": "url",
+ "cllimit": 50,
}
-
- response = self.session.get(content_url, params=content_params)
+
+ response = self.session.get(
+ content_url, params=content_params
+ )
response.raise_for_status()
-
+
data = response.json()
- pages = data.get('query', {}).get('pages', {})
-
+ pages = data.get("query", {}).get("pages", {})
+
if pages:
page_id = list(pages.keys())[0]
page_data = pages[page_id]
-
+
return {
- 'title': page_data.get('title', ''),
- 'extract': page_data.get('extract', ''),
- 'url': page_data.get('fullurl', ''),
- 'categories': [cat['title'] for cat in page_data.get('categories', [])],
- 'pageid': page_data.get('pageid', ''),
- 'length': page_data.get('length', 0)
+ "title": page_data.get("title", ""),
+ "extract": page_data.get("extract", ""),
+ "url": page_data.get("fullurl", ""),
+ "categories": [
+ cat["title"]
+ for cat in page_data.get("categories", [])
+ ],
+ "pageid": page_data.get("pageid", ""),
+ "length": page_data.get("length", 0),
}
-
+
except Exception as e:
if self.verbose:
- logger.warning(f"Error getting Wikipedia content for {page_title}: {e}")
-
+ logger.warning(
+ f"Error getting Wikipedia content for {page_title}: {e}"
+ )
+
return None
- def parse_wikipedia_content(self, content: str, mep_name: str) -> Dict[str, str]:
+ def parse_wikipedia_content(
+ self, content: str, mep_name: str
+ ) -> Dict[str, str]:
"""
Parse Wikipedia content to extract structured personality information.
-
+
Args:
content: Raw Wikipedia content
mep_name: Name of the MEP
-
+
Returns:
Dictionary of parsed personality information
"""
personality_data = {
- 'summary': '',
- 'early_life': '',
- 'political_career': '',
- 'political_views': '',
- 'policy_focus': '',
- 'achievements': '',
- 'controversies': '',
- 'personal_life': '',
- 'education': '',
- 'professional_background': '',
- 'party_affiliations': '',
- 'committee_experience': '',
- 'voting_record': '',
- 'public_statements': '',
- 'interests': '',
- 'languages': '',
- 'awards': '',
- 'publications': '',
- 'social_media': ''
+ "summary": "",
+ "early_life": "",
+ "political_career": "",
+ "political_views": "",
+ "policy_focus": "",
+ "achievements": "",
+ "controversies": "",
+ "personal_life": "",
+ "education": "",
+ "professional_background": "",
+ "party_affiliations": "",
+ "committee_experience": "",
+ "voting_record": "",
+ "public_statements": "",
+ "interests": "",
+ "languages": "",
+ "awards": "",
+ "publications": "",
+ "social_media": "",
}
-
+
# Extract summary (first paragraph)
- paragraphs = content.split('\n\n')
+ paragraphs = content.split("\n\n")
if paragraphs:
- personality_data['summary'] = paragraphs[0][:1000] # Limit summary length
-
+ personality_data["summary"] = paragraphs[0][
+ :1000
+ ] # Limit summary length
+
# Look for specific sections
content_lower = content.lower()
-
+
# Early life and education
early_life_patterns = [
- r'early life[^.]*\.',
- r'born[^.]*\.',
- r'childhood[^.]*\.',
- r'grew up[^.]*\.',
- r'education[^.]*\.'
+ r"early life[^.]*\.",
+ r"born[^.]*\.",
+ r"childhood[^.]*\.",
+ r"grew up[^.]*\.",
+ r"education[^.]*\.",
]
-
+
for pattern in early_life_patterns:
- matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ matches = re.findall(
+ pattern, content_lower, re.IGNORECASE
+ )
if matches:
- personality_data['early_life'] = ' '.join(matches[:3]) # Take first 3 matches
+ personality_data["early_life"] = " ".join(
+ matches[:3]
+ ) # Take first 3 matches
break
-
+
# Political career
political_patterns = [
- r'political career[^.]*\.',
- r'elected[^.]*\.',
- r'parliament[^.]*\.',
- r'minister[^.]*\.',
- r'party[^.]*\.'
+ r"political career[^.]*\.",
+ r"elected[^.]*\.",
+ r"parliament[^.]*\.",
+ r"minister[^.]*\.",
+ r"party[^.]*\.",
]
-
+
for pattern in political_patterns:
- matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ matches = re.findall(
+ pattern, content_lower, re.IGNORECASE
+ )
if matches:
- personality_data['political_career'] = ' '.join(matches[:5]) # Take first 5 matches
+ personality_data["political_career"] = " ".join(
+ matches[:5]
+ ) # Take first 5 matches
break
-
+
# Political views
views_patterns = [
- r'political views[^.]*\.',
- r'positions[^.]*\.',
- r'advocates[^.]*\.',
- r'supports[^.]*\.',
- r'opposes[^.]*\.'
+ r"political views[^.]*\.",
+ r"positions[^.]*\.",
+ r"advocates[^.]*\.",
+ r"supports[^.]*\.",
+ r"opposes[^.]*\.",
]
-
+
for pattern in views_patterns:
- matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ matches = re.findall(
+ pattern, content_lower, re.IGNORECASE
+ )
if matches:
- personality_data['political_views'] = ' '.join(matches[:3])
+ personality_data["political_views"] = " ".join(
+ matches[:3]
+ )
break
-
+
# Policy focus
policy_patterns = [
- r'policy[^.]*\.',
- r'focus[^.]*\.',
- r'issues[^.]*\.',
- r'legislation[^.]*\.'
+ r"policy[^.]*\.",
+ r"focus[^.]*\.",
+ r"issues[^.]*\.",
+ r"legislation[^.]*\.",
]
-
+
for pattern in policy_patterns:
- matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ matches = re.findall(
+ pattern, content_lower, re.IGNORECASE
+ )
if matches:
- personality_data['policy_focus'] = ' '.join(matches[:3])
+ personality_data["policy_focus"] = " ".join(
+ matches[:3]
+ )
break
-
+
# Achievements
achievement_patterns = [
- r'achievements[^.]*\.',
- r'accomplishments[^.]*\.',
- r'success[^.]*\.',
- r'won[^.]*\.',
- r'received[^.]*\.'
+ r"achievements[^.]*\.",
+ r"accomplishments[^.]*\.",
+ r"success[^.]*\.",
+ r"won[^.]*\.",
+ r"received[^.]*\.",
]
-
+
for pattern in achievement_patterns:
- matches = re.findall(pattern, content_lower, re.IGNORECASE)
+ matches = re.findall(
+ pattern, content_lower, re.IGNORECASE
+ )
if matches:
- personality_data['achievements'] = ' '.join(matches[:3])
+ personality_data["achievements"] = " ".join(
+ matches[:3]
+ )
break
-
+
return personality_data
- def create_personality_profile(self, mep_data: Dict[str, str]) -> MEPPersonalityProfile:
+ def create_personality_profile(
+ self, mep_data: Dict[str, str]
+ ) -> MEPPersonalityProfile:
"""
Create a personality profile for an MEP.
-
+
Args:
mep_data: MEP data from XML file
-
+
Returns:
MEPPersonalityProfile object
"""
- mep_name = mep_data['full_name']
- country = mep_data['country']
-
+ mep_name = mep_data["full_name"]
+ country = mep_data["country"]
+
# Search for Wikipedia page
page_title = self.search_wikipedia_page(mep_name, country)
-
+
if page_title:
# Get Wikipedia content
wiki_content = self.get_wikipedia_content(page_title)
-
+
if wiki_content:
# Parse content
- personality_data = self.parse_wikipedia_content(wiki_content['extract'], mep_name)
-
+ personality_data = self.parse_wikipedia_content(
+ wiki_content["extract"], mep_name
+ )
+
# Create profile
profile = MEPPersonalityProfile(
full_name=mep_name,
- mep_id=mep_data['mep_id'],
- wikipedia_url=wiki_content['url'],
- summary=personality_data['summary'],
- early_life=personality_data['early_life'],
- political_career=personality_data['political_career'],
- political_views=personality_data['political_views'],
- policy_focus=personality_data['policy_focus'],
- achievements=personality_data['achievements'],
- controversies=personality_data['controversies'],
- personal_life=personality_data['personal_life'],
- education=personality_data['education'],
- professional_background=personality_data['professional_background'],
- party_affiliations=personality_data['party_affiliations'],
- committee_experience=personality_data['committee_experience'],
- voting_record=personality_data['voting_record'],
- public_statements=personality_data['public_statements'],
- interests=personality_data['interests'],
- languages=personality_data['languages'],
- awards=personality_data['awards'],
- publications=personality_data['publications'],
- social_media=personality_data['social_media'],
- last_updated=time.strftime("%Y-%m-%d %H:%M:%S")
+ mep_id=mep_data["mep_id"],
+ wikipedia_url=wiki_content["url"],
+ summary=personality_data["summary"],
+ early_life=personality_data["early_life"],
+ political_career=personality_data[
+ "political_career"
+ ],
+ political_views=personality_data[
+ "political_views"
+ ],
+ policy_focus=personality_data["policy_focus"],
+ achievements=personality_data["achievements"],
+ controversies=personality_data["controversies"],
+ personal_life=personality_data["personal_life"],
+ education=personality_data["education"],
+ professional_background=personality_data[
+ "professional_background"
+ ],
+ party_affiliations=personality_data[
+ "party_affiliations"
+ ],
+ committee_experience=personality_data[
+ "committee_experience"
+ ],
+ voting_record=personality_data["voting_record"],
+ public_statements=personality_data[
+ "public_statements"
+ ],
+ interests=personality_data["interests"],
+ languages=personality_data["languages"],
+ awards=personality_data["awards"],
+ publications=personality_data["publications"],
+ social_media=personality_data["social_media"],
+ last_updated=time.strftime("%Y-%m-%d %H:%M:%S"),
)
-
+
if self.verbose:
- logger.info(f"Created personality profile for {mep_name} from Wikipedia")
-
+ logger.info(
+ f"Created personality profile for {mep_name} from Wikipedia"
+ )
+
return profile
-
+
# Create minimal profile if no Wikipedia data found
profile = MEPPersonalityProfile(
full_name=mep_name,
- mep_id=mep_data['mep_id'],
+ mep_id=mep_data["mep_id"],
summary=f"{mep_name} is a Member of the European Parliament representing {country}.",
political_career=f"Currently serving as MEP for {country}.",
political_views=f"Member of {mep_data['political_group']} and {mep_data['national_party']}.",
- last_updated=time.strftime("%Y-%m-%d %H:%M:%S")
+ last_updated=time.strftime("%Y-%m-%d %H:%M:%S"),
)
-
+
if self.verbose:
- logger.warning(f"No Wikipedia data found for {mep_name}, created minimal profile")
-
+ logger.warning(
+ f"No Wikipedia data found for {mep_name}, created minimal profile"
+ )
+
return profile
- def save_personality_profile(self, profile: MEPPersonalityProfile) -> str:
+ def save_personality_profile(
+ self, profile: MEPPersonalityProfile
+ ) -> str:
"""
Save personality profile to JSON file.
-
+
Args:
profile: MEPPersonalityProfile object
-
+
Returns:
Path to saved file
"""
# Create safe filename
- safe_name = re.sub(r'[^\w\s-]', '', profile.full_name).strip()
- safe_name = re.sub(r'[-\s]+', '_', safe_name)
+ safe_name = re.sub(r"[^\w\s-]", "", profile.full_name).strip()
+ safe_name = re.sub(r"[-\s]+", "_", safe_name)
filename = f"{safe_name}_{profile.mep_id}.json"
filepath = os.path.join(self.output_dir, filename)
-
+
# Convert to dictionary and save
profile_dict = asdict(profile)
-
- with open(filepath, 'w', encoding='utf-8') as f:
+
+ with open(filepath, "w", encoding="utf-8") as f:
json.dump(profile_dict, f, indent=2, ensure_ascii=False)
-
+
if self.verbose:
logger.info(f"Saved personality profile: {filepath}")
-
+
return filepath
- def scrape_all_mep_personalities(self, xml_file: str = "EU.xml", delay: float = 1.0) -> Dict[str, str]:
+ def scrape_all_mep_personalities(
+ self, xml_file: str = "EU.xml", delay: float = 1.0
+ ) -> Dict[str, str]:
"""
Scrape personality data for all MEPs.
-
+
Args:
xml_file: Path to EU.xml file
delay: Delay between requests to be respectful to Wikipedia
-
+
Returns:
Dictionary mapping MEP names to their personality profile file paths
"""
meps = self.extract_mep_data_from_xml(xml_file)
profile_files = {}
-
+
if self.verbose:
- logger.info(f"Starting personality scraping for {len(meps)} MEPs")
-
+ logger.info(
+ f"Starting personality scraping for {len(meps)} MEPs"
+ )
+
for i, mep_data in enumerate(meps, 1):
- mep_name = mep_data['full_name']
-
+ mep_name = mep_data["full_name"]
+
if self.verbose:
logger.info(f"Processing {i}/{len(meps)}: {mep_name}")
-
+
try:
# Create personality profile
profile = self.create_personality_profile(mep_data)
-
+
# Save profile
filepath = self.save_personality_profile(profile)
profile_files[mep_name] = filepath
-
+
# Respectful delay
time.sleep(delay)
-
+
except Exception as e:
logger.error(f"Error processing {mep_name}: {e}")
continue
-
+
if self.verbose:
- logger.info(f"Completed personality scraping. {len(profile_files)} profiles created.")
-
+ logger.info(
+ f"Completed personality scraping. {len(profile_files)} profiles created."
+ )
+
return profile_files
- def load_personality_profile(self, filepath: str) -> MEPPersonalityProfile:
+ def load_personality_profile(
+ self, filepath: str
+ ) -> MEPPersonalityProfile:
"""
Load personality profile from JSON file.
-
+
Args:
filepath: Path to personality profile JSON file
-
+
Returns:
MEPPersonalityProfile object
"""
- with open(filepath, 'r', encoding='utf-8') as f:
+ with open(filepath, "r", encoding="utf-8") as f:
data = json.load(f)
-
+
return MEPPersonalityProfile(**data)
- def get_personality_summary(self, profile: MEPPersonalityProfile) -> str:
+ def get_personality_summary(
+ self, profile: MEPPersonalityProfile
+ ) -> str:
"""
Generate a personality summary for use in AI agent system prompts.
-
+
Args:
profile: MEPPersonalityProfile object
-
+
Returns:
Formatted personality summary
"""
summary_parts = []
-
+
if profile.summary:
summary_parts.append(f"Background: {profile.summary}")
-
+
if profile.political_career:
- summary_parts.append(f"Political Career: {profile.political_career}")
-
+ summary_parts.append(
+ f"Political Career: {profile.political_career}"
+ )
+
if profile.political_views:
- summary_parts.append(f"Political Views: {profile.political_views}")
-
+ summary_parts.append(
+ f"Political Views: {profile.political_views}"
+ )
+
if profile.policy_focus:
- summary_parts.append(f"Policy Focus: {profile.policy_focus}")
-
+ summary_parts.append(
+ f"Policy Focus: {profile.policy_focus}"
+ )
+
if profile.achievements:
- summary_parts.append(f"Notable Achievements: {profile.achievements}")
-
+ summary_parts.append(
+ f"Notable Achievements: {profile.achievements}"
+ )
+
if profile.education:
summary_parts.append(f"Education: {profile.education}")
-
+
if profile.professional_background:
- summary_parts.append(f"Professional Background: {profile.professional_background}")
-
+ summary_parts.append(
+ f"Professional Background: {profile.professional_background}"
+ )
+
return "\n".join(summary_parts)
def main():
"""Main function to run the Wikipedia personality scraper."""
-
+
print("šļø WIKIPEDIA PERSONALITY SCRAPER FOR EUROSWARM PARLIAMENT")
print("=" * 70)
-
+
# Initialize scraper
- scraper = WikipediaPersonalityScraper(output_dir="mep_personalities", verbose=True)
-
+ scraper = WikipediaPersonalityScraper(
+ output_dir="mep_personalities", verbose=True
+ )
+
# Scrape all MEP personalities
profile_files = scraper.scrape_all_mep_personalities(delay=1.0)
-
- print(f"\nā
Scraping completed!")
+
+ print("\nā
Scraping completed!")
print(f"š Profiles saved to: {scraper.output_dir}")
print(f"š Total profiles created: {len(profile_files)}")
-
+
# Show sample profile
if profile_files:
sample_name = list(profile_files.keys())[0]
sample_file = profile_files[sample_name]
sample_profile = scraper.load_personality_profile(sample_file)
-
+
print(f"\nš Sample Profile: {sample_name}")
print("-" * 50)
print(scraper.get_personality_summary(sample_profile))
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py
index 8da55bf3..288c0273 100644
--- a/swarms/structs/__init__.py
+++ b/swarms/structs/__init__.py
@@ -1,5 +1,6 @@
from swarms.structs.agent import Agent
from swarms.structs.agent_builder import AgentsBuilder
+from swarms.structs.agent_rearrange import AgentRearrange, rearrange
from swarms.structs.auto_swarm_builder import AutoSwarmBuilder
from swarms.structs.base_structure import BaseStructure
from swarms.structs.base_swarm import BaseSwarm
@@ -66,7 +67,6 @@ from swarms.structs.multi_agent_exec import (
run_single_agent,
)
from swarms.structs.multi_agent_router import MultiAgentRouter
-from swarms.structs.agent_rearrange import AgentRearrange, rearrange
from swarms.structs.round_robin import RoundRobinSwarm
from swarms.structs.sequential_workflow import SequentialWorkflow
from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm
diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py
index 914c0adb..f9e04013 100644
--- a/swarms/structs/agent.py
+++ b/swarms/structs/agent.py
@@ -21,6 +21,13 @@ from typing import (
import toml
import yaml
+from litellm import model_list
+from litellm.utils import (
+ get_max_tokens,
+ supports_function_calling,
+ supports_parallel_function_calling,
+ supports_vision,
+)
from loguru import logger
from pydantic import BaseModel
@@ -45,7 +52,6 @@ from swarms.schemas.base_schemas import (
ChatMessageResponse,
)
from swarms.schemas.conversation_schema import ConversationSchema
-from swarms.schemas.llm_agent_schema import ModelConfigOrigin
from swarms.schemas.mcp_schemas import (
MCPConnection,
)
@@ -422,7 +428,6 @@ class Agent:
mcp_config: Optional[MCPConnection] = None,
top_p: Optional[float] = 0.90,
conversation_schema: Optional[ConversationSchema] = None,
- aditional_llm_config: Optional[ModelConfigOrigin] = None,
llm_base_url: Optional[str] = None,
llm_api_key: Optional[str] = None,
rag_config: Optional[RAGConfig] = None,
@@ -430,8 +435,8 @@ class Agent:
output_raw_json_from_tool_call: bool = False,
summarize_multiple_images: bool = False,
tool_retry_attempts: int = 3,
- speed_mode: str = None,
reasoning_prompt_on: bool = True,
+ dynamic_context_window: bool = True,
*args,
**kwargs,
):
@@ -562,7 +567,6 @@ class Agent:
self.mcp_config = mcp_config
self.top_p = top_p
self.conversation_schema = conversation_schema
- self.aditional_llm_config = aditional_llm_config
self.llm_base_url = llm_base_url
self.llm_api_key = llm_api_key
self.rag_config = rag_config
@@ -572,8 +576,8 @@ class Agent:
)
self.summarize_multiple_images = summarize_multiple_images
self.tool_retry_attempts = tool_retry_attempts
- self.speed_mode = speed_mode
self.reasoning_prompt_on = reasoning_prompt_on
+ self.dynamic_context_window = dynamic_context_window
# Initialize the feedback
self.feedback = []
@@ -676,17 +680,15 @@ class Agent:
# Initialize the short term memory
memory = Conversation(
name=f"{self.agent_name}_conversation",
+ system_prompt=prompt,
user=self.user_name,
rules=self.rules,
token_count=False,
message_id_on=False,
time_enabled=True,
- )
-
- # Add the system prompt to the conversation
- memory.add(
- role="system",
- content=prompt,
+ dynamic_context_window=self.dynamic_context_window,
+ tokenizer_model_name=self.model_name,
+ context_length=self.context_length,
)
return memory
@@ -888,11 +890,7 @@ class Agent:
Returns:
bool: True if model supports vision and image is provided, False otherwise.
"""
- from litellm.utils import (
- supports_function_calling,
- supports_parallel_function_calling,
- supports_vision,
- )
+
# Only check vision support if an image is provided
if img is not None:
@@ -1294,8 +1292,6 @@ class Agent:
self._handle_run_error(error)
def __handle_run_error(self, error: any):
- import traceback
-
if self.autosave is True:
self.save()
log_agent_data(self.to_dict())
@@ -1539,11 +1535,6 @@ class Agent:
raise
def reliability_check(self):
- from litellm import model_list
- from litellm.utils import (
- get_max_tokens,
- supports_function_calling,
- )
if self.system_prompt is None:
logger.warning(
diff --git a/swarms/structs/conversation.py b/swarms/structs/conversation.py
index 97316aa3..de7c1de2 100644
--- a/swarms/structs/conversation.py
+++ b/swarms/structs/conversation.py
@@ -1,21 +1,21 @@
-import traceback
import concurrent.futures
import datetime
+import inspect
import json
import os
+import traceback
import uuid
from typing import (
TYPE_CHECKING,
+ Any,
Dict,
List,
+ Literal,
Optional,
Union,
- Literal,
- Any,
)
import yaml
-import inspect
from swarms.utils.any_to_str import any_to_str
from swarms.utils.litellm_tokenizer import count_tokens
@@ -26,6 +26,18 @@ if TYPE_CHECKING:
from loguru import logger
+# Define available providers
+providers = Literal[
+ "mem0",
+ "in-memory",
+ "supabase",
+ "redis",
+ "sqlite",
+ "duckdb",
+ "pulsar",
+]
+
+
def generate_conversation_id():
"""Generate a unique conversation ID."""
return str(uuid.uuid4())
@@ -50,18 +62,6 @@ def get_conversation_dir():
return conversation_dir
-# Define available providers
-providers = Literal[
- "mem0",
- "in-memory",
- "supabase",
- "redis",
- "sqlite",
- "duckdb",
- "pulsar",
-]
-
-
def _create_backend_conversation(backend: str, **kwargs):
"""
Create a backend conversation instance based on the specified backend type.
@@ -183,9 +183,9 @@ class Conversation:
name: str = "conversation-test",
system_prompt: Optional[str] = None,
time_enabled: bool = False,
- autosave: bool = False, # Changed default to False
+ autosave: bool = False,
save_filepath: str = None,
- load_filepath: str = None, # New parameter to specify which file to load from
+ load_filepath: str = None,
context_length: int = 8192,
rules: str = None,
custom_rules_prompt: str = None,
@@ -211,6 +211,8 @@ class Conversation:
redis_data_dir: Optional[str] = None,
conversations_dir: Optional[str] = None,
export_method: str = "json",
+ dynamic_context_window: bool = True,
+ caching: bool = True,
*args,
**kwargs,
):
@@ -249,6 +251,8 @@ class Conversation:
self.auto_persist = auto_persist
self.redis_data_dir = redis_data_dir
self.export_method = export_method
+ self.dynamic_context_window = dynamic_context_window
+ self.caching = caching
if self.name is None:
self.name = id
@@ -933,7 +937,15 @@ class Conversation:
# Fallback to in-memory implementation
pass
+ elif self.dynamic_context_window is True:
+ return self.dynamic_auto_chunking()
+
+ else:
+ return self._return_history_as_string_worker()
+
+ def _return_history_as_string_worker(self):
formatted_messages = []
+
for message in self.conversation_history:
formatted_messages.append(
f"{message['role']}: {message['content']}"
@@ -1778,20 +1790,38 @@ class Conversation:
pass
self.conversation_history = []
+ def dynamic_auto_chunking(self):
+ all_tokens = self._return_history_as_string_worker()
+
+ total_tokens = count_tokens(
+ all_tokens, self.tokenizer_model_name
+ )
+
+ if total_tokens > self.context_length:
+ # Get the difference between the count_tokens and the context_length
+ difference = total_tokens - self.context_length
+
+ # Slice the first difference number of messages and contents from the beginning of the conversation history
+ new_history = all_tokens[difference:]
+
+ return new_history
-# # Example usage
-# # conversation = Conversation()
-# conversation = Conversation(token_count=True)
+
+# Example usage
+# conversation = Conversation()
+# conversation = Conversation(token_count=True, context_length=14)
# conversation.add("user", "Hello, how are you?")
# conversation.add("assistant", "I am doing well, thanks.")
+# conversation.add("user", "What is the weather in Tokyo?")
+# print(conversation.dynamic_auto_chunking())
# # conversation.add(
# # "assistant", {"name": "tool_1", "output": "Hello, how are you?"}
-# # )
-# # print(conversation.return_json())
+# )
+# print(conversation.return_json())
-# # # print(conversation.get_last_message_as_string())
+# # print(conversation.get_last_message_as_string())
# print(conversation.return_json())
-# # # conversation.add("assistant", "I am doing well, thanks.")
-# # # # print(conversation.to_json())
-# # print(type(conversation.to_dict()))
-# # print(conversation.to_yaml())
+# # conversation.add("assistant", "I am doing well, thanks.")
+# # # print(conversation.to_json())
+# print(type(conversation.to_dict()))
+# print(conversation.to_yaml())