CommunityRAPP

Power Platform Integration Guide

Deploy CommunityRAPP to Microsoft Teams and Microsoft 365 Copilot using Power Platform.

πŸ“– Table of Contents

Overview

Power Platform integration enables you to deploy your AI assistant to:

Why Power Platform?

Benefits

Feature Standalone Mode Power Platform Mode
Access Point REST API, Web UI Teams, M365 Copilot, Web
User Authentication Function key Azure AD/SSO
User Context Manual (GUID) Automatic (Office 365 profile)
Conversation UI Custom HTML Teams native UI
Analytics Application Insights Power Platform Analytics + App Insights
Deployment Azure only Azure + Microsoft 365

Use Cases

Perfect for Power Platform when:

Stick with Standalone when:

Prerequisites

Licenses Required

Per User:

Organization:

Technical Requirements

Permissions Needed:

Azure Resources:

Verify Prerequisites

Check you have everything:

# Check if you have Power Automate Premium
# 1. Go to https://flow.microsoft.com
# 2. Click "My flows" β†’ "New flow"
# 3. If you see "Automated cloud flow" and premium connectors, you're good!

# Get your Azure Function details
# You'll need these from your deployment:
# - Function URL: https://YOUR-APP.azurewebsites.net/api/businessinsightbot_function
# - Function Key: (from Azure Portal β†’ Function App β†’ Functions β†’ businessinsightbot_function β†’ Function Keys)

Architecture

Full Stack Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         User Interface Layer                     β”‚
β”‚  Microsoft Teams  β”‚  M365 Copilot  β”‚  Power Apps  β”‚  Web UI     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Conversation Layer                            β”‚
β”‚                     Copilot Studio                               β”‚
β”‚  β€’ Natural Language Processing                                   β”‚
β”‚  β€’ Dialog Management                                             β”‚
β”‚  β€’ Intent Recognition                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Integration Layer                             β”‚
β”‚                     Power Automate                               β”‚
β”‚  β€’ User Context Enrichment (Office 365 profile)                 β”‚
β”‚  β€’ Data Transformation                                           β”‚
β”‚  β€’ Error Handling & Retry Logic                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Processing Layer                             β”‚
β”‚                   Azure Function App                             β”‚
β”‚  β€’ Agent Selection & Routing                                     β”‚
β”‚  β€’ Memory Management                                             β”‚
β”‚  β€’ Azure OpenAI Integration                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Agent Layer                                β”‚
β”‚   Memory  β”‚  Email  β”‚  Calendar  β”‚  Custom  β”‚  GitConflict     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Data Layer                                 β”‚
β”‚    Azure Storage    β”‚    Azure OpenAI    β”‚   Microsoft Graph   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow

Request Flow:

1. User sends message in Teams/M365 Copilot
   ↓
2. Copilot Studio processes natural language
   ↓
3. Triggers Power Automate flow
   ↓
4. Power Automate enriches with Office 365 user data
   β”‚ - User name
   β”‚ - Email address
   β”‚ - Department
   β”‚ - Job title
   ↓
5. HTTP POST to Azure Function
   {
     "user_input": "User's message",
     "conversation_history": [...],
     "user_guid": "office365-user-id",
     "user_context": {
       "email": "user@company.com",
       "name": "John Doe",
       "department": "Engineering"
     }
   }
   ↓
6. Azure Function processes request
   β”‚ - Loads user memory
   β”‚ - Routes to appropriate agents
   β”‚ - Calls Azure OpenAI
   ↓
7. Returns response to Power Automate
   ↓
8. Power Automate formats for Copilot Studio
   ↓
9. Copilot Studio displays in Teams/M365 Copilot

Step-by-Step Setup

Phase 1: Download Power Platform Solution

Option 1: From GitHub Releases (Recommended)

  1. Visit CommunityRAPP Releases
  2. Download Copilot365_PowerPlatform_Solution.zip

Option 2: Create Manually

If no solution package is available, follow the manual setup in Phase 2-4.

Phase 2: Set Up Power Automate Flow

