ai-agenttutorialdeploymentazureapp-servicefunctionsenterprise

Deploying AI Agents to the Cloud - Part 4: Deploying to Azure

By AgentForge Hub8/14/202516 min read
Intermediate
Deploying AI Agents to the Cloud - Part 4: Deploying to Azure

Ad Space

Deploying AI Agents to the Cloud - Part 4: Deploying to Azure

Azure offers a unique value proposition for AI agent deployment, especially for organizations already invested in the Microsoft ecosystem. With seamless integration with Office 365, Teams, and enterprise services, Azure provides deployment options that can make your AI agent a natural extension of existing business workflows.

However, Azure's approach differs significantly from AWS and Vercel. Understanding Azure's service model, pricing structure, and integration patterns is crucial for successful AI agent deployment.

Why Choose Azure for AI Agent Deployment

Enterprise Integration Excellence Azure excels at integrating with Microsoft's business ecosystem:

  • Azure Active Directory: Enterprise-grade identity management
  • Microsoft Teams: Native integration for workplace AI agents
  • Office 365: Direct integration with Word, Excel, PowerPoint, and Outlook
  • Power Platform: Low-code integration with business processes

Hybrid Cloud Capabilities Azure's hybrid approach allows:

  • On-premises integration with Azure Arc
  • Edge computing with Azure IoT Edge
  • Hybrid identity with Azure AD Connect
  • Data residency options for compliance requirements

AI and Cognitive Services Azure provides comprehensive AI services:

  • Azure OpenAI Service: Enterprise-grade OpenAI models
  • Cognitive Services: Pre-built AI capabilities
  • Machine Learning Studio: Custom model training and deployment
  • Bot Framework: Specialized tools for conversational AI

What You'll Learn in This Tutorial

By the end of this tutorial, you'll have:

  • βœ… Complete Azure App Service deployment with enterprise configuration
  • βœ… Azure Functions integration for serverless AI processing
  • βœ… Database integration with Azure SQL and Cosmos DB
  • βœ… Enterprise security with Azure AD and Key Vault
  • βœ… Monitoring and analytics with Application Insights
  • βœ… CI/CD pipeline with Azure DevOps

Estimated Time: 45-50 minutes


Step 1: Understanding Azure's AI Agent Architecture

Azure offers multiple deployment options for AI agents, each with different strengths and use cases.

Azure Deployment Options Comparison

Service Best For Pricing Model Scaling Complexity
App Service Full web applications Fixed monthly cost Manual/Auto Medium
Functions Event-driven processing Pay-per-execution Automatic Low
Container Instances Custom environments Pay-per-second Manual High
Kubernetes Service Complex microservices Infrastructure cost Advanced Very High

Why App Service is Ideal for AI Agents

Always-On Availability Unlike serverless functions, App Service provides always-on hosting that's perfect for AI agents that need to maintain persistent connections (WebSockets, long-polling, etc.).

Integrated Development Tools App Service integrates seamlessly with:

  • Visual Studio Code: Direct deployment from IDE
  • GitHub Actions: Automated CI/CD pipelines
  • Azure DevOps: Enterprise development workflows

Enterprise Security Features

  • Managed Identity: Secure access to Azure services without storing credentials
  • Private Endpoints: Keep your AI agent off the public internet
  • Azure AD Integration: Enterprise authentication and authorization

Azure Architecture for AI Agents

Internet β†’ Azure Front Door β†’ App Service β†’ Azure SQL Database
                          ↓
                    Application Insights (Monitoring)
                          ↓
                    Key Vault (Secrets)
                          ↓
                    Azure OpenAI Service

Step 2: Setting Up Azure Infrastructure

Let's create the Azure infrastructure needed for your AI agent using Azure CLI and ARM templates.

Azure Account Setup and Security

