From 380a034574002567712a2d1dff9789e4e50ae1b8 Mon Sep 17 00:00:00 2001 From: Huihui Wu Date: Mon, 9 Mar 2026 17:15:44 +0800 Subject: [PATCH 1/6] feat: enable a365 sample runnable in ATK agents playground --- nodejs/langchain/sample-agent/.gitignore | 24 ++++ .../sample-agent/.vscode/extensions.json | 5 + .../sample-agent/.vscode/launch.json | 31 +++++ .../.vscode/scripts/refresh-bearer-token.ps1 | 77 +++++++++++ .../langchain/sample-agent/.vscode/tasks.json | 121 ++++++++++++++++++ nodejs/langchain/sample-agent/README.md | 34 ++--- .../sample-agent/env/.env.playground | 28 ++++ .../sample-agent/env/.env.playground.user | 12 ++ .../sample-agent/m365agents.playground.yml | 41 ++++++ nodejs/langchain/sample-agent/m365agents.yml | 5 + nodejs/langchain/sample-agent/package.json | 9 +- 11 files changed, 368 insertions(+), 19 deletions(-) create mode 100644 nodejs/langchain/sample-agent/.gitignore create mode 100644 nodejs/langchain/sample-agent/.vscode/extensions.json create mode 100644 nodejs/langchain/sample-agent/.vscode/launch.json create mode 100644 nodejs/langchain/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 create mode 100644 nodejs/langchain/sample-agent/.vscode/tasks.json create mode 100644 nodejs/langchain/sample-agent/env/.env.playground create mode 100644 nodejs/langchain/sample-agent/env/.env.playground.user create mode 100644 nodejs/langchain/sample-agent/m365agents.playground.yml create mode 100644 nodejs/langchain/sample-agent/m365agents.yml diff --git a/nodejs/langchain/sample-agent/.gitignore b/nodejs/langchain/sample-agent/.gitignore new file mode 100644 index 00000000..75a5c39d --- /dev/null +++ b/nodejs/langchain/sample-agent/.gitignore @@ -0,0 +1,24 @@ +# TeamsFx files +env/.env.*.user +env/.env.local +env/.env.sandbox +.localConfigs +.localConfigs.playground +.localConfigs +.notification.localstore.json +.notification.playgroundstore.json +appPackage/build + +# dependencies +node_modules/ + +# misc +.env +.deployment +.DS_Store + +# build +dist/ + +# Dev tool directories +/devTools/ \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/.vscode/extensions.json b/nodejs/langchain/sample-agent/.vscode/extensions.json new file mode 100644 index 00000000..1b70a393 --- /dev/null +++ b/nodejs/langchain/sample-agent/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "TeamsDevApp.ms-teams-vscode-extension" + ] +} \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/.vscode/launch.json b/nodejs/langchain/sample-agent/.vscode/launch.json new file mode 100644 index 00000000..6bb77973 --- /dev/null +++ b/nodejs/langchain/sample-agent/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Local Service", + "type": "node", + "request": "attach", + "port": 9239, + "restart": true, + "presentation": { + "group": "all", + "hidden": true + }, + "internalConsoleOptions": "neverOpen" + } + ], + "compounds": [ + { + "name": "Debug in Microsoft 365 Agents Playground", + "configurations": [ + "Attach to Local Service" + ], + "preLaunchTask": "Start App in Microsoft 365 Agents Playground", + "presentation": { + "group": "1-playground", + "order": 1 + }, + "stopAll": true + } + ] +} \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 b/nodejs/langchain/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 new file mode 100644 index 00000000..9d9a98dc --- /dev/null +++ b/nodejs/langchain/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 @@ -0,0 +1,77 @@ +$ErrorActionPreference = 'Stop' + +$workspace = Get-Location +$playgroundEnvPath = Join-Path $workspace 'env/.env.playground' +$playgroundUserEnvPath = Join-Path $workspace 'env/.env.playground.user' + +$a365Command = Get-Command a365 -ErrorAction SilentlyContinue +if (-not $a365Command) { + throw "a365 CLI is not installed or not on PATH. Install with: dotnet tool install --global Microsoft.Agents.A365.DevTools.Cli" +} + +if (-not (Test-Path $playgroundEnvPath)) { + throw "Missing env file: $playgroundEnvPath" +} + +$appIdLine = Get-Content $playgroundEnvPath | Where-Object { $_ -match '^\s*CLIENT_APP_ID\s*=\s*.+$' } | Select-Object -First 1 +if (-not $appIdLine) { + throw "CLIENT_APP_ID is required in env/.env.playground" +} + +$appId = ($appIdLine -split '=', 2)[1].Trim() +if ([string]::IsNullOrWhiteSpace($appId)) { + throw "CLIENT_APP_ID in env/.env.playground is empty" +} + +Write-Host "Running a365 develop add-permissions for app id $appId" +& a365 develop add-permissions --app-id $appId +if ($LASTEXITCODE -ne 0) { + throw "a365 develop add-permissions failed" +} + +Write-Host "Getting bearer token via a365..." +Write-Host "This may complete silently using cached credentials, or it may require interactive Windows sign-in (WAM)." +Write-Host "If interactive sign-in is required and no prompt appears, check the taskbar for a hidden sign-in window and bring it to front." +Write-Host "Running a365 develop get-token for app id $appId" +$tokenOutput = & a365 develop get-token --app-id $appId --output raw +if ($LASTEXITCODE -ne 0) { + throw "a365 develop get-token failed" +} + +$rawOutput = [string]::Join("`n", $tokenOutput) +$rawOutput = $rawOutput -replace "`r", '' + +$bearerToken = $null +$jwtRegex = '(?[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)' +$jwtMatches = [regex]::Matches($rawOutput, $jwtRegex) +if ($jwtMatches.Count -gt 0) { + $bearerToken = ($jwtMatches | ForEach-Object { $_.Groups['token'].Value } | Sort-Object Length -Descending | Select-Object -First 1).Trim() +} + +if ([string]::IsNullOrWhiteSpace($bearerToken)) { + throw "Unable to extract a bearer token from a365 develop get-token output" +} + +$userEnvLines = @() +if (Test-Path $playgroundUserEnvPath) { + $userEnvLines = Get-Content $playgroundUserEnvPath +} + +$updated = $false +for ($i = 0; $i -lt $userEnvLines.Count; $i++) { + if ($userEnvLines[$i] -match '^\s*SECRET_BEARER_TOKEN\s*=') { + $userEnvLines[$i] = "SECRET_BEARER_TOKEN=$bearerToken" + $updated = $true + break + } +} + +if (-not $updated) { + if ($userEnvLines.Count -gt 0 -and -not [string]::IsNullOrWhiteSpace($userEnvLines[$userEnvLines.Count - 1])) { + $userEnvLines += '' + } + $userEnvLines += "SECRET_BEARER_TOKEN=$bearerToken" +} + +Set-Content -Path $playgroundUserEnvPath -Value $userEnvLines -Encoding UTF8 +Write-Host 'SECRET_BEARER_TOKEN has been updated in env/.env.playground.user' \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/.vscode/tasks.json b/nodejs/langchain/sample-agent/.vscode/tasks.json new file mode 100644 index 00000000..ca71683f --- /dev/null +++ b/nodejs/langchain/sample-agent/.vscode/tasks.json @@ -0,0 +1,121 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Start App in Microsoft 365 Agents Playground", + "dependsOn": [ + "Validate prerequisites (Microsoft 365 Agents Playground)", + "Refresh bearer token (Microsoft 365 Agents Playground)", + "Deploy (Microsoft 365 Agents Playground)", + "Start application (Microsoft 365 Agents Playground)", + "Start Microsoft 365 Agents Playground" + ], + "dependsOrder": "sequence" + }, + { + // Check all required prerequisites. + // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. + "label": "Validate prerequisites (Microsoft 365 Agents Playground)", + "type": "teamsfx", + "command": "debug-check-prerequisites", + "args": { + "prerequisites": [ + "nodejs", // Validate if Node.js is installed. + "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. + ], + "portOccupancy": [ + 3978, // app service port + 9239, // app inspector port for Node.js debugger + 56150 // Microsoft 365 Agents Playground port + ] + } + }, + { + "label": "Refresh bearer token (Microsoft 365 Agents Playground)", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-File", + "${workspaceFolder}/.vscode/scripts/refresh-bearer-token.ps1" + ], + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + // Build project. + // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. + "label": "Deploy (Microsoft 365 Agents Playground)", + "dependsOrder": "sequence", + "type": "teamsfx", + "command": "deploy", + "args": { + "env": "playground" + } + }, + { + "label": "Start application (Microsoft 365 Agents Playground)", + "type": "shell", + "command": "npm run dev:teamsfx:playground", + "isBackground": true, + "options": { + "cwd": "${workspaceFolder}", + }, + "problemMatcher": { + "pattern": [ + { + "regexp": "^.*$", + "file": 0, + "location": 1, + "message": 2 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": "[nodemon] starting", + "endsPattern": "Server listening on|Bot/ME service listening at|[nodemon] app crashed" + } + } + }, + { + "label": "Start Microsoft 365 Agents Playground", + "type": "shell", + "command": "npm run dev:teamsfx:launch-playground", + "isBackground": true, + "options": { + "env": { + "PATH": "${workspaceFolder}/devTools/playground/node_modules/.bin;${env:PATH}" + } + }, + "windows": { + "options": { + "env": { + "PATH": "${workspaceFolder}/devTools/playground/node_modules/.bin;${env:PATH}" + } + } + }, + "problemMatcher": { + "pattern": [ + { + "regexp": "^.*$", + "file": 0, + "location": 1, + "message": 2 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": ".*", + "endsPattern": "Listening on" + } + }, + "presentation": { + "panel": "dedicated", + "reveal": "silent" + } + } + ] +} \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/README.md b/nodejs/langchain/sample-agent/README.md index fb1366cb..7644b950 100644 --- a/nodejs/langchain/sample-agent/README.md +++ b/nodejs/langchain/sample-agent/README.md @@ -12,30 +12,32 @@ This sample uses the [Microsoft Agent 365 SDK for Node.js](https://github.com/mi For comprehensive documentation and guidance on building agents with the Microsoft Agent 365 SDK, including how to add tooling, observability, and notifications, visit the [Microsoft Agent 365 Developer Documentation](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/). ## Prerequisites +> +> To run the template in your local dev machine, you will need: +> +> - [Node.js](https://nodejs.org/), supported versions: 18.x or higher +> - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) latest version +> - Prepare your own Azure/openAI API credentials +> - Azure CLI signed in with `az login` -- Node.js 18.x or higher -- Microsoft Agent 365 SDK -- LangChain 1.0.1 or higher -- Azure/OpenAI API credentials +> - Microsoft Agent 365 SDK +> - LangChain 1.0.1 or higher +> - A365 CLI: Required for agent deployment and management. -## Working with User Identity +## Running the Agent in Microsoft 365 Agents Playground -On every incoming message, the A365 platform populates `activity.from` with basic user -information — always available with no API calls or token acquisition: +1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. +1. In file *env/.env.playground.user*, fill in your Azure OpenAI key `SECRET_AZURE_OPENAI_API_KEY=`, endpoint `AZURE_OPENAI_ENDPOINT=`, and deployment name `AZURE_OPENAI_DEPLOYMENT_NAME=` if you're using Azure OpenAI. +1. In file *env/.env.playground.user*, fill in your OpenAI key `SECRET_OPENAI_API_KEY=` if you're using OpenAI. +1. In file *env/.env.playground*, fill in your custom app registration client id `CLIENT_APP_ID`. +1. Press F5 to start debugging which launches your agent in Microsoft 365 Agents Playground using a web browser. Select `Debug in Microsoft 365 Agents Playground`. +1. You can send any message to get a response from the agent. -| Field | Description | -|---|---| -| `activity.from.id` | Channel-specific user ID (e.g., `29:1AbcXyz...` in Teams) | -| `activity.from.name` | Display name as known to the channel | -| `activity.from.aadObjectId` | Azure AD Object ID — use this to call Microsoft Graph | - -The sample logs these fields at the start of every message turn and injects the display name -into the LLM system instructions for personalized responses. +**Congratulations**! You are running an agent that can now interact with users in Microsoft 365 Agents Playground. ## Running the Agent To set up and test this agent, refer to the [Configure Agent Testing](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/testing?tabs=nodejs) guide for complete instructions. - For a detailed explanation of the agent code and implementation, see the [Agent Code Walkthrough](Agent-Code-Walkthrough.md). ## Support diff --git a/nodejs/langchain/sample-agent/env/.env.playground b/nodejs/langchain/sample-agent/env/.env.playground new file mode 100644 index 00000000..b9031a4a --- /dev/null +++ b/nodejs/langchain/sample-agent/env/.env.playground @@ -0,0 +1,28 @@ +# This file includes environment variables that can be committed to git. It's gitignored by default because it represents your local development environment. + +# Built-in environment variables +TEAMSFX_ENV=playground + +# Environment variables used by Microsoft 365 Agents Playground +TEAMSAPPTESTER_PORT=56150 +TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json + +# Custom app registration needed for bearer token +CLIENT_APP_ID= + +# Use Agentic Authentication rather than OBO +USE_AGENTIC_AUTH=false + +# Service Connection Settings +connections__service_connection__settings__clientId= +connections__service_connection__settings__clientSecret= +connections__service_connection__settings__tenantId= + +# Set service connection as default +connectionsMap__0__serviceUrl=* +connectionsMap__0__connection=service_connection + +# AgenticAuthentication Options +agentic_type=agentic +agentic_altBlueprintConnectionName=service_connection +agentic_scopes=ea9ffc3e-8a23-4a7d-836d-234d7c7565c1/.default # Prod Agentic scope \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/env/.env.playground.user b/nodejs/langchain/sample-agent/env/.env.playground.user new file mode 100644 index 00000000..f087929f --- /dev/null +++ b/nodejs/langchain/sample-agent/env/.env.playground.user @@ -0,0 +1,12 @@ +# LLM Configuration (choose one option) + +# Option 1: Azure OpenAI (preferred for enterprise) +SECRET_AZURE_OPENAI_API_KEY= +AZURE_OPENAI_ENDPOINT= +AZURE_OPENAI_DEPLOYMENT_NAME= + +# Option 2: OpenAI (if Azure OpenAI not configured) +# SECRET_OPENAI_API_KEY= +# OPENAI_MODEL=gpt-4o + +SECRET_BEARER_TOKEN= \ No newline at end of file diff --git a/nodejs/langchain/sample-agent/m365agents.playground.yml b/nodejs/langchain/sample-agent/m365agents.playground.yml new file mode 100644 index 00000000..47de8b79 --- /dev/null +++ b/nodejs/langchain/sample-agent/m365agents.playground.yml @@ -0,0 +1,41 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 + +environmentFolderPath: ./env + +deploy: + # Install development tool(s) + - uses: devTool/install + with: + testTool: + version: ~0.2.7 + symlinkDir: ./devTools/playground + + # Run npm command + - uses: cli/runNpmCommand + with: + args: install + + - uses: file/createOrUpdateEnvironmentFile + with: + target: ./.localConfigs.playground + envs: + NODE_ENV: local + PORT: 3978 + TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} + AZURE_OPENAI_API_KEY: ${{SECRET_AZURE_OPENAI_API_KEY}} + AZURE_OPENAI_ENDPOINT: ${{AZURE_OPENAI_ENDPOINT}} + AZURE_OPENAI_DEPLOYMENT: ${{AZURE_OPENAI_DEPLOYMENT_NAME}} + # OPENAI_API_KEY: ${{SECRET_OPENAI_API_KEY}} + BEARER_TOKEN: ${{SECRET_BEARER_TOKEN}} + USE_AGENTIC_AUTH: ${{USE_AGENTIC_AUTH}} + connectionsMap__0__serviceUrl: ${{connectionsMap__0__serviceUrl}} + connectionsMap__0__connection: ${{connectionsMap__0__connection}} + agentic_type: ${{agentic_type}} + agentic_altBlueprintConnectionName: ${{agentic_altBlueprintConnectionName}} + agentic_scopes: ${{agentic_scopes}} + connections__service_connection__settings__clientId: ${{connections__service_connection__settings__clientId}} + connections__service_connection__settings__clientSecret: ${{connections__service_connection__settings__clientSecret}} + connections__service_connection__settings__tenantId: ${{connections__service_connection__settings__tenantId}} diff --git a/nodejs/langchain/sample-agent/m365agents.yml b/nodejs/langchain/sample-agent/m365agents.yml new file mode 100644 index 00000000..de22d0d0 --- /dev/null +++ b/nodejs/langchain/sample-agent/m365agents.yml @@ -0,0 +1,5 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 + diff --git a/nodejs/langchain/sample-agent/package.json b/nodejs/langchain/sample-agent/package.json index 346868fc..5605fa14 100644 --- a/nodejs/langchain/sample-agent/package.json +++ b/nodejs/langchain/sample-agent/package.json @@ -6,10 +6,12 @@ "type": "commonjs", "scripts": { "start": "node dist/index.js", - "dev": "nodemon --watch src --exec ts-node src/index.ts", + "dev": "nodemon --exec node --inspect=9239 --signal SIGINT -r ts-node/register src/index.ts", "test-tool": "agentsplayground", "eval": "node --env-file .env src/evals/index.js", - "build": "tsc" + "build": "tsc", + "dev:teamsfx:playground": "env-cmd --silent -f .localConfigs.playground npm run dev", + "dev:teamsfx:launch-playground": "env-cmd --silent -f env/.env.playground agentsplayground start" }, "keywords": [ "langchain", @@ -46,6 +48,7 @@ "@types/express": "^4.17.21", "@types/node": "^20.14.9", "nodemon": "^3.1.10", - "ts-node": "^10.9.2" + "ts-node": "^10.9.2", + "env-cmd": "^11.0.0" } } From 1fdb456726b3fff472a8cede42c2d1f72359aacd Mon Sep 17 00:00:00 2001 From: Huihui Wu Date: Tue, 10 Mar 2026 10:40:18 +0800 Subject: [PATCH 2/6] fix: remove service connection envs --- nodejs/langchain/sample-agent/env/.env.playground | 5 ----- nodejs/langchain/sample-agent/m365agents.playground.yml | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/nodejs/langchain/sample-agent/env/.env.playground b/nodejs/langchain/sample-agent/env/.env.playground index b9031a4a..6c5e027d 100644 --- a/nodejs/langchain/sample-agent/env/.env.playground +++ b/nodejs/langchain/sample-agent/env/.env.playground @@ -13,11 +13,6 @@ CLIENT_APP_ID= # Use Agentic Authentication rather than OBO USE_AGENTIC_AUTH=false -# Service Connection Settings -connections__service_connection__settings__clientId= -connections__service_connection__settings__clientSecret= -connections__service_connection__settings__tenantId= - # Set service connection as default connectionsMap__0__serviceUrl=* connectionsMap__0__connection=service_connection diff --git a/nodejs/langchain/sample-agent/m365agents.playground.yml b/nodejs/langchain/sample-agent/m365agents.playground.yml index 47de8b79..a589f6cb 100644 --- a/nodejs/langchain/sample-agent/m365agents.playground.yml +++ b/nodejs/langchain/sample-agent/m365agents.playground.yml @@ -36,6 +36,6 @@ deploy: agentic_type: ${{agentic_type}} agentic_altBlueprintConnectionName: ${{agentic_altBlueprintConnectionName}} agentic_scopes: ${{agentic_scopes}} - connections__service_connection__settings__clientId: ${{connections__service_connection__settings__clientId}} - connections__service_connection__settings__clientSecret: ${{connections__service_connection__settings__clientSecret}} - connections__service_connection__settings__tenantId: ${{connections__service_connection__settings__tenantId}} + connections__service_connection__settings__clientId: "" + connections__service_connection__settings__clientSecret: "" + connections__service_connection__settings__tenantId: "" From 36e8053d392d8dac6199adc3b0938b310fcf2c6a Mon Sep 17 00:00:00 2001 From: Huihui Wu Date: Tue, 10 Mar 2026 11:17:33 +0800 Subject: [PATCH 3/6] feat: enable claude nodejs sample running in atk playground --- nodejs/claude/sample-agent/.gitignore | 24 ++++ .../sample-agent/.vscode/extensions.json | 5 + .../claude/sample-agent/.vscode/launch.json | 31 +++++ .../.vscode/scripts/refresh-bearer-token.ps1 | 77 +++++++++++ nodejs/claude/sample-agent/.vscode/tasks.json | 121 ++++++++++++++++++ nodejs/claude/sample-agent/README.md | 26 +++- .../claude/sample-agent/env/.env.playground | 23 ++++ .../sample-agent/env/.env.playground.user | 4 + .../sample-agent/m365agents.playground.yml | 38 ++++++ nodejs/claude/sample-agent/m365agents.yml | 4 + nodejs/claude/sample-agent/package.json | 7 +- 11 files changed, 353 insertions(+), 7 deletions(-) create mode 100644 nodejs/claude/sample-agent/.gitignore create mode 100644 nodejs/claude/sample-agent/.vscode/extensions.json create mode 100644 nodejs/claude/sample-agent/.vscode/launch.json create mode 100644 nodejs/claude/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 create mode 100644 nodejs/claude/sample-agent/.vscode/tasks.json create mode 100644 nodejs/claude/sample-agent/env/.env.playground create mode 100644 nodejs/claude/sample-agent/env/.env.playground.user create mode 100644 nodejs/claude/sample-agent/m365agents.playground.yml create mode 100644 nodejs/claude/sample-agent/m365agents.yml diff --git a/nodejs/claude/sample-agent/.gitignore b/nodejs/claude/sample-agent/.gitignore new file mode 100644 index 00000000..8aca3335 --- /dev/null +++ b/nodejs/claude/sample-agent/.gitignore @@ -0,0 +1,24 @@ +# TeamsFx files +env/.env.*.user +env/.env.local +env/.env.sandbox +.localConfigs +.localConfigs.playground +.localConfigs +.notification.localstore.json +.notification.playgroundstore.json +appPackage/build + +# dependencies +node_modules/ + +# misc +.env +.deployment +.DS_Store + +# build +dist/ + +# Dev tool directories +/devTools/ diff --git a/nodejs/claude/sample-agent/.vscode/extensions.json b/nodejs/claude/sample-agent/.vscode/extensions.json new file mode 100644 index 00000000..aac0a6e3 --- /dev/null +++ b/nodejs/claude/sample-agent/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "TeamsDevApp.ms-teams-vscode-extension" + ] +} diff --git a/nodejs/claude/sample-agent/.vscode/launch.json b/nodejs/claude/sample-agent/.vscode/launch.json new file mode 100644 index 00000000..20f088e2 --- /dev/null +++ b/nodejs/claude/sample-agent/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Local Service", + "type": "node", + "request": "attach", + "port": 9239, + "restart": true, + "presentation": { + "group": "all", + "hidden": true + }, + "internalConsoleOptions": "neverOpen" + } + ], + "compounds": [ + { + "name": "Debug in Microsoft 365 Agents Playground", + "configurations": [ + "Attach to Local Service" + ], + "preLaunchTask": "Start App in Microsoft 365 Agents Playground", + "presentation": { + "group": "1-playground", + "order": 1 + }, + "stopAll": true + } + ] +} diff --git a/nodejs/claude/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 b/nodejs/claude/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 new file mode 100644 index 00000000..2fee52fa --- /dev/null +++ b/nodejs/claude/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 @@ -0,0 +1,77 @@ +$ErrorActionPreference = 'Stop' + +$workspace = Get-Location +$playgroundEnvPath = Join-Path $workspace 'env/.env.playground' +$playgroundUserEnvPath = Join-Path $workspace 'env/.env.playground.user' + +$a365Command = Get-Command a365 -ErrorAction SilentlyContinue +if (-not $a365Command) { + throw "a365 CLI is not installed or not on PATH. Install with: dotnet tool install --global Microsoft.Agents.A365.DevTools.Cli" +} + +if (-not (Test-Path $playgroundEnvPath)) { + throw "Missing env file: $playgroundEnvPath" +} + +$appIdLine = Get-Content $playgroundEnvPath | Where-Object { $_ -match '^\s*CLIENT_APP_ID\s*=\s*.+$' } | Select-Object -First 1 +if (-not $appIdLine) { + throw "CLIENT_APP_ID is required in env/.env.playground" +} + +$appId = ($appIdLine -split '=', 2)[1].Trim() +if ([string]::IsNullOrWhiteSpace($appId)) { + throw "CLIENT_APP_ID in env/.env.playground is empty" +} + +Write-Host "Running a365 develop add-permissions for app id $appId" +& a365 develop add-permissions --app-id $appId +if ($LASTEXITCODE -ne 0) { + throw "a365 develop add-permissions failed" +} + +Write-Host "Getting bearer token via a365..." +Write-Host "This may complete silently using cached credentials, or it may require interactive Windows sign-in (WAM)." +Write-Host "If interactive sign-in is required and no prompt appears, check the taskbar for a hidden sign-in window and bring it to front." +Write-Host "Running a365 develop get-token for app id $appId" +$tokenOutput = & a365 develop get-token --app-id $appId --output raw +if ($LASTEXITCODE -ne 0) { + throw "a365 develop get-token failed" +} + +$rawOutput = [string]::Join("`n", $tokenOutput) +$rawOutput = $rawOutput -replace "`r", '' + +$bearerToken = $null +$jwtRegex = '(?[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)' +$jwtMatches = [regex]::Matches($rawOutput, $jwtRegex) +if ($jwtMatches.Count -gt 0) { + $bearerToken = ($jwtMatches | ForEach-Object { $_.Groups['token'].Value } | Sort-Object Length -Descending | Select-Object -First 1).Trim() +} + +if ([string]::IsNullOrWhiteSpace($bearerToken)) { + throw "Unable to extract a bearer token from a365 develop get-token output" +} + +$userEnvLines = @() +if (Test-Path $playgroundUserEnvPath) { + $userEnvLines = Get-Content $playgroundUserEnvPath +} + +$updated = $false +for ($i = 0; $i -lt $userEnvLines.Count; $i++) { + if ($userEnvLines[$i] -match '^\s*SECRET_BEARER_TOKEN\s*=') { + $userEnvLines[$i] = "SECRET_BEARER_TOKEN=$bearerToken" + $updated = $true + break + } +} + +if (-not $updated) { + if ($userEnvLines.Count -gt 0 -and -not [string]::IsNullOrWhiteSpace($userEnvLines[$userEnvLines.Count - 1])) { + $userEnvLines += '' + } + $userEnvLines += "SECRET_BEARER_TOKEN=$bearerToken" +} + +Set-Content -Path $playgroundUserEnvPath -Value $userEnvLines -Encoding UTF8 +Write-Host 'SECRET_BEARER_TOKEN has been updated in env/.env.playground.user' diff --git a/nodejs/claude/sample-agent/.vscode/tasks.json b/nodejs/claude/sample-agent/.vscode/tasks.json new file mode 100644 index 00000000..f40092c3 --- /dev/null +++ b/nodejs/claude/sample-agent/.vscode/tasks.json @@ -0,0 +1,121 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Start App in Microsoft 365 Agents Playground", + "dependsOn": [ + "Validate prerequisites (Microsoft 365 Agents Playground)", + "Refresh bearer token (Microsoft 365 Agents Playground)", + "Deploy (Microsoft 365 Agents Playground)", + "Start application (Microsoft 365 Agents Playground)", + "Start Microsoft 365 Agents Playground" + ], + "dependsOrder": "sequence" + }, + { + // Check all required prerequisites. + // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. + "label": "Validate prerequisites (Microsoft 365 Agents Playground)", + "type": "teamsfx", + "command": "debug-check-prerequisites", + "args": { + "prerequisites": [ + "nodejs", // Validate if Node.js is installed. + "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. + ], + "portOccupancy": [ + 3978, // app service port + 9239, // app inspector port for Node.js debugger + 56150 // Microsoft 365 Agents Playground port + ] + } + }, + { + "label": "Refresh bearer token (Microsoft 365 Agents Playground)", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-File", + "${workspaceFolder}/.vscode/scripts/refresh-bearer-token.ps1" + ], + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + // Build project. + // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. + "label": "Deploy (Microsoft 365 Agents Playground)", + "dependsOrder": "sequence", + "type": "teamsfx", + "command": "deploy", + "args": { + "env": "playground" + } + }, + { + "label": "Start application (Microsoft 365 Agents Playground)", + "type": "shell", + "command": "npm run dev:teamsfx:playground", + "isBackground": true, + "options": { + "cwd": "${workspaceFolder}", + }, + "problemMatcher": { + "pattern": [ + { + "regexp": "^.*$", + "file": 0, + "location": 1, + "message": 2 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": "[nodemon] starting", + "endsPattern": "Server listening on|Bot/ME service listening at|[nodemon] app crashed" + } + } + }, + { + "label": "Start Microsoft 365 Agents Playground", + "type": "shell", + "command": "npm run dev:teamsfx:launch-playground", + "isBackground": true, + "options": { + "env": { + "PATH": "${workspaceFolder}/devTools/playground/node_modules/.bin;${env:PATH}" + } + }, + "windows": { + "options": { + "env": { + "PATH": "${workspaceFolder}/devTools/playground/node_modules/.bin;${env:PATH}" + } + } + }, + "problemMatcher": { + "pattern": [ + { + "regexp": "^.*$", + "file": 0, + "location": 1, + "message": 2 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": ".*", + "endsPattern": "Listening on" + } + }, + "presentation": { + "panel": "dedicated", + "reveal": "silent" + } + } + ] +} diff --git a/nodejs/claude/sample-agent/README.md b/nodejs/claude/sample-agent/README.md index 9d232426..f3bd16cc 100644 --- a/nodejs/claude/sample-agent/README.md +++ b/nodejs/claude/sample-agent/README.md @@ -12,11 +12,17 @@ This sample uses the [Microsoft Agent 365 SDK for Node.js](https://github.com/mi For comprehensive documentation and guidance on building agents with the Microsoft Agent 365 SDK, including how to add tooling, observability, and notifications, visit the [Microsoft Agent 365 Developer Documentation](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/). ## Prerequisites - -- Node.js 18.x or higher -- Microsoft Agent 365 SDK -- Claude Agent SDK 0.1.1 or higher -- Claude API credentials +> +> To run the template in your local dev machine, you will need: +> +> - [Node.js](https://nodejs.org/), supported versions: 18.x or higher +> - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) latest version +> - Prepare your own Anthropic API credentials +> - Azure CLI signed in with `az login` + +> - Microsoft Agent 365 SDK +> - Claude Agent SDK 0.1.1 or higher +> - A365 CLI: Required for agent deployment and management. ## Working with User Identity @@ -32,6 +38,16 @@ information — always available with no API calls or token acquisition: The sample logs these fields at the start of every message turn and injects the display name into the LLM system instructions for personalized responses. +## Running the Agent in Microsoft 365 Agents Playground + +1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. +1. In file *env/.env.playground.user*, fill in your Anthropic API key `SECRET_ANTHROPIC_API_KEY=`. +1. In file *env/.env.playground*, fill in your custom app registration client id `CLIENT_APP_ID`. +1. Press F5 to start debugging which launches your agent in Microsoft 365 Agents Playground using a web browser. Select `Debug in Microsoft 365 Agents Playground`. +1. You can send any message to get a response from the agent. + +**Congratulations**! You are running an agent that can now interact with users in Microsoft 365 Agents Playground. + ## Running the Agent To set up and test this agent, refer to the [Configure Agent Testing](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/testing?tabs=nodejs) guide for complete instructions. diff --git a/nodejs/claude/sample-agent/env/.env.playground b/nodejs/claude/sample-agent/env/.env.playground new file mode 100644 index 00000000..c1d20191 --- /dev/null +++ b/nodejs/claude/sample-agent/env/.env.playground @@ -0,0 +1,23 @@ +# This file includes environment variables that can be committed to git. It's gitignored by default because it represents your local development environment. + +# Built-in environment variables +TEAMSFX_ENV=playground + +# Environment variables used by Microsoft 365 Agents Playground +TEAMSAPPTESTER_PORT=56150 +TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json + +# Custom app registration needed for bearer token +CLIENT_APP_ID= + +# Use Agentic Authentication rather than OBO +USE_AGENTIC_AUTH=false + +# Set service connection as default +connectionsMap__0__serviceUrl=* +connectionsMap__0__connection=service_connection + +# AgenticAuthentication Options +agentic_type=agentic +agentic_altBlueprintConnectionName=service_connection +agentic_scopes=ea9ffc3e-8a23-4a7d-836d-234d7c7565c1/.default # Prod Agentic scope diff --git a/nodejs/claude/sample-agent/env/.env.playground.user b/nodejs/claude/sample-agent/env/.env.playground.user new file mode 100644 index 00000000..ac051992 --- /dev/null +++ b/nodejs/claude/sample-agent/env/.env.playground.user @@ -0,0 +1,4 @@ +# Anthropic Configuration +SECRET_ANTHROPIC_API_KEY= + +SECRET_BEARER_TOKEN= diff --git a/nodejs/claude/sample-agent/m365agents.playground.yml b/nodejs/claude/sample-agent/m365agents.playground.yml new file mode 100644 index 00000000..b9dabdef --- /dev/null +++ b/nodejs/claude/sample-agent/m365agents.playground.yml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 + +environmentFolderPath: ./env + +deploy: + # Install development tool(s) + - uses: devTool/install + with: + testTool: + version: ~0.2.7 + symlinkDir: ./devTools/playground + + # Run npm command + - uses: cli/runNpmCommand + with: + args: install + + - uses: file/createOrUpdateEnvironmentFile + with: + target: ./.localConfigs.playground + envs: + NODE_ENV: local + PORT: 3978 + TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} + ANTHROPIC_API_KEY: ${{SECRET_ANTHROPIC_API_KEY}} + BEARER_TOKEN: ${{SECRET_BEARER_TOKEN}} + USE_AGENTIC_AUTH: ${{USE_AGENTIC_AUTH}} + connectionsMap__0__serviceUrl: ${{connectionsMap__0__serviceUrl}} + connectionsMap__0__connection: ${{connectionsMap__0__connection}} + agentic_type: ${{agentic_type}} + agentic_altBlueprintConnectionName: ${{agentic_altBlueprintConnectionName}} + agentic_scopes: ${{agentic_scopes}} + connections__service_connection__settings__clientId: "" + connections__service_connection__settings__clientSecret: "" + connections__service_connection__settings__tenantId: "" diff --git a/nodejs/claude/sample-agent/m365agents.yml b/nodejs/claude/sample-agent/m365agents.yml new file mode 100644 index 00000000..50d15fc3 --- /dev/null +++ b/nodejs/claude/sample-agent/m365agents.yml @@ -0,0 +1,4 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 diff --git a/nodejs/claude/sample-agent/package.json b/nodejs/claude/sample-agent/package.json index aa44ad32..c6a445c2 100644 --- a/nodejs/claude/sample-agent/package.json +++ b/nodejs/claude/sample-agent/package.json @@ -5,11 +5,13 @@ "type": "commonjs", "scripts": { "start": "node dist/index.js", - "dev": "nodemon --watch src --exec ts-node src/index.ts", + "dev": "nodemon --exec node --inspect=9239 --signal SIGINT -r ts-node/register src/index.ts", "test-tool": "agentsplayground", "install:clean": "npm run clean && npm install", "clean": "rimraf dist node_modules package-lock.json", - "build": "tsc" + "build": "tsc", + "dev:teamsfx:playground": "env-cmd --silent -f .localConfigs.playground npm run dev", + "dev:teamsfx:launch-playground": "env-cmd --silent -f env/.env.playground agentsplayground start" }, "keywords": [], "author": "Microsoft", @@ -32,6 +34,7 @@ "@microsoft/m365agentsplayground": "^0.2.18", "@types/express": "^4.17.21", "@types/node": "^20.14.9", + "env-cmd": "^11.0.0", "nodemon": "^3.1.10", "rimraf": "^5.0.0", "ts-node": "^10.9.2", From a142b46bc89201dd23888eca30bfb7a1e74214cc Mon Sep 17 00:00:00 2001 From: Huihui Wu Date: Tue, 10 Mar 2026 13:53:01 +0800 Subject: [PATCH 4/6] feat: add agents toolkit configurations for openai python sample --- python/openai/sample-agent/.gitignore | 28 +++++++ .../sample-agent/.vscode/extensions.json | 6 ++ .../openai/sample-agent/.vscode/launch.json | 47 +++++++++++ .../.vscode/scripts/refresh-bearer-token.ps1 | 77 +++++++++++++++++++ python/openai/sample-agent/.vscode/tasks.json | 52 +++++++++++++ python/openai/sample-agent/README.md | 27 +++++-- .../openai/sample-agent/env/.env.playground | 23 ++++++ .../sample-agent/env/.env.playground.user | 12 +++ .../sample-agent/m365agents.playground.yml | 37 +++++++++ python/openai/sample-agent/m365agents.yml | 4 + 10 files changed, 308 insertions(+), 5 deletions(-) create mode 100644 python/openai/sample-agent/.gitignore create mode 100644 python/openai/sample-agent/.vscode/extensions.json create mode 100644 python/openai/sample-agent/.vscode/launch.json create mode 100644 python/openai/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 create mode 100644 python/openai/sample-agent/.vscode/tasks.json create mode 100644 python/openai/sample-agent/env/.env.playground create mode 100644 python/openai/sample-agent/env/.env.playground.user create mode 100644 python/openai/sample-agent/m365agents.playground.yml create mode 100644 python/openai/sample-agent/m365agents.yml diff --git a/python/openai/sample-agent/.gitignore b/python/openai/sample-agent/.gitignore new file mode 100644 index 00000000..ba1c1747 --- /dev/null +++ b/python/openai/sample-agent/.gitignore @@ -0,0 +1,28 @@ +# TeamsFx files +env/.env.*.user +env/.env.local +env/.env.sandbox +.localConfigs +.localConfigs.playground +.localConfigs +.notification.localstore.json +.notification.playgroundstore.json +appPackage/build + +# Python +__pycache__/ +*.pyc +*.pyo +*.egg-info/ +dist/ +build/ +.venv/ +venv/ + +# misc +.env +.deployment +.DS_Store + +# Dev tool directories +/devTools/ diff --git a/python/openai/sample-agent/.vscode/extensions.json b/python/openai/sample-agent/.vscode/extensions.json new file mode 100644 index 00000000..1f2ba3b2 --- /dev/null +++ b/python/openai/sample-agent/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "TeamsDevApp.ms-teams-vscode-extension", + "ms-python.python" + ] +} diff --git a/python/openai/sample-agent/.vscode/launch.json b/python/openai/sample-agent/.vscode/launch.json new file mode 100644 index 00000000..39622092 --- /dev/null +++ b/python/openai/sample-agent/.vscode/launch.json @@ -0,0 +1,47 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Start Python", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/src/app.py", + "cwd": "${workspaceFolder}/src", + "console": "integratedTerminal", + "serverReadyAction": { + "pattern": "(started|listening|Running|Serving) (at|on) (https?://\\S+)", + "action": "startDebugging", + "name": "Start Microsoft 365 Agents Playground" + } + }, + { + "name": "Start Microsoft 365 Agents Playground", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/devTools/playground/node_modules/@microsoft/m365agentsplayground/cli.js", + "args": [ + "start" + ], + "env": { + "PATH": "${workspaceFolder}/devTools/nodejs;${env:PATH}" + }, + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ], + "compounds": [ + { + "name": "Debug in Microsoft 365 Agents Playground", + "configurations": [ + "Start Python" + ], + "preLaunchTask": "Deploy (Microsoft 365 Agents Playground)", + "presentation": { + "group": "1-playground", + "order": 1 + }, + "stopAll": true + } + ] +} \ No newline at end of file diff --git a/python/openai/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 b/python/openai/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 new file mode 100644 index 00000000..2fee52fa --- /dev/null +++ b/python/openai/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 @@ -0,0 +1,77 @@ +$ErrorActionPreference = 'Stop' + +$workspace = Get-Location +$playgroundEnvPath = Join-Path $workspace 'env/.env.playground' +$playgroundUserEnvPath = Join-Path $workspace 'env/.env.playground.user' + +$a365Command = Get-Command a365 -ErrorAction SilentlyContinue +if (-not $a365Command) { + throw "a365 CLI is not installed or not on PATH. Install with: dotnet tool install --global Microsoft.Agents.A365.DevTools.Cli" +} + +if (-not (Test-Path $playgroundEnvPath)) { + throw "Missing env file: $playgroundEnvPath" +} + +$appIdLine = Get-Content $playgroundEnvPath | Where-Object { $_ -match '^\s*CLIENT_APP_ID\s*=\s*.+$' } | Select-Object -First 1 +if (-not $appIdLine) { + throw "CLIENT_APP_ID is required in env/.env.playground" +} + +$appId = ($appIdLine -split '=', 2)[1].Trim() +if ([string]::IsNullOrWhiteSpace($appId)) { + throw "CLIENT_APP_ID in env/.env.playground is empty" +} + +Write-Host "Running a365 develop add-permissions for app id $appId" +& a365 develop add-permissions --app-id $appId +if ($LASTEXITCODE -ne 0) { + throw "a365 develop add-permissions failed" +} + +Write-Host "Getting bearer token via a365..." +Write-Host "This may complete silently using cached credentials, or it may require interactive Windows sign-in (WAM)." +Write-Host "If interactive sign-in is required and no prompt appears, check the taskbar for a hidden sign-in window and bring it to front." +Write-Host "Running a365 develop get-token for app id $appId" +$tokenOutput = & a365 develop get-token --app-id $appId --output raw +if ($LASTEXITCODE -ne 0) { + throw "a365 develop get-token failed" +} + +$rawOutput = [string]::Join("`n", $tokenOutput) +$rawOutput = $rawOutput -replace "`r", '' + +$bearerToken = $null +$jwtRegex = '(?[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)' +$jwtMatches = [regex]::Matches($rawOutput, $jwtRegex) +if ($jwtMatches.Count -gt 0) { + $bearerToken = ($jwtMatches | ForEach-Object { $_.Groups['token'].Value } | Sort-Object Length -Descending | Select-Object -First 1).Trim() +} + +if ([string]::IsNullOrWhiteSpace($bearerToken)) { + throw "Unable to extract a bearer token from a365 develop get-token output" +} + +$userEnvLines = @() +if (Test-Path $playgroundUserEnvPath) { + $userEnvLines = Get-Content $playgroundUserEnvPath +} + +$updated = $false +for ($i = 0; $i -lt $userEnvLines.Count; $i++) { + if ($userEnvLines[$i] -match '^\s*SECRET_BEARER_TOKEN\s*=') { + $userEnvLines[$i] = "SECRET_BEARER_TOKEN=$bearerToken" + $updated = $true + break + } +} + +if (-not $updated) { + if ($userEnvLines.Count -gt 0 -and -not [string]::IsNullOrWhiteSpace($userEnvLines[$userEnvLines.Count - 1])) { + $userEnvLines += '' + } + $userEnvLines += "SECRET_BEARER_TOKEN=$bearerToken" +} + +Set-Content -Path $playgroundUserEnvPath -Value $userEnvLines -Encoding UTF8 +Write-Host 'SECRET_BEARER_TOKEN has been updated in env/.env.playground.user' diff --git a/python/openai/sample-agent/.vscode/tasks.json b/python/openai/sample-agent/.vscode/tasks.json new file mode 100644 index 00000000..ad03a2f8 --- /dev/null +++ b/python/openai/sample-agent/.vscode/tasks.json @@ -0,0 +1,52 @@ +{ + "version": "2.0.0", + "tasks": [ + { + // Check all required prerequisites. + // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. + "label": "Validate prerequisites (Microsoft 365 Agents Playground)", + "type": "teamsfx", + "command": "debug-check-prerequisites", + "args": { + "prerequisites": [ + "nodejs", // Check if Node.js is installed and the version is >= 12. + "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. + ], + "portOccupancy": [ + 3978, // app service port + 56150, // Microsoft 365 Agents Playground port + ] + } + }, + { + "label": "Refresh bearer token (Microsoft 365 Agents Playground)", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-File", + "${workspaceFolder}/.vscode/scripts/refresh-bearer-token.ps1" + ], + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + // Build project. + // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. + "label": "Deploy (Microsoft 365 Agents Playground)", + "dependsOn": [ + "Validate prerequisites (Microsoft 365 Agents Playground)", + "Refresh bearer token (Microsoft 365 Agents Playground)" + ], + "dependsOrder": "sequence", + "type": "teamsfx", + "command": "deploy", + "args": { + "env": "playground" + } + }, + ] +} \ No newline at end of file diff --git a/python/openai/sample-agent/README.md b/python/openai/sample-agent/README.md index 4b5c152c..c5ed224c 100644 --- a/python/openai/sample-agent/README.md +++ b/python/openai/sample-agent/README.md @@ -12,11 +12,17 @@ This sample uses the [Microsoft Agent 365 SDK for Python](https://github.com/mic For comprehensive documentation and guidance on building agents with the Microsoft Agent 365 SDK, including how to add tooling, observability, and notifications, visit the [Microsoft Agent 365 Developer Documentation](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/). ## Prerequisites - -- Python 3.x -- Microsoft Agent 365 SDK -- OpenAI Agents SDK (openai-agents) -- Azure/OpenAI API credentials +> +> To run the template in your local dev machine, you will need: +> +> - [Python](https://www.python.org/), supported versions: 3.11 or higher +> - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) latest version +> - Prepare your own Azure OpenAI / OpenAI API credentials +> - Azure CLI signed in with `az login` + +> - Microsoft Agent 365 SDK +> - OpenAI Agents SDK (openai-agents) +> - A365 CLI: Required for agent deployment and management. ## Working with User Identity @@ -32,6 +38,17 @@ information — always available with no API calls or token acquisition: The sample logs these fields at the start of every message turn and injects the display name into the LLM system instructions for personalized responses. +## Running the Agent in Microsoft 365 Agents Playground + +1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. +1. In file *env/.env.playground.user*, fill in your Azure OpenAI key `SECRET_AZURE_OPENAI_API_KEY=`, endpoint `AZURE_OPENAI_ENDPOINT=`, and deployment name `AZURE_OPENAI_DEPLOYMENT_NAME=` if you're using Azure OpenAI. +1. In file *env/.env.playground.user*, fill in your OpenAI key `SECRET_OPENAI_API_KEY=` if you're using OpenAI. +1. In file *env/.env.playground*, fill in your custom app registration client id `CLIENT_APP_ID`. +1. Press F5 to start debugging which launches your agent in Microsoft 365 Agents Playground using a web browser. Select `Debug in Microsoft 365 Agents Playground`. +1. You can send any message to get a response from the agent. + +**Congratulations**! You are running an agent that can now interact with users in Microsoft 365 Agents Playground. + ## Running the Agent To set up and test this agent, refer to the [Configure Agent Testing](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/testing?tabs=python) guide for complete instructions. diff --git a/python/openai/sample-agent/env/.env.playground b/python/openai/sample-agent/env/.env.playground new file mode 100644 index 00000000..c1d20191 --- /dev/null +++ b/python/openai/sample-agent/env/.env.playground @@ -0,0 +1,23 @@ +# This file includes environment variables that can be committed to git. It's gitignored by default because it represents your local development environment. + +# Built-in environment variables +TEAMSFX_ENV=playground + +# Environment variables used by Microsoft 365 Agents Playground +TEAMSAPPTESTER_PORT=56150 +TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json + +# Custom app registration needed for bearer token +CLIENT_APP_ID= + +# Use Agentic Authentication rather than OBO +USE_AGENTIC_AUTH=false + +# Set service connection as default +connectionsMap__0__serviceUrl=* +connectionsMap__0__connection=service_connection + +# AgenticAuthentication Options +agentic_type=agentic +agentic_altBlueprintConnectionName=service_connection +agentic_scopes=ea9ffc3e-8a23-4a7d-836d-234d7c7565c1/.default # Prod Agentic scope diff --git a/python/openai/sample-agent/env/.env.playground.user b/python/openai/sample-agent/env/.env.playground.user new file mode 100644 index 00000000..8c9bdeb1 --- /dev/null +++ b/python/openai/sample-agent/env/.env.playground.user @@ -0,0 +1,12 @@ +# LLM Configuration (choose one option) + +# Option 1: Azure OpenAI (preferred for enterprise) +SECRET_AZURE_OPENAI_API_KEY= +AZURE_OPENAI_ENDPOINT= +AZURE_OPENAI_DEPLOYMENT_NAME= + +# Option 2: OpenAI (if Azure OpenAI not configured) +# SECRET_OPENAI_API_KEY= +# OPENAI_MODEL=gpt-4o + +SECRET_BEARER_TOKEN= diff --git a/python/openai/sample-agent/m365agents.playground.yml b/python/openai/sample-agent/m365agents.playground.yml new file mode 100644 index 00000000..eac0ae37 --- /dev/null +++ b/python/openai/sample-agent/m365agents.playground.yml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 + +environmentFolderPath: ./env + +deploy: + # Install development tool(s) + - uses: devTool/install + with: + testTool: + version: ~0.2.7 + symlinkDir: ./devTools/playground + nodejs: + symlinkDir: ./devTools/nodejs + + - uses: file/createOrUpdateEnvironmentFile + with: + target: ./.env + envs: + PORT: 3978 + TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} + AZURE_OPENAI_API_KEY: ${{SECRET_AZURE_OPENAI_API_KEY}} + AZURE_OPENAI_ENDPOINT: ${{AZURE_OPENAI_ENDPOINT}} + AZURE_OPENAI_DEPLOYMENT: ${{AZURE_OPENAI_DEPLOYMENT_NAME}} + OPENAI_API_KEY: ${{SECRET_OPENAI_API_KEY}} + BEARER_TOKEN: ${{SECRET_BEARER_TOKEN}} + USE_AGENTIC_AUTH: ${{USE_AGENTIC_AUTH}} + connectionsMap__0__serviceUrl: ${{connectionsMap__0__serviceUrl}} + connectionsMap__0__connection: ${{connectionsMap__0__connection}} + agentic_type: ${{agentic_type}} + agentic_altBlueprintConnectionName: ${{agentic_altBlueprintConnectionName}} + agentic_scopes: ${{agentic_scopes}} + connections__service_connection__settings__clientId: "" + connections__service_connection__settings__clientSecret: "" + connections__service_connection__settings__tenantId: "" diff --git a/python/openai/sample-agent/m365agents.yml b/python/openai/sample-agent/m365agents.yml new file mode 100644 index 00000000..50d15fc3 --- /dev/null +++ b/python/openai/sample-agent/m365agents.yml @@ -0,0 +1,4 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 From e1cffdd343df04e2be92a1df2e11643d586258df Mon Sep 17 00:00:00 2001 From: Huihui Wu Date: Thu, 12 Mar 2026 10:35:01 +0800 Subject: [PATCH 5/6] fix: update readme and configurations --- python/openai/sample-agent/.vscode/launch.json | 5 +++-- python/openai/sample-agent/README.md | 12 ++++++++++++ python/openai/sample-agent/m365agents.playground.yml | 7 ++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/python/openai/sample-agent/.vscode/launch.json b/python/openai/sample-agent/.vscode/launch.json index 39622092..f684a410 100644 --- a/python/openai/sample-agent/.vscode/launch.json +++ b/python/openai/sample-agent/.vscode/launch.json @@ -5,8 +5,9 @@ "name": "Start Python", "type": "debugpy", "request": "launch", - "program": "${workspaceFolder}/src/app.py", - "cwd": "${workspaceFolder}/src", + "python": "${workspaceFolder}/.venv/Scripts/python.exe", + "program": "${workspaceFolder}/start_with_generic_host.py", + "cwd": "${workspaceFolder}", "console": "integratedTerminal", "serverReadyAction": { "pattern": "(started|listening|Running|Serving) (at|on) (https?://\\S+)", diff --git a/python/openai/sample-agent/README.md b/python/openai/sample-agent/README.md index c5ed224c..f16af1e1 100644 --- a/python/openai/sample-agent/README.md +++ b/python/openai/sample-agent/README.md @@ -24,6 +24,18 @@ For comprehensive documentation and guidance on building agents with the Microso > - OpenAI Agents SDK (openai-agents) > - A365 CLI: Required for agent deployment and management. +## Python Environment Configuration + +Set up the Python virtual environment manually before running the agent or deploy steps: + +1. Install `uv`: + - `pip install uv` +2. Create a virtual environment: + - `uv venv` +3. Activate the virtual environment: + - Windows PowerShell: `.venv\Scripts\Activate.ps1` + - macOS/Linux: `source .venv/bin/activate` + ## Working with User Identity On every incoming message, the A365 platform populates `activity.from_property` with basic user diff --git a/python/openai/sample-agent/m365agents.playground.yml b/python/openai/sample-agent/m365agents.playground.yml index eac0ae37..9b192ae7 100644 --- a/python/openai/sample-agent/m365agents.playground.yml +++ b/python/openai/sample-agent/m365agents.playground.yml @@ -15,6 +15,11 @@ deploy: nodejs: symlinkDir: ./devTools/nodejs + # Install Python dependencies + - uses: script + with: + run: uv pip install -e . + - uses: file/createOrUpdateEnvironmentFile with: target: ./.env @@ -24,7 +29,7 @@ deploy: AZURE_OPENAI_API_KEY: ${{SECRET_AZURE_OPENAI_API_KEY}} AZURE_OPENAI_ENDPOINT: ${{AZURE_OPENAI_ENDPOINT}} AZURE_OPENAI_DEPLOYMENT: ${{AZURE_OPENAI_DEPLOYMENT_NAME}} - OPENAI_API_KEY: ${{SECRET_OPENAI_API_KEY}} + # OPENAI_API_KEY: ${{SECRET_OPENAI_API_KEY}} BEARER_TOKEN: ${{SECRET_BEARER_TOKEN}} USE_AGENTIC_AUTH: ${{USE_AGENTIC_AUTH}} connectionsMap__0__serviceUrl: ${{connectionsMap__0__serviceUrl}} From 6604b9dac0efc33db7eede821a24f1b9f6b0bef6 Mon Sep 17 00:00:00 2001 From: Huihui Wu Date: Thu, 12 Mar 2026 17:26:45 +0800 Subject: [PATCH 6/6] feat: enable agent framework python sample to debug in atk playground --- .../agent-framework/sample-agent/.gitignore | 28 +++++++ .../sample-agent/.vscode/extensions.json | 6 ++ .../sample-agent/.vscode/launch.json | 48 ++++++++++++ .../.vscode/scripts/refresh-bearer-token.ps1 | 77 +++++++++++++++++++ .../sample-agent/.vscode/settings.json | 3 + .../sample-agent/.vscode/tasks.json | 52 +++++++++++++ python/agent-framework/sample-agent/README.md | 39 ++++++++-- .../sample-agent/env/.env.playground | 23 ++++++ .../sample-agent/env/.env.playground.user | 13 ++++ .../sample-agent/m365agents.playground.yml | 43 +++++++++++ .../sample-agent/m365agents.yml | 4 + 11 files changed, 331 insertions(+), 5 deletions(-) create mode 100644 python/agent-framework/sample-agent/.gitignore create mode 100644 python/agent-framework/sample-agent/.vscode/extensions.json create mode 100644 python/agent-framework/sample-agent/.vscode/launch.json create mode 100644 python/agent-framework/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 create mode 100644 python/agent-framework/sample-agent/.vscode/settings.json create mode 100644 python/agent-framework/sample-agent/.vscode/tasks.json create mode 100644 python/agent-framework/sample-agent/env/.env.playground create mode 100644 python/agent-framework/sample-agent/env/.env.playground.user create mode 100644 python/agent-framework/sample-agent/m365agents.playground.yml create mode 100644 python/agent-framework/sample-agent/m365agents.yml diff --git a/python/agent-framework/sample-agent/.gitignore b/python/agent-framework/sample-agent/.gitignore new file mode 100644 index 00000000..ba1c1747 --- /dev/null +++ b/python/agent-framework/sample-agent/.gitignore @@ -0,0 +1,28 @@ +# TeamsFx files +env/.env.*.user +env/.env.local +env/.env.sandbox +.localConfigs +.localConfigs.playground +.localConfigs +.notification.localstore.json +.notification.playgroundstore.json +appPackage/build + +# Python +__pycache__/ +*.pyc +*.pyo +*.egg-info/ +dist/ +build/ +.venv/ +venv/ + +# misc +.env +.deployment +.DS_Store + +# Dev tool directories +/devTools/ diff --git a/python/agent-framework/sample-agent/.vscode/extensions.json b/python/agent-framework/sample-agent/.vscode/extensions.json new file mode 100644 index 00000000..1f2ba3b2 --- /dev/null +++ b/python/agent-framework/sample-agent/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "TeamsDevApp.ms-teams-vscode-extension", + "ms-python.python" + ] +} diff --git a/python/agent-framework/sample-agent/.vscode/launch.json b/python/agent-framework/sample-agent/.vscode/launch.json new file mode 100644 index 00000000..5b004f21 --- /dev/null +++ b/python/agent-framework/sample-agent/.vscode/launch.json @@ -0,0 +1,48 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Start Python", + "type": "debugpy", + "request": "launch", + "python": "${workspaceFolder}/.venv/Scripts/python.exe", + "program": "${workspaceFolder}/start_with_generic_host.py", + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "serverReadyAction": { + "pattern": "(started|listening|Running|Serving) (at|on) (https?://\\S+)", + "action": "startDebugging", + "name": "Start Microsoft 365 Agents Playground" + } + }, + { + "name": "Start Microsoft 365 Agents Playground", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/devTools/playground/node_modules/@microsoft/m365agentsplayground/cli.js", + "args": [ + "start" + ], + "env": { + "PATH": "${workspaceFolder}/devTools/nodejs;${env:PATH}" + }, + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ], + "compounds": [ + { + "name": "Debug in Microsoft 365 Agents Playground", + "configurations": [ + "Start Python" + ], + "preLaunchTask": "Deploy (Microsoft 365 Agents Playground)", + "presentation": { + "group": "1-playground", + "order": 1 + }, + "stopAll": true + } + ] +} diff --git a/python/agent-framework/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 b/python/agent-framework/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 new file mode 100644 index 00000000..2fee52fa --- /dev/null +++ b/python/agent-framework/sample-agent/.vscode/scripts/refresh-bearer-token.ps1 @@ -0,0 +1,77 @@ +$ErrorActionPreference = 'Stop' + +$workspace = Get-Location +$playgroundEnvPath = Join-Path $workspace 'env/.env.playground' +$playgroundUserEnvPath = Join-Path $workspace 'env/.env.playground.user' + +$a365Command = Get-Command a365 -ErrorAction SilentlyContinue +if (-not $a365Command) { + throw "a365 CLI is not installed or not on PATH. Install with: dotnet tool install --global Microsoft.Agents.A365.DevTools.Cli" +} + +if (-not (Test-Path $playgroundEnvPath)) { + throw "Missing env file: $playgroundEnvPath" +} + +$appIdLine = Get-Content $playgroundEnvPath | Where-Object { $_ -match '^\s*CLIENT_APP_ID\s*=\s*.+$' } | Select-Object -First 1 +if (-not $appIdLine) { + throw "CLIENT_APP_ID is required in env/.env.playground" +} + +$appId = ($appIdLine -split '=', 2)[1].Trim() +if ([string]::IsNullOrWhiteSpace($appId)) { + throw "CLIENT_APP_ID in env/.env.playground is empty" +} + +Write-Host "Running a365 develop add-permissions for app id $appId" +& a365 develop add-permissions --app-id $appId +if ($LASTEXITCODE -ne 0) { + throw "a365 develop add-permissions failed" +} + +Write-Host "Getting bearer token via a365..." +Write-Host "This may complete silently using cached credentials, or it may require interactive Windows sign-in (WAM)." +Write-Host "If interactive sign-in is required and no prompt appears, check the taskbar for a hidden sign-in window and bring it to front." +Write-Host "Running a365 develop get-token for app id $appId" +$tokenOutput = & a365 develop get-token --app-id $appId --output raw +if ($LASTEXITCODE -ne 0) { + throw "a365 develop get-token failed" +} + +$rawOutput = [string]::Join("`n", $tokenOutput) +$rawOutput = $rawOutput -replace "`r", '' + +$bearerToken = $null +$jwtRegex = '(?[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)' +$jwtMatches = [regex]::Matches($rawOutput, $jwtRegex) +if ($jwtMatches.Count -gt 0) { + $bearerToken = ($jwtMatches | ForEach-Object { $_.Groups['token'].Value } | Sort-Object Length -Descending | Select-Object -First 1).Trim() +} + +if ([string]::IsNullOrWhiteSpace($bearerToken)) { + throw "Unable to extract a bearer token from a365 develop get-token output" +} + +$userEnvLines = @() +if (Test-Path $playgroundUserEnvPath) { + $userEnvLines = Get-Content $playgroundUserEnvPath +} + +$updated = $false +for ($i = 0; $i -lt $userEnvLines.Count; $i++) { + if ($userEnvLines[$i] -match '^\s*SECRET_BEARER_TOKEN\s*=') { + $userEnvLines[$i] = "SECRET_BEARER_TOKEN=$bearerToken" + $updated = $true + break + } +} + +if (-not $updated) { + if ($userEnvLines.Count -gt 0 -and -not [string]::IsNullOrWhiteSpace($userEnvLines[$userEnvLines.Count - 1])) { + $userEnvLines += '' + } + $userEnvLines += "SECRET_BEARER_TOKEN=$bearerToken" +} + +Set-Content -Path $playgroundUserEnvPath -Value $userEnvLines -Encoding UTF8 +Write-Host 'SECRET_BEARER_TOKEN has been updated in env/.env.playground.user' diff --git a/python/agent-framework/sample-agent/.vscode/settings.json b/python/agent-framework/sample-agent/.vscode/settings.json new file mode 100644 index 00000000..a9dd15cd --- /dev/null +++ b/python/agent-framework/sample-agent/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.defaultInterpreterPath": "${workspaceFolder}/.venv/Scripts/python.exe" +} diff --git a/python/agent-framework/sample-agent/.vscode/tasks.json b/python/agent-framework/sample-agent/.vscode/tasks.json new file mode 100644 index 00000000..637738e3 --- /dev/null +++ b/python/agent-framework/sample-agent/.vscode/tasks.json @@ -0,0 +1,52 @@ +{ + "version": "2.0.0", + "tasks": [ + { + // Check all required prerequisites. + // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. + "label": "Validate prerequisites (Microsoft 365 Agents Playground)", + "type": "teamsfx", + "command": "debug-check-prerequisites", + "args": { + "prerequisites": [ + "nodejs", // Check if Node.js is installed and the version is >= 12. + "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. + ], + "portOccupancy": [ + 3978, // app service port + 56150, // Microsoft 365 Agents Playground port + ] + } + }, + { + "label": "Refresh bearer token (Microsoft 365 Agents Playground)", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-File", + "${workspaceFolder}/.vscode/scripts/refresh-bearer-token.ps1" + ], + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + // Build project. + // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. + "label": "Deploy (Microsoft 365 Agents Playground)", + "dependsOn": [ + "Validate prerequisites (Microsoft 365 Agents Playground)", + "Refresh bearer token (Microsoft 365 Agents Playground)" + ], + "dependsOrder": "sequence", + "type": "teamsfx", + "command": "deploy", + "args": { + "env": "playground" + } + }, + ] +} diff --git a/python/agent-framework/sample-agent/README.md b/python/agent-framework/sample-agent/README.md index ad1040a3..5914717f 100644 --- a/python/agent-framework/sample-agent/README.md +++ b/python/agent-framework/sample-agent/README.md @@ -12,11 +12,29 @@ This sample uses the [Microsoft Agent 365 SDK for Python](https://github.com/mic For comprehensive documentation and guidance on building agents with the Microsoft Agent 365 SDK, including how to add tooling, observability, and notifications, visit the [Microsoft Agent 365 Developer Documentation](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/). ## Prerequisites - -- Python 3.x -- Microsoft Agent 365 SDK -- Agent Framework (agent-framework-azure-ai) -- Azure/OpenAI API credentials +> +> To run the template in your local dev machine, you will need: +> +> - [Python](https://www.python.org/), supported versions: 3.11 or higher +> - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) latest version +> - Prepare your own Azure OpenAI / OpenAI API credentials +> - Azure CLI signed in with `az login` + +> - Microsoft Agent 365 SDK +> - Agent Framework (agent-framework-azure-ai) +> - A365 CLI: Required for agent deployment and management. + +## Python Environment Configuration + +Set up the Python virtual environment manually before running the agent or deploy steps: + +1. Install `uv`: + - `pip install uv` +2. Create a virtual environment: + - `uv venv` +3. Activate the virtual environment: + - Windows PowerShell: `.venv\Scripts\Activate.ps1` + - macOS/Linux: `source .venv/bin/activate` ## Working with User Identity @@ -32,6 +50,17 @@ information — always available with no API calls or token acquisition: The sample logs these fields at the start of every message turn and injects the display name into the LLM system instructions for personalized responses. +## Running the Agent in Microsoft 365 Agents Playground + +1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. +1. In file *env/.env.playground.user*, fill in your Azure OpenAI key `SECRET_AZURE_OPENAI_API_KEY=`, endpoint `AZURE_OPENAI_ENDPOINT=`, and deployment name `AZURE_OPENAI_DEPLOYMENT_NAME=` if you're using Azure OpenAI. +1. In file *env/.env.playground.user*, fill in your OpenAI key `SECRET_OPENAI_API_KEY=` if you're using OpenAI. +1. In file *env/.env.playground*, fill in your custom app registration client id `CLIENT_APP_ID`. +1. Press F5 to start debugging which launches your agent in Microsoft 365 Agents Playground using a web browser. Select `Debug in Microsoft 365 Agents Playground`. +1. You can send any message to get a response from the agent. + +**Congratulations**! You are running an agent that can now interact with users in Microsoft 365 Agents Playground. + ## Running the Agent To set up and test this agent, refer to the [Configure Agent Testing](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/testing?tabs=python) guide for complete instructions. diff --git a/python/agent-framework/sample-agent/env/.env.playground b/python/agent-framework/sample-agent/env/.env.playground new file mode 100644 index 00000000..c1d20191 --- /dev/null +++ b/python/agent-framework/sample-agent/env/.env.playground @@ -0,0 +1,23 @@ +# This file includes environment variables that can be committed to git. It's gitignored by default because it represents your local development environment. + +# Built-in environment variables +TEAMSFX_ENV=playground + +# Environment variables used by Microsoft 365 Agents Playground +TEAMSAPPTESTER_PORT=56150 +TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json + +# Custom app registration needed for bearer token +CLIENT_APP_ID= + +# Use Agentic Authentication rather than OBO +USE_AGENTIC_AUTH=false + +# Set service connection as default +connectionsMap__0__serviceUrl=* +connectionsMap__0__connection=service_connection + +# AgenticAuthentication Options +agentic_type=agentic +agentic_altBlueprintConnectionName=service_connection +agentic_scopes=ea9ffc3e-8a23-4a7d-836d-234d7c7565c1/.default # Prod Agentic scope diff --git a/python/agent-framework/sample-agent/env/.env.playground.user b/python/agent-framework/sample-agent/env/.env.playground.user new file mode 100644 index 00000000..fbe833b4 --- /dev/null +++ b/python/agent-framework/sample-agent/env/.env.playground.user @@ -0,0 +1,13 @@ +# LLM Configuration (choose one option) + +# Option 1: Azure OpenAI (preferred for enterprise) +SECRET_AZURE_OPENAI_API_KEY= +AZURE_OPENAI_ENDPOINT= +AZURE_OPENAI_DEPLOYMENT_NAME= +AZURE_OPENAI_API_VERSION= + +# Option 2: OpenAI (if Azure OpenAI not configured) +# SECRET_OPENAI_API_KEY= +# OPENAI_MODEL=gpt-4o + +SECRET_BEARER_TOKEN= \ No newline at end of file diff --git a/python/agent-framework/sample-agent/m365agents.playground.yml b/python/agent-framework/sample-agent/m365agents.playground.yml new file mode 100644 index 00000000..a40acdb7 --- /dev/null +++ b/python/agent-framework/sample-agent/m365agents.playground.yml @@ -0,0 +1,43 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11 + +environmentFolderPath: ./env + +deploy: + # Install development tool(s) + - uses: devTool/install + with: + testTool: + version: ~0.2.7 + symlinkDir: ./devTools/playground + nodejs: + symlinkDir: ./devTools/nodejs + + # Install Python dependencies + - uses: script + with: + run: uv pip install -e . + + - uses: file/createOrUpdateEnvironmentFile + with: + target: ./.env + envs: + PORT: 3978 + TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} + AZURE_OPENAI_API_KEY: ${{SECRET_AZURE_OPENAI_API_KEY}} + AZURE_OPENAI_ENDPOINT: ${{AZURE_OPENAI_ENDPOINT}} + AZURE_OPENAI_DEPLOYMENT: ${{AZURE_OPENAI_DEPLOYMENT_NAME}} + AZURE_OPENAI_API_VERSION: ${{AZURE_OPENAI_API_VERSION}} + # OPENAI_API_KEY: ${{SECRET_OPENAI_API_KEY}} + BEARER_TOKEN: ${{SECRET_BEARER_TOKEN}} + USE_AGENTIC_AUTH: ${{USE_AGENTIC_AUTH}} + connectionsMap__0__serviceUrl: ${{connectionsMap__0__serviceUrl}} + connectionsMap__0__connection: ${{connectionsMap__0__connection}} + agentic_type: ${{agentic_type}} + agentic_altBlueprintConnectionName: ${{agentic_altBlueprintConnectionName}} + agentic_scopes: ${{agentic_scopes}} + connections__service_connection__settings__clientId: "" + connections__service_connection__settings__clientSecret: "" + connections__service_connection__settings__tenantId: "" diff --git a/python/agent-framework/sample-agent/m365agents.yml b/python/agent-framework/sample-agent/m365agents.yml new file mode 100644 index 00000000..50d15fc3 --- /dev/null +++ b/python/agent-framework/sample-agent/m365agents.yml @@ -0,0 +1,4 @@ +# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json +# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file +# Visit https://aka.ms/teamsfx-actions for details on actions +version: v1.11