Step 1: Create the Flow

  1. Go to Power Automate
  2. Click + Create β†’ Automated cloud flow
  3. Name it: Copilot365-Backend-Connector
  4. Skip trigger selection (we’ll add it later)
  5. Click Create

Step 2: Add Copilot Studio Trigger

  1. Click + New step β†’ Search for β€œCopilot Studio”
  2. Select When Copilot Studio calls a flow
  3. Add input parameters:
    • Name: user_message Type: Text
    • Name: conversation_id Type: Text (optional)

Step 3: Get User Profile Information

  1. Click + New step β†’ Search for β€œOffice 365 Users”
  2. Select Get my profile (V2)
  3. This automatically gets the current user’s profile

Step 4: Call Azure Function

  1. Click + New step β†’ Search for β€œHTTP”
  2. Select HTTP action
  3. Configure:
    • Method: POST
    • URI: https://YOUR-FUNCTION-APP.azurewebsites.net/api/businessinsightbot_function
    • Headers:
      {
        "Content-Type": "application/json",
        "x-functions-key": "YOUR_FUNCTION_KEY_HERE"
      }
      
    • Body: Click β€œAdd dynamic content” and construct:
      {
        "user_input": @{triggerBody()?['user_message']},
        "conversation_history": [],
        "user_guid": "@{outputs('Get_my_profile_(V2)')?['body/id']}",
        "user_context": {
          "email": "@{outputs('Get_my_profile_(V2)')?['body/mail']}",
          "name": "@{outputs('Get_my_profile_(V2)')?['body/displayName']}",
          "department": "@{outputs('Get_my_profile_(V2)')?['body/department']}",
          "jobTitle": "@{outputs('Get_my_profile_(V2)')?['body/jobTitle']}"
        }
      }
      

Step 5: Parse Response

  1. Click + New step β†’ Search for β€œParse JSON”
  2. Select Parse JSON
  3. Content: body('HTTP')
  4. Schema: Click β€œUse sample payload” and paste:
    {
      "assistant_response": "Hello! How can I help you?",
      "voice_response": "Hello!",
      "agent_logs": "Session initialized",
      "user_guid": "abc-123"
    }
    

Step 6: Return to Copilot Studio

  1. Click + New step β†’ Search for β€œCopilot Studio”
  2. Select Return value(s) to Copilot Studio
  3. Add outputs:
    • Name: bot_response Value: body('Parse_JSON')?['assistant_response']
    • Name: voice_response Value: body('Parse_JSON')?['voice_response']

Step 7: Add Error Handling

  1. On the HTTP action, click … β†’ Configure run after
  2. Add parallel branch for error handling:
    • Condition: body('HTTP')?['status'] equals failed
    • Action: Return error message to Copilot Studio

Step 8: Save and Test

  1. Click Save
  2. Click Test β†’ Manually β†’ Run flow
  3. Enter test data: user_message: "Hello"
  4. Verify response is received

Phase 3: Configure Copilot Studio

Step 1: Create Copilot

  1. Go to Copilot Studio
  2. Click + Create β†’ New copilot
  3. Choose Skip to configure
  4. Name: Copilot 365 Agent
  5. Language: English
  6. Click Create

Step 2: Create Main Topic

  1. In Copilot Studio, go to Topics
  2. Click + Add a topic β†’ From blank
  3. Name: Main Assistant Topic
  4. Add trigger phrases: ```
    • help me
    • I need assistance
    • can you help
    • I have a question
    • assist me ```

Step 3: Add Flow Action

  1. In the topic authoring canvas, click + Add node
  2. Select Call an action β†’ Your flow name (Copilot365-Backend-Connector)
  3. Map inputs:
    • user_message ← Activity.Text (user’s message)
  4. Map outputs to variables:
    • Create variable: BotResponse ← bot_response
    • Create variable: VoiceResponse ← voice_response

Step 4: Display Response

  1. After the flow action, click + Add node
  2. Select Send a message
  3. Message content: {x:BotResponse}