Initial Azure Setup Steps:

  1. Create Azure Account

    • Sign up at azure.microsoft.com
    • Complete identity verification
    • Set up billing and spending limits
  2. Install Azure CLI

    # Windows (using winget)
    winget install Microsoft.AzureCLI
    
    # macOS (using Homebrew)
    brew install azure-cli
    
    # Linux (Ubuntu/Debian)
    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
    
  3. Login and Configure

    # Login to Azure
    az login
    
    # Set default subscription (if you have multiple)
    az account set --subscription "Your Subscription Name"
    
    # Create resource group for your AI agent
    az group create --name ai-agent-rg --location eastus
    

Why Resource Groups Matter: Resource groups in Azure are logical containers that group related resources. This makes it easy to manage, monitor, and delete all resources related to your AI agent as a unit.

Creating App Service for AI Agents

# Create App Service Plan (defines compute resources)
az appservice plan create \
    --name ai-agent-plan \
    --resource-group ai-agent-rg \
    --sku B1 \
    --is-linux

# Create Web App
az webapp create \
    --name your-ai-agent-app \
    --resource-group ai-agent-rg \
    --plan ai-agent-plan \
    --runtime "NODE|18-lts"

App Service Configuration Explanation:

SKU Selection: B1 (Basic) provides 1.75GB RAM and 10GB storage, suitable for development. Production might need S1 (Standard) or P1V2 (Premium) for better performance.

Linux vs Windows: Linux App Service is generally more cost-effective and has better Node.js support.

Runtime Version: Specify the exact Node.js version to ensure consistency between development and production.


Step 3: Database Integration with Azure SQL

AI agents need persistent storage for conversations and user data. Azure SQL provides enterprise-grade database hosting.

Azure SQL Database Setup

Why Azure SQL for AI Agents:

  • Managed Service: Automatic updates, backups, and maintenance
  • Enterprise Security: Advanced threat protection and encryption
  • Elastic Scaling: Automatically adjust performance based on demand
  • Global Distribution: Geo-replication for worldwide performance
# Create Azure SQL Server
az sql server create \
    --name ai-agent-sql-server \
    --resource-group ai-agent-rg \
    --location eastus \
    --admin-user sqladmin \
    --admin-password 'YourSecurePassword123!'

# Create SQL Database
az sql db create \
    --name ai-agent-db \
    --server ai-agent-sql-server \
    --resource-group ai-agent-rg \
    --service-objective Basic \
    --backup-storage-redundancy Local

# Configure firewall to allow Azure services
az sql server firewall-rule create \
    --name AllowAzureServices \
    --server ai-agent-sql-server \
    --resource-group ai-agent-rg \
    --start-ip-address 0.0.0.0 \
    --end-ip-address 0.0.0.0

Database Connection in Node.js

// database/azure-sql-connection.js

const sql = require('mssql');

class AzureSQLConnection {
    constructor() {
        this.config = {
            server: process.env.AZURE_SQL_SERVER,
            database: process.env.AZURE_SQL_DATABASE,
            user: process.env.AZURE_SQL_USER,
            password: process.env.AZURE_SQL_PASSWORD,
            port: 1433,
            
            // Security settings
            options: {
                encrypt: true, // Use encryption
                trustServerCertificate: false // Don't trust self-signed certificates
            },
            
            // Connection pool settings
            pool: {
                max: 10,
                min: 0,
                idleTimeoutMillis: 30000
            }
        };
        
        this.pool = null;
        this.isConnected = false;
    }
    
    async connect() {
        /**
         * Establish connection to Azure SQL Database
         */
        
        try {
            console.log('πŸ”Œ Connecting to Azure SQL Database...');
            
            this.pool = await sql.connect(this.config);
            this.isConnected = true;
            
            console.log('βœ… Connected to Azure SQL Database');
            
            // Test connection with simple query
            const result = await this.pool.request().query('SELECT 1 as test');
            console.log('βœ… Database connection test successful');
            
        } catch (error) {
            console.error('❌ Failed to connect to Azure SQL:', error);
            this.isConnected = false;
            throw error;
        }
    }
    
