diff --git a/.gitignore b/.gitignore index 4f0e933..e5b3198 100644 --- a/.gitignore +++ b/.gitignore @@ -87,6 +87,13 @@ out.log *.tmp *.temp .cache/ +test* +AGENTS.md +.github/ +*key* +*.pub +.config/ +user* test* diff --git a/scripts/README.md b/scripts/README.md index 5a9447b..3deef37 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,11 +1,34 @@ # ๐Ÿš€ NANDA Agent Deployment Scripts -Production-ready scripts for deploying NANDA agents to AWS EC2. +Production-ready scripts for deploying NANDA agents to multiple cloud providers. + +## โ˜๏ธ Supported Cloud Providers + +- **AWS EC2** - Amazon Web Services +- **DigitalOcean** - Simple cloud infrastructure +- **Azure** - Microsoft Azure Virtual Machines +- **GCP** - Google Cloud Platform Compute Engine ## ๐Ÿ“‹ Available Scripts +### AWS EC2 +- `aws/aws-single-agent-deployment.sh` - Deploy one agent to AWS EC2 +- `aws/aws-multi-agent-deployment.sh` - Deploy multiple agents to one EC2 instance + +### DigitalOcean +- `digitalocean/single-agent-deployment.sh` - Deploy one agent to DigitalOcean +- `digitalocean/multi-agent-deployment.sh` - Deploy multiple agents to one droplet + +- [DigitalOcean Documentation](./digitalocean/README.md) +- [Azure Documentation](./azure/README.md) +- [GCP Documentation](./gcp/README.md) + +--- + +## AWS Quick Start + ### ๐Ÿค– Single Agent Deployment -**`aws-single-agent-deployment.sh`** - Deploy one specialized agent to one EC2 instance +**`aws/aws-single-agent-deployment.sh`** - Deploy one specialized agent to one EC2 instance ```bash bash aws-single-agent-deployment.sh [SMITHERY_API_KEY] [REGISTRY_URL] [MCP_REGISTRY_URL] [PORT] [REGION] [INSTANCE_TYPE] @@ -13,7 +36,7 @@ bash aws-single-agent-deployment.sh [SMITHERY_API_KEY] [REGISTRY_URL] [MCP_REGISTRY_URL] [REGION] [INSTANCE_TYPE] @@ -38,7 +61,7 @@ bash aws-multi-agent-deployment.sh [SMITHERY_API_KEY] [R **Example:** ```bash -bash aws-multi-agent-deployment.sh \ +bash scripts/aws/aws-multi-agent-deployment.sh \ "sk-ant-api03-..." \ "agent_configs/group-01-business-and-finance-experts.json" \ "smithery-key-xxxxx" \ @@ -164,7 +187,7 @@ ps aux | grep python ### Deploy 100 Agents (10 instances) ```bash for i in {1..10}; do - bash aws-multi-agent-deployment.sh \ + bash scripts/aws/aws-multi-agent-deployment.sh \ "sk-ant-api03-..." \ "group-0${i}-*.json" \ "http://registry.chat39.com:6900" \ @@ -177,7 +200,7 @@ done ```bash # Deploy to multiple regions for region in us-east-1 us-west-2 eu-west-1; do - bash aws-multi-agent-deployment.sh \ + bash scripts/aws/aws-multi-agent-deployment.sh \ "sk-ant-api03-..." \ "group-01-business-and-finance-experts.json" \ "http://registry.chat39.com:6900" \ diff --git a/scripts/aws/README.md b/scripts/aws/README.md new file mode 100644 index 0000000..a2d5328 --- /dev/null +++ b/scripts/aws/README.md @@ -0,0 +1,209 @@ +# ๐Ÿš€ NANDA Agent Deployment Scripts + +Production-ready scripts for deploying NANDA agents to multiple cloud providers. + +## โ˜๏ธ Supported Cloud Providers + +- **AWS EC2** - Amazon Web Services +- **DigitalOcean** - Simple cloud infrastructure +- **Azure** - Microsoft Azure Virtual Machines +- **GCP** - Google Cloud Platform Compute Engine + +## ๐Ÿ“‹ Available Scripts + +### AWS EC2 +- `aws-single-agent-deployment.sh` - Deploy one agent to AWS EC2 +- `aws-multi-agent-deployment.sh` - Deploy multiple agents to one EC2 instance + +### DigitalOcean +- `digitalocean/single-agent-deployment.sh` - Deploy one agent to DigitalOcean +- `digitalocean/multi-agent-deployment.sh` - Deploy multiple agents to one droplet +- [DigitalOcean Documentation](./digitalocean/README.md) +- [Azure Documentation](./azure/README.md) +- [GCP Documentation](./gcp/README.md) + +--- + +## AWS Quick Start + +### ๐Ÿค– Single Agent Deployment +**`aws/aws-single-agent-deployment.sh`** - Deploy one specialized agent to one EC2 instance + +```bash +bash scripts/aws/aws-single-agent-deployment.sh [REGISTRY_URL] [PORT] [REGION] [INSTANCE_TYPE] +``` + +**Example:** +```bash +bash aws-single-agent-deployment.sh \ + "data-scientist" \ + "sk-ant-api03-..." \ + "Data Scientist" \ + "data analysis" \ + "expert data analyst and machine learning specialist" \ + "I help with statistical analysis, machine learning, and data visualization" \ + "python,statistics,machine learning,data visualization" \ + "http://registry.chat39.com:6900" \ + "6000" \ + "us-east-1" \ + "t3.micro" +``` + +### ๐Ÿญ Multi-Agent Deployment +**`aws-multi-agent-deployment.sh`** - Deploy 10 agents to one EC2 instance + +```bash +bash aws-multi-agent-deployment.sh [REGISTRY_URL] [REGION] [INSTANCE_TYPE] +``` + +**Example:** +```bash +bash aws-multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "agent_configs/group-01-business-and-finance-experts.json" \ + "http://registry.chat39.com:6900" \ + "us-east-1" \ + "t3.xlarge" +``` + +### ๐Ÿ–ฅ๏ธ Existing Server Deployment +**`deploy-agent.sh`** - Deploy agent to existing Ubuntu/Amazon Linux server + +```bash +bash deploy-agent.sh [PORT] [REGISTRY_URL] +``` + +## ๐Ÿ“ฆ Pre-configured Agent Groups + +Ready-to-deploy agent configurations: + +| File | Agents | Description | +|------|--------|-------------| +| `agent_configs/group-01-business-and-finance-experts.json` | 10 | Financial analysts, advisors, strategists | +| `agent_configs/group-02-technology-and-engineering.json` | 10 | Software engineers, DevOps, AI researchers | +| `agent_configs/group-03-creative-and-design.json` | 10 | Designers, content creators, brand experts | +| `agent_configs/group-04-healthcare-and-life-sciences.json` | 10 | Medical researchers, health informatics | +| `agent_configs/group-05-education-and-research.json` | 10 | Academic researchers, educators | +| `agent_configs/group-06-media-and-entertainment.json` | 10 | Journalists, producers, social media | +| `agent_configs/group-07-environmental-and-sustainability.json` | 10 | Climate scientists, sustainability experts | +| `agent_configs/group-08-social-services-and-community.json` | 10 | Social workers, policy analysts | +| `agent_configs/group-09-sports-and-recreation.json` | 10 | Fitness trainers, sports analysts | +| `agent_configs/group-10-travel-and-hospitality.json` | 10 | Travel planners, hospitality managers | +| `agent_configs/100-agents-config.json` | 100 | All agent personalities combined | + +## ๐Ÿ› ๏ธ Prerequisites + +- **AWS CLI** configured with credentials (`aws configure`) +- **Anthropic API Key** for Claude LLM +- **SSH Key Pair** for EC2 access (automatically created) + +## ๐ŸŽฏ Recommended Instance Types + +| Deployment | Instance Type | Cost | Use Case | +|------------|---------------|------|----------| +| Single Agent | `t3.micro` | $8/month | Development, testing | +| Multi-Agent (10) | `t3.xlarge` | $150/month | Production, high traffic | +| High Performance | `t3.2xlarge` | $300/month | Enterprise, 20+ agents | + +## ๐Ÿ”ง What the Scripts Do + +1. **๐Ÿ” AWS Setup**: Create security groups, key pairs, open ports +2. **๐Ÿ–ฅ๏ธ EC2 Launch**: Launch Ubuntu 22.04 instance with user-data script +3. **๐Ÿ“ฆ Dependencies**: Install Python, git, anthropic library +4. **๐Ÿ“‚ Project Setup**: Clone repo, create virtual environment +5. **๐Ÿค– Agent Start**: Configure and start agent(s) with supervisor +6. **๐Ÿ“‹ Registry**: Register agent(s) with NANDA registry +7. **โœ… Health Check**: Verify agent(s) are responding + +## ๐Ÿงช Testing Deployed Agents + +### Test Single Agent +```bash +curl -X POST http://AGENT_IP:6000/a2a \ + -H "Content-Type: application/json" \ + -d '{"content":{"text":"Hello! What are your capabilities?","type":"text"},"role":"user","conversation_id":"test123"}' +``` + +### Test A2A Communication +```bash +curl -X POST http://AGENT_A_IP:6000/a2a \ + -H "Content-Type: application/json" \ + -d '{"content":{"text":"@agent-b-id Can you help with this task?","type":"text"},"role":"user","conversation_id":"test123"}' +``` + +## ๐Ÿ›‘ Cleanup + +To terminate instances: +```bash +# Single agent +aws ec2 terminate-instances --region us-east-1 --instance-ids i-xxxxx + +# Multiple instances +aws ec2 describe-instances --filters "Name=tag:Project,Values=NANDA*" --query 'Reservations[*].Instances[*].InstanceId' --output text | xargs aws ec2 terminate-instances --region us-east-1 --instance-ids +``` + +## ๐Ÿšจ Troubleshooting + +### Common Issues + +**Agent not responding:** +- Check security group has port open +- Verify agent process is running: `ps aux | grep python` +- Check logs: `tail -f agent.log` + +**SSH connection failed:** +- Ensure using correct `.pem` key file +- Check key permissions: `chmod 400 *.pem` +- Verify instance is running: `aws ec2 describe-instances` + +**Registration failed:** +- Verify registry URL is accessible +- Check public IP retrieval in user-data logs +- Ensure ANTHROPIC_API_KEY is valid + +### Debug Commands + +```bash +# SSH into instance +ssh -i nanda-agent-key.pem ubuntu@INSTANCE_IP + +# Check user-data logs +sudo tail -f /var/log/cloud-init-output.log + +# Check agent logs +cd nanda-agent-* && tail -f agent.log + +# Check running processes +ps aux | grep python +``` + +## ๐Ÿ“ˆ Scaling + +### Deploy 100 Agents (10 instances) +```bash +for i in {1..10}; do + bash aws-multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "group-0${i}-*.json" \ + "http://registry.chat39.com:6900" \ + "us-east-1" \ + "t3.xlarge" & +done +``` + +### Cross-Region Deployment +```bash +# Deploy to multiple regions +for region in us-east-1 us-west-2 eu-west-1; do + bash aws-multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "group-01-business-and-finance-experts.json" \ + "http://registry.chat39.com:6900" \ + "$region" \ + "t3.xlarge" & +done +``` + +--- + +**๐ŸŽฏ Ready to deploy? Start with a single agent to test, then scale to multi-agent deployments!** \ No newline at end of file diff --git a/scripts/aws-multi-agent-deployment.sh b/scripts/aws/aws-multi-agent-deployment.sh similarity index 100% rename from scripts/aws-multi-agent-deployment.sh rename to scripts/aws/aws-multi-agent-deployment.sh diff --git a/scripts/aws-single-agent-deployment.sh b/scripts/aws/aws-single-agent-deployment.sh similarity index 100% rename from scripts/aws-single-agent-deployment.sh rename to scripts/aws/aws-single-agent-deployment.sh diff --git a/scripts/digitalocean/README.md b/scripts/digitalocean/README.md new file mode 100644 index 0000000..0e150f2 --- /dev/null +++ b/scripts/digitalocean/README.md @@ -0,0 +1,206 @@ +# DigitalOcean Deployment Scripts for NANDA Agents + +This directory contains scripts for deploying NANDA agents on DigitalOcean droplets. + +## Prerequisites + +1. **DigitalOcean Account**: Sign up at [digitalocean.com](https://www.digitalocean.com/) +2. **doctl CLI**: Install the DigitalOcean command-line tool + ```bash + # macOS + brew install doctl + + # Linux + cd ~ + wget https://github.com/digitalocean/doctl/releases/download/v1.98.1/doctl-1.98.1-linux-amd64.tar.gz + tar xf ~/doctl-1.98.1-linux-amd64.tar.gz + sudo mv ~/doctl /usr/local/bin + + # Windows + # Download from https://github.com/digitalocean/doctl/releases + ``` + +3. **Authenticate doctl**: + ```bash + doctl auth init + # Enter your DigitalOcean API token when prompted + # Generate token at: https://cloud.digitalocean.com/account/api/tokens + ``` + +4. **Anthropic API Key**: Get your API key from [console.anthropic.com](https://console.anthropic.com/) + +## Scripts + +### 1. Single Agent Deployment + +Deploy a single NANDA agent on a DigitalOcean droplet. + +**Usage:** +```bash +bash scripts/digitalocean/single-agent-deployment.sh \ + \ + \ + \ + \ + \ + \ + \ + [REGISTRY_URL] \ + [PORT] \ + [REGION] \ + [DROPLET_SIZE] +``` + +**Example:** +```bash +bash scripts/digitalocean/single-agent-deployment.sh \ + "finance-analyst" \ + "sk-ant-api03-xxxxx" \ + "Finance Analyst" \ + "finance" \ + "financial analysis expert" \ + "Specializes in financial analysis, market research, and investment strategies" \ + "finance,analysis,markets,trading" \ + "http://registry.chat39.com:6900" \ + 6001 \ + nyc3 \ + s-1vcpu-2gb +``` + +**Parameters:** +- `AGENT_ID`: Unique identifier (e.g., "finance-analyst") +- `ANTHROPIC_API_KEY`: Your Anthropic API key +- `AGENT_NAME`: Display name (e.g., "Finance Analyst") +- `DOMAIN`: Primary domain (e.g., "finance") +- `SPECIALIZATION`: Brief role description +- `DESCRIPTION`: Detailed description +- `CAPABILITIES`: Comma-separated capabilities +- `REGISTRY_URL`: Optional registry URL (default: http://registry.chat39.com:6900) +- `PORT`: Agent port (default: 6000) +- `REGION`: DigitalOcean region (default: nyc1) +- `DROPLET_SIZE`: Droplet size (default: s-1vcpu-1gb) + +### 2. Multi-Agent Deployment + +Deploy multiple NANDA agents on a single DigitalOcean droplet using supervisor. + +**Usage:** +```bash +bash scripts/digitalocean/multi-agent-deployment.sh \ + \ + \ + [REGISTRY_URL] \ + [REGION] \ + [DROPLET_SIZE] +``` + +**Example:** +```bash +bash scripts/digitalocean/multi-agent-deployment.sh \ + "sk-ant-api03-xxxxx" \ + "scripts/agent_configs/test-3-agents.json" \ + "http://registry.chat39.com:6900" \ + nyc3 \ + s-2vcpu-4gb +``` + +**Parameters:** +- `ANTHROPIC_API_KEY`: Your Anthropic API key +- `AGENT_CONFIG_JSON`: Path to JSON config file or JSON string +- `REGISTRY_URL`: Registry URL (default: http://registry.chat39.com:6900) +- `REGION`: DigitalOcean region (default: nyc1) +- `DROPLET_SIZE`: Droplet size (default: s-2vcpu-4gb) + + +## Cleanup + +### Delete droplet: +```bash +doctl compute droplet delete +``` + +### Delete firewall: +```bash +doctl compute firewall delete +``` + +### Delete SSH key (if no longer needed): +```bash +doctl compute ssh-key delete +``` + +## Features + +### Single Agent Deployment +- โœ… Automated droplet creation and configuration +- โœ… Firewall setup with SSH and agent port access +- โœ… SSH key generation and management +- โœ… User data script for automatic agent setup +- โœ… Public IP retrieval via DigitalOcean metadata service +- โœ… Comprehensive deployment logging + +### Multi-Agent Deployment +- โœ… Deploy multiple agents on one droplet +- โœ… Supervisor process management for all agents +- โœ… Automatic restart on failure +- โœ… Individual agent log files +- โœ… Port validation (no duplicates) +- โœ… Dynamic firewall configuration for all ports +- โœ… Health checks for all deployed agents + +## Troubleshooting + +### Authentication issues: +```bash +# Re-initialize doctl authentication +doctl auth init + +# Verify authentication +doctl account get +``` + +### Droplet not accessible: +```bash +# Check droplet status +doctl compute droplet list + +# Check firewall rules +doctl compute firewall list +``` + +### Agent not responding: +```bash +# Check if agent process is running +ssh -i root@ 'ps aux | grep nanda_agent' + +# Check agent logs +ssh -i root@ 'tail -100 /root/nanda-agent-*/agent.log' +``` + +### Multi-agent supervisor issues: +```bash +# Check supervisor status +ssh -i nanda-multi-agent-key root@ 'supervisorctl status' + +# Check supervisor logs +ssh -i nanda-multi-agent-key root@ 'tail -100 /var/log/supervisor/supervisord.log' + +# Manually restart supervisor +ssh -i nanda-multi-agent-key root@ 'systemctl restart supervisor' +``` + +## Cost Considerations + +- Droplets are billed hourly (monthly cap applies) +- Bandwidth is included (1TB+ on most plans) +- Snapshots and backups are additional +- Use smaller droplet sizes for testing/development +- Delete unused droplets to avoid charges + +## Security Best Practices + +1. **SSH Keys**: Always use SSH keys (scripts generate them automatically) +2. **Firewalls**: Scripts create droplet-specific firewalls +3. **API Keys**: Never commit API keys to version control +4. **Regular Updates**: Keep droplets updated with security patches +5. **Monitoring**: Enable DigitalOcean monitoring for production deployments diff --git a/scripts/digitalocean/multi-agent-deployment.sh b/scripts/digitalocean/multi-agent-deployment.sh new file mode 100755 index 0000000..0aa396d --- /dev/null +++ b/scripts/digitalocean/multi-agent-deployment.sh @@ -0,0 +1,334 @@ +#!/bin/bash + +# CONFIGURABLE DigitalOcean Multi-Agent Deployment Script +# This script creates a DigitalOcean droplet and deploys multiple fully configurable modular NANDA agents +# Usage: bash digitalocean-multi-agent-deployment.sh [REGISTRY_URL] [REGION] [DROPLET_SIZE] + +set -e + +# Parse arguments +ANTHROPIC_API_KEY="$1" +AGENT_CONFIG_JSON="$2" +REGISTRY_URL="${3:-http://registry.chat39.com:6900}" +REGION="${4:-nyc1}" +DROPLET_SIZE="${5:-s-2vcpu-4gb}" # 4GB for multiple agents + +# Validation +if [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$AGENT_CONFIG_JSON" ]; then + echo "โŒ Usage: $0 [REGISTRY_URL] [REGION] [DROPLET_SIZE]" + echo "" + echo "Example:" + echo " $0 sk-ant-xxxxx ./scripts/agent_configs/group-01-business-and-finance-experts.json \"http://registry.chat39.com:6900\" nyc1 s-2vcpu-4gb" + echo "" + echo "Parameters:" + echo " ANTHROPIC_API_KEY: Your Anthropic API key" + echo " AGENT_CONFIG_JSON: Path to JSON file or JSON string with agent configurations" + echo " REGISTRY_URL: Registry URL for agent discovery (default: http://registry.chat39.com:6900)" + echo " REGION: DigitalOcean region (default: nyc1)" + echo " DROPLET_SIZE: Droplet size slug (default: s-2vcpu-4gb for 4GB RAM)" + echo "" + echo "Common DigitalOcean regions: nyc1, nyc3, sfo3, ams3, sgp1, lon1, fra1, tor1, blr1" + echo "Common droplet sizes: s-1vcpu-2gb (2GB), s-2vcpu-4gb (4GB), s-4vcpu-8gb (8GB)" + exit 1 +fi + +# Parse and validate agent config +if [ -f "$AGENT_CONFIG_JSON" ]; then + AGENTS_JSON=$(cat "$AGENT_CONFIG_JSON") +else + AGENTS_JSON="$AGENT_CONFIG_JSON" +fi + +AGENT_COUNT=$(echo "$AGENTS_JSON" | python3 -c "import json, sys; print(len(json.load(sys.stdin)))") +echo "Agents to deploy: $AGENT_COUNT" + +# Validate instance type for agent count +if [ "$AGENT_COUNT" -gt 5 ] && [ "$DROPLET_SIZE" = "s-1vcpu-2gb" ]; then + echo "โš ๏ธ WARNING: s-1vcpu-2gb may be insufficient for $AGENT_COUNT agents. Consider s-2vcpu-4gb or larger." + read -p "Continue anyway? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Validate port uniqueness +echo "Validating port configuration..." +DUPLICATE_PORTS=$(echo "$AGENTS_JSON" | python3 -c " +import json, sys +from collections import Counter +agents = json.load(sys.stdin) +ports = [agent['port'] for agent in agents] +duplicates = [port for port, count in Counter(ports).items() if count > 1] +if duplicates: + print(' '.join(map(str, duplicates))) + sys.exit(1) +") + +if [ $? -eq 1 ]; then + echo "โŒ Duplicate ports found: $DUPLICATE_PORTS" + exit 1 +fi + +# Configuration +SSH_KEY_NAME="nanda-multi-agent-key" +IMAGE_SLUG="ubuntu-22-04-x64" +DEPLOYMENT_ID=$(date +%Y%m%d-%H%M%S) + +echo "๐Ÿš€ Configurable DigitalOcean Multi-Agent Deployment" +echo "====================================================" +echo "Deployment ID: $DEPLOYMENT_ID" +echo "Agent Count: $AGENT_COUNT" +echo "Registry URL: $REGISTRY_URL" +echo "Region: $REGION" +echo "Droplet Size: $DROPLET_SIZE" +echo "" + +# Check DigitalOcean CLI +echo "[1/7] Checking DigitalOcean CLI (doctl)..." +if ! command -v doctl &> /dev/null; then + echo "โŒ doctl not installed. Install it: https://docs.digitalocean.com/reference/doctl/how-to/install/" + exit 1 +fi + +if ! doctl account get >/dev/null 2>&1; then + echo "โŒ doctl not authenticated. Run 'doctl auth init' first." + exit 1 +fi +echo "โœ… DigitalOcean CLI authenticated" + +# Setup SSH key +echo "[2/7] Setting up SSH key..." +if [ ! -f "${SSH_KEY_NAME}" ]; then + echo "Generating SSH key pair..." + ssh-keygen -t rsa -b 4096 -f "$SSH_KEY_NAME" -N "" -C "nanda-multi-agent-$DEPLOYMENT_ID" +fi + +SSH_KEY_ID=$(doctl compute ssh-key list --format ID,Name --no-header | grep "$SSH_KEY_NAME" | awk '{print $1}' || echo "") +if [ -z "$SSH_KEY_ID" ]; then + echo "Uploading SSH key to DigitalOcean..." + SSH_KEY_ID=$(doctl compute ssh-key create "$SSH_KEY_NAME" --public-key "$(cat ${SSH_KEY_NAME}.pub)" --format ID --no-header) +fi +echo "โœ… SSH key ID: $SSH_KEY_ID" + +# Setup firewall +echo "[3/7] Setting up firewall..." +FIREWALL_NAME="nanda-multi-agent-fw-${DEPLOYMENT_ID}" + +# Get agent ports for firewall rules +AGENT_PORTS=$(echo "$AGENTS_JSON" | python3 -c " +import json, sys +agents = json.load(sys.stdin) +ports = [str(agent['port']) for agent in agents] +print(','.join(ports)) +") + +# Build firewall inbound rules (SSH + all agent ports) +INBOUND_RULES="protocol:tcp,ports:22,address:0.0.0.0/0" +IFS=',' read -ra PORTS <<< "$AGENT_PORTS" +for PORT in "${PORTS[@]}"; do + INBOUND_RULES="${INBOUND_RULES} protocol:tcp,ports:${PORT},address:0.0.0.0/0" +done + +# Create firewall +FIREWALL_ID=$(doctl compute firewall create \ + --name "$FIREWALL_NAME" \ + --inbound-rules "$INBOUND_RULES" \ + --outbound-rules "protocol:tcp,ports:all,address:0.0.0.0/0 protocol:udp,ports:all,address:0.0.0.0/0 protocol:icmp,address:0.0.0.0/0" \ + --format ID --no-header) + +echo "โœ… Firewall created with ports: SSH, $AGENT_PORTS" +echo "โœ… Firewall ID: $FIREWALL_ID" + +# Create improved user data script with supervisor +echo "[4/7] Creating improved user data script..." +cat > "user_data_multi_${DEPLOYMENT_ID}.sh" << EOF +#!/bin/bash +exec > /var/log/user-data.log 2>&1 + +echo "=== NANDA Multi-Agent Setup Started: $DEPLOYMENT_ID ===" +date + +# Update system and install dependencies +apt-get update -y +apt-get install -y python3 python3-venv python3-pip git curl jq supervisor + +# Setup project as root +cd /root +git clone https://github.com/projnanda/NEST.git nanda-multi-agents-$DEPLOYMENT_ID +cd nanda-multi-agents-$DEPLOYMENT_ID + +# Create virtual environment and install +python3 -m venv env +bash -c "source env/bin/activate && pip install --upgrade pip && pip install -e . && pip install anthropic" + +# Get public IP using DigitalOcean metadata service +echo "Getting public IP address from metadata service..." +for attempt in {1..10}; do + PUBLIC_IP=\$(curl -s --connect-timeout 5 --max-time 10 http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address 2>/dev/null) + + if [ -n "\$PUBLIC_IP" ] && [[ \$PUBLIC_IP =~ ^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\$ ]]; then + echo "Retrieved public IP: \$PUBLIC_IP" + break + fi + echo "Attempt \$attempt failed, retrying..." + sleep 3 +done + +if [ -z "\$PUBLIC_IP" ]; then + echo "ERROR: Could not retrieve public IP after 10 attempts" + exit 1 +fi + +# Save agent configuration +cat > /tmp/agents_config.json << 'AGENTS_EOF' +$AGENTS_JSON +AGENTS_EOF + +# Create supervisor configuration for each agent +echo "Creating supervisor configurations..." +mkdir -p /etc/supervisor/conf.d + +while IFS= read -r agent_config; do + AGENT_ID=\$(echo "\$agent_config" | jq -r '.agent_id') + AGENT_NAME=\$(echo "\$agent_config" | jq -r '.agent_name') + DOMAIN=\$(echo "\$agent_config" | jq -r '.domain') + SPECIALIZATION=\$(echo "\$agent_config" | jq -r '.specialization') + DESCRIPTION=\$(echo "\$agent_config" | jq -r '.description') + CAPABILITIES=\$(echo "\$agent_config" | jq -c '.capabilities') + PORT=\$(echo "\$agent_config" | jq -r '.port') + + echo "Configuring supervisor for agent: \$AGENT_ID" + + # Create supervisor configuration file + cat > "/etc/supervisor/conf.d/agent_\$AGENT_ID.conf" << SUPERVISOR_EOF +[program:agent_\$AGENT_ID] +command=/root/nanda-multi-agents-$DEPLOYMENT_ID/env/bin/python examples/nanda_agent.py +directory=/root/nanda-multi-agents-$DEPLOYMENT_ID +user=root +autostart=true +autorestart=true +startretries=3 +stderr_logfile=/var/log/agent_\$AGENT_ID.err.log +stdout_logfile=/var/log/agent_\$AGENT_ID.out.log +environment=ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY",AGENT_ID="\$AGENT_ID",AGENT_NAME="\$AGENT_NAME",AGENT_DOMAIN="\$DOMAIN",AGENT_SPECIALIZATION="\$SPECIALIZATION",AGENT_DESCRIPTION="\$DESCRIPTION",AGENT_CAPABILITIES='\$CAPABILITIES',REGISTRY_URL="$REGISTRY_URL",PUBLIC_URL="http://\$PUBLIC_IP:\$PORT",PORT="\$PORT" + +SUPERVISOR_EOF + + echo "โœ… Supervisor config created for agent \$AGENT_ID on port \$PORT" + +done < <(cat /tmp/agents_config.json | jq -c '.[]') + +# Start supervisor and wait for all agents +echo "Starting supervisor..." +systemctl enable supervisor +systemctl start supervisor +supervisorctl reread +supervisorctl update + +# Wait for all agents to start +echo "Waiting for all agents to start..." +sleep 30 + +# Verify all agents are running +echo "Verifying agent status..." +supervisorctl status + +echo "=== NANDA Multi-Agent Setup Complete: $DEPLOYMENT_ID ===" +echo "All agents managed by supervisor on: \$PUBLIC_IP" +EOF + +# Launch droplet +echo "[5/7] Launching DigitalOcean droplet..." +DROPLET_ID=$(doctl compute droplet create "nanda-multi-agent-$DEPLOYMENT_ID" \ + --region "$REGION" \ + --size "$DROPLET_SIZE" \ + --image "$IMAGE_SLUG" \ + --ssh-keys "$SSH_KEY_ID" \ + --user-data-file "user_data_multi_${DEPLOYMENT_ID}.sh" \ + --tag-names "NANDA,multi-agent" \ + --format ID --no-header \ + --wait) + +echo "โœ… Droplet created: $DROPLET_ID" + +# Wait for droplet to be active and get IP +echo "[6/7] Waiting for droplet to be active..." +sleep 10 + +PUBLIC_IP=$(doctl compute droplet get "$DROPLET_ID" --format PublicIPv4 --no-header) +echo "โœ… Public IP: $PUBLIC_IP" + +# Attach firewall to droplet +doctl compute firewall add-droplets "$FIREWALL_ID" --droplet-ids "$DROPLET_ID" +echo "โœ… Firewall attached to droplet" + +echo "[7/7] Waiting for multi-agent deployment (2-3 minutes)..." +sleep 150 + +# Cleanup +rm "user_data_multi_${DEPLOYMENT_ID}.sh" + +# Health check all agents +echo "" +echo "๐Ÿ” Performing health checks..." +echo "$AGENTS_JSON" | python3 -c " +import json, sys +try: + import requests + agents = json.load(sys.stdin) + for agent in agents: + url = f'http://$PUBLIC_IP:{agent[\"port\"]}/health' + try: + response = requests.get(url, timeout=5) + if response.status_code == 200: + print(f'โœ… {agent[\"agent_id\"]}: Healthy') + else: + print(f'โš ๏ธ {agent[\"agent_id\"]}: HTTP {response.status_code}') + except Exception as e: + print(f'โŒ {agent[\"agent_id\"]}: {str(e)}') +except ImportError: + print('Health check skipped (requests not available)') +" 2>/dev/null || echo "Health check skipped (requests not available)" + +echo "" +echo "๐ŸŽ‰ NANDA Multi-Agent Deployment Complete!" +echo "==========================================" +echo "Deployment ID: $DEPLOYMENT_ID" +echo "Droplet ID: $DROPLET_ID" +echo "Public IP: $PUBLIC_IP" +echo "Firewall ID: $FIREWALL_ID" + +# Display agent URLs +echo "" +echo "๐Ÿค– Agent URLs:" +echo "$AGENTS_JSON" | python3 -c " +import json, sys +agents = json.load(sys.stdin) +for agent in agents: + print(f\" {agent['agent_id']}: http://$PUBLIC_IP:{agent['port']}/a2a\") +" + +echo "" +echo "๐Ÿงช Test an agent (direct communication):" +FIRST_PORT=$(echo "$AGENTS_JSON" | python3 -c "import json, sys; agents = json.load(sys.stdin); print(agents[0]['port']) if agents else print('6000')") +echo "curl -X POST http://$PUBLIC_IP:$FIRST_PORT/a2a \\" +echo " -H \"Content-Type: application/json\" \\" +echo " -d '{\"content\":{\"text\":\"Hello! What can you help me with?\",\"type\":\"text\"},\"role\":\"user\",\"conversation_id\":\"test123\"}'" + +echo "" +echo "๐Ÿ” SSH Access:" +echo "ssh -i ${SSH_KEY_NAME} root@$PUBLIC_IP" + +echo "" +echo "๐Ÿ“Š Monitor agents:" +echo "ssh -i ${SSH_KEY_NAME} root@$PUBLIC_IP 'supervisorctl status'" + +echo "" +echo "๐Ÿ”„ Restart all agents:" +echo "ssh -i ${SSH_KEY_NAME} root@$PUBLIC_IP 'supervisorctl restart all'" + +echo "" +echo "๐Ÿ›‘ To terminate:" +echo "doctl compute droplet delete $DROPLET_ID" +echo "doctl compute firewall delete $FIREWALL_ID" diff --git a/scripts/digitalocean/single-agent-deployment.sh b/scripts/digitalocean/single-agent-deployment.sh new file mode 100755 index 0000000..d0a169a --- /dev/null +++ b/scripts/digitalocean/single-agent-deployment.sh @@ -0,0 +1,242 @@ +#!/bin/bash + +# CONFIGURABLE DigitalOcean Droplet + NANDA Agent Deployment Script +# This script creates a DigitalOcean droplet and deploys a fully configurable modular NANDA agent +# Usage: bash digitalocean-single-agent-deployment.sh [REGISTRY_URL] [PORT] [REGION] [DROPLET_SIZE] + +set -e + +# Parse arguments +AGENT_ID="$1" +ANTHROPIC_API_KEY="$2" +AGENT_NAME="$3" +DOMAIN="$4" +SPECIALIZATION="$5" +DESCRIPTION="$6" +CAPABILITIES="$7" +REGISTRY_URL="${8:-}" +PORT="${9:-6000}" +REGION="${10:-nyc1}" +DROPLET_SIZE="${11:-s-1vcpu-1gb}" + +# Validate inputs +if [ -z "$AGENT_ID" ] || [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$AGENT_NAME" ] || [ -z "$DOMAIN" ] || [ -z "$SPECIALIZATION" ] || [ -z "$DESCRIPTION" ] || [ -z "$CAPABILITIES" ]; then + echo "โŒ Usage: $0 [REGISTRY_URL] [PORT] [REGION] [DROPLET_SIZE]" + echo "" + echo "Example:" + echo " $0 data-scientist sk-ant-xxxxx \"Data Scientist\" \"data analysis\" \"analytical and precise AI assistant\" \"I specialize in data analysis, statistics, and machine learning.\" \"data analysis,statistics,machine learning,Python,R\" \"https://registry.example.com\" 6000 nyc1 s-1vcpu-1gb" + echo "" + echo "Parameters:" + echo " AGENT_ID: Unique identifier for the agent" + echo " ANTHROPIC_API_KEY: Your Anthropic API key" + echo " AGENT_NAME: Display name for the agent" + echo " DOMAIN: Primary domain/field of expertise" + echo " SPECIALIZATION: Brief description of agent's role" + echo " DESCRIPTION: Detailed description of the agent" + echo " CAPABILITIES: Comma-separated list of capabilities" + echo " REGISTRY_URL: Optional registry URL for agent discovery" + echo " PORT: Port for agent HTTP server (default: 6000)" + echo " REGION: DigitalOcean region (default: nyc1)" + echo " DROPLET_SIZE: Droplet size slug (default: s-1vcpu-1gb)" + echo "" + echo "Common DigitalOcean regions: nyc1, nyc3, sfo3, ams3, sgp1, lon1, fra1, tor1, blr1" + echo "Common droplet sizes: s-1vcpu-1gb, s-1vcpu-2gb, s-2vcpu-2gb, s-2vcpu-4gb" + exit 1 +fi + +echo "๐Ÿš€ Configurable DigitalOcean + NANDA Agent Deployment" +echo "=====================================================" +echo "Agent ID: $AGENT_ID" +echo "Agent Name: $AGENT_NAME" +echo "Domain: $DOMAIN" +echo "Specialization: $SPECIALIZATION" +echo "Capabilities: $CAPABILITIES" +echo "Registry URL: ${REGISTRY_URL:-"None"}" +echo "Port: $PORT" +echo "Region: $REGION" +echo "Droplet Size: $DROPLET_SIZE" +echo "" + +# Configuration +SSH_KEY_NAME="nanda-agent-key" +DEPLOYMENT_ID=$(date +%Y%m%d-%H%M%S) +IMAGE_SLUG="ubuntu-22-04-x64" + +# Check doctl (DigitalOcean CLI) installation +echo "[1/7] Checking DigitalOcean CLI (doctl)..." +if ! command -v doctl &> /dev/null; then + echo "โŒ doctl not installed. Install it: https://docs.digitalocean.com/reference/doctl/how-to/install/" + exit 1 +fi + +# Check authentication +if ! doctl account get >/dev/null 2>&1; then + echo "โŒ doctl not authenticated. Run 'doctl auth init' first." + exit 1 +fi +echo "โœ… DigitalOcean CLI authenticated" + +# Setup SSH key +echo "[2/7] Setting up SSH key..." +if [ ! -f "${SSH_KEY_NAME}" ]; then + echo "Generating SSH key pair..." + ssh-keygen -t rsa -b 4096 -f "$SSH_KEY_NAME" -N "" -C "nanda-agent-$DEPLOYMENT_ID" +fi + +# Upload SSH key to DigitalOcean if not exists +SSH_KEY_ID=$(doctl compute ssh-key list --format ID,Name --no-header | grep "$SSH_KEY_NAME" | awk '{print $1}' || echo "") +if [ -z "$SSH_KEY_ID" ]; then + echo "Uploading SSH key to DigitalOcean..." + SSH_KEY_ID=$(doctl compute ssh-key create "$SSH_KEY_NAME" --public-key "$(cat ${SSH_KEY_NAME}.pub)" --format ID --no-header) +fi +echo "โœ… SSH key ID: $SSH_KEY_ID" + +# Setup firewall +echo "[3/7] Setting up firewall..." +FIREWALL_NAME="nanda-agent-fw-${DEPLOYMENT_ID}" + +# Create firewall with SSH and agent port +FIREWALL_ID=$(doctl compute firewall create \ + --name "$FIREWALL_NAME" \ + --inbound-rules "protocol:tcp,ports:22,address:0.0.0.0/0 protocol:tcp,ports:${PORT},address:0.0.0.0/0" \ + --outbound-rules "protocol:tcp,ports:all,address:0.0.0.0/0 protocol:udp,ports:all,address:0.0.0.0/0 protocol:icmp,address:0.0.0.0/0" \ + --format ID --no-header) + +echo "โœ… Firewall created: $FIREWALL_ID" + +# Create user data script +echo "[4/7] Creating user data script..." +cat > "user_data_${AGENT_ID}_${DEPLOYMENT_ID}.sh" << 'USERDATA_EOF' +#!/bin/bash +exec > /var/log/user-data.log 2>&1 + +echo "=== NANDA Agent Setup Started: ${AGENT_ID} ===" +date + +# Update system and install dependencies +apt-get update -y +apt-get install -y python3 python3-venv python3-pip git curl + +# Setup project as root (DigitalOcean uses root by default) +cd /root +git clone https://github.com/projnanda/NEST.git nanda-agent-${AGENT_ID} +cd nanda-agent-${AGENT_ID} + +# Create virtual environment and install +python3 -m venv env +bash -c "source env/bin/activate && pip install --upgrade pip && pip install -e . && pip install anthropic" + +# Get public IP using DigitalOcean metadata service +echo "Getting public IP address from metadata service..." +for attempt in {1..10}; do + PUBLIC_IP=$(curl -s --connect-timeout 5 --max-time 10 http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address 2>/dev/null) + + if [ -n "$PUBLIC_IP" ] && [[ $PUBLIC_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Retrieved public IP: $PUBLIC_IP" + break + fi + echo "Attempt $attempt failed, retrying..." + sleep 3 +done + +if [ -z "$PUBLIC_IP" ]; then + echo "ERROR: Could not retrieve public IP after 10 attempts" + exit 1 +fi + +# Start the agent with all configuration +echo "Starting NANDA agent with PUBLIC_URL: http://$PUBLIC_IP:${PORT}" +bash -c " + cd /root/nanda-agent-${AGENT_ID} + source env/bin/activate + export ANTHROPIC_API_KEY='${ANTHROPIC_API_KEY}' + export AGENT_ID='${AGENT_ID}' + export AGENT_NAME='${AGENT_NAME}' + export AGENT_DOMAIN='${DOMAIN}' + export AGENT_SPECIALIZATION='${SPECIALIZATION}' + export AGENT_DESCRIPTION='${DESCRIPTION}' + export AGENT_CAPABILITIES='${CAPABILITIES}' + export REGISTRY_URL='${REGISTRY_URL}' + export PUBLIC_URL='http://$PUBLIC_IP:${PORT}' + export PORT='${PORT}' + nohup python3 examples/nanda_agent.py > agent.log 2>&1 & +" + +echo "=== NANDA Agent Setup Complete: ${AGENT_ID} ===" +echo "Agent URL: http://$PUBLIC_IP:${PORT}/a2a" +USERDATA_EOF + +# Substitute variables in user data +sed -i.bak \ + -e "s|\${AGENT_ID}|$AGENT_ID|g" \ + -e "s|\${ANTHROPIC_API_KEY}|$ANTHROPIC_API_KEY|g" \ + -e "s|\${AGENT_NAME}|$AGENT_NAME|g" \ + -e "s|\${DOMAIN}|$DOMAIN|g" \ + -e "s|\${SPECIALIZATION}|$SPECIALIZATION|g" \ + -e "s|\${DESCRIPTION}|$DESCRIPTION|g" \ + -e "s|\${CAPABILITIES}|$CAPABILITIES|g" \ + -e "s|\${REGISTRY_URL}|$REGISTRY_URL|g" \ + -e "s|\${PORT}|$PORT|g" \ + "user_data_${AGENT_ID}_${DEPLOYMENT_ID}.sh" + +# Launch droplet +echo "[5/7] Launching DigitalOcean droplet..." +DROPLET_ID=$(doctl compute droplet create "nanda-agent-$AGENT_ID" \ + --region "$REGION" \ + --size "$DROPLET_SIZE" \ + --image "$IMAGE_SLUG" \ + --ssh-keys "$SSH_KEY_ID" \ + --user-data-file "user_data_${AGENT_ID}_${DEPLOYMENT_ID}.sh" \ + --tag-names "NANDA,agent,single" \ + --format ID --no-header \ + --wait) + +echo "โœ… Droplet created: $DROPLET_ID" + +# Wait for droplet to be active and get IP +echo "[6/7] Waiting for droplet to be active..." +sleep 10 + +PUBLIC_IP=$(doctl compute droplet get "$DROPLET_ID" --format PublicIPv4 --no-header) +echo "โœ… Public IP: $PUBLIC_IP" + +# Attach firewall to droplet +doctl compute firewall add-droplets "$FIREWALL_ID" --droplet-ids "$DROPLET_ID" +echo "โœ… Firewall attached to droplet" + +echo "[7/7] Waiting for agent deployment (2-3 minutes)..." +sleep 120 + +# Cleanup +rm "user_data_${AGENT_ID}_${DEPLOYMENT_ID}.sh" "user_data_${AGENT_ID}_${DEPLOYMENT_ID}.sh.bak" + +echo "" +echo "๐ŸŽ‰ NANDA Agent Deployment Complete!" +echo "==================================" +echo "Droplet ID: $DROPLET_ID" +echo "Public IP: $PUBLIC_IP" +echo "Agent URL: http://$PUBLIC_IP:$PORT/a2a" +echo "Firewall ID: $FIREWALL_ID" +echo "" +echo "๐Ÿค– Agent ID for A2A Communication: ${AGENT_ID}-[6-char-hex]" +echo "" +echo "๐Ÿ“ž Use this agent in A2A messages:" +echo " @${AGENT_ID}-[hex] your message here" +echo " (The actual hex suffix is generated at runtime)" + +echo "" +echo "๐Ÿงช Test your agent (direct communication):" +echo "curl -X POST http://$PUBLIC_IP:$PORT/a2a \\" +echo " -H \"Content-Type: application/json\" \\" +echo " -d '{\"content\":{\"text\":\"Hello! What can you help me with?\",\"type\":\"text\"},\"role\":\"user\",\"conversation_id\":\"test123\"}'" + +echo "" +echo "๐Ÿ” SSH Access:" +echo "ssh -i ${SSH_KEY_NAME} root@$PUBLIC_IP" +echo "" +echo "๐Ÿ“Š View agent logs:" +echo "ssh -i ${SSH_KEY_NAME} root@$PUBLIC_IP 'tail -f /root/nanda-agent-${AGENT_ID}/agent.log'" +echo "" +echo "๐Ÿ›‘ To terminate:" +echo "doctl compute droplet delete $DROPLET_ID" +echo "doctl compute firewall delete $FIREWALL_ID"