Step 5: Create Fallback Topic

  1. Go to Topics β†’ System β†’ Fallback
  2. Customize message: β€œI can help you with that. Let me think…”
  3. Add same flow action as Main topic
  4. Display response

Step 6: Test in Copilot Studio

  1. Click Test your copilot (top right)
  2. Type: β€œHello, can you help me?”
  3. Verify response comes from your Azure Function

Phase 4: Deploy to Channels

Deploy to Microsoft Teams

Step 1: Publish Copilot

  1. In Copilot Studio, click Publish (top right)
  2. Click Publish to confirm
  3. Wait for β€œSuccessfully published” message

Step 2: Configure Teams Channel

  1. Go to Channels (left sidebar)
  2. Click Microsoft Teams
  3. Click Turn on Teams
  4. Choose availability:
    • Show to everyone (public)
    • Show to my teammates (specific people)
    • Show to my organization (all employees)
  5. Click Turn on

Step 3: Add to Teams

  1. Click Open bot (opens Teams)
  2. Chat with your bot in Teams!

Step 4: Add to Teams App Store

  1. In Copilot Studio, under Teams channel settings
  2. Click Submit for admin approval
  3. Teams admin reviews and approves
  4. Bot appears in Teams app store for organization

Deploy to Microsoft 365 Copilot

Step 1: Create Declarative Agent

  1. Create a manifest file (declarativeAgent.json):
{
  "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.0/schema.json",
  "version": "v1.0",
  "id": "contoso-rapp-agent",
  "name": "Copilot 365 Agent",
  "description": "Enterprise AI assistant with persistent memory and custom agents",
  "instructions": "You are an enterprise AI assistant. Help users with their questions using available agents and tools.",
  "conversation_starters": [
    {
      "title": "Help me get started",
      "text": "What can you help me with?"
    },
    {
      "title": "Draft an email",
      "text": "Help me draft a professional email"
    },
    {
      "title": "Search my documents",
      "text": "Find documents about project planning"
    }
  ],
  "actions": [
    {
      "id": "contoso-rapp-backend",
      "type": "powerPlatform",
      "powerPlatformFlowId": "YOUR_FLOW_ID_HERE"
    }
  ],
  "capabilities": {
    "conversationHistory": true,
    "webSearch": false
  }
}

Step 2: Package as Teams App

  1. Create folder structure:
    Copilot365Agent/
    β”œβ”€β”€ manifest.json
    β”œβ”€β”€ declarativeAgent.json
    β”œβ”€β”€ color.png (192x192)
    └── outline.png (32x32)
    
  2. Create manifest.json:
    {
      "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
      "manifestVersion": "1.16",
      "id": "YOUR-UNIQUE-GUID",
      "version": "1.0.0",
      "developer": {
        "name": "Your Organization",
        "websiteUrl": "https://yourcompany.com",
        "privacyUrl": "https://yourcompany.com/privacy",
        "termsOfUseUrl": "https://yourcompany.com/terms"
      },
      "name": {
        "short": "Copilot 365 Agent",
        "full": "Copilot 365 Enterprise AI Assistant"
      },
      "description": {
        "short": "AI assistant with persistent memory",
        "full": "Enterprise AI assistant built on Azure with GPT-4, featuring persistent memory, custom agents, and Microsoft 365 integration."
      },
      "icons": {
        "color": "color.png",
        "outline": "outline.png"
      },
      "copilotAgents": {
        "declarativeAgents": [
          {
            "id": "contoso-rapp-agent",
            "file": "declarativeAgent.json"
          }
        ]
      }
    }
    
  3. Zip all files (manifest.json, declarativeAgent.json, and icons)

Step 3: Deploy to M365 Copilot

  1. Go to Teams Admin Center
  2. Navigate to Teams apps β†’ Manage apps
  3. Click Upload new app
  4. Upload your ZIP file
  5. Set permissions and availability
  6. Click Publish