    async executeQuery(query, parameters = {}) {
        /**
         * Execute SQL query with parameters
         */
        
        if (!this.isConnected) {
            await this.connect();
        }
        
        try {
            const request = this.pool.request();
            
            // Add parameters to prevent SQL injection
            for (const [key, value] of Object.entries(parameters)) {
                request.input(key, value);
            }
            
            const result = await request.query(query);
            return result;
            
        } catch (error) {
            console.error('❌ SQL query failed:', error);
            throw error;
        }
    }
    
    async storeConversation(userId, message, response) {
        /**
         * Store conversation in Azure SQL Database
         */
        
        const query = `
            INSERT INTO conversations (user_id, user_message, ai_response, created_at)
            VALUES (@userId, @message, @response, GETDATE())
        `;
        
        const parameters = {
            userId: userId,
            message: message,
            response: response
        };
        
        try {
            await this.executeQuery(query, parameters);
            console.log(`πŸ’Ύ Conversation stored for user: ${userId}`);
            
        } catch (error) {
            console.error('❌ Failed to store conversation:', error);
            throw error;
        }
    }
}

module.exports = AzureSQLConnection;

Azure SQL Integration Explanation:

Encryption by Default: Azure SQL automatically encrypts connections and can encrypt data at rest with Transparent Data Encryption (TDE).

Connection Pooling: Efficient connection management reduces database load and improves performance.

Parameterized Queries: Using parameters prevents SQL injection attacks, a critical security measure.


Step 4: Implementing Azure Key Vault Integration

Azure Key Vault provides enterprise-grade secret management that's superior to environment variables for production deployments.

Why Azure Key Vault for AI Agents

Enterprise Security

  • Hardware Security Modules (HSM): Keys are protected by FIPS 140-2 Level 2 validated HSMs
  • Access Policies: Fine-grained control over who can access which secrets
  • Audit Logging: Complete audit trail of all secret access
  • Automatic Rotation: Built-in secret rotation capabilities

Compliance Benefits

  • SOC 2 Type II: Key Vault is compliant with major security frameworks
  • GDPR: Supports data residency and privacy requirements
  • HIPAA: Appropriate for healthcare applications

Key Vault Setup and Integration

# Create Key Vault
az keyvault create \
    --name ai-agent-keyvault \
    --resource-group ai-agent-rg \
    --location eastus \
    --sku standard

# Add secrets to Key Vault
az keyvault secret set \
    --vault-name ai-agent-keyvault \
    --name "OpenAI-API-Key" \
    --value "your-openai-api-key-here"

az keyvault secret set \
    --vault-name ai-agent-keyvault \
    --name "Database-Connection-String" \
    --value "your-database-connection-string"

# Grant App Service access to Key Vault
az webapp identity assign \
    --name your-ai-agent-app \
    --resource-group ai-agent-rg

# Get the managed identity principal ID
PRINCIPAL_ID=$(az webapp identity show \
    --name your-ai-agent-app \
    --resource-group ai-agent-rg \
    --query principalId --output tsv)

# Grant Key Vault access to the managed identity
az keyvault set-policy \
    --name ai-agent-keyvault \
    --object-id $PRINCIPAL_ID \
    --secret-permissions get list

Key Vault Integration in Code

// security/azure-key-vault.js

const { DefaultAzureCredential } = require('@azure/identity');
const { SecretClient } = require('@azure/keyvault-secrets');

class AzureKeyVaultClient {
    constructor() {
        this.keyVaultUrl = process.env.AZURE_KEY_VAULT_URL || 'https://ai-agent-keyvault.vault.azure.net/';
        
        // Use managed identity for authentication (no credentials needed in code)
        this.credential = new DefaultAzureCredential();
        this.client = new SecretClient(this.keyVaultUrl, this.credential);
        
        // Cache secrets for performance
        this.secretCache = new Map();
        this.cacheExpiry = new Map();
        
        console.log('βœ… Azure Key Vault client initialized');
    }
    
