From 59a3597061dcc9dad13aa8b1c46800fccdda26e1 Mon Sep 17 00:00:00 2001 From: Rahul Sohandani Date: Wed, 22 Oct 2025 14:44:40 -0400 Subject: [PATCH 1/2] feat: Azure multi-cloud deployment with reorganized structure Azure deployment features: - Single agent deployment script for Azure VMs - Multi-agent deployment with supervisor management (multiple agents per VM) - Multi-region deployment across Azure regions - Base64-encoded API keys for security - Quota checking and public IP reuse support - Clean cloud-init YAML generation with Python templating Project reorganization: - Moved AWS scripts into scripts/aws/ directory - Moved Azure scripts into scripts/azure/ directory - Updated all READMEs with multi-cloud documentation - Updated .gitignore for cloud-init temp files --- .gitignore | 5 +- README.md | 83 ++-- scripts/README.md | 178 +++++++-- scripts/aws/README.md | 303 +++++++++++++++ scripts/{ => aws}/deploy-agent.sh | 0 .../multi-agent-deployment.sh} | 0 .../single-agent-deployment.sh} | 0 scripts/azure/README.md | 352 +++++++++++++++++ scripts/azure/multi-agent-deployment.sh | 354 ++++++++++++++++++ scripts/azure/multi-region-deployment.sh | 102 +++++ scripts/azure/single-agent-deployment.sh | 339 +++++++++++++++++ 11 files changed, 1658 insertions(+), 58 deletions(-) create mode 100644 scripts/aws/README.md rename scripts/{ => aws}/deploy-agent.sh (100%) rename scripts/{aws-multi-agent-deployment.sh => aws/multi-agent-deployment.sh} (100%) rename scripts/{aws-single-agent-deployment.sh => aws/single-agent-deployment.sh} (100%) create mode 100644 scripts/azure/README.md create mode 100755 scripts/azure/multi-agent-deployment.sh create mode 100755 scripts/azure/multi-region-deployment.sh create mode 100755 scripts/azure/single-agent-deployment.sh diff --git a/.gitignore b/.gitignore index 26ac513..b883ba8 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,8 @@ test_logs/ *.swp *.swo *~ +AGENTS.md +.github/ # macOS .DS_Store @@ -81,4 +83,5 @@ out.log # Temporary files *.tmp *.temp -.cache/ \ No newline at end of file +.cache/ +test* \ No newline at end of file diff --git a/README.md b/README.md index 325a37e..e0cdad8 100644 --- a/README.md +++ b/README.md @@ -15,53 +15,63 @@ A production-ready framework for deploying and managing specialized AI agents wi ## Quick Start -### Deploy a Single Agent +### Deploy on AWS ```bash -bash scripts/aws-single-agent-deployment.sh \ - "agent-id" \ # Unique identifier - "your-api-key" \ # Anthropic Claude API key - "Agent Name" \ # Display name - "domain" \ # Field of expertise - "specialization" \ # Role description - "description" \ # Detailed agent description - "capabilities" \ # Comma-separated capabilities - "registry-url" \ # Registry URL - "port" \ # Port number - "region" \ # AWS region - "instance-type" # EC2 instance type +# Single agent deployment +bash scripts/aws/single-agent-deployment.sh \ + "agent-id" "anthropic-api-key" "Agent Name" "domain" \ + "specialization" "description" "capabilities" "smithery-api-key" \ + "registry-url" "mcp-registry-url" "port" "region" "instance-type" + +# Multi-agent deployment +bash scripts/aws/multi-agent-deployment.sh \ + "anthropic-api-key" "agent-config-json" "smithery-api-key" \ + "registry-url" "mcp-registry-url" "region" "instance-type" ``` -**Example:** +### Deploy on Google Cloud Platform (GCP) + +```bash +# Single agent deployment +bash scripts/gcp/single-agent-deployment.sh \ + "agent-id" "anthropic-api-key" "Agent Name" "domain" \ + "specialization" "description" "capabilities" "smithery-api-key" \ + "registry-url" "mcp-registry-url" "port" "zone" "machine-type" + +# Multi-agent deployment +bash scripts/gcp/multi-agent-deployment.sh \ + "anthropic-api-key" "agent-config-json" "smithery-api-key" \ + "registry-url" "mcp-registry-url" "zone" "machine-type" +``` + +**Example (AWS):** + ```bash -bash scripts/aws-single-agent-deployment.sh \ - "furniture-expert" \ - "sk-ant-api03-..." \ - "Furniture Expert" \ - "furniture and interior design" \ - "knowledgeable furniture specialist" \ +bash scripts/aws/single-agent-deployment.sh \ + "furniture-expert" "sk-ant-api03-..." "Furniture Expert" \ + "furniture and interior design" "knowledgeable furniture specialist" \ "I help with furniture selection and interior design" \ - "furniture,interior design,decor" \ - "http://registry.chat39.com:6900" \ - "6000" \ - "us-east-1" \ - "t3.micro" + "furniture,interior design,decor" "smithery-key-123..." \ + "http://registry.chat39.com:6900" "https://mcp-registry.ngrok.app" \ + "6000" "us-east-1" "t3.micro" ``` -### Deploy Multiple Agents (10 per instance) +**Example (GCP):** ```bash -bash scripts/aws-multi-agent-deployment.sh \ - "your-api-key" \ - "scripts/agent_configs/group-01-business-and-finance-experts.json" \ - "http://registry.chat39.com:6900" \ - "us-east-1" \ - "t3.xlarge" +bash scripts/gcp/single-agent-deployment.sh \ + "gcp-data-scientist" "sk-ant-api03-..." "GCP Data Scientist" \ + "data analysis" "analytical AI assistant" \ + "I specialize in data analysis on GCP" \ + "data,analytics,gcp,bigquery" "smithery-key-123..." \ + "http://registry.chat39.com:6900" "https://mcp-registry.ngrok.app" \ + "6000" "us-central1-a" "e2-micro" ``` ## Architecture -``` +```text NEST/ ├── nanda_core/ # Core framework │ ├── core/ @@ -125,6 +135,7 @@ Pre-configured agent groups for quick deployment: ## Monitoring Each deployed agent includes: + - **Health checks** on startup - **Automatic registry registration** - **Process management** with supervisor @@ -145,6 +156,7 @@ Each deployed agent includes: ### Agent Personality Configuration Agents are configured with: + - **Domain**: Primary area of expertise - **Specialization**: Specific role and personality - **Description**: Detailed background for system prompt @@ -153,6 +165,7 @@ Agents are configured with: ## Testing ### Test Single Agent + ```bash curl -X POST http://agent-ip:{PORT}/a2a \ -H "Content-Type: application/json" \ @@ -160,6 +173,7 @@ curl -X POST http://agent-ip:{PORT}/a2a \ ``` ### Test A2A Communication + ```bash curl -X POST http://agent-a-ip:{PORT}/a2a \ -H "Content-Type: application/json" \ @@ -191,6 +205,7 @@ MIT License - see LICENSE file for details. ## Support For issues and questions: + - Create an issue in this repository - Check the documentation in `/scripts/README.md` - Review example configurations in `/scripts/` @@ -198,4 +213,4 @@ For issues and questions: --- **Built by Project NANDA** -[Visit Project NANDA](https://github.com/projnanda) | [NEST Repository](https://github.com/projnanda/NEST) \ No newline at end of file +[Visit Project NANDA](https://github.com/projnanda) | [NEST Repository](https://github.com/projnanda/NEST) diff --git a/scripts/README.md b/scripts/README.md index 63f36d3..86e7553 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,57 +1,189 @@ # 🚀 NANDA Agent Deployment Scripts -Production-ready scripts for deploying NANDA agents to AWS EC2. +Production-ready scripts for deploying NANDA agents across multiple cloud platforms. -## 📋 Available Scripts +## ☁️ Multi-Cloud Support -### 🤖 Single Agent Deployment -**`aws-single-agent-deployment.sh`** - Deploy one specialized agent to one EC2 instance +Deploy NANDA agents on your preferred cloud provider: + +| Platform | Directory | Status | Documentation | +|----------|-----------|--------|---------------| +| **AWS** | `aws/` | ✅ Production Ready | [AWS README](aws/README.md) | +| **GCP** | `gcp/` | ✅ Production Ready | [GCP README](gcp/README.md) | +| **Azure** | `azure/` | ✅ Production Ready | [Azure README](azure/README.md) | +Each platform supports: +- 🤖 **Single Agent Deployment** - One agent per VM/instance +- 🏭 **Multi-Agent Deployment** - Multiple agents on one VM (supervisor-managed) +- 🌍 **Multi-Region Deployment** - Deploy across multiple regions + +--- + +## Quick Start + +### AWS Deployment ```bash -bash aws-single-agent-deployment.sh [REGISTRY_URL] [PORT] [REGION] [INSTANCE_TYPE] +cd aws +bash single-agent-deployment.sh "agent-id" "sk-ant-..." "Agent Name" ``` -**Example:** +### GCP Deployment ```bash -bash aws-single-agent-deployment.sh \ +cd gcp +bash single-agent-deployment.sh "agent-id" "sk-ant-..." "Agent Name" +``` + +### Azure Deployment +```bash +cd azure +bash single-agent-deployment.sh "agent-id" "sk-ant-..." "Agent Name" +``` + +## 📋 Cloud-Specific Features + +### AWS (`aws/`) +- ✅ EC2 instance deployment +- ✅ Security groups auto-configuration +- ✅ IMDSv2 for metadata retrieval +- ✅ Supervisor-based multi-agent management +- ✅ Automatic key pair generation + +### GCP (`gcp/`) +- ✅ Compute Engine deployment +- ✅ Firewall rules auto-configuration +- ✅ Metadata service integration +- ✅ Supervisor-based multi-agent management +- ✅ SSH key management + +### Azure (`azure/`) +- ✅ Virtual Machine deployment +- ✅ Network Security Groups (NSG) +- ✅ Virtual network auto-setup +- ✅ Cloud-init configuration +- ✅ Systemd/supervisor service management + +--- + +## 📋 Script Types (Available on All Platforms) + +### 🤖 Single Agent Deployment +Deploy one specialized agent to one VM/instance + +**Example (AWS):** +```bash +cd aws +bash single-agent-deployment.sh \ "data-scientist" \ "sk-ant-api03-..." \ "Data Scientist" \ + "main" \ "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" \ + "python,statistics,machine learning" \ + "" \ "http://registry.chat39.com:6900" \ - "6000" \ - "us-east-1" \ - "t3.micro" + "" \ + 6000 \ + us-east-1 \ + t3.micro ``` -### 🏭 Multi-Agent Deployment -**`aws-multi-agent-deployment.sh`** - Deploy 10 agents to one EC2 instance +**Example (GCP):** +```bash +cd gcp +bash single-agent-deployment.sh \ + "data-scientist" \ + "sk-ant-api03-..." \ + "Data Scientist" \ + "main" \ + "data analysis" \ + "expert data analyst" \ + "python,statistics" \ + "" \ + "http://registry.chat39.com:6900" \ + "" \ + 6000 \ + us-central1-a \ + e2-micro +``` +**Example (Azure):** ```bash -bash aws-multi-agent-deployment.sh [REGISTRY_URL] [REGION] [INSTANCE_TYPE] +cd azure +bash single-agent-deployment.sh \ + "data-scientist" \ + "sk-ant-api03-..." \ + "Data Scientist" \ + "main" \ + "data analysis" \ + "python,statistics" \ + "" \ + "http://registry.chat39.com:6900" \ + "" \ + 6000 \ + eastus \ + Standard_B1s ``` -**Example:** +### 🏭 Multi-Agent Deployment +Deploy multiple agents (typically 10) to one VM/instance with supervisor management + +**Example (AWS):** ```bash -bash aws-multi-agent-deployment.sh \ +cd aws +bash multi-agent-deployment.sh \ "sk-ant-api03-..." \ - "agent_configs/group-01-business-and-finance-experts.json" \ + "../agent_configs/group-01-business-and-finance-experts.json" \ "http://registry.chat39.com:6900" \ "us-east-1" \ - "t3.xlarge" + "t3.large" ``` -### 🖥️ Existing Server Deployment -**`deploy-agent.sh`** - Deploy agent to existing Ubuntu/Amazon Linux server +**Example (GCP):** +```bash +cd gcp +bash multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "../agent_configs/group-01-business-and-finance-experts.json" \ + "" \ + "http://registry.chat39.com:6900" \ + "" \ + "us-central1-a" \ + "e2-standard-4" +``` +**Example (Azure):** ```bash -bash deploy-agent.sh [PORT] [REGISTRY_URL] +cd azure +bash multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "../agent_configs/group-01-business-and-finance-experts.json" \ + "http://registry.chat39.com:6900" \ + "" \ + "eastus" \ + "Standard_B4ms" +``` + +### 🌍 Multi-Region Deployment +Deploy agent groups across multiple regions for geographic distribution + +**Example (GCP):** +```bash +cd gcp +bash multi-region-deployment.sh \ + "sk-ant-api03-..." \ + '[{"region":"us-central1-a","config":"../agent_configs/group-01.json"},{"region":"us-west1-b","config":"../agent_configs/group-02.json"}]' +``` + +**Example (Azure):** +```bash +cd azure +bash multi-region-deployment.sh \ + "sk-ant-api03-..." \ + '[{"region":"eastus","config":"../agent_configs/group-01.json"},{"region":"westus","config":"../agent_configs/group-02.json"}]' ``` -## 📦 Pre-configured Agent Groups +--- Ready-to-deploy agent configurations: diff --git a/scripts/aws/README.md b/scripts/aws/README.md new file mode 100644 index 0000000..5bc6d67 --- /dev/null +++ b/scripts/aws/README.md @@ -0,0 +1,303 @@ +# AWS Deployment Scripts for NANDA Agents + +This directory contains Amazon Web Services (AWS) deployment scripts for NANDA agents with full MCP (Model Context Protocol) integration. + +## Prerequisites + +1. **AWS Account**: Active Amazon Web Services account +2. **AWS CLI**: Installed and configured with credentials +3. **IAM Permissions**: EC2, VPC, and security group management permissions +4. **Key Pair**: SSH key pair for instance access (created automatically) + +### Setup AWS Environment + +```bash +# Install AWS CLI (if not installed) +# Follow: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html + +# Configure AWS credentials +aws configure +# Enter your Access Key ID, Secret Access Key, Default region, and output format + +# Verify configuration +aws sts get-caller-identity +``` + +## Scripts Overview + +### Single Agent Deployment (`single-agent-deployment.sh`) + +Deploy a single NANDA agent on AWS EC2 with full MCP support. + +**Usage:** +```bash +bash scripts/aws/single-agent-deployment.sh \ + "agent-id" \ + "anthropic-api-key" \ + "Agent Name" \ + "domain" \ + "specialization" \ + "description" \ + "capabilities" \ + "smithery-api-key" \ + "registry-url" \ + "mcp-registry-url" \ + "port" \ + "region" \ + "instance-type" +``` + +**Example:** +```bash +bash scripts/aws/single-agent-deployment.sh \ + "aws-data-scientist" \ + "sk-ant-api03-..." \ + "AWS Data Scientist" \ + "data analysis" \ + "analytical and precise AI assistant" \ + "I specialize in data analysis on AWS" \ + "data,analytics,aws,sagemaker" \ + "smithery-key-123..." \ + "http://registry.chat39.com:6900" \ + "https://mcp-registry.ngrok.app" \ + "6000" \ + "us-east-1" \ + "t3.micro" +``` + +### Multi-Agent Deployment (`multi-agent-deployment.sh`) + +Deploy multiple NANDA agents on a single AWS EC2 instance with supervisor process management. + +**Usage:** +```bash +bash scripts/aws/multi-agent-deployment.sh \ + "anthropic-api-key" \ + "agent-config-json" \ + "smithery-api-key" \ + "registry-url" \ + "mcp-registry-url" \ + "region" \ + "instance-type" +``` + +**Example:** +```bash +bash scripts/aws/multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "scripts/agent_configs/group-01-business-and-finance-experts.json" \ + "smithery-key-123..." \ + "http://registry.chat39.com:6900" \ + "https://mcp-registry.ngrok.app" \ + "us-east-1" \ + "t3.xlarge" +``` + +## AWS-Specific Features + +### Instance Types + +- **t3.micro**: Free tier eligible, single agent +- **t3.small**: 1-2 agents, light workloads +- **t3.medium**: 3-5 agents +- **t3.large/xlarge**: 5-10+ agents, recommended for multi-agent deployments + +### Networking + +- **Security Groups**: Automatically created with required ports (SSH + agent ports) +- **VPC**: Uses default VPC with public subnets +- **Elastic IP**: Public IP automatically assigned +- **Internet Gateway**: Required for agent communication + +### Storage + +- **EBS Volumes**: GP3 storage with auto-delete enabled +- **Root Volume**: 20GB (single) / 50GB (multi-agent) +- **Encryption**: Available but not enabled by default + +### AMI and User Data + +- **Ubuntu 22.04 LTS**: Reliable, well-supported base image +- **User Data Scripts**: Automated installation and configuration +- **IMDSv2**: Secure metadata service for IP retrieval + +## Environment Variables + +All scripts support these environment variables: + +- `ANTHROPIC_API_KEY`: Your Claude API key +- `SMITHERY_API_KEY`: Your Smithery API key for MCP server access +- `AGENT_ID`: Unique agent identifier +- `AGENT_NAME`: Display name for the agent +- `REGISTRY_URL`: NANDA registry endpoint +- `MCP_REGISTRY_URL`: MCP server registry endpoint +- `PUBLIC_URL`: Agent's public URL for A2A communication + +## MCP Integration + +Both scripts include full MCP (Model Context Protocol) support: + +### Smithery MCP Servers +```bash +# Test Smithery MCP integration +curl -X POST http://PUBLIC_IP:PORT/a2a \ + -H "Content-Type: application/json" \ + -d '{"content":{"text":"#smithery:fetch get weather data","type":"text"},"role":"user","conversation_id":"test"}' +``` + +### NANDA MCP Servers +```bash +# Test NANDA MCP integration +curl -X POST http://PUBLIC_IP:PORT/a2a \ + -H "Content-Type: application/json" \ + -d '{"content":{"text":"#nanda:nanda-points get balance","type":"text"},"role":"user","conversation_id":"test"}' +``` + +## Management Commands + +### Instance Management +```bash +# SSH into instance +ssh -i nanda-agent-key.pem ubuntu@PUBLIC_IP + +# View instance details +aws ec2 describe-instances --instance-ids INSTANCE_ID + +# Stop instance +aws ec2 stop-instances --instance-ids INSTANCE_ID + +# Start instance +aws ec2 start-instances --instance-ids INSTANCE_ID + +# Terminate instance +aws ec2 terminate-instances --instance-ids INSTANCE_ID +``` + +### Multi-Agent Management (via SSH) +```bash +# Check agent status +sudo supervisorctl status + +# Restart all agents +sudo supervisorctl restart all + +# Restart specific agent +sudo supervisorctl restart agent_AGENT_ID + +# View agent logs +sudo tail -f /var/log/agent_AGENT_ID.out.log +``` + +## Cost Optimization + +### Free Tier Usage +- Use `t3.micro` instances (750 hours/month free) +- Deploy in regions with free tier availability +- Monitor usage through AWS Cost Explorer + +### Cost Management +```bash +# Set up billing alerts +aws budgets create-budget --account-id ACCOUNT_ID \ + --budget file://budget.json + +# Use Spot instances for cost savings (add to launch config) +--instance-market-options '{"MarketType":"spot","SpotOptions":{"MaxPrice":"0.05"}}' +``` + +## Troubleshooting + +### Common Issues + +1. **Authentication Errors** + ```bash + aws configure list + aws sts get-caller-identity + ``` + +2. **Permission Denied** + - Check IAM permissions for EC2, VPC operations + - Ensure AWS CLI has proper credentials + +3. **Security Group Issues** + ```bash + aws ec2 describe-security-groups --group-ids sg-xxxxx + ``` + +4. **Instance Launch Failures** + ```bash + aws ec2 describe-instances --instance-ids i-xxxxx + aws logs describe-log-groups + ``` + +5. **Agent Not Responding** + ```bash + ssh -i nanda-agent-key.pem ubuntu@PUBLIC_IP + sudo tail -f /var/log/user-data.log + ``` + +## Security Best Practices + +1. **Key Management**: Scripts generate SSH keys automatically +2. **Security Groups**: Minimal port exposure (SSH + required agent ports) +3. **IAM Roles**: Consider using instance profiles instead of access keys +4. **VPC Security**: Consider private subnets with NAT Gateway for production +5. **Secrets**: Use AWS Secrets Manager for production API key management + +## Monitoring and Logging + +### CloudWatch Integration +```bash +# View logs +aws logs describe-log-streams --log-group-name /var/log/user-data + +# Create custom metrics +aws cloudwatch put-metric-data --namespace "NANDA/Agents" \ + --metric-data MetricName=AgentHealth,Value=1 +``` + +### Custom Monitoring +- Agent response times via CloudWatch +- MCP server connection health +- A2A communication success rates + +## Regions and Availability Zones + +### Recommended Regions +- **us-east-1**: Virginia (lowest cost, most services) +- **us-west-2**: Oregon (good performance, lower latency to West Coast) +- **eu-west-1**: Ireland (European operations) +- **ap-southeast-1**: Singapore (Asian operations) + +### Multi-AZ Deployment +```bash +# Deploy across multiple AZs for high availability +bash single-agent-deployment.sh ... us-east-1a +bash single-agent-deployment.sh ... us-east-1b +``` + +## Support + +For AWS-specific issues: +- Check [AWS EC2 documentation](https://docs.aws.amazon.com/ec2/) +- Review [AWS troubleshooting guides](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/troubleshooting.html) +- Monitor [AWS Service Health Dashboard](https://health.aws.amazon.com/health/status) + +For NANDA-specific issues: +- Check agent logs: `/var/log/agent_*.out.log` +- Review user-data logs: `/var/log/user-data.log` +- Test MCP functionality with provided curl commands + +## Advanced Features + +### Auto Scaling Groups +Consider setting up Auto Scaling for production workloads to handle varying demand. + +### Load Balancing +Use Application Load Balancer for distributing traffic across multiple agent instances. + +### CloudFormation +Convert deployment scripts to CloudFormation templates for infrastructure as code. + +### ECS/EKS Deployment +Consider containerizing agents for deployment on ECS or EKS for better scalability. \ No newline at end of file diff --git a/scripts/deploy-agent.sh b/scripts/aws/deploy-agent.sh similarity index 100% rename from scripts/deploy-agent.sh rename to scripts/aws/deploy-agent.sh diff --git a/scripts/aws-multi-agent-deployment.sh b/scripts/aws/multi-agent-deployment.sh similarity index 100% rename from scripts/aws-multi-agent-deployment.sh rename to scripts/aws/multi-agent-deployment.sh diff --git a/scripts/aws-single-agent-deployment.sh b/scripts/aws/single-agent-deployment.sh similarity index 100% rename from scripts/aws-single-agent-deployment.sh rename to scripts/aws/single-agent-deployment.sh diff --git a/scripts/azure/README.md b/scripts/azure/README.md new file mode 100644 index 0000000..59568ab --- /dev/null +++ b/scripts/azure/README.md @@ -0,0 +1,352 @@ +# Azure Deployment Scripts for NANDA Agents + +This directory contains scripts for deploying NANDA agents on Microsoft Azure. + +## Prerequisites + +### 1. Install Azure CLI + +**macOS:** +```bash +brew install azure-cli +``` + +**Linux:** +```bash +curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash +``` + +**Windows:** +Download from: https://aka.ms/installazurecliwindows + +### 2. Login to Azure + +```bash +az login +``` + +### 3. Set Default Subscription (if you have multiple) + +```bash +# List subscriptions +az account list --output table + +# Set default +az account set --subscription "YOUR_SUBSCRIPTION_ID" +``` + +## Scripts Overview + +### 1. `single-agent-deployment.sh` +Deploy a single NANDA agent on an Azure VM. + +**Usage:** +```bash +bash single-agent-deployment.sh \ + \ + \ + \ + [GIT_BRANCH] \ + [SPECIALIZATION] \ + [CAPABILITIES] \ + [SMITHERY_API_KEY] \ + [AGENT_REGISTRY_URL] \ + [MCP_REGISTRY_URL] \ + [PORT] \ + [LOCATION] \ + [VM_SIZE] +``` + +**Example:** +```bash +bash single-agent-deployment.sh \ + "test-agent" \ + "sk-ant-api03-..." \ + "Test Agent" \ + "main" \ + "general assistant" \ + "help,conversation" \ + "" \ + "http://registry.chat39.com:6900" \ + "" \ + 6050 \ + eastus \ + Standard_B2s +``` + +**Parameters:** +- `AGENT_ID`: Unique identifier for the agent +- `ANTHROPIC_API_KEY`: Your Anthropic API key for Claude +- `AGENT_NAME`: Display name for the agent +- `GIT_BRANCH`: Git branch to deploy (default: main) +- `SPECIALIZATION`: Agent's area of expertise +- `CAPABILITIES`: Comma-separated capabilities +- `SMITHERY_API_KEY`: Optional Smithery API key for MCP +- `AGENT_REGISTRY_URL`: URL for agent registry +- `MCP_REGISTRY_URL`: URL for MCP registry +- `PORT`: Port number (must be in allowed ranges) +- `LOCATION`: Azure region (default: eastus) +- `VM_SIZE`: VM size (default: Standard_B2s) + +**Common Azure Regions:** +- `eastus` - East US +- `westus` - West US +- `centralus` - Central US +- `westeurope` - West Europe +- `northeurope` - North Europe +- `southeastasia` - Southeast Asia +- `eastasia` - East Asia + +**Common VM Sizes:** +- `Standard_B1s` - 1 vCPU, 1 GB RAM (basic, low cost) +- `Standard_B2s` - 2 vCPUs, 4 GB RAM (recommended for single agent) +- `Standard_B4ms` - 4 vCPUs, 16 GB RAM (for multi-agent) +- `Standard_D2s_v3` - 2 vCPUs, 8 GB RAM (production single agent) +- `Standard_D4s_v3` - 4 vCPUs, 16 GB RAM (production multi-agent) + +### 2. `multi-agent-deployment.sh` +Deploy multiple NANDA agents on a single Azure VM using supervisor. + +**Usage:** +```bash +bash multi-agent-deployment.sh \ + \ + \ + [AGENT_REGISTRY_URL] \ + [MCP_REGISTRY_URL] \ + [LOCATION] \ + [VM_SIZE] +``` + +**Example:** +```bash +bash multi-agent-deployment.sh \ + "sk-ant-api03-..." \ + "../agent_configs/group-01-business-and-finance-experts.json" \ + "http://registry.chat39.com:6900" \ + "" \ + eastus \ + Standard_B4ms +``` + +**Parameters:** +- `ANTHROPIC_API_KEY`: Your Anthropic API key +- `AGENT_CONFIG_JSON`: Path to agent configuration JSON or JSON string +- `AGENT_REGISTRY_URL`: URL for agent registry +- `MCP_REGISTRY_URL`: URL for MCP registry +- `LOCATION`: Azure region +- `VM_SIZE`: VM size (recommend Standard_B4ms or larger for multiple agents) + +### 3. `multi-region-deployment.sh` +Deploy agent groups across multiple Azure regions. + +**Usage:** +```bash +bash multi-region-deployment.sh \ + \ + \ + [AGENT_REGISTRY_URL] \ + [MCP_REGISTRY_URL] \ + [VM_SIZE] +``` + +**Example:** +```bash +bash multi-region-deployment.sh \ + "sk-ant-api03-..." \ + '[{"region":"eastus","config":"../agent_configs/group-01-business-and-finance-experts.json"},{"region":"westus","config":"../agent_configs/group-02-technology-and-engineering.json"}]' \ + "http://registry.chat39.com:6900" \ + "" \ + Standard_B4ms +``` + +## Agent Configuration Format + +Agent configuration files should be JSON arrays with the following structure: + +```json +[ + { + "agent_id": "agent-identifier", + "agent_name": "Agent Display Name", + "domain": "agent domain", + "specialization": "what the agent specializes in", + "description": "detailed description", + "capabilities": "capability1,capability2,capability3", + "port": 6000 + } +] +``` + +**Port Requirements:** +- Ports must be in allowed ranges: 6000-6100, 7000-7100, 8000-8100, etc. +- Each agent must have a unique port +- See agent_configs directory for examples + +## Monitoring & Management + +### Check Agent Status +```bash +# SSH into the VM +ssh azureuser@ + +# For single agent +sudo systemctl status nanda-agent + +# For multi-agent +sudo supervisorctl status +``` + +### View Logs +```bash +# Single agent +ssh azureuser@ 'sudo journalctl -u nanda-agent -f' + +# Multi-agent +ssh azureuser@ 'sudo tail -f /var/log/agent_*.out.log' +``` + +### Restart Agents +```bash +# Single agent +ssh azureuser@ 'sudo systemctl restart nanda-agent' + +# Multi-agent +ssh azureuser@ 'sudo supervisorctl restart all' +``` + +### List All VMs +```bash +az vm list --resource-group nanda-agents-rg --output table +``` + +### Get VM Details +```bash +az vm show --resource-group nanda-agents-rg --name +``` + +## Cleanup + +### Delete Single VM +```bash +az vm delete --resource-group nanda-agents-rg --name --yes +``` + +### Delete All Resources +```bash +az group delete --name nanda-agents-rg --yes +``` + +This will delete: +- All VMs +- All network interfaces +- All public IPs +- Virtual network +- Network security group + +## Network Configuration + +The scripts automatically create and configure: +- **Resource Group**: `nanda-agents-rg` +- **Virtual Network**: `nanda-agents-vnet` (10.0.0.0/16) +- **Subnet**: `nanda-agents-subnet` (10.0.1.0/24) +- **Network Security Group**: `nanda-agents-nsg` + +**Firewall Rules:** +- SSH (22) - Open to all +- Agent ports (6000-15100 in ranges) - Open to all + +## Cost Optimization + +### VM Sizes by Use Case + +**Development/Testing:** +- Single agent: `Standard_B1s` or `Standard_B2s` +- Multi-agent (3-5): `Standard_B2ms` +- Multi-agent (6-10): `Standard_B4ms` + +**Production:** +- Single agent: `Standard_D2s_v3` +- Multi-agent (3-5): `Standard_D2s_v3` +- Multi-agent (6-10): `Standard_D4s_v3` + +### Auto-shutdown +Set up auto-shutdown to save costs during off-hours: + +```bash +az vm auto-shutdown \ + --resource-group nanda-agents-rg \ + --name \ + --time 1900 \ + --location eastus +``` + +### Spot Instances +For non-critical workloads, use spot instances to save up to 90%: + +```bash +# Add to VM creation +--priority Spot \ +--max-price -1 \ +--eviction-policy Deallocate +``` + +## Troubleshooting + +### VM Creation Fails +- Check subscription quotas: `az vm list-usage --location eastus --output table` +- Verify you have permissions to create VMs +- Try a different region + +### Agents Not Starting +1. Check cloud-init logs: +```bash +ssh azureuser@ 'sudo cat /var/log/cloud-init-output.log' +``` + +2. Check agent service: +```bash +ssh azureuser@ 'sudo systemctl status nanda-agent' +``` + +3. Check agent logs: +```bash +ssh azureuser@ 'sudo journalctl -u nanda-agent -n 100' +``` + +### Connection Timeout +- Verify NSG rules: `az network nsg rule list --resource-group nanda-agents-rg --nsg-name nanda-agents-nsg --output table` +- Check if VM is running: `az vm get-instance-view --resource-group nanda-agents-rg --name ` +- Wait 2-3 minutes after deployment for cloud-init to complete + +## Security Best Practices + +1. **Restrict SSH Access**: Update NSG to allow SSH only from your IP +```bash +az network nsg rule update \ + --resource-group nanda-agents-rg \ + --nsg-name nanda-agents-nsg \ + --name AllowSSH \ + --source-address-prefixes /32 +``` + +2. **Use SSH Keys**: Scripts automatically generate SSH keys (stored in `~/.ssh/`) + +3. **Enable Disk Encryption**: Add to VM creation +```bash +--encryption-at-host true +``` + +4. **Use Azure Key Vault**: Store API keys in Key Vault instead of passing as parameters + +## Support + +For issues or questions: +- Check Azure documentation: https://docs.microsoft.com/azure/ +- Review deployment logs +- Check agent logs on the VM +- Verify network connectivity + +## License + +Part of the NANDA Agent Framework - See LICENSE in project root diff --git a/scripts/azure/multi-agent-deployment.sh b/scripts/azure/multi-agent-deployment.sh new file mode 100755 index 0000000..ad04edf --- /dev/null +++ b/scripts/azure/multi-agent-deployment.sh @@ -0,0 +1,354 @@ +#!/bin/bash + +# Azure Multi-Agent Deployment Script +# Deploys multiple NANDA agents on a single Azure VM managed by supervisor + +set -e + +# Trap to clean up cloud-init file on error or exit +cleanup() { + if [ -n "$DEPLOYMENT_ID" ] && [ -f "cloud-init-${DEPLOYMENT_ID}.yaml" ]; then + rm -f "cloud-init-${DEPLOYMENT_ID}.yaml" + fi +} +trap cleanup EXIT ERR + +# Color codes for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Parse arguments +ANTHROPIC_API_KEY="$1" +AGENT_CONFIG_JSON="$2" +LOCATION="${3:-centralindia}" +SMITHERY_API_KEY="${4:-}" +AGENT_REGISTRY_URL="${5:-http://registry.chat39.com:6900}" +MCP_REGISTRY_URL="${6:-http://registry.chat39.com:7878}" +VM_SIZE="${7:-Standard_B2s}" +PUBLIC_IP_NAME="${8:-}" + +if [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$AGENT_CONFIG_JSON" ]; then + echo -e "${RED}ERROR: Usage: $0 [LOCATION] [SMITHERY_API_KEY] [AGENT_REGISTRY_URL] [MCP_REGISTRY_URL] [VM_SIZE] [PUBLIC_IP_NAME]${NC}" + echo "" + echo "Example:" + echo " $0 sk-ant-xxx scripts/agent_configs/test-3-agents.json centralindia smth-xxx http://registry.chat39.com:6900 http://registry.chat39.com:7878 Standard_B2s" + 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 port configuration +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 -e "${RED}ERROR: Duplicate ports found: $DUPLICATE_PORTS${NC}" + exit 1 +fi + +echo -e "${GREEN}OK: All ports are in allowed ranges${NC}" + +# Extract port list for NSG rules +AGENT_PORT_LIST=$(echo "$AGENTS_JSON" | python3 -c " +import json, sys +agents = json.load(sys.stdin) +print(' '.join(str(agent['port']) for agent in agents)) +") + +# Configuration +RESOURCE_GROUP="nanda-agents-rg" +NSG_NAME="nanda-agents-nsg" +VNET_NAME="nanda-agents-vnet" +SUBNET_NAME="nanda-agents-subnet" +DEPLOYMENT_ID=$(date +%Y%m%d-%H%M%S) +VM_NAME="nanda-multi-${DEPLOYMENT_ID}" + +# Clean up old cloud-init files (older than 1 day) +find . -maxdepth 1 -name "cloud-init-*.yaml" -type f -mtime +1 -delete 2>/dev/null || true + +# [1/7] Check Azure CLI +echo -e "${YELLOW}[1/7] Checking Azure CLI...${NC}" +if ! command -v az >/dev/null 2>&1; then + echo -e "${RED}❌ Azure CLI not installed. Install from https://learn.microsoft.com/cli/azure/install-azure-cli${NC}" + exit 1 +fi + +if ! az account show >/dev/null 2>&1; then + echo -e "${RED}❌ Not logged in to Azure. Run 'az login' first.${NC}" + exit 1 +fi + +SUBSCRIPTION_ID=$(az account show --query id -o tsv) +echo -e "${GREEN}✅ Using Azure subscription: $SUBSCRIPTION_ID${NC}" + +# [2/7] Ensure resource group +echo -e "${YELLOW}[2/7] Ensuring resource group exists...${NC}" +if ! az group show --name "$RESOURCE_GROUP" >/dev/null 2>&1; then + echo "Creating resource group $RESOURCE_GROUP in $LOCATION..." + az group create --name "$RESOURCE_GROUP" --location "$LOCATION" --output none +fi +echo -e "${GREEN}✅ Resource group ready: $RESOURCE_GROUP${NC}" + +# [3/7] Ensure network security group and rules +echo -e "${YELLOW}[3/7] Ensuring network security group exists...${NC}" +if ! az network nsg show --resource-group "$RESOURCE_GROUP" --name "$NSG_NAME" >/dev/null 2>&1; then + echo "Creating network security group $NSG_NAME..." + az network nsg create --resource-group "$RESOURCE_GROUP" --name "$NSG_NAME" --location "$LOCATION" --output none + az network nsg rule create --resource-group "$RESOURCE_GROUP" --nsg-name "$NSG_NAME" --name "AllowSSH" --priority 1000 --source-address-prefixes '*' --destination-port-ranges 22 --access Allow --protocol Tcp --output none +fi + +PRIORITY=2000 +for PORT in $AGENT_PORT_LIST; do + RULE_NAME="AllowAgentPort${PORT}" + if ! az network nsg rule show --resource-group "$RESOURCE_GROUP" --nsg-name "$NSG_NAME" --name "$RULE_NAME" >/dev/null 2>&1; then + az network nsg rule create \ + --resource-group "$RESOURCE_GROUP" \ + --nsg-name "$NSG_NAME" \ + --name "$RULE_NAME" \ + --priority $PRIORITY \ + --source-address-prefixes '*' \ + --destination-port-ranges "$PORT" \ + --access Allow \ + --protocol Tcp \ + --output none + PRIORITY=$((PRIORITY + 1)) + fi +done +echo -e "${GREEN}✅ Network security group ready: $NSG_NAME${NC}" + +# [4/7] Ensure virtual network and subnet +echo -e "${YELLOW}[4/7] Ensuring virtual network and subnet exist...${NC}" +if ! az network vnet show --resource-group "$RESOURCE_GROUP" --name "$VNET_NAME" >/dev/null 2>&1; then + echo "Creating virtual network $VNET_NAME..." + az network vnet create \ + --resource-group "$RESOURCE_GROUP" \ + --name "$VNET_NAME" \ + --address-prefix 10.0.0.0/16 \ + --subnet-name "$SUBNET_NAME" \ + --subnet-prefix 10.0.1.0/24 \ + --location "$LOCATION" \ + --output none +fi + +az network vnet subnet update \ + --resource-group "$RESOURCE_GROUP" \ + --vnet-name "$VNET_NAME" \ + --name "$SUBNET_NAME" \ + --network-security-group "$NSG_NAME" \ + --output none +echo -e "${GREEN}✅ Virtual network ready: $VNET_NAME / $SUBNET_NAME${NC}" + +# [5/7] Create cloud-init configuration +echo -e "${YELLOW}[5/7] Creating cloud-init configuration...${NC}" + +# Create the setup script as a separate file first +cat > "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" <<'SETUPSCRIPT' +#!/bin/bash +exec > /var/log/cloud-init-output.log 2>&1 +echo "=== NANDA Multi-Agent Setup Started: DEPLOYMENT_ID_PLACEHOLDER ===" +date + +cd /home/azureuser +if [ ! -d nanda-multi-agents ]; then + sudo -u azureuser git clone https://github.com/projnanda/NEST.git nanda-multi-agents +fi +cd nanda-multi-agents +sudo -u azureuser git fetch --all || true +sudo -u azureuser git checkout main || true +sudo -u azureuser git pull origin main || true + +sudo -u azureuser python3 -m venv env +sudo -u azureuser bash -c "source env/bin/activate && pip install --upgrade pip && pip install -e . && pip install anthropic" + +PUBLIC_IP="" +PUBLIC_IP=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2021-02-01&format=text" 2>/dev/null || true) +if [ -z "${PUBLIC_IP}" ]; then + PUBLIC_IP=$(curl -s --max-time 10 https://api.ipify.org 2>/dev/null || true) +fi +if [ -z "${PUBLIC_IP}" ]; then + PUBLIC_IP=$(curl -s --max-time 10 https://ifconfig.me/ip 2>/dev/null || true) +fi +if [ -z "${PUBLIC_IP}" ]; then + PUBLIC_IP="0.0.0.0" +fi + +echo "Retrieved public IP: ${PUBLIC_IP}" + +cat > /tmp/agents_config.json <<"AGENTJSONEOF" +AGENTS_JSON_PLACEHOLDER +AGENTJSONEOF + +while IFS= read -r agent_json; do + AGENT_ID=$(echo "$agent_json" | jq -r '.agent_id') + AGENT_NAME=$(echo "$agent_json" | jq -r '.agent_name') + PORT=$(echo "$agent_json" | jq -r '.port') + + HEX_SUFFIX=$(openssl rand -hex 3) + FULL_AGENT_ID="${AGENT_ID}-${HEX_SUFFIX}" + + echo "Starting agent: ${FULL_AGENT_ID} on port ${PORT}" + + sudo -u azureuser bash -c "cd /home/azureuser/nanda-multi-agents && source env/bin/activate && \ + export ANTHROPIC_API_KEY='ANTHROPIC_KEY_PLACEHOLDER' && \ + export AGENT_ID='${FULL_AGENT_ID}' && \ + export AGENT_NAME='${AGENT_NAME}' && \ + export PUBLIC_URL='http://${PUBLIC_IP}:${PORT}' && \ + export PORT='${PORT}' && \ + export REGISTRY_URL='AGENT_REGISTRY_PLACEHOLDER' && \ + export MCP_REGISTRY_URL='MCP_REGISTRY_PLACEHOLDER' && \ + export SMITHERY_API_KEY='SMITHERY_KEY_PLACEHOLDER' && \ + nohup python3 examples/nanda_agent.py > /home/azureuser/agent_${FULL_AGENT_ID}.log 2>&1 &" + +done < <(jq -c '.[]' /tmp/agents_config.json) + +echo "=== NANDA Multi-Agent Setup Complete: DEPLOYMENT_ID_PLACEHOLDER ===" +date +SETUPSCRIPT + +# Replace placeholders in the script +sed -i '' "s|DEPLOYMENT_ID_PLACEHOLDER|${DEPLOYMENT_ID}|g" "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" +sed -i '' "s|ANTHROPIC_KEY_PLACEHOLDER|${ANTHROPIC_API_KEY}|g" "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" +sed -i '' "s|AGENT_REGISTRY_PLACEHOLDER|${AGENT_REGISTRY_URL}|g" "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" +sed -i '' "s|MCP_REGISTRY_PLACEHOLDER|${MCP_REGISTRY_URL}|g" "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" +sed -i '' "s|SMITHERY_KEY_PLACEHOLDER|${SMITHERY_API_KEY}|g" "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" + +# Replace AGENTS_JSON_PLACEHOLDER +python3 < "cloud-init-${DEPLOYMENT_ID}.yaml" < /tmp/nanda_setup.sh + - chmod +x /tmp/nanda_setup.sh + - bash /tmp/nanda_setup.sh +CLOUDEOF + +rm -f "/tmp/nanda_setup_${DEPLOYMENT_ID}.sh" + +# Optional reuse of existing public IP +PUBLIC_IP_ARG=() +if [ -n "$PUBLIC_IP_NAME" ]; then + echo "Attempting to reuse public IP resource: $PUBLIC_IP_NAME" + if az network public-ip show --resource-group "$RESOURCE_GROUP" --name "$PUBLIC_IP_NAME" >/dev/null 2>&1; then + PUBLIC_IP_ARG=(--public-ip-address "$PUBLIC_IP_NAME") + echo "Reusing existing public IP: $PUBLIC_IP_NAME" + else + echo "Warning: Public IP $PUBLIC_IP_NAME not found in $RESOURCE_GROUP. A new IP will be created." + fi +fi + +# [6/7] Create VM +echo -e "${YELLOW}[6/7] Creating Azure VM...${NC}" +VM_CREATE_CMD=( + az vm create + --resource-group "$RESOURCE_GROUP" + --name "$VM_NAME" + --location "$LOCATION" + --size "$VM_SIZE" + --image Ubuntu2204 + --admin-username azureuser + --generate-ssh-keys + --vnet-name "$VNET_NAME" + --subnet "$SUBNET_NAME" + --nsg "$NSG_NAME" + --public-ip-sku Standard +) +if [ ${#PUBLIC_IP_ARG[@]} -gt 0 ]; then + VM_CREATE_CMD+=( "${PUBLIC_IP_ARG[@]}" ) +fi +VM_CREATE_CMD+=( + --custom-data @"cloud-init-${DEPLOYMENT_ID}.yaml" + --tags Project=NANDA Type=MultiAgent DeploymentId="$DEPLOYMENT_ID" + --output none +) +"${VM_CREATE_CMD[@]}" + +echo -e "${GREEN}✅ VM creation requested: $VM_NAME${NC}" + +# [7/7] Retrieve deployment details +echo -e "${YELLOW}[7/7] Retrieving VM details...${NC}" +PUBLIC_IP=$(az vm show -d --resource-group "$RESOURCE_GROUP" --name "$VM_NAME" --query publicIps -o tsv) + +echo "Waiting for agents to start (180 seconds)..." +sleep 180 + +# Cloud-init file will be cleaned up by trap on exit + +# Summary +echo "" +echo -e "${GREEN}🎉 Azure Multi-Agent Deployment Complete${NC}" +echo "=============================================" +echo "Deployment ID: $DEPLOYMENT_ID" +echo "VM Name: $VM_NAME" +echo "Location: $LOCATION" +echo "VM Size: $VM_SIZE" +echo "Public IP: $PUBLIC_IP" +echo "" +echo "🤖 Agent URLs:" +AGENTS_JSON_ENV="$AGENTS_JSON" PUBLIC_IP_SUMMARY="$PUBLIC_IP" python3 - <<'PY' +import json, os +public_ip = os.environ.get('PUBLIC_IP_SUMMARY', '0.0.0.0') +agents = json.loads(os.environ['AGENTS_JSON_ENV']) +for agent in agents: + print(f" {agent['agent_id']}: http://{public_ip}:{agent['port']}/a2a") +PY + +echo "" +echo "📊 Monitor agents:" +echo " ssh azureuser@$PUBLIC_IP 'ps aux | grep nanda_agent'" +echo "" +echo "📋 View logs:" +echo " ssh azureuser@$PUBLIC_IP 'tail -f /home/azureuser/agent_*.log'" +echo "" +echo "🔄 Restart agents (kill and restart):" +echo " ssh azureuser@$PUBLIC_IP 'pkill -f nanda_agent.py; cd /home/azureuser/nanda-multi-agents && source env/bin/activate && nohup python3 examples/nanda_agent.py &'" +echo "" +echo "🛑 Delete VM:" +echo " az vm delete --resource-group $RESOURCE_GROUP --name $VM_NAME --yes" +echo "" +echo "🗑️ Delete resource group:" +echo " az group delete --name $RESOURCE_GROUP --yes" diff --git a/scripts/azure/multi-region-deployment.sh b/scripts/azure/multi-region-deployment.sh new file mode 100755 index 0000000..176499b --- /dev/null +++ b/scripts/azure/multi-region-deployment.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +# Azure Multi-Region Deployment Script +# Deploys agent groups across multiple Azure regions + +set -e + +# Color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Parse arguments +ANTHROPIC_API_KEY="$1" +REGIONS_CONFIG="$2" # JSON array: [{"region":"eastus","config":"group-01.json"}, ...] +AGENT_REGISTRY_URL="${3:-http://registry.chat39.com:6900}" +MCP_REGISTRY_URL="${4:-}" +VM_SIZE="${5:-Standard_B4ms}" + +# Validation +if [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$REGIONS_CONFIG" ]; then + echo -e "${RED}❌ Usage: $0 [AGENT_REGISTRY_URL] [MCP_REGISTRY_URL] [VM_SIZE]${NC}" + echo "" + echo "Example:" + echo " $0 sk-ant-xxx '[{\"region\":\"eastus\",\"config\":\"group-01.json\"},{\"region\":\"westus\",\"config\":\"group-02.json\"}]'" + exit 1 +fi + +# Parse regions config +if [ -f "$REGIONS_CONFIG" ]; then + REGIONS_JSON=$(cat "$REGIONS_CONFIG") +else + REGIONS_JSON="$REGIONS_CONFIG" +fi + +REGION_COUNT=$(echo "$REGIONS_JSON" | python3 -c "import json, sys; print(len(json.load(sys.stdin)))") + +echo -e "${GREEN}🌍 Starting Azure Multi-Region Deployment${NC}" +echo "Regions to deploy: $REGION_COUNT" +echo "" + +# Deployment tracking +DEPLOYMENT_LOG="azure-multi-region-deployment-$(date +%Y%m%d-%H%M%S).log" +DEPLOYMENTS=() + +# Deploy to each region +REGION_INDEX=1 +echo "$REGIONS_JSON" | python3 -c " +import json, sys +regions = json.load(sys.stdin) +for region in regions: + print(f\"{region['region']}|{region['config']}\") +" | while IFS='|' read -r REGION AGENT_CONFIG; do + echo -e "${YELLOW}[$REGION_INDEX/$REGION_COUNT] Deploying to region: $REGION${NC}" + echo "Agent config: $AGENT_CONFIG" + + # Run multi-agent deployment for this region + bash "$(dirname "$0")/multi-agent-deployment.sh" \ + "$ANTHROPIC_API_KEY" \ + "$AGENT_CONFIG" \ + "$AGENT_REGISTRY_URL" \ + "$MCP_REGISTRY_URL" \ + "$REGION" \ + "$VM_SIZE" \ + 2>&1 | tee -a "$DEPLOYMENT_LOG" + + if [ ${PIPESTATUS[0]} -eq 0 ]; then + echo -e "${GREEN}✅ Successfully deployed to $REGION${NC}" + DEPLOYMENTS+=("$REGION:SUCCESS") + else + echo -e "${RED}❌ Failed to deploy to $REGION${NC}" + DEPLOYMENTS+=("$REGION:FAILED") + fi + + echo "" + REGION_INDEX=$((REGION_INDEX + 1)) +done + +# Summary +echo "" +echo -e "${GREEN}🎉 Multi-Region Deployment Complete!${NC}" +echo "======================================" +echo "" +echo "📊 Deployment Summary:" +for deployment in "${DEPLOYMENTS[@]}"; do + IFS=':' read -r region status <<< "$deployment" + if [ "$status" = "SUCCESS" ]; then + echo -e " ${GREEN}✅ $region${NC}" + else + echo -e " ${RED}❌ $region${NC}" + fi +done + +echo "" +echo "📋 Full deployment log: $DEPLOYMENT_LOG" +echo "" +echo "🔍 View all VMs:" +echo " az vm list --resource-group nanda-agents-rg --output table" +echo "" +echo "🗑️ Delete all deployments:" +echo " az group delete --name nanda-agents-rg --yes" diff --git a/scripts/azure/single-agent-deployment.sh b/scripts/azure/single-agent-deployment.sh new file mode 100755 index 0000000..ead684f --- /dev/null +++ b/scripts/azure/single-agent-deployment.sh @@ -0,0 +1,339 @@ +#!/bin/bash + +# Azure Single Agent Deployment Script +# Deploys a single NANDA agent on Azure VM + +set -e + +# Color codes for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Parse arguments +AGENT_ID="$1" # Removed stray 'd' +ANTHROPIC_API_KEY="$2" +AGENT_NAME="$3" +GIT_BRANCH="${4:-main}" +SPECIALIZATION="${5:-general assistant}" +CAPABILITIES="${6:-general,conversation,help}" +SMITHERY_API_KEY="${7:-}" +AGENT_REGISTRY_URL="${8:-http://registry.chat39.com:6900}" +MCP_REGISTRY_URL="${9:-}" +PORT="${10:-6050}" +LOCATION="${11:-eastus}" +VM_SIZE="${12:-Standard_B2s}" + +# Validation +if [ -z "$AGENT_ID" ] || [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$AGENT_NAME" ]; then + echo -e "${RED}❌ Usage: $0 [GIT_BRANCH] [SPECIALIZATION] [CAPABILITIES] [SMITHERY_API_KEY] [AGENT_REGISTRY_URL] [MCP_REGISTRY_URL] [PORT] [LOCATION] [VM_SIZE]${NC}" + echo "" + echo "Example:" + echo " $0 my-agent sk-ant-xxx 'My Agent' main 'coding expert' 'python,debugging' smithery-key http://registry.url http://mcp.url 6050 eastus Standard_B2s" + exit 1 +fi + +# Port validation function +validate_port() { + local port=$1 + # Allowed port ranges: 6000-6100, 7000-7100, 8000-8100, 9000-9100, 10000-10100, 11000-11100, 12000-12100, 13000-13100, 14000-14100, 15000-15100 + if (( (port >= 6000 && port <= 6100) || \ + (port >= 7000 && port <= 7100) || \ + (port >= 8000 && port <= 8100) || \ + (port >= 9000 && port <= 9100) || \ + (port >= 10000 && port <= 10100) || \ + (port >= 11000 && port <= 11100) || \ + (port >= 12000 && port <= 12100) || \ + (port >= 13000 && port <= 13100) || \ + (port >= 14000 && port <= 14100) || \ + (port >= 15000 && port <= 15100) )); then + return 0 + else + return 1 + fi +} + +# Validate port +if ! validate_port "$PORT"; then + echo -e "${RED}❌ Invalid port: $PORT${NC}" + echo "Allowed port ranges: 6000-6100, 7000-7100, 8000-8100, 9000-9100, 10000-10100," + echo " 11000-11100, 12000-12100, 13000-13100, 14000-14100, 15000-15100" + exit 1 +fi + +# Configuration +RESOURCE_GROUP="nanda-agents-rg" +NSG_NAME="nanda-agents-nsg" +VNET_NAME="nanda-agents-vnet" +SUBNET_NAME="nanda-agents-subnet" +VM_NAME="nanda-agent-${AGENT_ID}" +DEPLOYMENT_ID=$(date +%Y%m%d-%H%M%S) + +echo -e "${GREEN}🚀 Starting Azure Single Agent Deployment${NC}" +echo "Agent ID: $AGENT_ID" +echo "Agent Name: $AGENT_NAME" +echo "Port: $PORT" +echo "Location: $LOCATION" +echo "VM Size: $VM_SIZE" +echo "" + +# [1/7] Check Azure CLI +echo -e "${YELLOW}[1/7] Checking Azure CLI...${NC}" +if ! command -v az &> /dev/null; then + echo -e "${RED}❌ Azure CLI not installed. Install from: https://docs.microsoft.com/cli/azure/install-azure-cli${NC}" + exit 1 +fi + +# Check if logged in +if ! az account show &> /dev/null; then + echo -e "${RED}❌ Not logged in to Azure. Run 'az login' first.${NC}" + exit 1 +fi + +SUBSCRIPTION_ID=$(az account show --query id -o tsv) +echo -e "${GREEN}✅ Using Azure subscription: $SUBSCRIPTION_ID${NC}" + +# [2/7] Create or verify resource group +echo -e "${YELLOW}[2/7] Setting up resource group...${NC}" +if ! az group show --name "$RESOURCE_GROUP" &> /dev/null; then + echo "Creating resource group..." + az group create --name "$RESOURCE_GROUP" --location "$LOCATION" --output none +fi +echo -e "${GREEN}✅ Resource group: $RESOURCE_GROUP${NC}" + +# [3/7] Create or verify network security group +echo -e "${YELLOW}[3/7] Setting up network security group...${NC}" +if ! az network nsg show --resource-group "$RESOURCE_GROUP" --name "$NSG_NAME" &> /dev/null; then + echo "Creating network security group..." + az network nsg create \ + --resource-group "$RESOURCE_GROUP" \ + --name "$NSG_NAME" \ + --location "$LOCATION" \ + --output none + + # Add SSH rule + az network nsg rule create \ + --resource-group "$RESOURCE_GROUP" \ + --nsg-name "$NSG_NAME" \ + --name "AllowSSH" \ + --priority 1000 \ + --source-address-prefixes '*' \ + --destination-port-ranges 22 \ + --access Allow \ + --protocol Tcp \ + --output none + + # Add agent port ranges + PRIORITY=1100 + for PORT_RANGE in "6000-6100" "7000-7100" "8000-8100" "9000-9100" "10000-10100" "11000-11100" "12000-12100" "13000-13100" "14000-14100" "15000-15100"; do + az network nsg rule create \ + --resource-group "$RESOURCE_GROUP" \ + --nsg-name "$NSG_NAME" \ + --name "AllowAgentPorts${PORT_RANGE}" \ + --priority $PRIORITY \ + --source-address-prefixes '*' \ + --destination-port-ranges "$PORT_RANGE" \ + --access Allow \ + --protocol Tcp \ + --output none + PRIORITY=$((PRIORITY + 10)) + done + + # Add specific rule for the agent's port (in case it's not in the ranges) + az network nsg rule create \ + --resource-group "$RESOURCE_GROUP" \ + --nsg-name "$NSG_NAME" \ + --name "AllowAgentPort${PORT}" \ + --priority $PRIORITY \ + --source-address-prefixes '*' \ + --destination-port-ranges "$PORT" \ + --access Allow \ + --protocol Tcp \ + --output none 2>/dev/null || echo "Port $PORT rule already exists or in range" +fi +echo -e "${GREEN}✅ Network security group: $NSG_NAME${NC}" + +# [4/7] Create or verify virtual network +echo -e "${YELLOW}[4/7] Setting up virtual network...${NC}" +if ! az network vnet show --resource-group "$RESOURCE_GROUP" --name "$VNET_NAME" &> /dev/null; then + echo "Creating virtual network..." + az network vnet create \ + --resource-group "$RESOURCE_GROUP" \ + --name "$VNET_NAME" \ + --address-prefix 10.0.0.0/16 \ + --subnet-name "$SUBNET_NAME" \ + --subnet-prefix 10.0.1.0/24 \ + --location "$LOCATION" \ + --output none + + # Associate NSG with subnet + az network vnet subnet update \ + --resource-group "$RESOURCE_GROUP" \ + --vnet-name "$VNET_NAME" \ + --name "$SUBNET_NAME" \ + --network-security-group "$NSG_NAME" \ + --output none +fi +echo -e "${GREEN}✅ Virtual network: $VNET_NAME${NC}" + +# [5/7] Create cloud-init configuration +echo -e "${YELLOW}[5/7] Creating cloud-init configuration...${NC}" +cat > "cloud-init-${DEPLOYMENT_ID}.yaml" << EOF +#cloud-config + +package_update: true +package_upgrade: true + +packages: + - python3 + - python3-venv + - python3-pip + - python3-dev + - build-essential + - git + - curl + - jq + +runcmd: + - | + # Log all output + exec > /var/log/cloud-init-output.log 2>&1 + + echo "=== NANDA Agent Setup Started: ${DEPLOYMENT_ID} ===" + date + + # Setup project as the non-root service user (azureuser) - simplified approach + cd /home/azureuser + sudo -u azureuser git clone https://github.com/projnanda/NEST.git nanda-agent-${AGENT_ID} + cd nanda-agent-${AGENT_ID} + + # Fetch all remote branches and ensure we're on the correct branch + echo "Fetching all remote branches..." + sudo -u azureuser git fetch --all + + # Checkout the specified branch + echo "Checking out branch: ${GIT_BRANCH}" + sudo -u azureuser git checkout ${GIT_BRANCH} + sudo -u azureuser git pull origin ${GIT_BRANCH} + echo "Successfully on ${GIT_BRANCH} branch with latest changes" + + # Create virtual environment and install (simplified) + sudo -u azureuser python3 -m venv env + sudo -u azureuser bash -c "source env/bin/activate && pip install --upgrade pip && pip install -e . && pip install anthropic" + + # Get public IP using multiple methods + echo "Getting public IP address..." + PUBLIC_IP="" + + # Try Azure metadata service first + PUBLIC_IP=\$(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2021-02-01&format=text" 2>/dev/null) + + # If that fails, try external service + if [ -z "\$PUBLIC_IP" ]; then + echo "Azure metadata failed, trying external service..." + PUBLIC_IP=\$(curl -s --max-time 10 "https://api.ipify.org" 2>/dev/null) + fi + + # If still no IP, try another service + if [ -z "\$PUBLIC_IP" ]; then + echo "External service failed, trying alternative..." + PUBLIC_IP=\$(curl -s --max-time 10 "https://ifconfig.me/ip" 2>/dev/null) + fi + + if [ -z "\$PUBLIC_IP" ]; then + echo "WARNING: Could not retrieve public IP, using placeholder" + PUBLIC_IP="0.0.0.0" + else + echo "Retrieved public IP: \$PUBLIC_IP" + fi + + # Generate agent ID with hex suffix + HEX_SUFFIX=\$(openssl rand -hex 3) + FULL_AGENT_ID="${AGENT_ID}-\${HEX_SUFFIX}" + + echo "Generated agent_id: \$FULL_AGENT_ID" + + # Start the agent directly (simpler approach like AWS/GCP) + echo "Starting NANDA agent with PUBLIC_URL: http://\${PUBLIC_IP}:${PORT}" + sudo -u azureuser bash -c " + cd /home/azureuser/nanda-agent-${AGENT_ID} + source env/bin/activate + export ANTHROPIC_API_KEY='${ANTHROPIC_API_KEY}' + export AGENT_ID='\${FULL_AGENT_ID}' + export AGENT_NAME='${AGENT_NAME}' + export AGENT_DOMAIN='${AGENT_NAME}' + export AGENT_SPECIALIZATION='${SPECIALIZATION}' + export AGENT_DESCRIPTION='I am ${AGENT_NAME}, specializing in ${SPECIALIZATION}' + export AGENT_CAPABILITIES='${CAPABILITIES}' + export SMITHERY_API_KEY='${SMITHERY_API_KEY}' + export REGISTRY_URL='${AGENT_REGISTRY_URL}' + export MCP_REGISTRY_URL='${MCP_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: ${DEPLOYMENT_ID} ===" + echo "Agent is running at: http://\${PUBLIC_IP}:${PORT}/a2a" + date +EOF + +echo -e "${GREEN}✅ Cloud-init configuration created${NC}" + +# [6/7] Create VM +echo -e "${YELLOW}[6/7] Creating Azure VM...${NC}" +az vm create \ + --resource-group "$RESOURCE_GROUP" \ + --name "$VM_NAME" \ + --location "$LOCATION" \ + --size "$VM_SIZE" \ + --image Ubuntu2204 \ + --admin-username azureuser \ + --generate-ssh-keys \ + --vnet-name "$VNET_NAME" \ + --subnet "$SUBNET_NAME" \ + --nsg "$NSG_NAME" \ + --public-ip-sku Standard \ + --custom-data "cloud-init-${DEPLOYMENT_ID}.yaml" \ + --tags "Project=NANDA" "AgentId=$AGENT_ID" "DeploymentId=$DEPLOYMENT_ID" \ + --output none + +echo -e "${GREEN}✅ VM created: $VM_NAME${NC}" + +# [7/7] Get VM details +echo -e "${YELLOW}[7/7] Retrieving VM details...${NC}" +PUBLIC_IP=$(az vm show -d --resource-group "$RESOURCE_GROUP" --name "$VM_NAME" --query publicIps -o tsv) + +echo "Waiting for agent to start (60 seconds)..." +sleep 60 + +# Cleanup +rm "cloud-init-${DEPLOYMENT_ID}.yaml" + +# Summary +echo "" +echo -e "${GREEN}🎉 Azure Single Agent Deployment Complete!${NC}" +echo "=============================================" +echo "Deployment ID: $DEPLOYMENT_ID" +echo "VM Name: $VM_NAME" +echo "Public IP: $PUBLIC_IP" +echo "Agent URL: http://$PUBLIC_IP:$PORT/a2a" +echo "" +echo "📊 Check agent status:" +echo " ssh azureuser@$PUBLIC_IP 'ps aux | grep nanda_agent'" +echo "" +echo "📋 View agent logs:" +echo " ssh azureuser@$PUBLIC_IP 'tail -f /home/azureuser/nanda-agent-$AGENT_ID/agent.log'" +echo "" +echo "🔄 Restart agent:" +echo " ssh azureuser@$PUBLIC_IP 'pkill -f nanda_agent && cd /home/azureuser/nanda-agent-$AGENT_ID && source env/bin/activate && nohup python3 examples/nanda_agent.py > agent.log 2>&1 &'" +echo "" +echo "🧪 Test agent:" +echo " curl -X POST http://$PUBLIC_IP:$PORT/a2a -H \"Content-Type: application/json\" -d '{\"content\":{\"text\":\"Hello!\",\"type\":\"text\"},\"role\":\"user\",\"conversation_id\":\"test\"}'" +echo "" +echo "🛑 To delete VM:" +echo " az vm delete --resource-group $RESOURCE_GROUP --name $VM_NAME --yes" +echo "" +echo "🗑️ To delete entire resource group:" +echo " az group delete --name $RESOURCE_GROUP --yes" From da5a4285748e683e7746f885c8e9332553b6dc48 Mon Sep 17 00:00:00 2001 From: Rahul Sohandani Date: Tue, 28 Oct 2025 16:33:52 -0400 Subject: [PATCH 2/2] fixed issues --- .gitignore | 3 ++- scripts/azure/README.md | 4 ++-- scripts/azure/multi-agent-deployment.sh | 4 ++-- scripts/azure/single-agent-deployment.sh | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index b883ba8..e32bf5f 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,5 @@ out.log *.tmp *.temp .cache/ -test* \ No newline at end of file +test* +*key* \ No newline at end of file diff --git a/scripts/azure/README.md b/scripts/azure/README.md index 59568ab..541abe1 100644 --- a/scripts/azure/README.md +++ b/scripts/azure/README.md @@ -114,8 +114,8 @@ bash multi-agent-deployment.sh \ \ [AGENT_REGISTRY_URL] \ [MCP_REGISTRY_URL] \ - [LOCATION] \ - [VM_SIZE] + [VM_SIZE] \ + [LOCATION] ``` **Example:** diff --git a/scripts/azure/multi-agent-deployment.sh b/scripts/azure/multi-agent-deployment.sh index ad04edf..e8bdc90 100755 --- a/scripts/azure/multi-agent-deployment.sh +++ b/scripts/azure/multi-agent-deployment.sh @@ -22,7 +22,7 @@ NC='\033[0m' # No Color # Parse arguments ANTHROPIC_API_KEY="$1" AGENT_CONFIG_JSON="$2" -LOCATION="${3:-centralindia}" +LOCATION="${3:-eastus}" SMITHERY_API_KEY="${4:-}" AGENT_REGISTRY_URL="${5:-http://registry.chat39.com:6900}" MCP_REGISTRY_URL="${6:-http://registry.chat39.com:7878}" @@ -33,7 +33,7 @@ if [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$AGENT_CONFIG_JSON" ]; then echo -e "${RED}ERROR: Usage: $0 [LOCATION] [SMITHERY_API_KEY] [AGENT_REGISTRY_URL] [MCP_REGISTRY_URL] [VM_SIZE] [PUBLIC_IP_NAME]${NC}" echo "" echo "Example:" - echo " $0 sk-ant-xxx scripts/agent_configs/test-3-agents.json centralindia smth-xxx http://registry.chat39.com:6900 http://registry.chat39.com:7878 Standard_B2s" + echo " $0 sk-ant-xxx scripts/agent_configs/test-3-agents.json eastus smth-xxx http://registry.chat39.com:6900 http://registry.chat39.com:7878 Standard_B2s" exit 1 fi diff --git a/scripts/azure/single-agent-deployment.sh b/scripts/azure/single-agent-deployment.sh index ead684f..b629448 100755 --- a/scripts/azure/single-agent-deployment.sh +++ b/scripts/azure/single-agent-deployment.sh @@ -12,7 +12,7 @@ YELLOW='\033[1;33m' NC='\033[0m' # No Color # Parse arguments -AGENT_ID="$1" # Removed stray 'd' +AGENT_ID="$1" ANTHROPIC_API_KEY="$2" AGENT_NAME="$3" GIT_BRANCH="${4:-main}"