Step 4: Test in M365 Copilot

  1. Open Microsoft 365 Copilot (microsoft365.com)
  2. Click on agents/plugins icon
  3. Find β€œCopilot 365 Agent”
  4. Start chatting!

User Context Integration

Accessing User Information in Agents

Update your agents to use Office 365 user context:

from agents.basic_agent import BasicAgent

class PersonalizedAgent(BasicAgent):
    def __init__(self):
        self.name = 'Personalized'
        self.metadata = {
            "name": self.name,
            "description": "Provides personalized assistance using user context",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_context": {
                        "type": "object",
                        "description": "Office 365 user profile information",
                        "properties": {
                            "email": {"type": "string"},
                            "name": {"type": "string"},
                            "department": {"type": "string"},
                            "jobTitle": {"type": "string"}
                        }
                    },
                    "query": {
                        "type": "string",
                        "description": "User's request"
                    }
                },
                "required": ["query"]
            }
        }
        super().__init__(self.name, self.metadata)

    def perform(self, user_context=None, query="", **kwargs):
        """
        Perform personalized assistance using user context.

        Args:
            user_context (dict): Office 365 user profile
            query (str): User's request
        """
        if user_context:
            name = user_context.get('name', 'User')
            email = user_context.get('email', 'unknown')
            department = user_context.get('department', 'Unknown')
            job_title = user_context.get('jobTitle', 'Unknown')

            # Personalize response based on department
            if 'Engineering' in department:
                return f"Hi {name}, as an engineer, I can help you with technical documentation, code reviews, and development workflows. What do you need?"
            elif 'Sales' in department:
                return f"Hello {name}, I can assist with CRM data, customer insights, and sales reports. How can I help?"
            else:
                return f"Hello {name} from {department}, how can I assist you today?"
        else:
            return "Hello! How can I assist you?"

Storing User-Specific Data

from utils.azure_file_storage import AzureFileStorageManager

class UserPreferencesAgent(BasicAgent):
    def __init__(self):
        self.name = 'UserPreferences'
        self.storage = AzureFileStorageManager()
        # ... metadata setup ...

    def perform(self, user_guid="", action="get", preference_key="", preference_value="", **kwargs):
        """
        Manage user-specific preferences.

        Args:
            user_guid (str): Office 365 user ID
            action (str): 'get' or 'set'
            preference_key (str): Preference name
            preference_value (str): Preference value (for 'set')
        """
        file_name = f"user_preferences_{user_guid}.json"

        if action == "set":
            # Load existing preferences
            preferences = self.storage.read_file("user_data", file_name)
            if not preferences:
                preferences = {}
            else:
                import json
                preferences = json.loads(preferences)

            # Update preference
            preferences[preference_key] = preference_value

            # Save back
            import json
            self.storage.write_file("user_data", file_name, json.dumps(preferences))

            return f"Preference '{preference_key}' saved successfully."

        elif action == "get":
            preferences = self.storage.read_file("user_data", file_name)
            if preferences:
                import json
                prefs = json.loads(preferences)
                return prefs.get(preference_key, "Preference not found")
            return "No preferences found"

Advanced Configuration

Multi-Environment Setup

For dev/test/prod environments:

Development Environment:

{
  "user_input": "test message",
  "conversation_history": [],
  "user_guid": "dev-test-user",
  "environment": "development",
  "azure_function_url": "https://dev-contoso-rapp.azurewebsites.net/api/businessinsightbot_function"
}

Production Environment:

{
  "user_input": "production message",
  "conversation_history": [],
  "user_guid": "@{outputs('Get_my_profile_(V2)')?['body/id']}",
  "environment": "production",
  "azure_function_url": "https://prod-contoso-rapp.azurewebsites.net/api/businessinsightbot_function"
}

Create separate Power Automate flows for each environment.

Custom Authentication

For scenarios requiring additional authentication:

  1. Add API Management Layer:
    • Deploy Azure API Management
    • Add OAuth 2.0 / JWT validation
    • Route to Function App
  2. Update Power Automate:
    • Change HTTP connector to use APIM endpoint
    • Add authentication header with token