    async getSecret(secretName, useCache = true) {
        /**
         * Retrieve secret from Azure Key Vault
         * 
         * Args:
         *   secretName: Name of the secret in Key Vault
         *   useCache: Whether to use cached value if available
         */
        
        try {
            // Check cache first
            if (useCache && this.secretCache.has(secretName)) {
                const cacheExpiry = this.cacheExpiry.get(secretName);
                
                if (Date.now() < cacheExpiry) {
                    console.log(`🎯 Using cached secret: ${secretName}`);
                    return this.secretCache.get(secretName);
                } else {
                    // Cache expired, remove it
                    this.secretCache.delete(secretName);
                    this.cacheExpiry.delete(secretName);
                }
            }
            
            console.log(`πŸ” Retrieving secret from Key Vault: ${secretName}`);
            
            // Retrieve secret from Key Vault
            const secret = await this.client.getSecret(secretName);
            
            // Cache the secret for 5 minutes
            if (useCache) {
                this.secretCache.set(secretName, secret.value);
                this.cacheExpiry.set(secretName, Date.now() + (5 * 60 * 1000));
            }
            
            return secret.value;
            
        } catch (error) {
            console.error(`❌ Failed to retrieve secret ${secretName}:`, error);
            
            // If it's a network error and we have a cached value, use it
            if (this.secretCache.has(secretName)) {
                console.warn(`⚠️ Using stale cached secret due to Key Vault error: ${secretName}`);
                return this.secretCache.get(secretName);
            }
            
            throw error;
        }
    }
    
    async setSecret(secretName, secretValue, options = {}) {
        /**
         * Store secret in Azure Key Vault
         */
        
        try {
            console.log(`πŸ” Storing secret in Key Vault: ${secretName}`);
            
            const secretOptions = {
                contentType: options.contentType || 'text/plain',
                tags: options.tags || {},
                enabled: options.enabled !== false
            };
            
            // Set expiration if specified
            if (options.expiresOn) {
                secretOptions.expiresOn = options.expiresOn;
            }
            
            await this.client.setSecret(secretName, secretValue, secretOptions);
            
            // Clear cache for this secret
            this.secretCache.delete(secretName);
            this.cacheExpiry.delete(secretName);
            
            console.log(`βœ… Secret stored successfully: ${secretName}`);
            
        } catch (error) {
            console.error(`❌ Failed to store secret ${secretName}:`, error);
            throw error;
        }
    }
    
    async initializeAIAgentSecrets() {
        /**
         * Initialize all secrets needed for AI agent operation
         */
        
        const requiredSecrets = [
            'OpenAI-API-Key',
            'Database-Connection-String',
            'JWT-Secret',
            'Slack-Bot-Token',
            'Discord-Bot-Token'
        ];
        
        const secretValues = {};
        const missingSecrets = [];
        
        for (const secretName of requiredSecrets) {
            try {
                const secretValue = await this.getSecret(secretName);
                secretValues[secretName] = secretValue;
                console.log(`βœ… Retrieved secret: ${secretName}`);
                
            } catch (error) {
                console.error(`❌ Missing secret: ${secretName}`);
                missingSecrets.push(secretName);
            }
        }
        
        if (missingSecrets.length > 0) {
            throw new Error(`Missing required secrets: ${missingSecrets.join(', ')}`);
        }
        
        return secretValues;
    }
}

module.exports = AzureKeyVaultClient;

Key Vault Integration Benefits:

Managed Identity: Your App Service can access Key Vault without storing any credentials in your code or configuration.

Secret Caching: Secrets are cached temporarily to improve performance and reduce Key Vault API calls.

Automatic Rotation: Key Vault can automatically rotate secrets and notify your application.


Step 5: Azure Functions for Serverless AI Processing

For certain AI operations, Azure Functions provides a cost-effective serverless option.

When to Use Azure Functions vs App Service

Use Azure Functions For:

  • Event-driven processing (webhook handlers, scheduled tasks)
  • Batch processing (data analysis, report generation)
  • Integration endpoints (connecting to external services)
  • Background tasks (cleanup, maintenance, notifications)

Use App Service For:

  • Interactive chat interfaces requiring persistent connections
  • Complex routing with multiple endpoints
  • Session management and user state
  • Real-time features like WebSockets

