-
-
Notifications
You must be signed in to change notification settings - Fork 1
Code Documentation
Technical documentation of the ACSforMCS codebase, including architecture, key components, data models, and implementation details.
ACSforMCS is built as a .NET 9 web application that bridges Azure Communication Services (ACS) telephony with Microsoft Copilot Studio agents. The application follows a modular architecture with clear separation of concerns.
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Phone Call │───▶│ Azure Comm │───▶│ ACSforMCS │
│ │ │ Services │ │ Web App │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ Event Grid │ │ Azure Key │
│ Webhooks │ │ Vault │
└──────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Copilot Studio │
│ (DirectLine) │
└─────────────────┘
- Incoming Call: Phone call triggers ACS to send webhook notification
-
Event Processing: ACSforMCS receives EventGrid notification via
/api/incomingCall - Caller ID Extraction: CallerInfoExtractor processes event data to identify caller and callee
- Call Answering: Application answers call with transcription and AI capabilities
- Bot Integration: DirectLine conversation established with Copilot Studio
- Caller Personalization: Caller information sent to bot for personalized responses
- Real-time Processing: Bidirectional audio/text processing via WebSockets
- Response Delivery: TTS conversion and audio playback to caller
ACSforMCS/
├── Program.cs # Application entry point and configuration
├── AgentActivity.cs # Bot activity representation
├── CallContext.cs # Call session context
├── Conversation.cs # DirectLine conversation model
├── Constants.cs # Application constants
├── Configuration/
│ └── AppSettings.cs # Application configuration models
├── Services/
│ ├── CallAutomationService.cs # Core call processing logic
│ └── CallerInfoExtractor.cs # Caller ID/Callee ID extraction utilities
├── Middleware/
│ └── WebSocketMiddleware.cs # WebSocket handling for real-time audio
├── HealthChecks/
│ └── DirectLineHealthCheck.cs # Health monitoring for DirectLine API
├── Properties/
│ └── launchSettings.json # Development launch configuration
└── scripts/ # PowerShell deployment automation
The main entry point configures the entire application pipeline:
Key Responsibilities:
- Azure Key Vault integration for secure configuration
- Environment-specific service registration
- HTTP pipeline configuration
- Health check endpoints
- API documentation (Swagger) in Development mode
- Caller ID/Callee ID extraction and bot personalization
Configuration Sources:
- appsettings.json - Base configuration
- Azure Key Vault - Sensitive values (connection strings, secrets)
- Environment Variables - Runtime overrides (VS_TUNNEL_URL for dev tunnels)
- .NET User Secrets - Local development configuration
Environment Modes:
- Development: Full monitoring, Swagger UI, detailed logging
- Production: Minimal endpoints, optimized performance, security hardening
Caller ID Processing:
- Extracts caller and callee information from EventGrid incoming call events
- Sends caller information to Copilot Studio for personalized bot responses
- Supports configurable caller ID processing and detailed logging
- Handles multiple caller ID formats (PSTN, ACS users, international numbers)
Primary service handling all call processing and bot integration:
Key Capabilities:
- DirectLine conversation management
- Real-time WebSocket communication with bots
- Speech-to-text and text-to-speech processing
- Call transfer orchestration
- Error handling and graceful degradation
Public Methods:
// DirectLine conversation lifecycle
Task<Conversation?> StartConversationAsync()
Task<Conversation?> StartConversationWithTokenAsync()
// Message processing
Task SendMessageAsync(string conversationId, string message)
// Real-time bot communication
Task ListenToBotWebSocketAsync(string streamUrl, CallConnection callConnection, CancellationToken cancellationToken)
// Call management
Task<bool> AnnounceAndTransferCallAsync(CallConnection callConnection, CallMedia callMedia, string phoneNumber, string transferMessage, CancellationToken cancellationToken)
// Audio processing
Task PlayToAllAsync(CallMedia callMedia, string textToPlay, CancellationToken cancellationToken)
// Utility methods
string GetCallbackUri()
string GetTranscriptionTransportUri()
void CleanupCall(string correlationId)Bot Activity Processing:
- Message Activities: Convert to speech and play to caller
- Transfer Activities: Parse transfer commands and initiate call transfers
- Error Activities: Handle errors gracefully with user-friendly fallbacks
- End of Conversation: Terminate calls appropriately
Handles WebSocket connections for streaming audio transcription from Azure Communication Services:
Functionality:
- WebSocket upgrade handling for
/wspath - Audio stream processing and correlation ID extraction
- Integration with speech recognition services
- Message routing to appropriate bot conversations
WebSocket Headers:
-
x-ms-call-correlation-id: Links WebSocket to specific call context - Standard WebSocket upgrade headers
Utility service for extracting and processing caller identification information from Azure Communication Services EventGrid events:
Key Capabilities:
- Robust JSON parsing of EventGrid IncomingCall events
- Multiple extraction strategies with fallback mechanisms
- Phone number normalization and format validation
- Caller type detection (PSTN, ACS users, international)
- Privacy-aware handling of blocked or private caller IDs
- Thread-safe caller information processing
Extraction Features:
// Primary extraction method with comprehensive error handling
CallerInfo ExtractCallerInfo(EventGridEvent eventGridEvent, string correlationId, ILogger logger)
// Caller ID status enumeration
public enum CallerIdStatus
{
Available, // Full phone number and display name
PartiallyAvailable, // Some identifier present
Blocked, // Caller intentionally blocked ID
Unavailable, // Technical issue prevented retrieval
International, // International number with format issues
Internal // Internal ACS user
}Data Quality Assessment:
- Complete: Both caller and callee information available
- Partial: Either caller or callee information available
- Minimal: No caller/callee information available
Bot Integration:
- Sends caller information to Copilot Studio using simple pipe-delimited format
- Format:
CALLER_ID=xxx|CALLEE_ID=yyy|CALLER_NAME=zzz - Enables bot personalization based on caller identification
- Supports anonymous callers with graceful fallbacks
Central configuration model with all required settings:
public class AppSettings
{
public string AcsConnectionString { get; set; } // Azure Communication Services
public string CognitiveServiceEndpoint { get; set; } // Azure Speech Services
public string AgentPhoneNumber { get; set; } // Transfer target number
public string DirectLineSecret { get; set; } // Bot authentication
public string BaseUri { get; set; } // Application URL
public string DefaultTransferNumber { get; set; } // Fallback transfer
}Caller identification and personalization configuration:
public class CallerIdOptions
{
public bool EnableCallerIdProcessing { get; set; } = true; // Enable/disable caller ID extraction
public bool EnableDetailedLogging { get; set; } = true; // Detailed caller ID logging
}Voice and speech recognition optimization settings:
public class VoiceOptions
{
public string VoiceName { get; set; } = "en-US-NancyNeural";
public string Language { get; set; } = "en-US";
public int InitialSilenceTimeoutMs { get; set; } = 800; // Fast response
public int EndSilenceTimeoutMs { get; set; } = 1500; // Quick detection
public bool EnableFastMode { get; set; } = true; // Performance optimization
public string SpeechRate { get; set; } = "fast"; // TTS speed
}Represents the relationship between an ACS call and its bot conversation, enhanced with comprehensive caller identification:
public class CallContext
{
// Core call identifiers
public string? CorrelationId { get; set; } // ACS call identifier
public string? ConversationId { get; set; } // DirectLine conversation ID
// Caller identification properties
public string? CallerId { get; set; } // Phone number or identifier of caller
public string? CalleeId { get; set; } // Phone number that was called
public string? CallerDisplayName { get; set; } // Display name for caller ID
public string CallerType { get; set; } = "unknown"; // Type of caller (pstn, acs, raw, unknown)
public bool HasCallerInfo { get; set; } = false; // Reliable caller info available
public bool HasCalleeInfo { get; set; } = false; // Reliable callee info available
// Session management
public DateTimeOffset CallStartTime { get; set; } // Call initiation timestamp
public DateTimeOffset? LastActivity { get; set; } // Last message activity
public bool IsActive { get; set; } = true; // Call is currently active
public int MessageCount { get; set; } = 0; // Messages processed
// Thread safety
public readonly object Lock = new object(); // Synchronization object
}Enhanced Methods:
// Thread-safe activity tracking
void UpdateLastActivity()
// Data quality assessment
string GetDataQuality() // Returns: "complete", "partial", or "minimal"
// Safe caller information access
(string CallerId, string CalleeId, string CallerDisplayName, bool HasCallerInfo, bool HasCalleeInfo, string CallerType) GetCallerInfoSnapshot()Usage:
- Stored in
ConcurrentDictionary<string, CallContext>for thread-safe access - Key: CorrelationId from ACS
- Enables routing transcribed speech to correct bot conversation
- Facilitates cleanup when calls end
- Provides caller identification context for bot personalization
Standardized representation of bot responses from DirectLine:
public class AgentActivity
{
public string? Type { get; set; } // Activity type (message, transfer, error)
public string? Text { get; set; } // Activity content/payload
}Activity Types:
-
"message": Regular text responses for speech synthesis -
"transfer": Call transfer commands (format:TRANSFER:+phone:message) -
"error": Error responses (filtered from user playback) -
"endOfConversation": Conversation termination signals
DirectLine conversation session information:
public class Conversation
{
public string? ConversationId { get; set; } // Unique conversation identifier
public string? Token { get; set; } // Optional authentication token
public string? StreamUrl { get; set; } // WebSocket URL for real-time communication
public string? ReferenceGrammarId { get; set; } // Optional speech recognition optimization
}GET /
- Basic service health check
- Returns: "Hello Azure Communication Services, here is Copilot Studio!"
POST /api/incomingCall
- EventGrid webhook for incoming call notifications
- Handles EventGrid subscription validation
- Extracts caller ID and callee ID from event data
- Sends caller information to Copilot Studio for personalization
- Initiates call answering with transcription and bot integration
POST /api/calls/{contextId}
- CloudEvent webhook for call automation events
- Processes call lifecycle events (connected, disconnected, transfer events)
- Manages bot communication and audio playback
Available only in Development mode with API key authentication:
GET /health/calls
- Active call monitoring and statistics
- Returns concurrent call counts and performance metrics
GET /health/metrics
- System performance metrics (memory, CPU, threads)
- Application-specific metrics (call capacity, performance)
GET /health/config
- Configuration validation status
- Security settings verification
GET /swagger
- Interactive API documentation
- Comprehensive endpoint testing interface
API Key Protection:
// All monitoring endpoints require X-API-Key header
if (!context.Request.Headers.ContainsKey("X-API-Key") ||
context.Request.Headers["X-API-Key"] != healthCheckApiKey)
{
context.Response.StatusCode = 401;
return;
}Azure Key Vault Integration:
builder.Configuration.AddAzureKeyVault(
new Uri(keyVaultEndpoint),
new DefaultAzureCredential());Managed Identity:
- System-assigned managed identity for Key Vault access
- RBAC-based permissions instead of access policies
- No stored credentials in application code
Development Mode:
- All endpoints secured with API key authentication
- Swagger UI with authentication requirements
- Detailed logging for debugging
Production Mode:
- Minimal endpoint exposure (only business endpoints)
- No debug information leakage
- Optimized logging for performance
- HSTS and security headers
DirectLine API Client:
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
{
MaxConnectionsPerServer = 10, // Connection pooling
UseCookies = false, // Performance optimization
UseProxy = false // Skip proxy detection
})
.AddTransientHttpErrorPolicy(policy =>
policy.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt =>
{
var baseDelay = TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));
var jitter = TimeSpan.FromMilliseconds(Random.Shared.Next(0, 1000));
return baseDelay.Add(jitter); // Prevent thundering herd
}));Fast Mode Configuration:
TranscriptionOptions = new TranscriptionOptions(voiceOptions.Language)
{
TransportUri = callAutomationService.GetTranscriptionTransportUri(),
TranscriptionTransport = StreamingTransport.Websocket,
EnableIntermediateResults = voiceOptions.EnableFastMode, // Real-time results
StartTranscription = true
}Optimized Timing Settings:
-
InitialSilenceTimeoutMs: 800- Quick response start -
EndSilenceTimeoutMs: 1500- Fast speech detection -
SpeechRate: "fast"- Accelerated TTS playback
Call Context Storage:
// Thread-safe concurrent dictionary for call contexts
ConcurrentDictionary<string, CallContext> callStore
// Automatic cleanup on call disconnection
callAutomationService.CleanupCall(correlationId);Resource Cleanup:
- Cancellation tokens for WebSocket operations
- Proper disposal of HTTP clients and connections
- Memory cache for SSML templates
ACSforMCS includes comprehensive caller identification and personalization capabilities that extract caller information from incoming call events and provide it to Copilot Studio for enhanced customer experiences.
Caller Information Extraction:
- Extracts caller ID, callee ID, and display names from EventGrid IncomingCall events
- Supports multiple caller types: PSTN phone numbers, ACS users, international calls
- Handles privacy scenarios like blocked or unavailable caller IDs
- Provides data quality assessment for personalization decisions
Bot Personalization:
- Sends caller information to Copilot Studio using simple pipe-delimited format
- Enables personalized greetings and context-aware responses
- Supports both identified and anonymous callers gracefully
- Integrates with Power FX formulas for dynamic bot behavior
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Incoming │───▶│ EventGrid │───▶│ CallerInfo │
│ Call Event │ │ Webhook │ │ Extractor │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ Call Context │ │ Bot Message │
│ Enhancement │ │ Generation │
└──────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Copilot Studio │
│ Personalization │
└─────────────────┘
CallerInfo Class:
public class CallerInfo
{
public string CorrelationId { get; set; } // Call correlation identifier
public string CallerId { get; set; } // Caller's phone number or ID
public string CalleeId { get; set; } // Called number (destination)
public string CallerDisplayName { get; set; } // Caller's display name
public string CallerType { get; set; } // Type: pstn, acs, raw, unknown
public bool HasCallerInfo { get; set; } // Reliable caller data available
public bool HasCalleeInfo { get; set; } // Reliable callee data available
public CallerIdStatus Status { get; set; } // Extraction status
public DateTimeOffset ExtractedAt { get; set; } // Extraction timestamp
public string DataQuality { get; } // Quality: complete, partial, minimal
}CallerIdStatus Enumeration:
- Available: Full phone number and display name present
- PartiallyAvailable: Some identifier present but not standard format
- Blocked: Caller intentionally blocked their ID
- Unavailable: Technical issue prevented ID retrieval
- International: International number with potential format challenges
- Internal: Internal Azure Communication Services user
CallerIdOptions Settings:
public class CallerIdOptions
{
public bool EnableCallerIdProcessing { get; set; } = true; // Master enable/disable switch
public bool EnableDetailedLogging { get; set; } = true; // Detailed extraction logging
}Configuration Usage:
{
"CallerId": {
"EnableCallerIdProcessing": true, // Set to false to treat all calls as anonymous
"EnableDetailedLogging": true // Enable detailed caller ID extraction logging
}
}1. EventGrid Event Processing:
// Extract caller information from incoming call event
var callerInfo = callerIdOptions.EnableCallerIdProcessing
? CallerInfoExtractor.ExtractCallerInfo(eventGridEvent, tempCorrelationId, logger)
: CallerInfoExtractor.CallerInfo.CreateDefault(tempCorrelationId);2. Multi-Strategy Extraction:
- Primary Strategy: Parse structured EventGrid data fields
- Secondary Strategy: Raw JSON property extraction with fallbacks
- Tertiary Strategy: Text-based parsing of identifiers
- Default Strategy: Create anonymous caller context
3. Phone Number Normalization:
- Converts various phone number formats to consistent representation
- Handles international numbers, domestic formats, and ACS identifiers
- Preserves original format while providing normalized versions
4. Data Quality Assessment:
- Complete: Both caller and callee information successfully extracted
- Partial: Either caller or callee information available
- Minimal: No identification information available (anonymous call)
1. Caller Information Transmission:
// Send caller information as first bot message
var callerMessage = $"CALLER_ID={callContext.CallerId}|CALLEE_ID={callContext.CalleeId}|CALLER_NAME={callContext.CallerDisplayName}";
await callAutomationService.SendMessageAsync(conversation.ConversationId!, callerMessage);2. Message Format:
-
Format:
CALLER_ID=value|CALLEE_ID=value|CALLER_NAME=value -
Example:
CALLER_ID=+1234567890|CALLEE_ID=+1987654321|CALLER_NAME=John Smith -
Anonymous:
CALLER_ID=Unknown|CALLEE_ID=Unknown|CALLER_NAME=Anonymous Caller
3. Copilot Studio Processing:
// Power FX formula to parse caller information
Set(
CallerData,
Split(Trigger.Text, "|")
);
Set(
CallerID,
Last(Split(First(Filter(CallerData, StartsWith(Value, "CALLER_ID="))).Value, "=")).Value
);
Set(
CallerName,
Last(Split(First(Filter(CallerData, StartsWith(Value, "CALLER_NAME="))).Value, "=")).Value
);
Personalized Greeting:
// When caller information is available:
"Hello John Smith, thank you for calling from 555-123-4567. How can I help you today?"
// When caller is anonymous:
"Hello, thank you for calling. How can I help you today?"
// When partial information is available:
"Hello caller from 555-123-4567, how can I help you today?"
Department Routing:
// Based on called number (CalleeId):
"+1800SUPPORT" → "You've reached our technical support line..."
"+1800SALES" → "Welcome to our sales department..."
"+1800BILLING" → "You've called our billing department..."
Privacy-Aware Processing:
- Respects caller privacy preferences and blocked IDs
- Handles "Private Number" and "Blocked" caller scenarios gracefully
- Provides appropriate messaging for privacy-conscious callers
- Does not store sensitive caller information beyond call duration
Security Measures:
- Caller information is processed in-memory only
- No persistent storage of caller identification data
- Thread-safe access to caller information
- Cleanup of caller data when calls end
Compliance Features:
- Configurable caller ID processing (can be disabled entirely)
- Detailed logging for audit trails (when enabled)
- Support for regulatory requirements around caller identification
Efficient Processing:
- Single-pass JSON parsing with multiple extraction attempts
- Thread-safe concurrent access to caller information
- Memory-efficient string processing and normalization
- Fast fallback mechanisms for extraction failures
Caching Strategy:
- Caller information cached in CallContext for call duration
- No cross-call caching to ensure privacy
- Automatic cleanup when calls disconnect
Extraction Success Metrics:
// Log extraction results for monitoring
logger.LogInformation("Extracted caller information - Status: {Status}, CallerId: {CallerId}, CalleeId: {CalleeId}, Quality: {Quality}",
callerInfo.Status, callerInfo.CallerId, callerInfo.CalleeId, callerInfo.DataQuality);Data Quality Tracking:
- Success/failure rates for caller ID extraction
- Distribution of caller types (PSTN, ACS, International)
- Data quality metrics (complete, partial, minimal)
- Performance metrics for extraction processing time
Common Issues:
- No Caller Information: Check EventGrid event payload format
- Extraction Failures: Enable detailed logging to see parsing attempts
- Bot Not Personalizing: Verify Power FX formulas in Copilot Studio
- International Number Issues: Check phone number normalization logic
Debug Configuration:
{
"CallerId": {
"EnableCallerIdProcessing": true,
"EnableDetailedLogging": true // Enable for troubleshooting
},
"Logging": {
"LogLevel": {
"ACSforMCS.Services.CallerInfoExtractor": "Debug" // Detailed extraction logs
}
}
}Bot Communication Failures:
try
{
conversation = await callAutomationService.StartConversationAsync();
}
catch (HttpRequestException ex) when (ex.Message.Contains("403"))
{
// Fallback to token-based authentication
conversation = await callAutomationService.StartConversationWithTokenAsync();
}Audio Playback Error Handling:
try
{
await PlayToAllAsync(callConnection.GetCallMedia(), agentActivity.Text, cancellationToken);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Could not play audio, call may have ended: {Message}", ex.Message);
// Continue processing - don't fail entire call for individual playback issues
}Error Message Filtering:
// Filter out technical errors from user playback
if (agentActivity.Text.Contains("An error has occurred") ||
agentActivity.Text.Contains("error has occurred"))
{
_logger.LogWarning("Filtered out generic error message from bot: {ErrorText}", agentActivity.Text);
continue; // Don't play technical errors to users
}Monitors DirectLine API connectivity:
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
// Test DirectLine API accessibility
var response = await _httpClient.GetAsync("", cancellationToken);
return response.IsSuccessStatusCode ?
HealthCheckResult.Healthy("DirectLine API is accessible") :
HealthCheckResult.Unhealthy($"DirectLine API returned {response.StatusCode}");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("DirectLine API is unreachable", ex);
}
}Application Insights Integration:
- Custom event tracking for call success/failure rates
- Performance counters for speech processing times
- Dependency tracking for DirectLine API calls
Metrics Collection:
- Active call counts
- Average call duration
- Speech recognition accuracy
- Bot response times
Health Check Endpoints:
- Kubernetes/Docker health probes supported
- Multiple health check levels (basic, detailed, specific services)
Environment Variables:
- Support for container orchestration configuration
- Override capabilities for all Key Vault settings
Stateless Design:
- Call contexts stored in memory (consider Redis for multi-instance)
- No session affinity requirements
- Horizontal scaling capabilities
Resource Limits:
- Concurrent call capacity monitoring
- Memory usage tracking
- Auto-scaling integration points
Service Registration:
// Singleton services for shared resources
builder.Services.AddSingleton<CallAutomationClient>(connectionString: appSettings.AcsConnectionString);
builder.Services.AddSingleton<ConcurrentDictionary<string, CallContext>>();
builder.Services.AddSingleton<CallAutomationService>();
// HTTP clients with retry policies
builder.Services.AddHttpClient("DirectLine", client => { /* configuration */ })
.AddTransientHttpErrorPolicy(/* retry policy */);Options Pattern:
builder.Services.Configure<AppSettings>(builder.Configuration);
builder.Services.Configure<VoiceOptions>(builder.Configuration.GetSection("Voice"));
builder.Services.Configure<CallerIdOptions>(builder.Configuration.GetSection("CallerId"));
// Usage in services
public class CallAutomationService
{
private readonly AppSettings _appSettings;
private readonly CallerIdOptions _callerIdOptions;
public CallAutomationService(IOptions<AppSettings> appSettings, IOptions<CallerIdOptions> callerIdOptions)
{
_appSettings = appSettings.Value;
_callerIdOptions = callerIdOptions.Value;
}
}Structured Logging:
_logger.LogInformation("📞 Call connected - Active calls: {ActiveCallCount}, New call correlation ID: {CorrelationId}",
callStore.Count, correlationId);Performance Logging:
- Environment-specific log levels
- Correlation ID tracking
- Performance metrics logging
Testable Components:
- CallAutomationService business logic
- Configuration validation
- Health check implementations
- Data model serialization
Mocking Points:
- HTTP clients for DirectLine API
- Azure Communication Services clients
- Configuration providers
Test Scenarios:
- End-to-end call flow simulation
- DirectLine API integration
- Azure Key Vault configuration retrieval
- Health endpoint validation
Performance Benchmarks:
- Concurrent call capacity
- Speech processing latency
- Memory usage under load
- DirectLine API response times
Configuration Problems:
// Validate all required settings at startup
ArgumentNullException.ThrowIfNullOrEmpty(appSettings.AcsConnectionString);
ArgumentNullException.ThrowIfNullOrEmpty(appSettings.DirectLineSecret);DirectLine Authentication:
// Multiple authentication fallback strategies
try
{
return await StartConversationAsync();
}
catch (HttpRequestException ex) when (ex.Message.Contains("403"))
{
return await StartConversationWithTokenAsync();
}Development Mode Features:
- Comprehensive Swagger documentation
- Real-time call monitoring endpoints
- Configuration validation endpoints
- Detailed application logging
Production Monitoring:
- Application Insights integration
- Azure Monitor compatibility
- Custom telemetry collection
SSML Customization:
- Custom SSML template generation
- Voice personality configuration
- Language-specific optimizations
Activity Processing:
- Custom activity type handlers
- Enhanced transfer logic
- Multi-bot support capabilities
Additional Cognitive Services:
- Language understanding (LUIS)
- QnA Maker integration
- Custom speech models
- Never store secrets in source code
- Use Azure Key Vault for all sensitive data
- Implement proper RBAC for Key Vault access
- Regular secret rotation capabilities
- API key authentication for monitoring endpoints
- HTTPS enforcement for all communication
- Proper input validation and sanitization
- Error message filtering to prevent information disclosure
- Restrict inbound traffic to required endpoints only
- Use Azure Private Endpoints for internal communication
- Implement proper firewall rules
- Monitor and log all API access
- Azure Development: Development workflow and deployment
- DirectLine Secret Setup: Bot configuration
- Local Development: Local testing with dev tunnels
- New to ACSforMCS? → Project Purpose
- Ready to deploy? → Quick Installation
- Configure bot? → Copilot Studio Integration
- Development? → Azure Development