Conversation History Management

To maintain conversation history across messages:

In Power Automate:

  1. Add Initialize variable action at the start:
    • Name: conversationHistory
    • Type: Array
    • Value: []
  2. After each response, Append to array variable:
    {
      "role": "user",
      "content": "@{triggerBody()?['user_message']}"
    }
    
  3. Include in HTTP request body:
    {
      "conversation_history": @{variables('conversationHistory')},
      ...
    }
    

Rate Limiting & Throttling

Protect your backend from abuse:

In Power Automate:

  1. Add Scope action for rate limiting check
  2. Check calls per user per hour
  3. Return error if exceeded

In Azure Function:

from datetime import datetime, timedelta
import json

def check_rate_limit(user_guid, storage_manager):
    """Check if user has exceeded rate limit."""
    rate_limit_file = f"rate_limit_{user_guid}.json"

    # Get current rate limit data
    data = storage_manager.read_file("rate_limits", rate_limit_file)

    if data:
        rate_data = json.loads(data)
        last_reset = datetime.fromisoformat(rate_data['last_reset'])

        # Reset if hour has passed
        if datetime.now() - last_reset > timedelta(hours=1):
            rate_data = {'count': 0, 'last_reset': datetime.now().isoformat()}

        # Check limit
        if rate_data['count'] >= 100:  # 100 requests per hour
            return False, "Rate limit exceeded. Try again later."

        rate_data['count'] += 1
    else:
        rate_data = {'count': 1, 'last_reset': datetime.now().isoformat()}

    # Save updated count
    storage_manager.write_file("rate_limits", rate_limit_file, json.dumps(rate_data))
    return True, ""

Monitoring & Troubleshooting

Power Automate Monitoring

View Flow Runs:

  1. Go to Power Automate
  2. Click My flows
  3. Select your flow
  4. Click 28-day run history
  5. Review succeeded/failed runs

Debug Failed Runs:

  1. Click a failed run
  2. Expand each action to see inputs/outputs
  3. Check HTTP response codes
  4. Verify function key is correct

Common Issues & Solutions

Issue Cause Solution
β€œUnauthorized” (401) Invalid function key Regenerate key in Azure Portal β†’ Function App β†’ Function Keys
β€œBad Request” (400) Invalid request body format Check JSON structure matches expected schema
β€œTimeout” (500) Function execution > 230s Optimize agents, enable streaming, or increase timeout
User context not passed Office 365 connector permissions Re-authenticate Office 365 Users connector
Copilot doesn’t trigger Missing trigger phrases Add more variations in Copilot Studio topics
Response not displaying Incorrect variable mapping Verify output variables match in flow and copilot
Slow responses Cold start latency Enable β€œAlways On” in Function App (requires Basic or higher plan)

Enable Detailed Logging

In Power Automate:

  1. Edit flow
  2. Add Compose actions to log data:
    Compose_UserInput: @{triggerBody()?['user_message']}
    Compose_HTTPResponse: @{body('HTTP')}
    

In Azure Function:

Update local.settings.json and Azure configuration:

{
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "LOGGING_LEVEL": "DEBUG"
  }
}

Check logs in Azure Portal β†’ Function App β†’ Logs (or Application Insights).

Performance Optimization

1. Reduce Cold Starts:

2. Cache Responses:

import hashlib
from functools import lru_cache

@lru_cache(maxsize=100)
def get_cached_response(user_input_hash):
    # Return cached response if available
    pass

def generate_response(user_input):
    input_hash = hashlib.md5(user_input.encode()).hexdigest()
    cached = get_cached_response(input_hash)
    if cached:
        return cached
    # Generate new response...

3. Parallel Agent Execution:

import asyncio

async def execute_agents_parallel(agents, user_input):
    tasks = [agent.perform_async(input=user_input) for agent in agents]
    results = await asyncio.gather(*tasks)
    return results

Cost Analysis

Detailed Cost Breakdown