Azure Functions Implementation

// azure-functions/ai-processing/index.js

const { app } = require('@azure/functions');
const { OpenAI } = require('openai');

// Initialize OpenAI client (reused across function invocations)
let openaiClient;

async function getOpenAIClient() {
    if (!openaiClient) {
        // Get API key from Key Vault or environment
        const apiKey = process.env.OPENAI_API_KEY;
        
        if (!apiKey) {
            throw new Error('OpenAI API key not configured');
        }
        
        openaiClient = new OpenAI({ apiKey });
    }
    
    return openaiClient;
}

app.http('aiProcessing', {
    methods: ['POST'],
    authLevel: 'function', // Requires function key for access
    handler: async (request, context) => {
        const startTime = Date.now();
        
        try {
            // Parse request body
            const requestBody = await request.json();
            const { message, userId, options = {} } = requestBody;
            
            // Validate input
            if (!message) {
                return {
                    status: 400,
                    jsonBody: {
                        error: 'Missing message field',
                        message: 'Please provide a message in the request body'
                    }
                };
            }
            
            context.log(`πŸ€– Processing AI request for user: ${userId}`);
            
            // Get OpenAI client
            const client = await getOpenAIClient();
            
            // Process with OpenAI
            const response = await client.chat.completions.create({
                model: options.model || 'gpt-3.5-turbo',
                messages: [
                    {
                        role: 'system',
                        content: options.systemPrompt || 'You are a helpful AI assistant.'
                    },
                    {
                        role: 'user',
                        content: message
                    }
                ],
                max_tokens: options.maxTokens || 500,
                temperature: options.temperature || 0.7
            });
            
            const aiResponse = response.choices[0].message.content;
            const processingTime = Date.now() - startTime;
            
            // Log metrics
            context.log(`πŸ“Š AI processing completed in ${processingTime}ms`);
            context.log(`πŸ’° Tokens used: ${response.usage.total_tokens}`);
            
            // Return successful response
            return {
                status: 200,
                jsonBody: {
                    success: true,
                    response: aiResponse,
                    metadata: {
                        processingTime: processingTime,
                        model: response.model,
                        tokensUsed: response.usage.total_tokens,
                        userId: userId
                    }
                }
            };
            
        } catch (error) {
            context.log.error('❌ AI processing error:', error);
            
            return {
                status: 500,
                jsonBody: {
                    error: 'AI processing failed',
                    message: 'Please try again or contact support',
                    requestId: context.invocationId
                }
            };
        }
    }
});

// Timer-triggered function for maintenance tasks
app.timer('maintenanceTasks', {
    schedule: '0 0 2 * * *', // Run daily at 2 AM
    handler: async (myTimer, context) => {
        context.log('🧹 Running daily maintenance tasks...');
        
        try {
            // Cleanup old conversation data
            await cleanupOldConversations();
            
            // Rotate API keys if needed
            await checkAPIKeyRotation();
            
            // Generate usage reports
            await generateUsageReports();
            
            context.log('βœ… Maintenance tasks completed successfully');
            
        } catch (error) {
            context.log.error('❌ Maintenance tasks failed:', error);
        }
    }
});

async function cleanupOldConversations() {
    // Implementation for cleaning up old conversation data
    console.log('🧹 Cleaning up conversations older than 30 days...');
}

async function checkAPIKeyRotation() {
    // Implementation for checking if API keys need rotation
    console.log('πŸ”„ Checking API key rotation status...');
}

async function generateUsageReports() {
    // Implementation for generating usage reports
    console.log('πŸ“Š Generating daily usage reports...');
}

Azure Functions Explanation:

Event-Driven Architecture: Functions only run when triggered, making them cost-effective for sporadic tasks.

Automatic Scaling: Azure automatically scales function instances based on demand.

Integrated Logging: All function logs are automatically sent to Application Insights for monitoring.

Timer Triggers: Scheduled functions handle maintenance tasks without requiring external cron jobs.


Step 6: Monitoring with Application Insights

