Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions ProxyAgent-CSharp/.github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# GitHub Copilot Instructions for Azure AI Foundry Agent for M365

## Project Overview
This is a proxy solution that connects Azure AI Foundry agents to Microsoft 365 Copilot and Teams using the Microsoft 365 Agents Toolkit.

## Technology Stack
- **.NET 9** - Bot application runtime
- **M365 Agent SDK** - Microsoft 365 Agent SDK
- **Microsoft 365 Agents Toolkit** - Formerly Teams Toolkit
- **Azure AI Foundry Agent SDK** - For agent integration
- **Bicep** - Infrastructure as Code
- **Managed Identity** - For production authentication (no secrets)

## Architecture Patterns
- Use the proxy pattern to route messages between M365 Copilot and Azure AI Foundry
- Bot Service acts as the messaging endpoint
- Managed Identity for authentication in production
- Client Secret + Single Tenant for local development
- SSO with federated credentials (no client secrets in SSO flow)

## Coding Standards
- Use C# 12 features and nullable reference types
- Follow async/await patterns consistently
- Use dependency injection for services
- Implement proper error handling and logging
- Use configuration-based settings (appsettings.json)

## Key Components
- `AzureAgent.cs` - Main agent integration logic
- `Program.cs` - Bot setup and middleware configuration
- Bicep modules - Reusable infrastructure components
- `m365agents.yml` - Orchestration for provisioning and deployment

## Common Patterns
- SSO authentication uses federated credentials
- Bot responds via `turnContext.SendActivityAsync()`
- Environment-specific configuration via `appsettings.{Environment}.json`
- Infrastructure deployments use conditional logic (first-time vs. update)

## Security Best Practices
- Never commit secrets or `.env` files
- Use Managed Identity in production (no secrets)
- Use federated credentials for SSO (no client secrets)
- Keep `appsettings.Development.json` in `.gitignore`

## Naming Conventions
- Bicep modules: lowercase with hyphens (e.g., `app-registration.bicep`)
- C# classes: PascalCase
- Environment variables: UPPER_SNAKE_CASE
- Resource names: Use consistent naming pattern with suffix

## Deployment
- Local: Press F5 in VS Code (automatic provisioning)
- Azure: Use `atk provision` and `atk deploy` commands
- Two deployment modes: Local (dev tunnel) and Production (Azure App Service)

## Testing
- Local debugging via F5 in VS Code
- Automatic sideloading in Teams/M365 Copilot
- Test SSO flow with federated credentials
16 changes: 16 additions & 0 deletions ProxyAgent-CSharp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

.vs/
.vs
*.pubxml








12 changes: 12 additions & 0 deletions ProxyAgent-CSharp/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"recommendations": [
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit",
"ms-azuretools.vscode-bicep",
"ms-azuretools.azure-dev",
"ms-azuretools.vscode-azureresourcegroups",
"microsoft.vscode-azure-agent-toolkit",
"ms-vscode.vscode-node-azure-pack",
"TeamsDevApp.ms-teams-vscode-extension"
]
}
124 changes: 124 additions & 0 deletions ProxyAgent-CSharp/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch in Teams (Edge)",
"type": "msedge",
"request": "launch",
"url": "https://teams.microsoft.com/l/app/${TEAMS_APP_ID}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}",
"presentation": {
"group": "Teams",
"order": 1
},
"internalConsoleOptions": "neverOpen"
},
{
"name": "Launch in Teams (Chrome)",
"type": "chrome",
"request": "launch",
"url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}",
"presentation": {
"group": "Teams",
"order": 2
},
"internalConsoleOptions": "neverOpen"
},
{
"name": "Launch in Copilot (Edge)",
"type": "msedge",
"request": "launch",
"url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&$login_hint=${TEAMSFX_M365_USER_NAME}&developerMode=Basic",
"presentation": {
"group": "Copilot",
"order": 3
},
"internalConsoleOptions": "neverOpen"
},
{
"name": "Launch in Copilot (Chrome)",
"type": "chrome",
"request": "launch",
"url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${{local:agent-hint}}?auth=2&${{TEAMSFX_M365_USER_NAME}}&developerMode=Basic",
"presentation": {
"group": "Copilot",
"order": 4
},
"internalConsoleOptions": "neverOpen"
},
{
"type": "coreclr",
"request": "launch",
"name": "Launch AzureAgentToM365ATK",
"preLaunchTask": "test build",
"program": "${workspaceFolder}/AzureAgentToM365ATK/bin/Debug/net9.0/AzureAgentToM365ATK.dll",
"args": [],
"cwd": "${workspaceFolder}/AzureAgentToM365ATK",
"stopAtEntry": false,
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"presentation": {
"hidden": true,
"group": "all"
}
}
],
"compounds": [
{
"name": "Debug in Teams (Edge)",
"configurations": [
"Launch in Teams (Edge)",
"Launch AzureAgentToM365ATK"
],
"preLaunchTask": "PreReq & Start Tunnel",
"postDebugTask": "Stop All Services",
"presentation": {
"group": "all",
"order": 1
},
"stopAll": true
},
{
"name": "Debug in Teams (Chrome)",
"configurations": [
"Launch in Teams (Chrome)",
"Launch AzureAgentToM365ATK"
],
"preLaunchTask": "PreReq & Start Tunnel",
"postDebugTask": "Stop All Services",
"presentation": {
"group": "all",
"order": 2
},
"stopAll": true
},
{
"name": "Debug in Copilot (Edge)",
"configurations": [
"Launch AzureAgentToM365ATK",
"Launch in Copilot (Edge)",
],
"preLaunchTask": "PreReq & Start Tunnel",
"postDebugTask": "Stop All Services",
"presentation": {
"group": "all",
"order": 3
},
"stopAll": true
},
{
"name": "Debug in Copilot (Chrome)",
"configurations": [
"Launch AzureAgentToM365ATK",
"Launch in Copilot (Chrome)"
],
"preLaunchTask": "PreReq & Start Tunnel",
"postDebugTask": "Stop All Services",
"presentation": {
"group": "all",
"order": 4
},
"stopAll": true
}
]
}
44 changes: 44 additions & 0 deletions ProxyAgent-CSharp/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
// C# Development
"dotnet.defaultSolution": "AzureAgentToM365ATK.sln",
"omnisharp.enableRoslynAnalyzers": true,
// Microsoft 365 Agents Toolkit
"m365agents.telemetry": false,
// File Associations
"files.associations": {
"*.bicep": "bicep",
"m365agents*.yml": "yaml",
"*.atkproj": "xml"
},
// Files to exclude from Explorer
"files.exclude": {
"**/bin": true,
"**/obj": true,
"**/.env.*.user": true
},
// Search exclusions
"search.exclude": {
"**/bin": true,
"**/obj": true,
"**/node_modules": true
},
// Editor settings
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
// Terminal settings
"terminal.integrated.cwd": "${workspaceFolder}",
// Recommended Extensions
"recommendations": [
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit",
"ms-azuretools.vscode-bicep",
"ms-azuretools.azure-dev",
"ms-vscode.azure-account",
"msazurermtools.azurerm-vscode-tools",
"microsoft.vscode-azure-agent-toolkit"
],
"dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true
}
Loading