Azure Components: | Service | Plan | Cost | |β€”β€”β€”|β€”β€”|β€”β€”| | Function App | Consumption | ~$0 (1M free executions/month) | | Storage | Standard | ~$5/month | | Azure OpenAI | Pay-per-use | ~$0.01-0.03 per 1K tokens | | Application Insights | Basic | ~$2-5/month |

Power Platform Components: | Service | Plan | Cost per User/Month | |β€”β€”β€”|β€”β€”|β€”β€”β€”β€”β€”β€”β€”| | Power Automate | Premium | ~$15 | | Copilot Studio | Included in Premium | $0 | | Microsoft 365 Copilot | Optional | ~$30 |

Total Estimates:

For 10 users with moderate usage (50 conversations/day):

For 100 users with moderate usage:

Cost Optimization Tips:

Security Best Practices

1. Secure Function Keys

DO:

DON’T:

Implementation:

# Rotate function key
az functionapp keys renew \
  --name YOUR_FUNCTION_APP \
  --resource-group YOUR_RESOURCE_GROUP \
  --key-type functionKeys \
  --key-name default

2. Data Loss Prevention (DLP)

Enable DLP policies in Power Platform Admin Center:

  1. Go to Power Platform Admin Center
  2. Navigate to Data policies
  3. Click New policy
  4. Name: Copilot365-DLP
  5. Add connectors to appropriate groups:
    • Business: Office 365 Users, HTTP (to your Azure Function only)
    • Blocked: Other HTTP connectors, file system connectors
  6. Apply to specific environments

3. Audit Logging

Enable in Power Platform:

  1. Admin Center β†’ Analytics β†’ Power Automate
  2. View flow execution logs
  3. Export to Log Analytics for long-term retention

Enable in Azure:

  1. Function App β†’ Monitoring β†’ Diagnostic settings
  2. Send to Log Analytics workspace
  3. Query logs:
    FunctionAppLogs
    | where TimeGenerated > ago(24h)
    | where Message contains "businessinsightbot_function"
    | project TimeGenerated, Message, Level
    

4. Network Security

Restrict Function App Access:

  1. Azure Portal β†’ Function App β†’ Networking
  2. Access restrictions β†’ Add rule
  3. Allow only Power Platform IP ranges (regional)
  4. Block all other IPs

Use Private Endpoints: For enhanced security, deploy Function App with private endpoints:

az functionapp vnet-integration add \
  --name YOUR_FUNCTION_APP \
  --resource-group YOUR_RESOURCE_GROUP \
  --vnet YOUR_VNET \
  --subnet YOUR_SUBNET

In Copilot Studio:

  1. Add welcome topic with privacy notice
  2. Explain data collection and usage
  3. Provide opt-out mechanism
  4. Link to privacy policy

Example Privacy Message:

πŸ‘‹ Welcome to Copilot 365 Agent!

Before we start, please note:
β€’ Your conversations are processed using Azure OpenAI
β€’ We store conversation history to improve responses
β€’ Your Office 365 profile (name, email) is used for personalization
β€’ All data is encrypted and complies with Microsoft's privacy standards

By using this assistant, you agree to our Privacy Policy: [link]

Ready to get started? Ask me anything!

6. Compliance & Governance

Microsoft Purview Integration:

  1. Enable sensitivity labels in Power Platform
  2. Apply labels to flows containing sensitive data
  3. Configure data retention policies
  4. Enable eDiscovery for compliance

Regular Security Reviews:

Next Steps

Now that you have Power Platform integration set up:

  1. Customize Experience
    • Update Copilot Studio welcome messages
    • Add conversation starters
    • Create specialized topics
  2. Extend Functionality
    • Build custom agents
    • Integrate with Microsoft Graph
    • Add more Power Automate flows
  3. Monitor & Optimize
    • Set up alerts for failures
    • Review usage analytics
    • Optimize token usage
  4. Scale Deployment
    • Roll out to pilot group
    • Gather feedback
    • Deploy organization-wide

Additional Resources

Need Help?


Ready to build amazing experiences? πŸš€ Start integrating with Power Platform today!