Application Insights provides comprehensive monitoring and analytics for your AI agent.

Application Insights Setup

# Create Application Insights resource
az monitor app-insights component create \
    --app ai-agent-insights \
    --location eastus \
    --resource-group ai-agent-rg \
    --application-type web

# Get instrumentation key
INSTRUMENTATION_KEY=$(az monitor app-insights component show \
    --app ai-agent-insights \
    --resource-group ai-agent-rg \
    --query instrumentationKey --output tsv)

# Configure App Service to use Application Insights
az webapp config appsettings set \
    --name your-ai-agent-app \
    --resource-group ai-agent-rg \
    --settings APPINSIGHTS_INSTRUMENTATIONKEY=$INSTRUMENTATION_KEY

Application Insights Integration

// monitoring/application-insights.js

const appInsights = require('applicationinsights');

class AzureMonitoring {
    constructor() {
        // Initialize Application Insights
        appInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY)
            .setAutoDependencyCorrelation(true)
            .setAutoCollectRequests(true)
            .setAutoCollectPerformance(true, true)
            .setAutoCollectExceptions(true)
            .setAutoCollectDependencies(true)
            .setAutoCollectConsole(true)
            .setUseDiskRetriesOnFailure(true)
            .start();
        
        this.client = appInsights.defaultClient;
        
        console.log('βœ… Application Insights monitoring initialized');
    }
    
    trackAIRequest(userId, message, response, processingTime, tokensUsed) {
        /**
         * Track AI request with custom metrics
         */
        
        // Track custom event
        this.client.trackEvent({
            name: 'AI_Request_Processed',
            properties: {
                userId: userId,
                messageLength: message.length,
                responseLength: response.length,
                model: 'gpt-3.5-turbo'
            },
            measurements: {
                processingTime: processingTime,
                tokensUsed: tokensUsed,
                costEstimate: (tokensUsed / 1000) * 0.002 // Rough cost estimate
            }
        });
        
        // Track performance metric
        this.client.trackMetric({
            name: 'AI_Processing_Time',
            value: processingTime
        });
        
        // Track token usage
        this.client.trackMetric({
            name: 'AI_Tokens_Used',
            value: tokensUsed
        });
        
        console.log(`πŸ“Š AI request metrics tracked for user: ${userId}`);
    }
    
    trackSecurityEvent(eventType, severity, details) {
        /**
         * Track security-related events
         */
        
        this.client.trackEvent({
            name: 'Security_Event',
            properties: {
                eventType: eventType,
                severity: severity,
                ...details
            }
        });
        
        // For critical security events, also track as exceptions
        if (severity === 'critical') {
            this.client.trackException({
                exception: new Error(`Critical security event: ${eventType}`),
                properties: details
            });
        }
        
        console.log(`🚨 Security event tracked: ${eventType} (${severity})`);
    }
    
    createCustomDashboard() {
        /**
         * Create custom dashboard queries for AI agent monitoring
         */
        
        const dashboardQueries = {
            // AI request volume over time
            aiRequestVolume: `
                customEvents
                | where name == "AI_Request_Processed"
                | summarize RequestCount = count() by bin(timestamp, 1h)
                | order by timestamp desc
            `,
            
            // Average processing time
            averageProcessingTime: `
                customMetrics
                | where name == "AI_Processing_Time"
                | summarize AvgProcessingTime = avg(value) by bin(timestamp, 1h)
                | order by timestamp desc
            `,
            
            // Token usage and cost tracking
            tokenUsageAndCost: `
                customMetrics
                | where name == "AI_Tokens_Used"
                | summarize TotalTokens = sum(value), EstimatedCost = sum(value) * 0.000002 by bin(timestamp, 1d)
                | order by timestamp desc
            `,
            
            // Security events
            securityEvents: `
                customEvents
                | where name == "Security_Event"
                | summarize EventCount = count() by tostring(customDimensions.severity), bin(timestamp, 1h)
                | order by timestamp desc
            `,
            
            // Error rates
            errorRates: `
                requests
                | summarize ErrorRate = (countif(success == false) * 100.0) / count() by bin(timestamp, 1h)
                | order by timestamp desc
            `
        };
        
        console.log('πŸ“Š Custom dashboard queries created');
        console.log('Use these queries in Azure Monitor to create dashboards');
        
        return dashboardQueries;
    }
}

module.exports = AzureMonitoring;

Application Insights Benefits:

Automatic Instrumentation: Many metrics are collected automatically without code changes.

Custom Metrics: You can track AI-specific metrics like token usage and processing time.

Correlation: Application Insights correlates requests across different services, making debugging easier.

Alerting: Set up alerts based on custom metrics or performance thresholds.


Step 7: Deployment and CI/CD Pipeline

Azure DevOps provides enterprise-grade CI/CD capabilities for your AI agent.

Azure DevOps Pipeline Setup

# azure-pipelines.yml - CI/CD pipeline for AI agent

trigger:
  branches:
    include:
      - main
      - develop

variables:
  # Build variables
  nodeVersion: '18.x'
  buildConfiguration: 'Release'
  
  # Azure variables
  azureSubscription: 'your-azure-subscription'
  resourceGroupName: 'ai-agent-rg'
  webAppName: 'your-ai-agent-app'

stages:
  # Build and test stage
  - stage: BuildAndTest
    displayName: 'Build and Test'
    jobs:
      - job: Build
        displayName: 'Build AI Agent'
        pool:
          vmImage: 'ubuntu-latest'
        
        steps:
          # Setup Node.js
          - task: NodeTool@0
            inputs:
              versionSpec: $(nodeVersion)
            displayName: 'Install Node.js'
          
          # Install dependencies
          - script: npm ci
            displayName: 'Install dependencies'
          
          # Run security audit
          - script: npm audit --audit-level high
            displayName: 'Security audit'
            continueOnError: true
          
          # Run tests
          - script: npm test
            displayName: 'Run tests'
          
          # Build application
          - script: npm run build
            displayName: 'Build application'
          
          # Create deployment package
          - task: ArchiveFiles@2
            inputs:
              rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
              includeRootFolder: false
              archiveType: 'zip'
              archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
              replaceExistingArchive: true
            displayName: 'Create deployment package'
          
          # Publish artifacts
          - task: PublishBuildArtifacts@1
            inputs:
              pathToPublish: '$(Build.ArtifactStagingDirectory)'
              artifactName: 'drop'
            displayName: 'Publish artifacts'

  # Deploy to staging
  - stage: DeployStaging
    displayName: 'Deploy to Staging'
    dependsOn: BuildAndTest
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
    
    jobs:
      - deployment: DeployToStaging
        displayName: 'Deploy to Staging Environment'
        environment: 'staging'
        pool:
          vmImage: 'ubuntu-latest'
        
        strategy:
          runOnce:
            deploy:
              steps:
                # Deploy to Azure App Service
                - task: AzureWebApp@1
                  inputs:
                    azureSubscription: $(azureSubscription)
                    appType: 'webAppLinux'
                    appName: '$(webAppName)-staging'
                    package

Ad Space

Recommended Tools & Resources

* This section contains affiliate links. We may earn a commission when you purchase through these links at no additional cost to you.

OpenAI API

AI Platform

Access GPT-4 and other powerful AI models for your agent development.

Pay-per-use

LangChain Plus

Framework

Advanced framework for building applications with large language models.

Free + Paid

Pinecone Vector Database

Database

High-performance vector database for AI applications and semantic search.

Free tier available

AI Agent Development Course

Education

Complete course on building production-ready AI agents from scratch.

$199

πŸ’‘ Pro Tip

Start with the free tiers of these tools to experiment, then upgrade as your AI agent projects grow. Most successful developers use a combination of 2-3 core tools rather than trying everything at once.

πŸš€ Join the AgentForge Community

Get weekly insights, tutorials, and the latest AI agent developments delivered to your inbox.

No spam, ever. Unsubscribe at any time.

Loading conversations...