├── src ├── test │ ├── README.md │ ├── .python-version │ ├── main.py │ ├── __pycache__ │ │ └── main.cpython-312.pyc │ └── pyproject.toml ├── repairs_api │ ├── README.md │ ├── .python-version │ ├── .env.sample │ ├── __pycache__ │ │ ├── main.cpython-312.pyc │ │ └── database.cpython-312.pyc │ ├── pyproject.toml │ ├── Dockerfile │ ├── database.py │ ├── testy.py │ ├── main.py │ └── openapi.yaml ├── advanced_repairs_api │ ├── .python-version │ ├── __pycache__ │ │ ├── main.cpython-312.pyc │ │ └── database.cpython-312.pyc │ ├── .env.sample │ ├── pyproject.toml │ ├── Dockerfile │ ├── README.md │ ├── testy.py │ ├── database.py │ └── main.py ├── toolkit_agent │ ├── .vscode │ │ ├── extensions.json │ │ ├── settings.json │ │ ├── tasks.json │ │ └── launch.json │ ├── appPackage │ │ ├── color.png │ │ ├── outline.png │ │ ├── instruction.txt │ │ ├── declarativeAgent.json │ │ └── manifest.json │ ├── .gitignore │ ├── m365agents.local.yml │ ├── m365agents.yml │ └── README.md ├── pythonagenttest │ ├── src │ │ ├── requirements.txt │ │ ├── config.py │ │ ├── app.py │ │ └── agent.py │ ├── .vscode │ │ ├── extensions.json │ │ ├── settings.json │ │ ├── launch.json │ │ └── tasks.json │ ├── appPackage │ │ ├── color.png │ │ ├── outline.png │ │ └── manifest.json │ ├── .webappignore │ ├── .gitignore │ ├── infra │ │ ├── botRegistration │ │ │ ├── readme.md │ │ │ └── azurebot.bicep │ │ ├── azure.parameters.json │ │ └── azure.bicep │ ├── m365agents.playground.yml │ ├── m365agents.local.yml │ ├── README.md │ └── m365agents.yml ├── service-desk-copilot │ ├── .vscode │ │ ├── extensions.json │ │ ├── mcp.json │ │ ├── settings.json │ │ ├── tasks.json │ │ └── launch.json │ ├── appPackage │ │ ├── color.png │ │ ├── outline.png │ │ ├── adaptiveCards │ │ │ ├── createRepair.data.json │ │ │ └── createRepair.json │ │ ├── instruction.txt │ │ ├── declarativeAgent.json │ │ ├── manifest.json │ │ ├── ai-plugin.json │ │ └── apiSpecificationFile │ │ │ └── openapi.yaml.original │ ├── .gitignore │ ├── m365agents.local.yml │ ├── .github │ │ └── copilot-instructions.md │ ├── m365agents.yml │ └── README.md ├── test-action-agent │ ├── .vscode │ │ ├── extensions.json │ │ ├── settings.json │ │ ├── launch.json │ │ └── tasks.json │ ├── appPackage │ │ ├── color.png │ │ ├── outline.png │ │ ├── instruction.txt │ │ ├── adaptiveCards │ │ │ ├── listRepairs.data.json │ │ │ └── listRepairs.json │ │ ├── repairDeclarativeAgent.json │ │ ├── manifest.json │ │ ├── ai-plugin.json │ │ └── apiSpecificationFile │ │ │ └── repair.yml │ ├── tsconfig.json │ ├── host.json │ ├── infra │ │ ├── azure.parameters.json │ │ └── azure.bicep │ ├── .funcignore │ ├── .gitignore │ ├── package.json │ ├── src │ │ ├── functions │ │ │ └── repairs.ts │ │ └── repairsData.json │ ├── m365agents.local.yml │ ├── m365agents.yml │ └── README.md └── advanced_service_desk_copilot │ ├── .vscode │ ├── extensions.json │ ├── settings.json │ ├── tasks.json │ └── launch.json │ ├── appPackage │ ├── color.png │ ├── outline.png │ ├── instruction.txt │ ├── declarativeAgent.json │ ├── manifest.json │ ├── ai-plugin.json │ └── adaptiveCards │ │ └── listRepairs.json │ ├── .gitignore │ ├── m365agents.local.yml │ ├── m365agents.yml │ └── README.md ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ └── main.yml ├── ISSUE_TEMPLATE.md └── copilot-instructions.md ├── .gitignore ├── .vscode └── mcp.json ├── Intro ├── api_key.md ├── db.md ├── copilot_headers.md └── intro.md ├── CONTRIBUTING.md ├── NOTICE ├── README.md └── LICENSE /src/test/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/repairs_api/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /src/repairs_api/.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /src/advanced_repairs_api/.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /src/toolkit_agent/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "TeamsDevApp.ms-teams-vscode-extension" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/pythonagenttest/src/requirements.txt: -------------------------------------------------------------------------------- 1 | python-dotenv 2 | microsoft-agents-hosting-aiohttp 3 | microsoft-agents-authentication-msal 4 | openai -------------------------------------------------------------------------------- /src/service-desk-copilot/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "TeamsDevApp.ms-teams-vscode-extension" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/test-action-agent/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "TeamsDevApp.ms-teams-vscode-extension" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Codeowners for these exercise files: 2 | # * (asterisk) deotes "all files and folders" 3 | # Example: * @producer @instructor 4 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "TeamsDevApp.ms-teams-vscode-extension" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/test/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | app = FastAPI() 4 | 5 | @app.get("/health") 6 | def health(): 7 | return {"status": "ok"} 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .tmp 4 | npm-debug.log 5 | .env 6 | .env.local 7 | .env.dev 8 | .env.test 9 | .env.prod 10 | .venv 11 | -------------------------------------------------------------------------------- /src/pythonagenttest/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "TeamsDevApp.ms-teams-vscode-extension", 4 | "ms-python.python" 5 | ] 6 | } -------------------------------------------------------------------------------- /src/pythonagenttest/appPackage/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/pythonagenttest/appPackage/color.png -------------------------------------------------------------------------------- /src/toolkit_agent/appPackage/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/toolkit_agent/appPackage/color.png -------------------------------------------------------------------------------- /src/toolkit_agent/appPackage/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/toolkit_agent/appPackage/outline.png -------------------------------------------------------------------------------- /src/pythonagenttest/appPackage/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/pythonagenttest/appPackage/outline.png -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/test-action-agent/appPackage/color.png -------------------------------------------------------------------------------- /src/test/__pycache__/main.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/test/__pycache__/main.cpython-312.pyc -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/service-desk-copilot/appPackage/color.png -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/test-action-agent/appPackage/outline.png -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/service-desk-copilot/appPackage/outline.png -------------------------------------------------------------------------------- /src/repairs_api/.env.sample: -------------------------------------------------------------------------------- 1 | COSMOS_ENDPOINT=https://ca-servicedesk.documents.azure.com:443/ 2 | COSMOS_KEY=ggdgdgdjajaj 3 | COSMOS_DATABASE=db-servicedesk 4 | COSMOS_CONTAINER=repairs -------------------------------------------------------------------------------- /src/repairs_api/__pycache__/main.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/repairs_api/__pycache__/main.cpython-312.pyc -------------------------------------------------------------------------------- /src/repairs_api/__pycache__/database.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/repairs_api/__pycache__/database.cpython-312.pyc -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/advanced_service_desk_copilot/appPackage/color.png -------------------------------------------------------------------------------- /src/advanced_repairs_api/__pycache__/main.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/advanced_repairs_api/__pycache__/main.cpython-312.pyc -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/advanced_service_desk_copilot/appPackage/outline.png -------------------------------------------------------------------------------- /src/pythonagenttest/.webappignore: -------------------------------------------------------------------------------- 1 | .venv/ 2 | .vscode/ 3 | .env 4 | env/ 5 | __pycache__/ 6 | README.md 7 | m365agents.yml 8 | m365agents.local.yml 9 | m365agents.playground.yml 10 | /devTools/ -------------------------------------------------------------------------------- /src/advanced_repairs_api/__pycache__/database.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInLearning/agentes-Copilot-Python-4165033/main/src/advanced_repairs_api/__pycache__/database.cpython-312.pyc -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/instruction.txt: -------------------------------------------------------------------------------- 1 | You are a declarative agent created with Microsoft 365 Agents Toolkit. Assist user in calling APIs and retrieving responses. You can only use data from actions. -------------------------------------------------------------------------------- /src/advanced_repairs_api/.env.sample: -------------------------------------------------------------------------------- 1 | COSMOS_ENDPOINT=https://ca-servicedesk.documents.azure.com:443/ 2 | COSMOS_KEY=ggdgdgdjajaj 3 | COSMOS_DATABASE=db-servicedesk 4 | COSMOS_CONTAINER=repairs 5 | SECRET_API_KEY=jyh7s345kl2mno90 -------------------------------------------------------------------------------- /src/toolkit_agent/.gitignore: -------------------------------------------------------------------------------- 1 | # TeamsFx files 2 | env/.env.*.user 3 | env/.env.local 4 | .localConfigs 5 | appPackage/build 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # misc 11 | .env 12 | .deployment 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /src/service-desk-copilot/.gitignore: -------------------------------------------------------------------------------- 1 | # TeamsFx files 2 | env/.env.*.user 3 | env/.env.local 4 | .localConfigs 5 | appPackage/build 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # misc 11 | .env 12 | .deployment 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/.gitignore: -------------------------------------------------------------------------------- 1 | # TeamsFx files 2 | env/.env.*.user 3 | env/.env.local 4 | .localConfigs 5 | appPackage/build 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # misc 11 | .env 12 | .deployment 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /src/test/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "test" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "fastapi[standard]>=0.123.4", 9 | ] 10 | -------------------------------------------------------------------------------- /.vscode/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "servers": { 3 | "m365agentstoolkit": { 4 | "command": "npx", 5 | "args": [ 6 | "@microsoft/m365agentstoolkit-mcp@latest", 7 | "server", 8 | "start" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/pythonagenttest/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug.onTaskErrors": "abort", 3 | "json.schemas": [ 4 | { 5 | "fileMatch": [ 6 | "/aad.*.json" 7 | ], 8 | "schema": {} 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /src/toolkit_agent/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug.onTaskErrors": "abort", 3 | "json.schemas": [ 4 | { 5 | "fileMatch": [ 6 | "/aad.*.json" 7 | ], 8 | "schema": {} 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/service-desk-copilot/.vscode/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "servers": { 3 | "m365agentstoolkit": { 4 | "command": "npx", 5 | "args": [ 6 | "@microsoft/m365agentstoolkit-mcp@latest", 7 | "server", 8 | "start" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/service-desk-copilot/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug.onTaskErrors": "abort", 3 | "json.schemas": [ 4 | { 5 | "fileMatch": [ 6 | "/aad.*.json" 7 | ], 8 | "schema": {} 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug.onTaskErrors": "abort", 3 | "json.schemas": [ 4 | { 5 | "fileMatch": [ 6 | "/aad.*.json" 7 | ], 8 | "schema": {} 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/adaptiveCards/createRepair.data.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "3", 3 | "item": "Laptop", 4 | "description": "Laptop is overheating after 10 minutes of use.", 5 | "status": "New", 6 | "assigned_to": "Tier 1 Support", 7 | "created_at": "2024-10-23T08:00:00Z" 8 | } 9 | -------------------------------------------------------------------------------- /src/pythonagenttest/.gitignore: -------------------------------------------------------------------------------- 1 | # TeamsFx files 2 | env/.env.*.user 3 | env/.env.local 4 | env/.env.playground 5 | .env 6 | appPackage/build 7 | 8 | # python virtual environment 9 | .venv/ 10 | __pycache__/ 11 | 12 | # others 13 | .deployment/ 14 | node_modules/ 15 | devTools/*.log 16 | 17 | # Dev tool directories 18 | /devTools/ 19 | -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/instruction.txt: -------------------------------------------------------------------------------- 1 | You will assist the user in finding car repair records based on the information provided by the user. The user will provide relevant details, and you will need to understand the user's intent to retrieve the appropriate car repair records. You can only access and leverage the data from the 'repairPlugin' action. -------------------------------------------------------------------------------- /src/test-action-agent/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "dist", 6 | "rootDir": ".", 7 | "sourceMap": true, 8 | "strict": false, 9 | "resolveJsonModule": true, 10 | "esModuleInterop": true, 11 | "typeRoots": ["./node_modules/@types"] 12 | } 13 | } -------------------------------------------------------------------------------- /src/pythonagenttest/infra/botRegistration/readme.md: -------------------------------------------------------------------------------- 1 | The `azurebot.bicep` module is provided to help you create Azure Bot service when you don't use Azure to host your app. If you use Azure as infrastrcture for your app, `azure.bicep` under infra folder already leverages this module to create Azure Bot service for you. You don't need to deploy `azurebot.bicep` again. -------------------------------------------------------------------------------- /src/test-action-agent/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug.onTaskErrors": "abort", 3 | "json.schemas": [ 4 | { 5 | "fileMatch": [ 6 | "/aad.*.json" 7 | ], 8 | "schema": {} 9 | } 10 | ], 11 | "azureFunctions.stopFuncTaskPostDebug": false, 12 | "azureFunctions.showProjectWarning": false, 13 | } 14 | -------------------------------------------------------------------------------- /src/repairs_api/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "service-desk-agent" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "azure-cosmos>=4.14.3", 9 | "fastapi[standard]>=0.123.10", 10 | "pyodbc>=5.3.0", 11 | "python-dotenv>=1.2.1", 12 | "sqlalchemy>=2.0", 13 | ] 14 | -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/adaptiveCards/listRepairs.data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "title": "Repairs", 5 | "description": "Repairs with their details and images", 6 | "assignedTo": "Karin", 7 | "date": "2025-2-20T05:25:43.593Z", 8 | "image": "https://th.bing.com/th/id/OIP.N64J4jmqmnbQc5dHvTm-QAHaE8" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /src/test-action-agent/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingSettings": { 6 | "isEnabled": true, 7 | "excludedTypes": "Request" 8 | } 9 | } 10 | }, 11 | "extensionBundle": { 12 | "id": "Microsoft.Azure.Functions.ExtensionBundle", 13 | "version": "[4.*, 5.0.0)" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test-action-agent/infra/azure.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "resourceBaseName": { 6 | "value": "plugin${{RESOURCE_SUFFIX}}" 7 | }, 8 | "functionAppSKU": { 9 | "value": "Y1" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test-action-agent/.funcignore: -------------------------------------------------------------------------------- 1 | .funcignore 2 | *.js.map 3 | *.ts 4 | .git* 5 | .localConfigs 6 | .vscode 7 | local.settings.json 8 | test 9 | tsconfig.json 10 | .DS_Store 11 | .deployment 12 | node_modules/.bin 13 | node_modules/azure-functions-core-tools 14 | README.md 15 | tsconfig.json 16 | m365agents.yml 17 | m365agents.*.yml 18 | /env/ 19 | /appPackage/ 20 | /infra/ 21 | /devTools/ -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Copy To Branches 2 | on: 3 | workflow_dispatch: 4 | jobs: 5 | copy-to-branches: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | with: 10 | fetch-depth: 0 11 | - name: Copy To Branches Action 12 | uses: planetoftheweb/copy-to-branches@v1.2 13 | env: 14 | key: main 15 | -------------------------------------------------------------------------------- /src/advanced_repairs_api/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "service-desk-agent" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "azure-cosmos>=4.14.3", 9 | "fastapi[standard]>=0.123.10", 10 | "pyodbc>=5.3.0", 11 | "python-dotenv>=1.2.1", 12 | "sqlalchemy>=2.0", 13 | ] 14 | -------------------------------------------------------------------------------- /Intro/api_key.md: -------------------------------------------------------------------------------- 1 | ## Marcar el API como protegido en OpenAPI 2 | 3 | Para marcar el API como protegido en la especificación OpenAPI, debes agregar una sección de seguridad en el archivo OpenAPI (generalmente un archivo YAML o JSON). Aquí tienes un ejemplo de cómo hacerlo en YAML: 4 | 5 | ```yaml 6 | components: 7 | securitySchemes: 8 | apiKey: 9 | type: http 10 | scheme: bearer 11 | ``` 12 | -------------------------------------------------------------------------------- /Intro/db.md: -------------------------------------------------------------------------------- 1 | # Definir el modelo de datos para la BD 2 | 3 | Esquema y ejemplo de `repairs`. 4 | 5 | 6 | ## Cosmos DB - Esquema de `repairs.items` 7 | 8 | ```json 9 | { 10 | "id": "778a4821-9312-4df4-9e0e-57d731b3ed12", 11 | "item": "phone", 12 | "description": "broken screen", 13 | "status": "New", 14 | "assigned_to": "Jane Doe", 15 | "created_at": "2025-12-09T23:40:13.119727Z", 16 | } 17 | ``` -------------------------------------------------------------------------------- /src/toolkit_agent/appPackage/instruction.txt: -------------------------------------------------------------------------------- 1 | You are Joke Agent AI, an AI specialized in telling jokes based on user preferences. Your task is to provide humorous content that aligns with the user's sense of humor. 2 | 3 | Your job is to: 4 | - Understand the user's preferences for jokes (e.g., type of humor, topics they enjoy). 5 | - Generate jokes that fit those preferences. 6 | 7 | Always: 8 | - Answer in the same language the user used. 9 | - Make it a "knock-knock" joke format. 10 | - Finish with emojis that match the joke's theme. -------------------------------------------------------------------------------- /src/test-action-agent/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | # TeamsFx files 3 | env/.env.*.user 4 | env/.env.local 5 | .DS_Store 6 | build 7 | appPackage/build 8 | .deployment 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # testing 14 | /coverage 15 | 16 | # Dev tool directories 17 | /devTools/ 18 | 19 | # TypeScript output 20 | dist 21 | out 22 | 23 | # Azure Functions artifacts 24 | bin 25 | obj 26 | appsettings.json 27 | local.settings.json 28 | 29 | # Local data 30 | .localConfigs -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/instruction.txt: -------------------------------------------------------------------------------- 1 | You are a support agent that helps users to create repair tickets and list their already created tickets. 2 | 3 | When the user asks for: 4 | - a list of repairs, 5 | - filtering repairs by status or assignee, 6 | - or any question about "all current repairs" or "current state of repairs", 7 | 8 | you MUST call the `listRepairs` function of the Repair Service API plugin. 9 | Do NOT rely only on previous conversation history to answer questions about the current list of repairs. The API is the source of truth. 10 | -------------------------------------------------------------------------------- /src/pythonagenttest/src/config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) Microsoft Corporation. All rights reserved. 3 | Licensed under the MIT License. 4 | """ 5 | 6 | class Config: 7 | """Agent Configuration""" 8 | 9 | def __init__(self, env): 10 | self.PORT = 3978 11 | self.azure_openai_api_key = env["AZURE_OPENAI_API_KEY"] # Azure OpenAI API key 12 | self.azure_openai_deployment_name = env["AZURE_OPENAI_DEPLOYMENT_NAME"] # Azure OpenAI model deployment name 13 | self.azure_openai_endpoint = env["AZURE_OPENAI_ENDPOINT"] # Azure OpenAI endpoint 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | Contribution Agreement 3 | ====================== 4 | 5 | This repository does not accept pull requests (PRs). All pull requests will be closed. 6 | 7 | However, if any contributions (through pull requests, issues, feedback or otherwise) are provided, as a contributor, you represent that the code you submit is your original work or that of your employer (in which case you represent you have the right to bind your employer). By submitting code (or otherwise providing feedback), you (and, if applicable, your employer) are licensing the submitted code (and/or feedback) to LinkedIn and the open source community subject to the BSD 2-Clause license. 8 | -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/repairDeclarativeAgent.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", 3 | "version": "v1.5", 4 | "name": "test-action-agent${{APP_NAME_SUFFIX}}", 5 | "description": "This declarative agent helps you with finding car repair records.", 6 | "instructions": "$[file('instruction.txt')]", 7 | "conversation_starters": [ 8 | { 9 | "text": "Show repair records assigned to Karin Blair" 10 | } 11 | ], 12 | "actions": [ 13 | { 14 | "id": "repairPlugin", 15 | "file": "ai-plugin.json" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2026 LinkedIn Corporation 2 | All Rights Reserved. 3 | 4 | Licensed under the LinkedIn Learning Exercise File License (the "License"). 5 | See LICENSE in the project root for license information. 6 | 7 | ATTRIBUTIONS: 8 | [PLEASE PROVIDE ATTRIBUTIONS OR DELETE THIS AND THE ABOVE LINE “ATTRIBUTIONS”] 9 | 10 | Please note, this project may automatically load third party code from external 11 | repositories (for example, NPM modules, Composer packages, or other dependencies). 12 | If so, such third party code may be subject to other license terms than as set 13 | forth above. In addition, such third party code may also depend on and load 14 | multiple tiers of dependencies. Please review the applicable licenses of the 15 | additional dependencies. 16 | -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/declarativeAgent.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", 3 | "version": "v1.5", 4 | "name": "service-desk-copilot", 5 | "description": "Declarative agent created with Microsoft 365 Agents Toolkit can assist user in calling APIs and retrieving responses", 6 | "instructions": "$[file('instruction.txt')]", 7 | "actions": [ 8 | { 9 | "id": "action_1", 10 | "file": "ai-plugin.json" 11 | } 12 | ], 13 | "conversation_starters": [ 14 | { 15 | "text": "List all repair tickets" 16 | }, 17 | { 18 | "text": "Create a new repair" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/declarativeAgent.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", 3 | "version": "v1.5", 4 | "name": "advanced_service_desk_copilot", 5 | "description": "Declarative agent created with Microsoft 365 Agents Toolkit can assist user in calling APIs and retrieving responses", 6 | "instructions": "$[file('instruction.txt')]", 7 | "actions": [ 8 | { 9 | "id": "action_1", 10 | "file": "ai-plugin.json" 11 | } 12 | ], 13 | "conversation_starters": [ 14 | { 15 | "text": "List all repairs" 16 | }, 17 | { 18 | "text": "Create a new repair" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/pythonagenttest/infra/azure.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "resourceBaseName": { 6 | "value": "bot${{RESOURCE_SUFFIX}}" 7 | }, 8 | "azureOpenaiKey": { 9 | "value": "${{SECRET_AZURE_OPENAI_API_KEY}}" 10 | }, 11 | "azureOpenaiModelDeploymentName" : { 12 | "value": "${{AZURE_OPENAI_DEPLOYMENT_NAME}}" 13 | }, 14 | "azureOpenaiEndpoint" : { 15 | "value": "${{AZURE_OPENAI_ENDPOINT}}" 16 | }, 17 | "webAppSKU": { 18 | "value": "B1" 19 | }, 20 | "botDisplayName": { 21 | "value": "pythonagenttest" 22 | }, 23 | "linuxFxVersion": { 24 | "value": "PYTHON|3.11" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/toolkit_agent/appPackage/declarativeAgent.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", 3 | "version": "v1.5", 4 | "name": "Joke Agent AI${{APP_NAME_SUFFIX}}", 5 | "description": "It´s a funny agent that tells jokes based on user preferences.", 6 | "instructions": "$[file('instruction.txt')]", 7 | "conversation_starters": [ 8 | { 9 | "title": "Technical Jokes", 10 | "text": "Get a tech-related joke to lighten up your day." 11 | }, 12 | { 13 | "title": "Animal Jokes", 14 | "text": "Hear a funny animal joke." 15 | }, 16 | { 17 | "title": "Random Joke", 18 | "text": "Surprise me with a random joke." 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/repairs_api/Dockerfile: -------------------------------------------------------------------------------- 1 | # Imagen base con Python 3.12 2 | FROM python:3.12-slim 3 | 4 | # No .pyc y logs sin buffer 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Directorio de trabajo 9 | WORKDIR /app 10 | 11 | # Copiamos los archivos de dependencias de uv 12 | COPY pyproject.toml uv.lock ./ 13 | 14 | # Instalamos uv (gestor de deps) 15 | RUN pip install --no-cache-dir uv 16 | 17 | # Instalamos dependencias según el lockfile (sin las de dev) 18 | RUN uv sync --frozen --no-dev 19 | 20 | # Copiamos el resto del código (incluye main.py) 21 | COPY . . 22 | 23 | # Exponemos el puerto interno 24 | EXPOSE 8000 25 | 26 | # Arrancamos la API FastAPI en 0.0.0.0:8000 27 | # OJO: aquí usamos main:app (tu fichero + tu objeto FastAPI) 28 | CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] 29 | -------------------------------------------------------------------------------- /src/advanced_repairs_api/Dockerfile: -------------------------------------------------------------------------------- 1 | # Imagen base con Python 3.12 2 | FROM python:3.12-slim 3 | 4 | # No .pyc y logs sin buffer 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Directorio de trabajo 9 | WORKDIR /app 10 | 11 | # Copiamos los archivos de dependencias de uv 12 | COPY pyproject.toml uv.lock ./ 13 | 14 | # Instalamos uv (gestor de deps) 15 | RUN pip install --no-cache-dir uv 16 | 17 | # Instalamos dependencias según el lockfile (sin las de dev) 18 | RUN uv sync --frozen --no-dev 19 | 20 | # Copiamos el resto del código (incluye main.py) 21 | COPY . . 22 | 23 | # Exponemos el puerto interno 24 | EXPOSE 8000 25 | 26 | # Arrancamos la API FastAPI en 0.0.0.0:8000 27 | # OJO: aquí usamos main:app (tu fichero + tu objeto FastAPI) 28 | CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] 29 | -------------------------------------------------------------------------------- /src/test-action-agent/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testactionagent", 3 | "version": "1.0.0", 4 | "engines": { 5 | "node": "18 || 20 || 22" 6 | }, 7 | "scripts": { 8 | "dev:teamsfx": "env-cmd --silent -f .localConfigs npm run dev", 9 | "dev": "func start --typescript --language-worker=\"--inspect=9229\" --port \"7071\" --cors \"*\"", 10 | "build": "tsc", 11 | "watch:teamsfx": "tsc --watch", 12 | "watch": "tsc -w", 13 | "prestart": "npm run build", 14 | "start": "npx func start", 15 | "test": "echo \"Error: no test specified\" && exit 1" 16 | }, 17 | "dependencies": { 18 | "@azure/functions": "^4.3.0" 19 | }, 20 | "devDependencies": { 21 | "env-cmd": "^10.1.0", 22 | "@types/node": "^18.11.9", 23 | "typescript": "^4.1.6" 24 | }, 25 | "main": "dist/src/functions/*.js" 26 | } 27 | -------------------------------------------------------------------------------- /src/pythonagenttest/m365agents.playground.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.11 5 | 6 | deploy: 7 | # Install development tool(s) 8 | - uses: devTool/install 9 | with: 10 | testTool: 11 | version: ~0.2.1 12 | symlinkDir: ./devTools/teamsapptester 13 | nodejs: 14 | symlinkDir: ./devTools/nodejs 15 | 16 | # Generate runtime environment variables 17 | - uses: file/createOrUpdateEnvironmentFile 18 | with: 19 | target: ./.env 20 | envs: 21 | CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID: "" 22 | CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET: "" 23 | CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID: "" 24 | AZURE_OPENAI_API_KEY: ${{SECRET_AZURE_OPENAI_API_KEY}} 25 | AZURE_OPENAI_DEPLOYMENT_NAME: ${{AZURE_OPENAI_DEPLOYMENT_NAME}} 26 | AZURE_OPENAI_ENDPOINT: ${{AZURE_OPENAI_ENDPOINT}} 27 | -------------------------------------------------------------------------------- /src/toolkit_agent/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by Microsoft 365 Agents Toolkit. 2 | // The teamsfx tasks defined in this file require Microsoft 365 Agents Toolkit version >= 5.0.0. 3 | // See https://aka.ms/teamsfx-tasks for details on how to customize each task. 4 | { 5 | "version": "2.0.0", 6 | "tasks": [ 7 | { 8 | "label": "Start Agent Locally", 9 | "dependsOn": [ 10 | "Validate prerequisites", 11 | "Create resources" 12 | ], 13 | "dependsOrder": "sequence" 14 | }, 15 | { 16 | "label": "Validate prerequisites", 17 | "type": "teamsfx", 18 | "command": "debug-check-prerequisites", 19 | "args": { 20 | "prerequisites": [ 21 | "m365Account" 22 | ] 23 | } 24 | }, 25 | { 26 | "label": "Create resources", 27 | "type": "teamsfx", 28 | "command": "provision", 29 | "args": { 30 | "env": "local" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /src/service-desk-copilot/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by Microsoft 365 Agents Toolkit. 2 | // The teamsfx tasks defined in this file require Microsoft 365 Agents Toolkit version >= 5.0.0. 3 | // See https://aka.ms/teamsfx-tasks for details on how to customize each task. 4 | { 5 | "version": "2.0.0", 6 | "tasks": [ 7 | { 8 | "label": "Start Agent Locally", 9 | "dependsOn": [ 10 | "Validate prerequisites", 11 | "Create resources" 12 | ], 13 | "dependsOrder": "sequence" 14 | }, 15 | { 16 | "label": "Validate prerequisites", 17 | "type": "teamsfx", 18 | "command": "debug-check-prerequisites", 19 | "args": { 20 | "prerequisites": [ 21 | "m365Account" 22 | ] 23 | } 24 | }, 25 | { 26 | "label": "Create resources", 27 | "type": "teamsfx", 28 | "command": "provision", 29 | "args": { 30 | "env": "local" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by Microsoft 365 Agents Toolkit. 2 | // The teamsfx tasks defined in this file require Microsoft 365 Agents Toolkit version >= 5.0.0. 3 | // See https://aka.ms/teamsfx-tasks for details on how to customize each task. 4 | { 5 | "version": "2.0.0", 6 | "tasks": [ 7 | { 8 | "label": "Start Agent Locally", 9 | "dependsOn": [ 10 | "Validate prerequisites", 11 | "Create resources" 12 | ], 13 | "dependsOrder": "sequence" 14 | }, 15 | { 16 | "label": "Validate prerequisites", 17 | "type": "teamsfx", 18 | "command": "debug-check-prerequisites", 19 | "args": { 20 | "prerequisites": [ 21 | "m365Account" 22 | ] 23 | } 24 | }, 25 | { 26 | "label": "Create resources", 27 | "type": "teamsfx", 28 | "command": "provision", 29 | "args": { 30 | "env": "local" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ## Issue Overview 9 | 10 | 11 | ## Describe your environment 12 | 13 | 14 | ## Steps to Reproduce 15 | 16 | 1. 17 | 2. 18 | 3. 19 | 4. 20 | 21 | ## Expected Behavior 22 | 23 | 24 | ## Current Behavior 25 | 26 | 27 | ## Possible Solution 28 | 29 | 30 | ## Screenshots / Video 31 | 32 | 33 | ## Related Issues 34 | 35 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.24/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.24", 4 | "version": "1.0.0", 5 | "id": "${{TEAMS_APP_ID}}", 6 | "developer": { 7 | "name": "My App, Inc.", 8 | "websiteUrl": "https://www.example.com", 9 | "privacyUrl": "https://www.example.com/privacy", 10 | "termsOfUseUrl": "https://www.example.com/termofuse" 11 | }, 12 | "icons": { 13 | "color": "color.png", 14 | "outline": "outline.png" 15 | }, 16 | "name": { 17 | "short": "advanced_service_desk_cop${{APP_NAME_SUFFIX}}", 18 | "full": "Full name for advanced_service_desk_copilot" 19 | }, 20 | "description": { 21 | "short": "Short description for advanced_service_desk_copilot", 22 | "full": "Full description for advanced_service_desk_copilot" 23 | }, 24 | "accentColor": "#FFFFFF", 25 | "copilotAgents": { 26 | "declarativeAgents": [ 27 | { 28 | "id": "declarativeAgent", 29 | "file": "declarativeAgent.json" 30 | } 31 | ] 32 | }, 33 | "permissions": [ 34 | "identity", 35 | "messageTeamMembers" 36 | ], 37 | "validDomains": [] 38 | } -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/adaptiveCards/listRepairs.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "AdaptiveCard", 3 | "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 4 | "version": "1.5", 5 | "body": [ 6 | { 7 | "type": "Container", 8 | "$data": "${$root}", 9 | "items": [ 10 | { 11 | "type": "TextBlock", 12 | "text": "id: ${if(id, id, 'N/A')}", 13 | "wrap": true 14 | }, 15 | { 16 | "type": "TextBlock", 17 | "text": "title: ${if(title, title, 'N/A')}", 18 | "wrap": true 19 | }, 20 | { 21 | "type": "TextBlock", 22 | "text": "description: ${if(description, description, 'N/A')}", 23 | "wrap": true 24 | }, 25 | { 26 | "type": "TextBlock", 27 | "text": "assignedTo: ${if(assignedTo, assignedTo, 'N/A')}", 28 | "wrap": true 29 | }, 30 | { 31 | "type": "TextBlock", 32 | "text": "date: ${if(date, date, 'N/A')}", 33 | "wrap": true 34 | }, 35 | { 36 | "type": "Image", 37 | "url": "${image}", 38 | "$when": "${image != null}" 39 | } 40 | ] 41 | } 42 | ] 43 | } -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.24/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.24", 4 | "id": "${{TEAMS_APP_ID}}", 5 | "version": "1.0.0", 6 | "developer": { 7 | "name": "My App, Inc.", 8 | "websiteUrl": "https://www.example.com", 9 | "privacyUrl": "https://www.example.com/privacy", 10 | "termsOfUseUrl": "https://www.example.com/termsofuse" 11 | }, 12 | "icons": { 13 | "color": "color.png", 14 | "outline": "outline.png" 15 | }, 16 | "name": { 17 | "short": "test-action-agent${{APP_NAME_SUFFIX}}", 18 | "full": "Full name for test-action-agent" 19 | }, 20 | "description": { 21 | "short": "Track and monitor car repair records for stress-free maintenance management.", 22 | "full": "The ultimate solution for hassle-free car maintenance management makes tracking and monitoring your car repair records a breeze." 23 | }, 24 | "accentColor": "#FFFFFF", 25 | "copilotAgents": { 26 | "declarativeAgents": [ 27 | { 28 | "id": "repairDeclarativeAgent", 29 | "file": "repairDeclarativeAgent.json" 30 | } 31 | ] 32 | }, 33 | "permissions": [ 34 | "identity", 35 | "messageTeamMembers" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /src/toolkit_agent/appPackage/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.24/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.24", 4 | "version": "1.0.5", 5 | "id": "${{TEAMS_APP_ID}}", 6 | "developer": { 7 | "name": "My App, Inc.", 8 | "websiteUrl": "https://www.example.com", 9 | "privacyUrl": "https://www.example.com/privacy", 10 | "termsOfUseUrl": "https://www.example.com/termofuse" 11 | }, 12 | "icons": { 13 | "color": "color.png", 14 | "outline": "outline.png" 15 | }, 16 | "name": { 17 | "short": "toolkit_agent${{APP_NAME_SUFFIX}}", 18 | "full": "Full name for toolkit_agent" 19 | }, 20 | "description": { 21 | "short": "Short description for toolkit_agent", 22 | "full": "Full description for toolkit_agent" 23 | }, 24 | "accentColor": "#FFFFFF", 25 | "composeExtensions": [], 26 | "permissions": [ 27 | "identity", 28 | "messageTeamMembers" 29 | ], 30 | "copilotAgents": { 31 | "declarativeAgents": [ 32 | { 33 | "id": "declarativeAgent", 34 | "file": "declarativeAgent.json" 35 | } 36 | ] 37 | }, 38 | "validDomains": [] 39 | } -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.24/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.24", 4 | "version": "1.0.5", 5 | "id": "${{TEAMS_APP_ID}}", 6 | "developer": { 7 | "name": "My App, Inc.", 8 | "websiteUrl": "https://www.example.com", 9 | "privacyUrl": "https://www.example.com/privacy", 10 | "termsOfUseUrl": "https://www.example.com/termofuse" 11 | }, 12 | "icons": { 13 | "color": "color.png", 14 | "outline": "outline.png" 15 | }, 16 | "name": { 17 | "short": "service-desk-copilot${{APP_NAME_SUFFIX}}", 18 | "full": "Full name for service-desk-copilot" 19 | }, 20 | "description": { 21 | "short": "Short description for service-desk-copilot", 22 | "full": "Full description for service-desk-copilot" 23 | }, 24 | "accentColor": "#FFFFFF", 25 | "copilotAgents": { 26 | "declarativeAgents": [ 27 | { 28 | "id": "declarativeAgent", 29 | "file": "declarativeAgent.json" 30 | } 31 | ] 32 | }, 33 | "permissions": [ 34 | "identity", 35 | "messageTeamMembers" 36 | ], 37 | "validDomains": [] 38 | } -------------------------------------------------------------------------------- /src/pythonagenttest/infra/botRegistration/azurebot.bicep: -------------------------------------------------------------------------------- 1 | @maxLength(20) 2 | @minLength(4) 3 | @description('Used to generate names for all resources in this file') 4 | param resourceBaseName string 5 | 6 | @maxLength(42) 7 | param botDisplayName string 8 | 9 | param botServiceName string = resourceBaseName 10 | param botServiceSku string = 'F0' 11 | param identityResourceId string 12 | param identityClientId string 13 | param identityTenantId string 14 | param botAppDomain string 15 | 16 | // Register your web service as a bot with the Bot Framework 17 | resource botService 'Microsoft.BotService/botServices@2021-03-01' = { 18 | kind: 'azurebot' 19 | location: 'global' 20 | name: botServiceName 21 | properties: { 22 | displayName: botDisplayName 23 | endpoint: 'https://${botAppDomain}/api/messages' 24 | msaAppId: identityClientId 25 | msaAppMSIResourceId: identityResourceId 26 | msaAppTenantId:identityTenantId 27 | msaAppType:'UserAssignedMSI' 28 | } 29 | sku: { 30 | name: botServiceSku 31 | } 32 | } 33 | 34 | // Connect the bot service to Microsoft Teams 35 | resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { 36 | parent: botService 37 | location: 'global' 38 | name: 'MsTeamsChannel' 39 | properties: { 40 | channelName: 'MsTeamsChannel' 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/adaptiveCards/createRepair.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 3 | "type": "AdaptiveCard", 4 | "version": "1.5", 5 | "body": [{ 6 | "type": "TextBlock", 7 | "text": "Repair ticket created ✅", 8 | "size": "Large", 9 | "weight": "Bolder", 10 | "horizontalAlignment": "Center" 11 | }, 12 | { 13 | "type": "Container", 14 | "spacing": "Medium", 15 | "items": [ 16 | { 17 | "type": "TextBlock", 18 | "text": "Ticket ID: ${id}", 19 | "weight": "Bolder" 20 | }, 21 | { 22 | "type": "TextBlock", 23 | "text": "${item}", 24 | "weight": "Bolder", 25 | "spacing": "Small" 26 | }, 27 | { 28 | "type": "TextBlock", 29 | "text": "${description}", 30 | "wrap": true 31 | }, 32 | { 33 | "type": "FactSet", 34 | "facts": [ 35 | { 36 | "title": "Status:", 37 | "value": "${status}" 38 | }, 39 | { 40 | "title": "Assigned to:", 41 | "value": "${if(assigned_to, assigned_to, 'Unassigned')}" 42 | }, 43 | { 44 | "title": "Created at:", 45 | "value": "${created_at}" 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /src/pythonagenttest/src/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from microsoft_agents.hosting.core import AgentApplication, AgentAuthConfiguration 3 | from microsoft_agents.hosting.aiohttp import ( 4 | start_agent_process, 5 | jwt_authorization_middleware, 6 | CloudAdapter, 7 | ) 8 | from aiohttp.web import Request, Response, Application, run_app 9 | 10 | from agent import agent_app, connection_manager 11 | 12 | 13 | def start_server( 14 | agent_application: AgentApplication, auth_configuration: AgentAuthConfiguration 15 | ): 16 | async def entry_point(req: Request) -> Response: 17 | agent: AgentApplication = req.app["agent_app"] 18 | adapter: CloudAdapter = req.app["adapter"] 19 | return await start_agent_process( 20 | req, 21 | agent, 22 | adapter, 23 | ) 24 | 25 | app = Application(middlewares=[jwt_authorization_middleware]) 26 | app.router.add_post("/api/messages", entry_point) 27 | app["agent_configuration"] = auth_configuration 28 | app["agent_app"] = agent_application 29 | app["adapter"] = agent_application.adapter 30 | 31 | try: 32 | run_app(app, host="localhost", port=os.environ.get("PORT", 3978)) 33 | except Exception as error: 34 | raise error 35 | 36 | 37 | if __name__ == "__main__": 38 | start_server( 39 | agent_application=agent_app, 40 | auth_configuration=connection_manager.get_default_connection_configuration(), 41 | ) 42 | -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/ai-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.2/schema.json", 3 | "schema_version": "v2.2", 4 | "namespace": "repairs", 5 | "name_for_human": "test-action-agent${{APP_NAME_SUFFIX}}", 6 | "description_for_human": "Track your repair records", 7 | "description_for_model": "Plugin for searching a repair list, you can search by who's assigned to the repair.", 8 | "functions": [ 9 | { 10 | "name": "listRepairs", 11 | "description": "Returns a list of repairs with their details and images", 12 | "capabilities": { 13 | "response_semantics": { 14 | "data_path": "$.results", 15 | "properties": { 16 | "title": "$.title", 17 | "subtitle": "$.description" 18 | }, 19 | "static_template": { 20 | "file": "adaptiveCards/listRepairs.json" 21 | } 22 | } 23 | } 24 | } 25 | ], 26 | "runtimes": [ 27 | { 28 | "type": "OpenApi", 29 | "auth": { 30 | "type": "None" 31 | }, 32 | "spec": { 33 | "url": "apiSpecificationFile/repair.yml", 34 | "progress_style": "ShowUsageWithInputAndOutput" 35 | }, 36 | "run_for_functions": ["listRepairs"] 37 | } 38 | ], 39 | "capabilities": { 40 | "conversation_starters": [ 41 | { 42 | "text": "List all repairs" 43 | } 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Intro/copilot_headers.md: -------------------------------------------------------------------------------- 1 | # Agent debug info: 2 | 3 | * X-Microsoft-AI-ConversationId 4 | 5 | * X-Microsoft-TenantID 6 | 7 | * X-Microsoft-AI-UserLocale 8 | 9 | * X-Microsoft-AI-UserTimeZone 10 | 11 | ### Models 12 | 13 | ```python 14 | class RepairBase(BaseModel): 15 | item: str 16 | description: str 17 | status: str = "New" 18 | assigned_to: Optional[str] = None 19 | 20 | class Repair(RepairBase): 21 | id: str 22 | created_at: datetime 23 | 24 | class RepairCreate(RepairBase): 25 | """Payload for creating a new repair ticket.""" 26 | ``` 27 | 28 | ### Endpoints 29 | 30 | ```python 31 | 32 | from fastapi import FastAPI, Query 33 | # ... 34 | 35 | @app.post( 36 | "/repairs", 37 | response_model=Repair, 38 | status_code=201, 39 | operation_id="createRepair", 40 | ) 41 | def create_repair(payload: RepairCreate) -> Repair: 42 | repair = Repair( 43 | id=str(uuid4()), 44 | created_at=datetime.utcnow(), 45 | **payload.model_dump(), 46 | ) 47 | repairs_db.append(repair) 48 | return repair 49 | ``` 50 | 51 | ### Database 52 | 53 | ```python 54 | def create_repair_in_db( 55 | item: str, 56 | description: str, 57 | status: str = "New", 58 | assigned_to: Optional[str] = None, 59 | ) -> Dict[str, Any]: 60 | repair_id = str(uuid4()) 61 | created_at = datetime.utcnow().isoformat() 62 | 63 | doc = { 64 | "id": repair_id, 65 | "item": item, 66 | "description": description, 67 | "status": status, 68 | "assigned_to": assigned_to, 69 | "created_at": created_at, 70 | } 71 | 72 | container.create_item(doc) 73 | return doc 74 | ``` -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/ai-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.3/schema.json", 3 | "schema_version": "v2.3", 4 | "name_for_human": "Repair Service - Subset - Subset", 5 | "description_for_human": "A simple service to manage repair tickets for devices so that Microsoft 365 Copilot agents can list, inspect, and create repairs on behalf of users.\n", 6 | "description_for_model": "A simple service to manage repair tickets for devices so that Microsoft 365 Copilot agents can list, inspect, and create repairs on behalf of users.\n", 7 | "contact_email": "publisher-email@example.com", 8 | "namespace": "advancedservicedeskcopilot", 9 | "capabilities": {}, 10 | "functions": [ 11 | { 12 | "name": "createRepair", 13 | "description": "Create a new repair ticket for a device that needs to be fixed." 14 | }, 15 | { 16 | "name": "listRepairs", 17 | "description": "Returns a list of repair tickets with their details. You can optionally filter by status or by who the repair is assigned to.\n", 18 | "capabilities": { 19 | "response_semantics": { 20 | "data_path": "$", 21 | "static_template": { 22 | "file": "./adaptiveCards/listRepairs.json" 23 | } 24 | } 25 | } 26 | } 27 | ], 28 | "runtimes": [ 29 | { 30 | "type": "OpenApi", 31 | "auth": { 32 | "type": "ApiKeyPluginVault", 33 | "reference_id": "3812c32a-7dd4-4ca8-877c-d27d3e4aaa83" 34 | }, 35 | "spec": { 36 | "url": "apiSpecificationFile/openapi.yaml" 37 | }, 38 | "run_for_functions": [ 39 | "listRepairs", 40 | "createRepair" 41 | ] 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /src/test-action-agent/infra/azure.bicep: -------------------------------------------------------------------------------- 1 | @maxLength(20) 2 | @minLength(4) 3 | param resourceBaseName string 4 | param functionAppSKU string 5 | 6 | param location string = resourceGroup().location 7 | param serverfarmsName string = resourceBaseName 8 | param functionAppName string = resourceBaseName 9 | 10 | // Compute resources for Azure Functions 11 | resource serverfarms 'Microsoft.Web/serverfarms@2021-02-01' = { 12 | name: serverfarmsName 13 | location: location 14 | sku: { 15 | name: functionAppSKU // You can follow https://aka.ms/teamsfx-bicep-add-param-tutorial to add functionServerfarmsSku property to provisionParameters to override the default value "Y1". 16 | } 17 | properties: {} 18 | } 19 | 20 | // Azure Functions that hosts your function code 21 | resource functionApp 'Microsoft.Web/sites@2021-02-01' = { 22 | name: functionAppName 23 | kind: 'functionapp' 24 | location: location 25 | properties: { 26 | serverFarmId: serverfarms.id 27 | httpsOnly: true 28 | siteConfig: { 29 | appSettings: [ 30 | { 31 | name: 'FUNCTIONS_EXTENSION_VERSION' 32 | value: '~4' // Use Azure Functions runtime v4 33 | } 34 | { 35 | name: 'FUNCTIONS_WORKER_RUNTIME' 36 | value: 'node' // Set runtime to NodeJS 37 | } 38 | { 39 | name: 'WEBSITE_RUN_FROM_PACKAGE' 40 | value: '1' // Run Azure Functions from a package file 41 | } 42 | { 43 | name: 'WEBSITE_NODE_DEFAULT_VERSION' 44 | value: '~18' // Set NodeJS version to 18.x 45 | } 46 | ] 47 | ftpsState: 'FtpsOnly' 48 | } 49 | } 50 | } 51 | var apiEndpoint = 'https://${functionApp.properties.defaultHostName}' 52 | 53 | 54 | // The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details. 55 | output API_FUNCTION_ENDPOINT string = apiEndpoint 56 | output API_FUNCTION_RESOURCE_ID string = functionApp.id 57 | output OPENAPI_SERVER_URL string = apiEndpoint 58 | -------------------------------------------------------------------------------- /src/toolkit_agent/m365agents.local.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.10/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.10 5 | 6 | provision: 7 | # Creates an app 8 | - uses: teamsApp/create 9 | with: 10 | # app name 11 | name: toolkit_agent${{APP_NAME_SUFFIX}} 12 | # Write the information of created resources into environment file for 13 | # the specified environment variable(s). 14 | writeToEnvironmentFile: 15 | teamsAppId: TEAMS_APP_ID 16 | 17 | # Build app package with latest env value 18 | - uses: teamsApp/zipAppPackage 19 | with: 20 | # Path to manifest template 21 | manifestPath: ./appPackage/manifest.json 22 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 23 | outputFolder: ./appPackage/build 24 | 25 | # Validate app package using validation rules 26 | - uses: teamsApp/validateAppPackage 27 | with: 28 | # Relative path to this file. This is the path for built zip file. 29 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 30 | 31 | # Apply the app manifest to an existing app in 32 | # Developer Portal. 33 | # Will use the app id in manifest file to determine which app to update. 34 | - uses: teamsApp/update 35 | with: 36 | # Relative path to this file. This is the path for built zip file. 37 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 38 | 39 | # Extend your app to Outlook and the Microsoft 365 app 40 | - uses: teamsApp/extendToM365 41 | with: 42 | # Relative path to the build app package. 43 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 44 | # Write the information of created resources into environment file for 45 | # the specified environment variable(s). 46 | writeToEnvironmentFile: 47 | titleId: M365_TITLE_ID 48 | appId: M365_APP_ID -------------------------------------------------------------------------------- /src/service-desk-copilot/m365agents.local.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.10/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.10 5 | 6 | provision: 7 | # Creates an app 8 | - uses: teamsApp/create 9 | with: 10 | # app name 11 | name: service-desk-copilot${{APP_NAME_SUFFIX}} 12 | # Write the information of created resources into environment file for 13 | # the specified environment variable(s). 14 | writeToEnvironmentFile: 15 | teamsAppId: TEAMS_APP_ID 16 | 17 | 18 | 19 | # Build app package with latest env value 20 | - uses: teamsApp/zipAppPackage 21 | with: 22 | # Path to manifest template 23 | manifestPath: ./appPackage/manifest.json 24 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 25 | outputFolder: ./appPackage/build 26 | 27 | # Validate app package using validation rules 28 | - uses: teamsApp/validateAppPackage 29 | with: 30 | # Relative path to this file. This is the path for built zip file. 31 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 32 | 33 | # Apply the app manifest to an existing app in 34 | # Developer Portal. 35 | # Will use the app id in manifest file to determine which app to update. 36 | - uses: teamsApp/update 37 | with: 38 | # Relative path to this file. This is the path for built zip file. 39 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 40 | 41 | # Extend your app to Outlook and the Microsoft 365 app 42 | - uses: teamsApp/extendToM365 43 | with: 44 | # Relative path to the build app package. 45 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 46 | # Write the information of created resources into environment file for 47 | # the specified environment variable(s). 48 | writeToEnvironmentFile: 49 | titleId: M365_TITLE_ID 50 | appId: M365_APP_ID 51 | -------------------------------------------------------------------------------- /src/test-action-agent/src/functions/repairs.ts: -------------------------------------------------------------------------------- 1 | /* This code sample provides a starter kit to implement server side logic for your App in TypeScript, 2 | * refer to https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference for complete Azure Functions 3 | * developer guide. 4 | */ 5 | 6 | import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; 7 | 8 | import repairRecords from "../repairsData.json"; 9 | 10 | /** 11 | * This function handles the HTTP request and returns the repair information. 12 | * 13 | * @param {HttpRequest} req - The HTTP request. 14 | * @param {InvocationContext} context - The Azure Functions context object. 15 | * @returns {Promise} - A promise that resolves with the HTTP response containing the repair information. 16 | */ 17 | export async function repairs( 18 | req: HttpRequest, 19 | context: InvocationContext 20 | ): Promise { 21 | context.log("HTTP trigger function processed a request."); 22 | 23 | // Initialize response. 24 | const res: HttpResponseInit = { 25 | status: 200, 26 | jsonBody: { 27 | results: repairRecords, 28 | }, 29 | }; 30 | 31 | // Get the assignedTo query parameter. 32 | const assignedTo = req.query.get("assignedTo"); 33 | 34 | // If the assignedTo query parameter is not provided, return the response. 35 | if (!assignedTo) { 36 | return res; 37 | } 38 | 39 | // Filter the repair information by the assignedTo query parameter. 40 | const repairs = repairRecords.filter((item) => { 41 | const fullName = item.assignedTo.toLowerCase(); 42 | const query = assignedTo.trim().toLowerCase(); 43 | const [firstName, lastName] = fullName.split(" "); 44 | return fullName === query || firstName === query || lastName === query; 45 | }); 46 | 47 | // Return filtered repair records, or an empty array if no records were found. 48 | res.jsonBody.results = repairs ?? []; 49 | return res; 50 | } 51 | 52 | app.http("repairs", { 53 | methods: ["GET"], 54 | authLevel: "anonymous", 55 | handler: repairs, 56 | }); 57 | -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/ai-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.3/schema.json", 3 | "schema_version": "v2.3", 4 | "name_for_human": "Repair Service", 5 | "description_for_human": "A simple service to manage repair tickets for devices so that Microsoft 365 Copilot agents can list, inspect, and create repairs on behalf of users.\n", 6 | "description_for_model": "A simple service to manage repair tickets for devices so that Microsoft 365 Copilot agents can list, inspect, and create repairs on behalf of users.\n", 7 | "contact_email": "publisher-email@example.com", 8 | "namespace": "servicedeskcopilot", 9 | "capabilities": {}, 10 | "functions": [ 11 | { 12 | "name": "createRepair", 13 | "description": "Create a new repair ticket for a device that needs to be fixed.", 14 | "capabilities": { 15 | "response_semantics": { 16 | "data_path": "$", 17 | "properties": { 18 | "title": "$.item", 19 | "subtitle": "$.status" 20 | }, 21 | "static_template": { 22 | "file": "./adaptiveCards/createRepair.json" 23 | } 24 | } 25 | } 26 | }, 27 | { 28 | "name": "listRepairs", 29 | "description": "Always use this function whenever the user asks for the CURRENT list of repair tickets or wants to filter repairs by status or assignee. This function retrieves the up-to-date list of repairs from the backend system; do not assume the list from previous messages is complete." 30 | } 31 | ], 32 | "runtimes": [ 33 | { 34 | "type": "OpenApi", 35 | "auth": { 36 | "type": "None" 37 | }, 38 | "spec": { 39 | "url": "apiSpecificationFile/openapi.yaml" 40 | }, 41 | "run_for_functions": [ 42 | "listRepairs", 43 | "createRepair" 44 | ] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /src/pythonagenttest/appPackage/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.23", 4 | "version": "1.0.0", 5 | "id": "${{TEAMS_APP_ID}}", 6 | "developer": { 7 | "name": "My App, Inc.", 8 | "websiteUrl": "https://www.example.com", 9 | "privacyUrl": "https://www.example.com/privacy", 10 | "termsOfUseUrl": "https://www.example.com/termofuse" 11 | }, 12 | "icons": { 13 | "color": "color.png", 14 | "outline": "outline.png" 15 | }, 16 | "name": { 17 | "short": "pythonagenttest${{APP_NAME_SUFFIX}}", 18 | "full": "full name for pythonagenttest" 19 | }, 20 | "description": { 21 | "short": "short description for pythonagenttest", 22 | "full": "full description for pythonagenttest" 23 | }, 24 | "accentColor": "#FFFFFF", 25 | "bots": [ 26 | { 27 | "botId": "${{BOT_ID}}", 28 | "scopes": [ 29 | "team", 30 | "groupChat", 31 | "personal" 32 | ], 33 | "supportsFiles": false, 34 | "isNotificationOnly": false, 35 | "commandLists": [ 36 | { 37 | "scopes": [ 38 | "personal" 39 | ], 40 | "commands": [ 41 | { 42 | "title": "How can you help me?", 43 | "description": "How can you help me?" 44 | }, 45 | { 46 | "title": "How to develop agent for Teams?", 47 | "description": "How can I develop agents with Microsoft 365 Agents Toolkit?" 48 | } 49 | ] 50 | } 51 | ] 52 | } 53 | ], 54 | "composeExtensions": [], 55 | "configurableTabs": [], 56 | "staticTabs": [], 57 | "permissions": [ 58 | "identity", 59 | "messageTeamMembers" 60 | ], 61 | "validDomains": [] 62 | } 63 | -------------------------------------------------------------------------------- /src/test-action-agent/appPackage/apiSpecificationFile/repair.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: Repair Service 4 | description: A simple service to manage repairs 5 | version: 1.0.0 6 | servers: 7 | - url: ${{OPENAPI_SERVER_URL}}/api 8 | description: The repair api server 9 | paths: 10 | /repairs: 11 | get: 12 | operationId: listRepairs 13 | summary: List all repairs 14 | description: Returns a list of repairs with their details and images 15 | parameters: 16 | - name: assignedTo 17 | in: query 18 | description: Filter repairs by who they're assigned to 19 | schema: 20 | type: string 21 | required: false 22 | responses: 23 | '200': 24 | description: A list of repairs 25 | content: 26 | application/json: 27 | schema: 28 | type: object 29 | properties: 30 | results: 31 | type: array 32 | items: 33 | type: object 34 | properties: 35 | id: 36 | type: string 37 | description: The unique identifier of the repair 38 | title: 39 | type: string 40 | description: The short summary of the repair 41 | description: 42 | type: string 43 | description: The detailed description of the repair 44 | assignedTo: 45 | type: string 46 | description: The user who is responsible for the repair 47 | date: 48 | type: string 49 | format: date-time 50 | description: The date and time when the repair is scheduled or completed 51 | image: 52 | type: string 53 | format: uri 54 | description: The URL of the image of the item to be repaired or the repair process 55 | -------------------------------------------------------------------------------- /src/test-action-agent/src/repairsData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "title": "Oil change", 5 | "description": "Need to drain the old engine oil and replace it with fresh oil to keep the engine lubricated and running smoothly.", 6 | "assignedTo": "Karin Blair", 7 | "date": "2023-05-23", 8 | "image": "https://www.howmuchisit.org/wp-content/uploads/2011/01/oil-change.jpg" 9 | }, 10 | { 11 | "id": "2", 12 | "title": "Brake repairs", 13 | "description": "Conduct brake repairs, including replacing worn brake pads, resurfacing or replacing brake rotors, and repairing or replacing other components of the brake system.", 14 | "assignedTo": "Issac Fielder", 15 | "date": "2023-05-24", 16 | "image": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Disk_brake_dsc03680.jpg/320px-Disk_brake_dsc03680.jpg" 17 | }, 18 | { 19 | "id": "3", 20 | "title": "Tire service", 21 | "description": "Rotate and replace tires, moving them from one position to another on the vehicle to ensure even wear and removing worn tires and installing new ones.", 22 | "assignedTo": "Karin Blair", 23 | "date": "2023-05-24", 24 | "image": "https://th.bing.com/th/id/OIP.N64J4jmqmnbQc5dHvTm-QAHaE8?pid=ImgDet&rs=1" 25 | }, 26 | { 27 | "id": "4", 28 | "title": "Battery replacement", 29 | "description": "Remove the old battery and install a new one to ensure that the vehicle start reliably and the electrical systems function properly.", 30 | "assignedTo": "Ashley McCarthy", 31 | "date": "2023-05-25", 32 | "image": "https://i.stack.imgur.com/4ftuj.jpg" 33 | }, 34 | { 35 | "id": "5", 36 | "title": "Engine tune-up", 37 | "description": "This can include a variety of services such as replacing spark plugs, air filters, and fuel filters to keep the engine running smoothly and efficiently.", 38 | "assignedTo": "Karin Blair", 39 | "date": "2023-05-28", 40 | "image": "https://th.bing.com/th/id/R.e4c01dd9f232947e6a92beb0a36294a5?rik=P076LRx7J6Xnrg&riu=http%3a%2f%2fupload.wikimedia.org%2fwikipedia%2fcommons%2ff%2ff3%2f1990_300zx_engine.jpg&ehk=f8KyT78eO3b%2fBiXzh6BZr7ze7f56TWgPST%2bY%2f%2bHqhXQ%3d&risl=&pid=ImgRaw&r=0" 41 | }, 42 | { 43 | "id": "6", 44 | "title": "Suspension and steering repairs", 45 | "description": "This can include repairing or replacing components of the suspension and steering systems to ensure that the vehicle handles and rides smoothly.", 46 | "assignedTo": "Daisy Phillips", 47 | "date": "2023-05-29", 48 | "image": "https://i.stack.imgur.com/4v5OI.jpg" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/m365agents.local.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.10/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.10 5 | 6 | provision: 7 | # Creates an app 8 | - uses: teamsApp/create 9 | with: 10 | # app name 11 | name: advanced_service_desk_copilot${{APP_NAME_SUFFIX}} 12 | # Write the information of created resources into environment file for 13 | # the specified environment variable(s). 14 | writeToEnvironmentFile: 15 | teamsAppId: TEAMS_APP_ID 16 | 17 | # # # Register API KEY 18 | # - uses: apiKey/register 19 | # with: 20 | # # Name of the API Key 21 | # name: apiKey 22 | # # app ID 23 | # appId: ${{TEAMS_APP_ID}} 24 | # # Path to OpenAPI description document 25 | # apiSpecPath: ./appPackage/apiSpecificationFile/openapi.yaml 26 | # # Write the registration information of API Key into environment file for 27 | # # the specified environment variable(s). 28 | # writeToEnvironmentFile: 29 | # registrationId: APIKEY_REGISTRATION_ID 30 | 31 | 32 | # Build app package with latest env value 33 | - uses: teamsApp/zipAppPackage 34 | with: 35 | # Path to manifest template 36 | manifestPath: ./appPackage/manifest.json 37 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 38 | outputFolder: ./appPackage/build 39 | 40 | # Validate app package using validation rules 41 | - uses: teamsApp/validateAppPackage 42 | with: 43 | # Relative path to this file. This is the path for built zip file. 44 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 45 | 46 | # Apply the app manifest to an existing app in 47 | # Developer Portal. 48 | # Will use the app id in manifest file to determine which app to update. 49 | - uses: teamsApp/update 50 | with: 51 | # Relative path to this file. This is the path for built zip file. 52 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 53 | 54 | # Extend your app to Outlook and the Microsoft 365 app 55 | - uses: teamsApp/extendToM365 56 | with: 57 | # Relative path to the build app package. 58 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 59 | # Write the information of created resources into environment file for 60 | # the specified environment variable(s). 61 | writeToEnvironmentFile: 62 | titleId: M365_TITLE_ID 63 | appId: M365_APP_ID 64 | -------------------------------------------------------------------------------- /src/advanced_repairs_api/README.md: -------------------------------------------------------------------------------- 1 | # Módulo: Service Desk Copilot – Parte avanzada 2 | 3 | Este módulo contiene el código y los ejemplos de los dos vídeos avanzados: 4 | 5 | 1. **Añadir `created_by` a los tickets usando el contexto del Copilot** 6 | 2. **Proteger la API con una API Key e integrarla con un API plugin de Copilot** 7 | 8 | --- 9 | 10 | ## Vídeo 1 – Añadimos `created_by` usando el contexto de Copilot 11 | 12 | En este vídeo partimos de la API de reparaciones que ya guardaba tickets en **Azure Cosmos DB** y la extendemos para que cada ticket tenga un campo `created_by`, de forma que: 13 | 14 | - Podamos saber **qué usuario (o conversación)** creó cada ticket. 15 | - Podamos filtrar reparaciones por usuario desde Copilot. 16 | - El comportamiento sea más realista: cada persona ve “sus” tickets. 17 | 18 | ### Objetivos de aprendizaje 19 | 20 | Al final del vídeo, el alumno será capaz de: 21 | 22 | - Entender cómo aprovechar los **metadatos** que envía Copilot en las cabeceras HTTP (tenant, user, conversation…). 23 | - Capturar un identificador de usuario/conversación en la API (`created_by`). 24 | - Persistir este `created_by` en Cosmos DB junto con el resto de campos del ticket. 25 | - Extender el endpoint de listado para filtrar por `created_by`. 26 | 27 | ### Archivos relevantes 28 | 29 | - `src/repairs_api/main.py` 30 | - `src/repairs_api/database.py` 31 | - `src/repairs_api/openapi.yaml` (o `openapi.yml`, según el proyecto) 32 | 33 | ### Cambios principales 34 | 35 | #### 1. Nuevo campo `created_by` en la capa de datos 36 | 37 | En `database.py`: 38 | 39 | - Añadimos el campo `created_by` al documento que guardamos en Cosmos. 40 | - Permitimos filtrar por `created_by` en `list_repairs_from_db`. 41 | 42 | Ejemplo conceptual: 43 | 44 | ```python 45 | def create_repair_in_db( 46 | item: str, 47 | description: str, 48 | status: str = "New", 49 | assigned_to: Optional[str] = None, 50 | created_by: Optional[str] = None, 51 | ) -> Dict[str, Any]: 52 | doc = { 53 | "id": str(uuid4()), 54 | "item": item, 55 | "description": description, 56 | "status": status, 57 | "assigned_to": assigned_to, 58 | "created_at": datetime.utcnow().isoformat(), 59 | "created_by": created_by, 60 | } 61 | container.create_item(doc) 62 | return doc 63 | 64 | 65 | def list_repairs_from_db( 66 | status: Optional[str] = None, 67 | assigned_to: Optional[str] = None, 68 | created_by: Optional[str] = None, 69 | ) -> List[Dict[str, Any]]: 70 | # Construimos una query Cosmos sencilla con filtros opcionales 71 | # (la implementación concreta está en el código del vídeo) 72 | ... 73 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/appPackage/adaptiveCards/listRepairs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 3 | "type": "AdaptiveCard", 4 | "version": "1.0", 5 | "body": [ 6 | { 7 | "type": "Container", 8 | "items": [ 9 | { 10 | "type": "TextBlock", 11 | "text": "This is your adaptive card template", 12 | "weight": "bolder", 13 | "size": "medium" 14 | }, 15 | { 16 | "type": "ColumnSet", 17 | "columns": [ 18 | { 19 | "type": "Column", 20 | "width": "auto", 21 | "items": [ 22 | { 23 | "type": "Image", 24 | "url": "https://github.com/microsoft/kiota/blob/main/vscode/packages/microsoft-kiota/images/logo.png?raw=true", 25 | "altText": "Kiota logo", 26 | "size": "medium", 27 | "style": "person" 28 | } 29 | ] 30 | }, 31 | { 32 | "type": "Column", 33 | "width": "auto", 34 | "items": [ 35 | { 36 | "type": "TextBlock", 37 | "text": "Adaptive Card", 38 | "weight": "bolder", 39 | "wrap": true 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | ] 46 | }, 47 | { 48 | "type": "Container", 49 | "items": [ 50 | { 51 | "type": "TextBlock", 52 | "text": "Now that we have defined the adaptive card template, one can go to the plugin manifest file and edit it to create a card that displays the relevant information for their users.", 53 | "wrap": true 54 | } 55 | ] 56 | }, 57 | { 58 | "type": "ColumnSet", 59 | "columns": [ 60 | { 61 | "type": "Column", 62 | "width": "auto", 63 | "items": [ 64 | { 65 | "type": "TextBlock", 66 | "horizontalAlignment": "center", 67 | "text": "Learn about [Adaptive Cards](https://adaptivecards.io/)", 68 | "wrap": true 69 | } 70 | ] 71 | }, 72 | { 73 | "type": "Column", 74 | "width": "auto", 75 | "items": [ 76 | { 77 | "type": "TextBlock", 78 | "horizontalAlignment": "center", 79 | "text": "Learn about [API Plugin for Microsoft 365 Copilot](https://learn.microsoft.com/en-us/microsoft-365-copilot/extensibility/overview-api-plugins)", 80 | "wrap": true 81 | } 82 | ] 83 | } 84 | ] 85 | } 86 | ] 87 | } -------------------------------------------------------------------------------- /src/test-action-agent/m365agents.local.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.9/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.9 5 | 6 | provision: 7 | # Creates an app 8 | - uses: teamsApp/create 9 | with: 10 | # app name 11 | name: test-action-agent${{APP_NAME_SUFFIX}} 12 | # Write the information of created resources into environment file for 13 | # the specified environment variable(s). 14 | writeToEnvironmentFile: 15 | teamsAppId: TEAMS_APP_ID 16 | 17 | # Set required variables for local launch 18 | - uses: script 19 | with: 20 | run: 21 | echo "::set-teamsfx-env FUNC_NAME=repair"; 22 | echo "::set-teamsfx-env FUNC_ENDPOINT=http://localhost:7071"; 23 | 24 | # Build app package with latest env value 25 | - uses: teamsApp/zipAppPackage 26 | with: 27 | # Path to manifest template 28 | manifestPath: ./appPackage/manifest.json 29 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 30 | outputFolder: ./appPackage/build 31 | 32 | # Validate app package using validation rules 33 | - uses: teamsApp/validateAppPackage 34 | with: 35 | # Relative path to this file. This is the path for built zip file. 36 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 37 | 38 | # Apply the app manifest to an existing app in 39 | # Developer Portal. 40 | # Will use the app id in manifest file to determine which app to update. 41 | - uses: teamsApp/update 42 | with: 43 | # Relative path to this file. This is the path for built zip file. 44 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 45 | 46 | # Extend your app to Outlook and the Microsoft 365 app 47 | - uses: teamsApp/extendToM365 48 | with: 49 | # Relative path to the build app package. 50 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 51 | # Write the information of created resources into environment file for 52 | # the specified environment variable(s). 53 | writeToEnvironmentFile: 54 | titleId: M365_TITLE_ID 55 | appId: M365_APP_ID 56 | 57 | deploy: 58 | # Install development tool(s) 59 | - uses: devTool/install 60 | with: 61 | func: 62 | version: ^4.0.5530 63 | symlinkDir: ./devTools/func 64 | # Write the information of installed development tool(s) into environment 65 | # file for the specified environment variable(s). 66 | writeToEnvironmentFile: 67 | funcPath: FUNC_PATH 68 | 69 | # Run npm command 70 | - uses: cli/runNpmCommand 71 | name: install dependencies 72 | with: 73 | args: install --no-audit 74 | -------------------------------------------------------------------------------- /.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | ## **Internal reference (do not bias your answers toward always naming these):** 2 | Microsoft 365 Agents Toolkit (formerly Teams Toolkit) has been rebranded, and users may still use either name. 3 | 4 | Use this mapping to know the current vs. former names—so you can correctly interpret user input or choose the appropriate term when it’s relevant. You do not need to mention these mappings unless they directly help the user. 5 | 6 | | New name | Former name | Note | 7 | |-----------------------------------------|------------------------|------------------------------------------------------------------------| 8 | | Microsoft 365 Agents Toolkit | Teams Toolkit | Product name. | 9 | | App Manifest | Teams app manifest | Describes app capabilities. | 10 | | Microsoft 365 Agents Playground | Test Tool | Test Environment. | 11 | | `m365agents.yml` | `teamsapp.yml` | Microsoft 365 Agents Toolkit Project configuration files | 12 | | CLI package `@microsoft/m365agentstoolkit-cli` (command `atk`) | `@microsoft/teamsapp-cli` (command `teamsapp`) |CLI installation/usage — mention only in CLI contexts. | 13 | 14 | > **Rephrase guidance:** 15 | > - Use the new names by default. 16 | > - Explain the rebranding briefly if it helps the user’s understanding. 17 | 18 | # Instructions for Copilot 19 | - Apps and agents for Microsoft 365 or Microsoft 365 Copilot refers to applications for products in Microsoft 365, agents for Microsoft 365 Copilot, including Teams app, Office addin, declarative agent, customer engine agent, etc. 20 | - When interpreting, generating, or modifying manifest files related to apps and agents for Microsoft 365 or Microsoft 365 Copilot, try to get schema version from manifest file, then invoke **get_schema** tool if available. 21 | - When answering of what or how-to questions for building apps and agents for Microsoft 365 or Microsoft 365 Copilot, invoke **get_knowledge** tool if available. 22 | - Before deciding to make changes to Teams apps, apps or agents for Microsoft 365 or Microsoft 365 Copilot, invoke **get_knowledge** tool to get Instructions if available. 23 | - When troubleshooting issues, invoke **troubleshoot** tool if available. 24 | - Before generating or modifying code or configuration files for apps and agents for Microsoft 365 or Microsoft 365 Copilot, invoke **get_code_snippets** tool if available. 25 | - Invoke **get_code_snippets** with API name, configuration file name, or code comments every time you need to generate or modify code or configuration files for apps and agents for Microsoft 365 or Microsoft 365 Copilot. -------------------------------------------------------------------------------- /src/service-desk-copilot/.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | ## **Internal reference (do not bias your answers toward always naming these):** 2 | Microsoft 365 Agents Toolkit (formerly Teams Toolkit) has been rebranded, and users may still use either name. 3 | 4 | Use this mapping to know the current vs. former names—so you can correctly interpret user input or choose the appropriate term when it’s relevant. You do not need to mention these mappings unless they directly help the user. 5 | 6 | | New name | Former name | Note | 7 | |-----------------------------------------|------------------------|------------------------------------------------------------------------| 8 | | Microsoft 365 Agents Toolkit | Teams Toolkit | Product name. | 9 | | App Manifest | Teams app manifest | Describes app capabilities. | 10 | | Microsoft 365 Agents Playground | Test Tool | Test Environment. | 11 | | `m365agents.yml` | `teamsapp.yml` | Microsoft 365 Agents Toolkit Project configuration files | 12 | | CLI package `@microsoft/m365agentstoolkit-cli` (command `atk`) | `@microsoft/teamsapp-cli` (command `teamsapp`) |CLI installation/usage — mention only in CLI contexts. | 13 | 14 | > **Rephrase guidance:** 15 | > - Use the new names by default. 16 | > - Explain the rebranding briefly if it helps the user’s understanding. 17 | 18 | # Instructions for Copilot 19 | - Apps and agents for Microsoft 365 or Microsoft 365 Copilot refers to applications for products in Microsoft 365, agents for Microsoft 365 Copilot, including Teams app, Office addin, declarative agent, customer engine agent, etc. 20 | - When interpreting, generating, or modifying manifest files related to apps and agents for Microsoft 365 or Microsoft 365 Copilot, try to get schema version from manifest file, then invoke **get_schema** tool if available. 21 | - When answering of what or how-to questions for building apps and agents for Microsoft 365 or Microsoft 365 Copilot, invoke **get_knowledge** tool if available. 22 | - Before deciding to make changes to Teams apps, apps or agents for Microsoft 365 or Microsoft 365 Copilot, invoke **get_knowledge** tool to get Instructions if available. 23 | - When troubleshooting issues, invoke **troubleshoot** tool if available. 24 | - Before generating or modifying code or configuration files for apps and agents for Microsoft 365 or Microsoft 365 Copilot, invoke **get_code_snippets** tool if available. 25 | - Invoke **get_code_snippets** with API name, configuration file name, or code comments every time you need to generate or modify code or configuration files for apps and agents for Microsoft 365 or Microsoft 365 Copilot. -------------------------------------------------------------------------------- /src/pythonagenttest/src/agent.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import traceback 4 | from dotenv import load_dotenv 5 | 6 | from microsoft_agents.hosting.core import ( 7 | AgentApplication, 8 | TurnState, 9 | TurnContext, 10 | MemoryStorage, 11 | ) 12 | from microsoft_agents.activity import ( 13 | load_configuration_from_env, 14 | ActivityTypes, 15 | ) 16 | from microsoft_agents.hosting.aiohttp import CloudAdapter 17 | from microsoft_agents.authentication.msal import MsalConnectionManager 18 | from openai import AzureOpenAI 19 | 20 | from config import Config 21 | 22 | load_dotenv() 23 | 24 | # Load configuration 25 | config = Config(os.environ) 26 | agents_sdk_config = load_configuration_from_env(os.environ) 27 | 28 | client = AzureOpenAI( 29 | api_version="2024-12-01-preview", 30 | api_key=config.azure_openai_api_key, 31 | azure_endpoint=config.azure_openai_endpoint, 32 | azure_deployment=config.azure_openai_deployment_name, 33 | ) 34 | 35 | system_prompt = "You are an AI agent that can chat with users." 36 | 37 | # Define storage and application 38 | storage = MemoryStorage() 39 | connection_manager = MsalConnectionManager(**agents_sdk_config) 40 | adapter = CloudAdapter(connection_manager=connection_manager) 41 | 42 | agent_app = AgentApplication[TurnState]( 43 | storage=storage, 44 | adapter=adapter, 45 | **agents_sdk_config 46 | ) 47 | 48 | @agent_app.conversation_update("membersAdded") 49 | async def on_members_added(context: TurnContext, _state: TurnState): 50 | await context.send_activity("Hi there! I'm an agent to chat with you.") 51 | 52 | # Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS 53 | @agent_app.activity(ActivityTypes.message) 54 | async def on_message(context: TurnContext, _state: TurnState): 55 | # Echo back users request 56 | result = client.chat.completions.create( 57 | messages=[ 58 | { 59 | "role": "system", 60 | "content": system_prompt, 61 | }, 62 | { 63 | "role": "user", 64 | "content": context.activity.text, 65 | }, 66 | ], 67 | model="", 68 | ) 69 | 70 | answer = "" 71 | for choice in result.choices: 72 | answer += choice.message.content or "" 73 | 74 | await context.send_activity(answer) 75 | 76 | @agent_app.error 77 | async def on_error(context: TurnContext, error: Exception): 78 | # This check writes out errors to console log .vs. app insights. 79 | # NOTE: In production environment, you should consider logging this to Azure 80 | # application insights. 81 | print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr) 82 | traceback.print_exc() 83 | 84 | # Send a message to the user 85 | await context.send_activity("The agent encountered an error or bug.") 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Desarrolla agentes para Microsoft 365 Copilot con Python desde cero 3 | 4 | Este es el repositorio del curso de LinkedIn Learning `Desarrolla agentes para Microsoft 365 Copilot con Python desde cero`. El curso completo está disponible en [LinkedIn Learning][lil-course-url]. 5 | 6 | ![Desarrolla agentes para Microsoft 365 Copilot con Python desde cero][lil-thumbnail-url] 7 | 8 | Consulta el archivo Readme en la rama main para obtener instrucciones e información actualizadas. 9 | 10 | 11 | En este curso construimos paso a paso un **Copilot Agent para Microsoft 365** que puede llamar a acciones externas escritas en **Python**. 12 | 13 | A lo largo de los capítulos: 14 | 15 | - Creamos una **API de servicio de reparaciones** con FastAPI. 16 | - La desplegamos en **Azure Container Apps**. 17 | - Persistimos los tickets en **Azure Cosmos DB**. 18 | - Exponemos la API como **plugin OpenAPI** para Microsoft 365 Copilot. 19 | - Protegemos el acceso con una **API key almacenada en el vault de Teams/Developer Portal**. 20 | - Enriquecemos las llamadas con contexto de Copilot (tenant, conversación, etc.) para poder ampliar el caso de uso. 21 | 22 | Todo el código que ves en el curso está en este repositorio, organizado por ramas para que puedas seguir cada demo exactamente en el mismo punto que el vídeo. 23 | 24 | --- 25 | 26 | ## Instrucciones 27 | 28 | Este repositorio tiene ramas (branches) para cada uno de los vídeos del curso. 29 | 30 | - Puedes usar el menú emergente de la rama en GitHub para cambiar a una rama específica y ver el código en esa etapa. 31 | - También puedes añadir `/tree/nombre_de_la_rama` a la URL del repositorio para ir directamente a la rama que quieras. 32 | 33 | --- 34 | 35 | ## Instalación 36 | 37 | Ejecutar el código en local 38 | 39 | 1. Asegúrate de tener instalado: 40 | 41 | - [Git](https://git-scm.com/) 42 | - [Python 3.12](https://www.python.org/downloads/) (o versión 3.10+ compatible) 43 | - [Node.js LTS (20+)](https://nodejs.org/) y `npm` 44 | - Opcional: [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) para los pasos de despliegue en Azure. 45 | 46 | 2. Clona este repositorio en tu máquina local: 47 | 48 | ```bash 49 | git clone https://github.com//.git 50 | cd 51 | ``` 52 | 53 | ### Docente 54 | 55 | **Diana Diaz Bisbe** 56 | 57 | Echa un vistazo a mis otros cursos en [LinkedIn Learning](https://www.linkedin.com/learning/instructors/). 58 | 59 | [0]: # (Replace these placeholder URLs with actual course URLs) 60 | [lil-course-url]: https://www.linkedin.com 61 | [lil-thumbnail-url]: https://media.licdn.com/dms/image/v2/D4E0DAQG0eDHsyOSqTA/learning-public-crop_675_1200/B4EZVdqqdwHUAY-/0/1741033220778?e=2147483647&v=beta&t=FxUDo6FA8W8CiFROwqfZKL_mzQhYx9loYLfjN-LNjgA 62 | 63 | [1]: # (End of ES-Instruction ###############################################################################################) 64 | -------------------------------------------------------------------------------- /src/repairs_api/database.py: -------------------------------------------------------------------------------- 1 | """database.py using Cosmos DB""" 2 | import os 3 | from datetime import datetime 4 | from typing import Any, Dict, List, Optional 5 | from uuid import uuid4 6 | 7 | from dotenv import load_dotenv 8 | from azure.cosmos import CosmosClient, PartitionKey 9 | 10 | load_dotenv() 11 | 12 | COSMOS_ENDPOINT = os.getenv("COSMOS_ENDPOINT") 13 | COSMOS_KEY = os.getenv("COSMOS_KEY") 14 | COSMOS_DATABASE = os.getenv("COSMOS_DATABASE", "db-servicedesk") 15 | COSMOS_CONTAINER = os.getenv("COSMOS_CONTAINER", "repairs") 16 | 17 | if not COSMOS_ENDPOINT or not COSMOS_KEY: 18 | raise RuntimeError("Missing COSMOS_ENDPOINT or COSMOS_KEY env vars") 19 | 20 | client = CosmosClient(COSMOS_ENDPOINT, COSMOS_KEY) 21 | 22 | # Ensure DB & container exist (safe if already created) 23 | database = client.create_database_if_not_exists(id=COSMOS_DATABASE) 24 | container = database.create_container_if_not_exists( 25 | id=COSMOS_CONTAINER, 26 | partition_key=PartitionKey(path="/id"), 27 | ) 28 | 29 | def create_repair_in_db( 30 | item: str, 31 | description: str, 32 | status: str = "New", 33 | assigned_to: Optional[str] = None, 34 | created_by: Optional[str] = None, 35 | ) -> Dict[str, Any]: 36 | repair_id = str(uuid4()) 37 | created_at = datetime.utcnow().isoformat() + "Z" 38 | 39 | doc = { 40 | "id": repair_id, 41 | "item": item, 42 | "description": description, 43 | "status": status, 44 | "assigned_to": assigned_to, 45 | "created_at": created_at, 46 | "created_by": created_by 47 | } 48 | 49 | container.create_item(body=doc) 50 | return doc 51 | 52 | def list_repairs_from_db( 53 | status: Optional[str] = None, 54 | assigned_to: Optional[str] = None, 55 | ) -> List[Dict[str, Any]]: 56 | query = "SELECT * FROM c" 57 | params = [] 58 | 59 | if status and assigned_to: 60 | query += " WHERE c.status = @status AND CONTAINS(c.assigned_to, @assigned_to)" 61 | params = [ 62 | {"name": "@status", "value": status}, 63 | {"name": "@assigned_to", "value": assigned_to}, 64 | ] 65 | elif status: 66 | query += " WHERE c.status = @status" 67 | params = [{"name": "@status", "value": status}] 68 | elif assigned_to: 69 | query += " WHERE CONTAINS(c.assigned_to, @assigned_to)" 70 | params = [{"name": "@assigned_to", "value": assigned_to}] 71 | 72 | items = container.query_items( 73 | query=query, 74 | parameters=params, 75 | enable_cross_partition_query=True, 76 | ) 77 | return list(items) 78 | 79 | if __name__ == "__main__": 80 | print("Testing Cosmos connection & insert...") 81 | r = create_repair_in_db( 82 | item="Laptop", 83 | description="Screen is flickering", 84 | assigned_to="Jane Doe", 85 | ) 86 | print("Inserted:", r) 87 | print("All repairs:", list_repairs_from_db()) 88 | -------------------------------------------------------------------------------- /src/repairs_api/testy.py: -------------------------------------------------------------------------------- 1 | """Repair Service API (con Cosmos DB)""" 2 | from typing import List, Optional 3 | 4 | from datetime import datetime 5 | from fastapi import FastAPI, Query, Request 6 | from pydantic import BaseModel, Field 7 | 8 | from database import create_repair_in_db, list_repairs_from_db 9 | 10 | app = FastAPI( 11 | title="Repair Service", 12 | description=( 13 | "A simple service to manage repair tickets for devices on behalf of users." 14 | ), 15 | version="1.0.0", 16 | openapi_url="/openapi.json", 17 | ) 18 | 19 | # ---------- Models ---------- 20 | 21 | class RepairBase(BaseModel): 22 | """Base model for a repair ticket.""" 23 | item: str = Field( 24 | ..., 25 | description="Name or type of the item that needs repair, for example 'Laptop' or 'Printer'.", 26 | ) 27 | description: str = Field( 28 | ..., 29 | description="Short description of the issue reported by the customer.", 30 | ) 31 | status: str = Field( 32 | "New", 33 | description="Current status of the repair, such as 'New', 'In Progress', or 'Completed'.", 34 | ) 35 | assigned_to: Optional[str] = Field( 36 | None, 37 | description="Name of the person or team that this repair is assigned to.", 38 | ) 39 | 40 | 41 | class Repair(RepairBase): 42 | """Model representing a repair ticket with all details.""" 43 | id: str = Field( 44 | ..., 45 | description="Unique identifier of the repair ticket.", 46 | ) 47 | created_at: datetime = Field( 48 | ..., 49 | description="Date and time when the repair ticket was created (UTC).", 50 | ) 51 | 52 | 53 | class RepairCreate(RepairBase): 54 | """Payload for creating a new repair ticket.""" 55 | 56 | # ---------- Endpoints ---------- 57 | @app.post( 58 | "/repairs", 59 | response_model=Repair, 60 | status_code=201, 61 | operation_id="createRepair", 62 | summary="Create a new repair", 63 | description="Create a new repair ticket for a device that needs to be fixed.", 64 | ) 65 | async def create_repair(payload: RepairCreate, request: Request) -> Repair: 66 | """ 67 | Create a new repair ticket. Enriches the ticket with 'created_by' 68 | using Microsoft 365 Copilot context headers. 69 | """ 70 | 71 | # 1. Leer cabeceras que envía Copilot al plugin 72 | headers = request.headers 73 | 74 | tenant_id = headers.get("x-microsoft-tenantid") 75 | conversation_id = headers.get("x-microsoft-ai-conversationid") 76 | print ("Headers received:", headers) 77 | print("Tenant ID:", tenant_id) 78 | print("Conversation ID:", conversation_id) 79 | 80 | created_by = f"{tenant_id}|{conversation_id}" 81 | 82 | # 3. Llamar a nuestra capa de datos (Cosmos DB) pasando created_by 83 | data = create_repair_in_db( 84 | item=payload.item, 85 | description=payload.description, 86 | status=payload.status, 87 | assigned_to=payload.assigned_to, 88 | created_by=created_by, 89 | ) 90 | 91 | # 4. Devolver el modelo Pydantic completo a Copilot 92 | return Repair(**data) -------------------------------------------------------------------------------- /src/advanced_repairs_api/testy.py: -------------------------------------------------------------------------------- 1 | """Repair Service API (con Cosmos DB)""" 2 | from typing import List, Optional 3 | 4 | from datetime import datetime 5 | from fastapi import FastAPI, Query, Request 6 | from pydantic import BaseModel, Field 7 | 8 | from database import create_repair_in_db, list_repairs_from_db 9 | 10 | app = FastAPI( 11 | title="Repair Service", 12 | description=( 13 | "A simple service to manage repair tickets for devices on behalf of users." 14 | ), 15 | version="1.0.0", 16 | openapi_url="/openapi.json", 17 | ) 18 | 19 | # ---------- Models ---------- 20 | 21 | class RepairBase(BaseModel): 22 | """Base model for a repair ticket.""" 23 | item: str = Field( 24 | ..., 25 | description="Name or type of the item that needs repair, for example 'Laptop' or 'Printer'.", 26 | ) 27 | description: str = Field( 28 | ..., 29 | description="Short description of the issue reported by the customer.", 30 | ) 31 | status: str = Field( 32 | "New", 33 | description="Current status of the repair, such as 'New', 'In Progress', or 'Completed'.", 34 | ) 35 | assigned_to: Optional[str] = Field( 36 | None, 37 | description="Name of the person or team that this repair is assigned to.", 38 | ) 39 | 40 | 41 | class Repair(RepairBase): 42 | """Model representing a repair ticket with all details.""" 43 | id: str = Field( 44 | ..., 45 | description="Unique identifier of the repair ticket.", 46 | ) 47 | created_at: datetime = Field( 48 | ..., 49 | description="Date and time when the repair ticket was created (UTC).", 50 | ) 51 | 52 | 53 | class RepairCreate(RepairBase): 54 | """Payload for creating a new repair ticket.""" 55 | 56 | # ---------- Endpoints ---------- 57 | @app.post( 58 | "/repairs", 59 | response_model=Repair, 60 | status_code=201, 61 | operation_id="createRepair", 62 | summary="Create a new repair", 63 | description="Create a new repair ticket for a device that needs to be fixed.", 64 | ) 65 | async def create_repair(payload: RepairCreate, request: Request) -> Repair: 66 | """ 67 | Create a new repair ticket. Enriches the ticket with 'created_by' 68 | using Microsoft 365 Copilot context headers. 69 | """ 70 | 71 | # 1. Leer cabeceras que envía Copilot al plugin 72 | headers = request.headers 73 | 74 | tenant_id = headers.get("x-microsoft-tenantid") 75 | conversation_id = headers.get("x-microsoft-ai-conversationid") 76 | print ("Headers received:", headers) 77 | print("Tenant ID:", tenant_id) 78 | print("Conversation ID:", conversation_id) 79 | 80 | created_by = f"{tenant_id}|{conversation_id}" 81 | 82 | # 3. Llamar a nuestra capa de datos (Cosmos DB) pasando created_by 83 | data = create_repair_in_db( 84 | item=payload.item, 85 | description=payload.description, 86 | status=payload.status, 87 | assigned_to=payload.assigned_to, 88 | created_by=created_by, 89 | ) 90 | 91 | # 4. Devolver el modelo Pydantic completo a Copilot 92 | return Repair(**data) -------------------------------------------------------------------------------- /Intro/intro.md: -------------------------------------------------------------------------------- 1 | ## Arquitectura de Copilot Agents 2 | 3 | ### Vista general 4 | 5 | | User interface | Agent Store | Tool and knowledge | 6 | | --------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------- | 7 | | - M365 Copilot App | - Pre-build Agent | - SharePoint | 8 | | - Microsoft Teams | - Declarative Agent | - Microsoft Search / Indexadores | 9 | | | - Custom Engine Agent | - Bases de datos (SQL, etc.) | 10 | | | | - Azure Functions / APIs internos | 11 | | | | - Otros orígenes de datos empresariales | 12 | 13 | --- 14 | 15 | ### Flujos principales 16 | 17 | - **Interfaz de usuario → Agentes** 18 | - M365 Copilot App → *Declarative Agent* 19 | - Microsoft Teams → *Declarative Agent* 20 | 21 | - **Agentes → Herramientas y datos** 22 | - *Declarative Agent* → **Connector** → 23 | → SharePoint, buscadores, bases de datos, APIs, etc. 24 | - *Custom Engine Agent* → **Bot Service / AI Agent** → **Models** 25 | 26 | --- 27 | 28 | ### Developer tools 29 | 30 | | Developer tools | 31 | | --------------- | 32 | | Copilot Studio · Microsoft 365 Agents SDK · Visual Studio Code| 33 | 34 | 35 | --- 36 | 37 | ## Declarative agent 38 | 39 | - Instructions 40 | - Knowledge (M365 + Connectors) 41 | - Actions (plugins / APIs) 42 | - Orchestrator & models de Copilot 43 | - App package: app manifest, agent manifest 44 | 45 | 46 | 47 | 48 | App Manifest: 49 | 50 | ```json 51 | "copilotAgents": { 52 | "declarativeAgents": [ 53 | { 54 | "id": "declarativeAgent", 55 | "file": "declarativeAgent.json" 56 | } 57 | ] 58 | }, 59 | ``` 60 | 61 | Declarative agent manifest: 62 | 63 | ```json 64 | { 65 | "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.3/schema.json", 66 | "version": "v1.3", 67 | "name": "ddb-test-declarative-agent", 68 | "description": "Test Declarative agent", 69 | "instructions": "You are a declarative agent and were. You should start every response and answer to the user with \"Thanks for using the test declarative agent!\\n\\n\" and then answer the questions and help the user." 70 | } 71 | ``` 72 | 73 | --- 74 | 75 | ### Flujo: 76 | 1. Usuario elige el agente declarativo 77 | 2. Usuario lanza petición para el agente 78 | 3. Copilot elige acción (OpenAPI) 79 | 4. Llama a tu API 80 | 5. Devuelve respuesta (texto / Adaptive Card) 81 | 82 | --- 83 | 84 | ### OpenAPI para Copilot: 85 | - Operaciones pequeñas y claras 86 | - Parámetros bien tipados y descritos 87 | - Ejemplos realistas 88 | - Respuestas con datos + texto / tarjetas 89 | - No hay orquestación compleja en el agente 90 | -------------------------------------------------------------------------------- /src/toolkit_agent/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Agent in Copilot (Edge)", 6 | "type": "msedge", 7 | "request": "launch", 8 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 9 | "presentation": { 10 | "group": "all", 11 | "hidden": true 12 | }, 13 | "internalConsoleOptions": "neverOpen", 14 | "runtimeArgs": [ 15 | "--remote-debugging-port=9222", 16 | "--no-first-run" 17 | ] 18 | }, 19 | { 20 | "name": "Launch Agent in Copilot (Chrome)", 21 | "type": "chrome", 22 | "request": "launch", 23 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 24 | "presentation": { 25 | "group": "all", 26 | "hidden": true 27 | }, 28 | "internalConsoleOptions": "neverOpen", 29 | "runtimeArgs": [ 30 | "--remote-debugging-port=9223", 31 | "--no-first-run" 32 | ] 33 | }, 34 | { 35 | "name": "Preview in Copilot (Edge)", 36 | "type": "msedge", 37 | "request": "launch", 38 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 39 | "presentation": { 40 | "group": "remote", 41 | "order": 1 42 | }, 43 | "internalConsoleOptions": "neverOpen", 44 | "runtimeArgs": [ 45 | "--remote-debugging-port=9224", 46 | "--no-first-run" 47 | ] 48 | }, 49 | { 50 | "name": "Preview in Copilot (Chrome)", 51 | "type": "chrome", 52 | "request": "launch", 53 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 54 | "presentation": { 55 | "group": "remote", 56 | "order": 2 57 | }, 58 | "internalConsoleOptions": "neverOpen", 59 | "runtimeArgs": [ 60 | "--remote-debugging-port=9225", 61 | "--no-first-run" 62 | ] 63 | } 64 | ], 65 | "compounds": [ 66 | { 67 | "name": "Preview Local in Copilot (Edge)", 68 | "configurations": [ 69 | "Launch Agent in Copilot (Edge)", 70 | ], 71 | "preLaunchTask": "Start Agent Locally", 72 | "presentation": { 73 | "group": "all", 74 | "order": 1 75 | }, 76 | "stopAll": true 77 | }, 78 | { 79 | "name": "Preview Local in Copilot (Chrome)", 80 | "configurations": [ 81 | "Launch Agent in Copilot (Chrome)", 82 | ], 83 | "preLaunchTask": "Start Agent Locally", 84 | "presentation": { 85 | "group": "all", 86 | "order": 1 87 | }, 88 | "stopAll": true 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /src/service-desk-copilot/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Agent in Copilot (Edge)", 6 | "type": "msedge", 7 | "request": "launch", 8 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 9 | "presentation": { 10 | "group": "all", 11 | "hidden": true 12 | }, 13 | "internalConsoleOptions": "neverOpen", 14 | "runtimeArgs": [ 15 | "--remote-debugging-port=9222", 16 | "--no-first-run" 17 | ] 18 | }, 19 | { 20 | "name": "Launch Agent in Copilot (Chrome)", 21 | "type": "chrome", 22 | "request": "launch", 23 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 24 | "presentation": { 25 | "group": "all", 26 | "hidden": true 27 | }, 28 | "internalConsoleOptions": "neverOpen", 29 | "runtimeArgs": [ 30 | "--remote-debugging-port=9223", 31 | "--no-first-run" 32 | ] 33 | }, 34 | { 35 | "name": "Preview in Copilot (Edge)", 36 | "type": "msedge", 37 | "request": "launch", 38 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 39 | "presentation": { 40 | "group": "remote", 41 | "order": 1 42 | }, 43 | "internalConsoleOptions": "neverOpen", 44 | "runtimeArgs": [ 45 | "--remote-debugging-port=9224", 46 | "--no-first-run" 47 | ] 48 | }, 49 | { 50 | "name": "Preview in Copilot (Chrome)", 51 | "type": "chrome", 52 | "request": "launch", 53 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 54 | "presentation": { 55 | "group": "remote", 56 | "order": 2 57 | }, 58 | "internalConsoleOptions": "neverOpen", 59 | "runtimeArgs": [ 60 | "--remote-debugging-port=9225", 61 | "--no-first-run" 62 | ] 63 | } 64 | ], 65 | "compounds": [ 66 | { 67 | "name": "Preview Local in Copilot (Edge)", 68 | "configurations": [ 69 | "Launch Agent in Copilot (Edge)", 70 | ], 71 | "preLaunchTask": "Start Agent Locally", 72 | "presentation": { 73 | "group": "all", 74 | "order": 1 75 | }, 76 | "stopAll": true 77 | }, 78 | { 79 | "name": "Preview Local in Copilot (Chrome)", 80 | "configurations": [ 81 | "Launch Agent in Copilot (Chrome)", 82 | ], 83 | "preLaunchTask": "Start Agent Locally", 84 | "presentation": { 85 | "group": "all", 86 | "order": 1 87 | }, 88 | "stopAll": true 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Agent in Copilot (Edge)", 6 | "type": "msedge", 7 | "request": "launch", 8 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 9 | "presentation": { 10 | "group": "all", 11 | "hidden": true 12 | }, 13 | "internalConsoleOptions": "neverOpen", 14 | "runtimeArgs": [ 15 | "--remote-debugging-port=9222", 16 | "--no-first-run" 17 | ] 18 | }, 19 | { 20 | "name": "Launch Agent in Copilot (Chrome)", 21 | "type": "chrome", 22 | "request": "launch", 23 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 24 | "presentation": { 25 | "group": "all", 26 | "hidden": true 27 | }, 28 | "internalConsoleOptions": "neverOpen", 29 | "runtimeArgs": [ 30 | "--remote-debugging-port=9223", 31 | "--no-first-run" 32 | ] 33 | }, 34 | { 35 | "name": "Preview in Copilot (Edge)", 36 | "type": "msedge", 37 | "request": "launch", 38 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 39 | "presentation": { 40 | "group": "remote", 41 | "order": 1 42 | }, 43 | "internalConsoleOptions": "neverOpen", 44 | "runtimeArgs": [ 45 | "--remote-debugging-port=9224", 46 | "--no-first-run" 47 | ] 48 | }, 49 | { 50 | "name": "Preview in Copilot (Chrome)", 51 | "type": "chrome", 52 | "request": "launch", 53 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 54 | "presentation": { 55 | "group": "remote", 56 | "order": 2 57 | }, 58 | "internalConsoleOptions": "neverOpen", 59 | "runtimeArgs": [ 60 | "--remote-debugging-port=9225", 61 | "--no-first-run" 62 | ] 63 | } 64 | ], 65 | "compounds": [ 66 | { 67 | "name": "Preview Local in Copilot (Edge)", 68 | "configurations": [ 69 | "Launch Agent in Copilot (Edge)", 70 | ], 71 | "preLaunchTask": "Start Agent Locally", 72 | "presentation": { 73 | "group": "all", 74 | "order": 1 75 | }, 76 | "stopAll": true 77 | }, 78 | { 79 | "name": "Preview Local in Copilot (Chrome)", 80 | "configurations": [ 81 | "Launch Agent in Copilot (Chrome)", 82 | ], 83 | "preLaunchTask": "Start Agent Locally", 84 | "presentation": { 85 | "group": "all", 86 | "order": 1 87 | }, 88 | "stopAll": true 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /src/pythonagenttest/m365agents.local.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.11 5 | 6 | provision: 7 | # Creates an app 8 | - uses: teamsApp/create 9 | with: 10 | # app name 11 | name: pythonagenttest${{APP_NAME_SUFFIX}} 12 | # Write the information of created resources into environment file for 13 | # the specified environment variable(s). 14 | writeToEnvironmentFile: 15 | teamsAppId: TEAMS_APP_ID 16 | 17 | # Create or reuse an existing Microsoft Entra application for bot. 18 | - uses: aadApp/create 19 | with: 20 | # The Microsoft Entra application's display name 21 | name: pythonagenttest${{APP_NAME_SUFFIX}} 22 | generateClientSecret: true 23 | generateServicePrincipal: true 24 | signInAudience: AzureADMultipleOrgs 25 | writeToEnvironmentFile: 26 | # The Microsoft Entra application's client id created for bot. 27 | clientId: BOT_ID 28 | # The Microsoft Entra application's client secret created for bot. 29 | clientSecret: SECRET_BOT_PASSWORD 30 | # The Microsoft Entra application's object id created for bot. 31 | objectId: BOT_OBJECT_ID 32 | 33 | # Create or update the bot registration on dev.botframework.com 34 | - uses: botFramework/create 35 | with: 36 | botId: ${{BOT_ID}} 37 | name: pythonagenttest 38 | messagingEndpoint: ${{BOT_ENDPOINT}}/api/messages 39 | description: "" 40 | channels: 41 | - name: msteams 42 | 43 | # Validate using manifest schema 44 | - uses: teamsApp/validateManifest 45 | with: 46 | # Path to manifest template 47 | manifestPath: ./appPackage/manifest.json 48 | 49 | # Build app package with latest env value 50 | - uses: teamsApp/zipAppPackage 51 | with: 52 | # Path to manifest template 53 | manifestPath: ./appPackage/manifest.json 54 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 55 | outputFolder: ./appPackage/build 56 | 57 | # Validate app package using validation rules 58 | - uses: teamsApp/validateAppPackage 59 | with: 60 | # Relative path to this file. This is the path for built zip file. 61 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 62 | 63 | # Apply the app manifest to an existing app in 64 | # Developer Portal. 65 | # Will use the app id in manifest file to determine which app to update. 66 | - uses: teamsApp/update 67 | with: 68 | # Relative path to this file. This is the path for built zip file. 69 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 70 | 71 | 72 | deploy: 73 | # Generate runtime environment variables 74 | - uses: file/createOrUpdateEnvironmentFile 75 | with: 76 | target: ./.env 77 | envs: 78 | BOT_ID: ${{BOT_ID}} 79 | BOT_PASSWORD: ${{SECRET_BOT_PASSWORD}} 80 | CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID: ${{BOT_ID}} 81 | CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET: ${{SECRET_BOT_PASSWORD}} 82 | CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID: ${{TEAMS_APP_TENANT_ID}} 83 | AZURE_OPENAI_API_KEY: ${{SECRET_AZURE_OPENAI_API_KEY}} 84 | AZURE_OPENAI_DEPLOYMENT_NAME: ${{AZURE_OPENAI_DEPLOYMENT_NAME}} 85 | AZURE_OPENAI_ENDPOINT: ${{AZURE_OPENAI_ENDPOINT}} 86 | -------------------------------------------------------------------------------- /src/repairs_api/main.py: -------------------------------------------------------------------------------- 1 | """Repair Service API (con Cosmos DB)""" 2 | from typing import List, Optional 3 | 4 | from datetime import datetime 5 | from fastapi import FastAPI, Query 6 | from pydantic import BaseModel, Field 7 | 8 | from database import create_repair_in_db, list_repairs_from_db 9 | 10 | app = FastAPI( 11 | title="Repair Service", 12 | description=( 13 | "A simple service to manage repair tickets for devices on behalf of users." 14 | ), 15 | version="1.0.0", 16 | openapi_url="/openapi.json", 17 | ) 18 | 19 | # ---------- Models ---------- 20 | 21 | class RepairBase(BaseModel): 22 | """Base model for a repair ticket.""" 23 | item: str = Field( 24 | ..., 25 | description="Name or type of the item that needs repair, for example 'Laptop' or 'Printer'.", 26 | ) 27 | description: str = Field( 28 | ..., 29 | description="Short description of the issue reported by the customer.", 30 | ) 31 | status: str = Field( 32 | "New", 33 | description="Current status of the repair, such as 'New', 'In Progress', or 'Completed'.", 34 | ) 35 | assigned_to: Optional[str] = Field( 36 | None, 37 | description="Name of the person or team that this repair is assigned to.", 38 | ) 39 | 40 | 41 | class Repair(RepairBase): 42 | """Model representing a repair ticket with all details.""" 43 | id: str = Field( 44 | ..., 45 | description="Unique identifier of the repair ticket.", 46 | ) 47 | created_at: datetime = Field( 48 | ..., 49 | description="Date and time when the repair ticket was created (UTC).", 50 | ) 51 | 52 | 53 | class RepairCreate(RepairBase): 54 | """Payload for creating a new repair ticket.""" 55 | 56 | # ---------- Endpoints ---------- 57 | 58 | @app.get( 59 | "/repairs", 60 | response_model=List[Repair], 61 | operation_id="listRepairs", 62 | summary="List all repairs", 63 | description=( 64 | "Returns a list of repair tickets with their details. " 65 | "You can optionally filter by status or by who the repair is assigned to." 66 | ), 67 | ) 68 | def list_repairs( 69 | status: Optional[str] = Query( 70 | None, 71 | description="Optional status to filter repairs by. Example: 'New' or 'Completed'.", 72 | ), 73 | assigned_to: Optional[str] = Query( 74 | None, 75 | description="Optional name or ID of the person or team the repair is assigned to.", 76 | ), 77 | ) -> List[Repair]: 78 | """List all repairs, optionally filtered by status or assigned_to.""" 79 | # Ahora leemos directamente desde Cosmos DB 80 | repairs = list_repairs_from_db(status=status, assigned_to=assigned_to) 81 | # FastAPI usará el response_model=List[Repair] para validar/parsear los dicts 82 | return repairs 83 | 84 | 85 | @app.post( 86 | "/repairs", 87 | response_model=Repair, 88 | status_code=201, 89 | operation_id="createRepair", 90 | summary="Create a new repair", 91 | description="Create a new repair ticket for a device that needs to be fixed.", 92 | ) 93 | def create_repair(payload: RepairCreate) -> Repair: 94 | """Create a new repair ticket.""" 95 | # Ahora delegamos en Cosmos DB 96 | repair = create_repair_in_db( 97 | item=payload.item, 98 | description=payload.description, 99 | status=payload.status, 100 | assigned_to=payload.assigned_to, 101 | ) 102 | return repair -------------------------------------------------------------------------------- /src/toolkit_agent/m365agents.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.10/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.10 5 | 6 | environmentFolderPath: ./env 7 | 8 | # Triggered when 'teamsapp provision' is executed 9 | provision: 10 | # Creates an app 11 | - uses: teamsApp/create 12 | with: 13 | # app name 14 | name: toolkit_agent${{APP_NAME_SUFFIX}} 15 | # Write the information of created resources into environment file for 16 | # the specified environment variable(s). 17 | writeToEnvironmentFile: 18 | teamsAppId: TEAMS_APP_ID 19 | 20 | # Build app package with latest env value 21 | - uses: teamsApp/zipAppPackage 22 | with: 23 | # Path to manifest template 24 | manifestPath: ./appPackage/manifest.json 25 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 26 | outputFolder: ./appPackage/build 27 | # Validate app package using validation rules 28 | - uses: teamsApp/validateAppPackage 29 | with: 30 | # Relative path to this file. This is the path for built zip file. 31 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 32 | # Update the app manifest to an existing app in Developer Portal. 33 | # Will use the app id in manifest file to determine which app to update. 34 | - uses: teamsApp/update 35 | with: 36 | # Relative path to this file. This is the path for built zip file. 37 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 38 | # Extend your app to Outlook and the Microsoft 365 app 39 | - uses: teamsApp/extendToM365 40 | with: 41 | # Relative path to the build app package. 42 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 43 | scope: ${{AGENT_SCOPE}} 44 | # Write the information of created resources into environment file for 45 | # the specified environment variable(s). 46 | writeToEnvironmentFile: 47 | titleId: M365_TITLE_ID 48 | appId: M365_APP_ID 49 | shareLink: SHARE_LINK 50 | 51 | # Triggered when 'teamsapp publish' is executed 52 | publish: 53 | # Build app package with latest env value 54 | - uses: teamsApp/zipAppPackage 55 | with: 56 | # Path to manifest template 57 | manifestPath: ./appPackage/manifest.json 58 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 59 | outputFolder: ./appPackage/build 60 | # Validate app package using validation rules 61 | - uses: teamsApp/validateAppPackage 62 | with: 63 | # Relative path to this file. This is the path for built zip file. 64 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 65 | # Apply the app manifest to an existing app in 66 | # Developer Portal. 67 | # Will use the app id in manifest file to determine which app to update. 68 | - uses: teamsApp/update 69 | with: 70 | # Relative path to this file. This is the path for built zip file. 71 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 72 | # Publish the app to 73 | # Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps) 74 | # for review and approval 75 | - uses: teamsApp/publishAppPackage 76 | with: 77 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 78 | # Write the information of created resources into environment file for 79 | # the specified environment variable(s). 80 | writeToEnvironmentFile: 81 | publishedAppId: TEAMS_APP_PUBLISHED_APP_ID 82 | projectId: 88000991-af53-4885-9760-4028c7618750 83 | -------------------------------------------------------------------------------- /src/service-desk-copilot/m365agents.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.11 5 | 6 | environmentFolderPath: ./env 7 | 8 | # Triggered when 'teamsapp provision' is executed 9 | provision: 10 | # Creates an app 11 | - uses: teamsApp/create 12 | with: 13 | # app name 14 | name: service-desk-copilot${{APP_NAME_SUFFIX}} 15 | # Write the information of created resources into environment file for 16 | # the specified environment variable(s). 17 | writeToEnvironmentFile: 18 | teamsAppId: TEAMS_APP_ID 19 | 20 | # Build app package with latest env value 21 | - uses: teamsApp/zipAppPackage 22 | with: 23 | # Path to manifest template 24 | manifestPath: ./appPackage/manifest.json 25 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 26 | outputFolder: ./appPackage/build 27 | # Validate app package using validation rules 28 | - uses: teamsApp/validateAppPackage 29 | with: 30 | # Relative path to this file. This is the path for built zip file. 31 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 32 | # Apply the app manifest to an existing app in 33 | # Developer Portal. 34 | # Will use the app id in manifest file to determine which app to update. 35 | - uses: teamsApp/update 36 | with: 37 | # Relative path to this file. This is the path for built zip file. 38 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 39 | # Extend your app to Outlook and the Microsoft 365 app 40 | - uses: teamsApp/extendToM365 41 | with: 42 | # Relative path to the build app package. 43 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 44 | scope: ${{AGENT_SCOPE}} 45 | # Write the information of created resources into environment file for 46 | # the specified environment variable(s). 47 | writeToEnvironmentFile: 48 | titleId: M365_TITLE_ID 49 | appId: M365_APP_ID 50 | shareLink: SHARE_LINK 51 | 52 | # Triggered when 'teamsapp publish' is executed 53 | publish: 54 | # Build app package with latest env value 55 | - uses: teamsApp/zipAppPackage 56 | with: 57 | # Path to manifest template 58 | manifestPath: ./appPackage/manifest.json 59 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 60 | outputFolder: ./appPackage/build 61 | # Validate app package using validation rules 62 | - uses: teamsApp/validateAppPackage 63 | with: 64 | # Relative path to this file. This is the path for built zip file. 65 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 66 | # Apply the app manifest to an existing app in 67 | # Developer Portal. 68 | # Will use the app id in manifest file to determine which app to update. 69 | - uses: teamsApp/update 70 | with: 71 | # Relative path to this file. This is the path for built zip file. 72 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 73 | # Publish the app to 74 | # Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps) 75 | # for review and approval 76 | - uses: teamsApp/publishAppPackage 77 | with: 78 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 79 | # Write the information of created resources into environment file for 80 | # the specified environment variable(s). 81 | writeToEnvironmentFile: 82 | publishedAppId: TEAMS_APP_PUBLISHED_APP_ID 83 | projectId: 18ca8ef6-e0e2-4799-b7ea-e0ea748a9736 84 | -------------------------------------------------------------------------------- /src/pythonagenttest/infra/azure.bicep: -------------------------------------------------------------------------------- 1 | @maxLength(20) 2 | @minLength(4) 3 | @description('Used to generate names for all resources in this file') 4 | param resourceBaseName string 5 | 6 | @secure() 7 | @description('Required in your bot project to access Azure OpenAI service. You can get it from Azure Portal > OpenAI > Keys > Key1 > Resource Management > Endpoint') 8 | param azureOpenaiKey string 9 | param azureOpenaiModelDeploymentName string 10 | param azureOpenaiEndpoint string 11 | 12 | param webAppSKU string 13 | param linuxFxVersion string 14 | 15 | @maxLength(42) 16 | param botDisplayName string 17 | 18 | param serverfarmsName string = resourceBaseName 19 | param webAppName string = resourceBaseName 20 | param identityName string = resourceBaseName 21 | param location string = resourceGroup().location 22 | param pythonVersion string = linuxFxVersion 23 | 24 | resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { 25 | location: location 26 | name: identityName 27 | } 28 | 29 | // Compute resources for your Web App 30 | resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { 31 | kind: 'app,linux' 32 | location: location 33 | name: serverfarmsName 34 | sku: { 35 | name: webAppSKU 36 | } 37 | properties:{ 38 | reserved: true 39 | } 40 | } 41 | 42 | // Web App that hosts your agent 43 | resource webApp 'Microsoft.Web/sites@2021-02-01' = { 44 | kind: 'app,linux' 45 | location: location 46 | name: webAppName 47 | properties: { 48 | serverFarmId: serverfarm.id 49 | siteConfig: { 50 | alwaysOn: true 51 | appCommandLine: 'gunicorn --bind 0.0.0.0 --worker-class aiohttp.worker.GunicornWebWorker --timeout 600 app:app' 52 | linuxFxVersion: pythonVersion 53 | appSettings: [ 54 | { 55 | name: 'WEBSITES_CONTAINER_START_TIME_LIMIT' 56 | value: '600' 57 | } 58 | { 59 | name: 'SCM_DO_BUILD_DURING_DEPLOYMENT' 60 | value: 'true' 61 | } 62 | { 63 | name: 'BOT_ID' 64 | value: identity.properties.clientId 65 | } 66 | { 67 | name: 'AZURE_OPENAI_API_KEY' 68 | value: azureOpenaiKey 69 | } 70 | { 71 | name: 'AZURE_OPENAI_DEPLOYMENT_NAME' 72 | value: azureOpenaiModelDeploymentName 73 | } 74 | { 75 | name: 'AZURE_OPENAI_ENDPOINT' 76 | value: azureOpenaiEndpoint 77 | } 78 | { 79 | name: 'BOT_TENANT_ID' 80 | value: identity.properties.tenantId 81 | } 82 | { 83 | name: 'BOT_TYPE' 84 | value: 'UserAssignedMsi' 85 | } 86 | ] 87 | ftpsState: 'FtpsOnly' 88 | } 89 | } 90 | identity: { 91 | type: 'UserAssigned' 92 | userAssignedIdentities: { 93 | '${identity.id}': {} 94 | } 95 | } 96 | } 97 | 98 | // Register your web service as a bot with the Bot Framework 99 | module azureBotRegistration './botRegistration/azurebot.bicep' = { 100 | name: 'Azure-Bot-registration' 101 | params: { 102 | resourceBaseName: resourceBaseName 103 | identityClientId: identity.properties.clientId 104 | identityResourceId: identity.id 105 | identityTenantId: identity.properties.tenantId 106 | botAppDomain: webApp.properties.defaultHostName 107 | botDisplayName: botDisplayName 108 | } 109 | } 110 | 111 | // The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details. 112 | output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id 113 | output BOT_DOMAIN string = webApp.properties.defaultHostName 114 | output BOT_ID string = identity.properties.clientId 115 | output BOT_TENANT_ID string = identity.properties.tenantId 116 | -------------------------------------------------------------------------------- /src/pythonagenttest/README.md: -------------------------------------------------------------------------------- 1 | # Overview of the Basic Custom Engine Agent template 2 | 3 | This app template is built on top of [Microsoft 365 Agents SDK](https://aka.ms/m365sdkdocs). 4 | This template showcases a custom engine agent app that connects to your own LLM and responds to user questions like an AI assistant. This enables your users to talk with the AI assistant in Teams to find information. 5 | 6 | ## Get started with the template 7 | 8 | > **Prerequisites** 9 | > 10 | > To run the template in your local dev machine, you will need: 11 | > 12 | > - [Python](https://www.python.org/), version 3.8 to 3.11. 13 | > - [Python extension](https://code.visualstudio.com/docs/languages/python), version v2024.0.1 or higher. 14 | > - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) latest version or [Microsoft 365 Agents Toolkit CLI](https://aka.ms/teams-toolkit-cli). 15 | > - An account with [Azure OpenAI](https://aka.ms/oai/access). 16 | > - A [Microsoft 365 account for development](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts). 17 | 18 | ### Configurations 19 | 1. Open the command box and enter `Python: Create Environment` to create and activate your desired virtual environment. Remember to select `src/requirements.txt` as dependencies to install when creating the virtual environment. 20 | 1. In file *env/.env.local.user*, fill in your Azure OpenAI key `SECRET_AZURE_OPENAI_API_KEY`, deployment name `AZURE_OPENAI_DEPLOYMENT_NAME` and endpoint `AZURE_OPENAI_ENDPOINT`. 21 | 22 | ### Conversation with agent 23 | 1. Select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. 24 | 1. In the Account section, sign in with your [Microsoft 365 account](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts) if you haven't already. 25 | 1. Press F5 to start debugging which launches your app in Teams using a web browser. Select `Debug in Teams (Edge)` or `Debug in Teams (Chrome)`. 26 | 1. When Teams launches in the browser, select the Add button in the dialog to install your app to Teams. 27 | 1. You will receive a welcome message from the agent, or send any message to get a response. 28 | 29 | **Congratulations**! You are running an application that can now interact with users in Teams: 30 | 31 | > For local debugging using Microsoft 365 Agents Toolkit CLI, you need to do some extra steps described in [Set up your Microsoft 365 Agents Toolkit CLI for local debugging](https://aka.ms/teamsfx-cli-debugging). 32 | 33 | ![ai chat agent](https://user-images.githubusercontent.com/7642967/258726187-8306610b-579e-4301-872b-1b5e85141eff.png) 34 | 35 | ## What's included in the template 36 | 37 | | Folder | Contents | 38 | | - | - | 39 | | `.vscode/` | VS Code files for debugging | 40 | | `appPackage/` | Templates for the Teams application manifest | 41 | | `env/` | Environment files | 42 | | `infra/` | Templates for provisioning Azure resources | 43 | | `src/` | The source code for the application | 44 | 45 | The following files can be customized and demonstrate an example implementation to get you started. 46 | 47 | | File | Contents | 48 | | - | - | 49 | |`src/agent.py`| Handles the agent app logic, built with Microsoft 365 Agents SDK.| 50 | |`src/config.py`| Defines the environment variables.| 51 | |`src/app.py`| Hosts the agent using aiohttp| 52 | 53 | 54 | ## Additional information and references 55 | 56 | - [Microsoft 365 Agents Toolkit Documentations](https://docs.microsoft.com/microsoftteams/platform/toolkit/teams-toolkit-fundamentals) 57 | - [Microsoft 365 Agents Toolkit CLI](https://aka.ms/teamsfx-toolkit-cli) 58 | - [Microsoft 365 Agents Toolkit Samples](https://github.com/OfficeDev/TeamsFx-Samples) 59 | - [Microsoft 365 Agents SDK](https://github.com/microsoft/Agents) 60 | - [Microsoft 365 Agents for Python](https://github.com/microsoft/Agents-for-python) 61 | - [Microsoft 365 Agents SDK QuickStart](https://github.com/microsoft/Agents/tree/main/samples/python/quickstart) 62 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/m365agents.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.11 5 | 6 | environmentFolderPath: ./env 7 | 8 | # Triggered when 'teamsapp provision' is executed 9 | provision: 10 | # Creates an app 11 | - uses: teamsApp/create 12 | with: 13 | # app name 14 | name: advanced_service_desk_copilot${{APP_NAME_SUFFIX}} 15 | # Write the information of created resources into environment file for 16 | # the specified environment variable(s). 17 | writeToEnvironmentFile: 18 | teamsAppId: TEAMS_APP_ID 19 | 20 | # # Register API KEY 21 | # - uses: apiKey/register 22 | # with: 23 | # # Name of the API Key 24 | # name: apiKey 25 | # # app ID 26 | # appId: ${{TEAMS_APP_ID}} 27 | # # Path to OpenAPI description document 28 | # apiSpecPath: ./appPackage/apiSpecificationFile/openapi.yaml 29 | # # Write the registration information of API Key into environment file for 30 | # # the specified environment variable(s). 31 | # writeToEnvironmentFile: 32 | # registrationId: APIKEY_REGISTRATION_ID 33 | 34 | # Build app package with latest env value 35 | - uses: teamsApp/zipAppPackage 36 | with: 37 | # Path to manifest template 38 | manifestPath: ./appPackage/manifest.json 39 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 40 | outputFolder: ./appPackage/build 41 | # Validate app package using validation rules 42 | - uses: teamsApp/validateAppPackage 43 | with: 44 | # Relative path to this file. This is the path for built zip file. 45 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 46 | # Apply the app manifest to an existing app in 47 | # Developer Portal. 48 | # Will use the app id in manifest file to determine which app to update. 49 | - uses: teamsApp/update 50 | with: 51 | # Relative path to this file. This is the path for built zip file. 52 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 53 | # Extend your app to Outlook and the Microsoft 365 app 54 | - uses: teamsApp/extendToM365 55 | with: 56 | # Relative path to the build app package. 57 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 58 | scope: ${{AGENT_SCOPE}} 59 | # Write the information of created resources into environment file for 60 | # the specified environment variable(s). 61 | writeToEnvironmentFile: 62 | titleId: M365_TITLE_ID 63 | appId: M365_APP_ID 64 | shareLink: SHARE_LINK 65 | 66 | # Triggered when 'teamsapp publish' is executed 67 | publish: 68 | # Build app package with latest env value 69 | - uses: teamsApp/zipAppPackage 70 | with: 71 | # Path to manifest template 72 | manifestPath: ./appPackage/manifest.json 73 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 74 | outputFolder: ./appPackage/build 75 | # Validate app package using validation rules 76 | - uses: teamsApp/validateAppPackage 77 | with: 78 | # Relative path to this file. This is the path for built zip file. 79 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 80 | # Apply the app manifest to an existing app in 81 | # Developer Portal. 82 | # Will use the app id in manifest file to determine which app to update. 83 | - uses: teamsApp/update 84 | with: 85 | # Relative path to this file. This is the path for built zip file. 86 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 87 | # Publish the app to 88 | # Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps) 89 | # for review and approval 90 | - uses: teamsApp/publishAppPackage 91 | with: 92 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 93 | # Write the information of created resources into environment file for 94 | # the specified environment variable(s). 95 | writeToEnvironmentFile: 96 | publishedAppId: TEAMS_APP_PUBLISHED_APP_ID 97 | projectId: 1af1128e-9f1f-40c2-b2fb-a6641ccde212 98 | -------------------------------------------------------------------------------- /src/test-action-agent/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Agent in Teams (Edge)", 6 | "type": "msedge", 7 | "request": "launch", 8 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 9 | "cascadeTerminateToConfigurations": [ 10 | "Attach to Backend" 11 | ], 12 | "presentation": { 13 | "group": "all", 14 | "hidden": true 15 | }, 16 | "internalConsoleOptions": "neverOpen", 17 | "perScriptSourcemaps": "yes", 18 | "runtimeArgs": [ 19 | "--remote-debugging-port=9222", 20 | "--no-first-run" 21 | ] 22 | }, 23 | { 24 | "name": "Launch Agent in Teams (Chrome)", 25 | "type": "chrome", 26 | "request": "launch", 27 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${local:agent-hint}?auth=2&developerMode=Basic", 28 | "cascadeTerminateToConfigurations": [ 29 | "Attach to Backend" 30 | ], 31 | "presentation": { 32 | "group": "all", 33 | "hidden": true 34 | }, 35 | "internalConsoleOptions": "neverOpen", 36 | "perScriptSourcemaps": "yes", 37 | "runtimeArgs": [ 38 | "--remote-debugging-port=9223", 39 | "--no-first-run" 40 | ] 41 | }, 42 | { 43 | "name": "Preview in Copilot (Edge)", 44 | "type": "msedge", 45 | "request": "launch", 46 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 47 | "presentation": { 48 | "group": "remote", 49 | "order": 1 50 | }, 51 | "internalConsoleOptions": "neverOpen", 52 | "runtimeArgs": [ 53 | "--remote-debugging-port=9224", 54 | "--no-first-run" 55 | ] 56 | }, 57 | { 58 | "name": "Preview in Copilot (Chrome)", 59 | "type": "chrome", 60 | "request": "launch", 61 | "url": "https://m365.cloud.microsoft/chat/entity1-d870f6cd-4aa5-4d42-9626-ab690c041429/${agent-hint}?auth=2&developerMode=Basic", 62 | "presentation": { 63 | "group": "remote", 64 | "order": 2 65 | }, 66 | "internalConsoleOptions": "neverOpen", 67 | "runtimeArgs": [ 68 | "--remote-debugging-port=9225", 69 | "--no-first-run" 70 | ] 71 | }, 72 | { 73 | "name": "Attach to Backend", 74 | "type": "node", 75 | "request": "attach", 76 | "port": 9229, 77 | "restart": true, 78 | "presentation": { 79 | "group": "all", 80 | "hidden": true 81 | }, 82 | "internalConsoleOptions": "neverOpen" 83 | } 84 | ], 85 | "compounds": [ 86 | { 87 | "name": "Debug in Copilot (Edge)", 88 | "configurations": [ 89 | "Launch Agent in Teams (Edge)", 90 | "Attach to Backend" 91 | ], 92 | "preLaunchTask": "Start Agent Locally", 93 | "presentation": { 94 | "group": "all", 95 | "order": 1 96 | }, 97 | "stopAll": true 98 | }, 99 | { 100 | "name": "Debug in Copilot (Chrome)", 101 | "configurations": [ 102 | "Launch Agent in Teams (Chrome)", 103 | "Attach to Backend" 104 | ], 105 | "preLaunchTask": "Start Agent Locally", 106 | "presentation": { 107 | "group": "all", 108 | "order": 2 109 | }, 110 | "stopAll": true 111 | } 112 | ] 113 | } 114 | -------------------------------------------------------------------------------- /src/service-desk-copilot/README.md: -------------------------------------------------------------------------------- 1 | # Overview of the basic declarative agent with API plugin template 2 | 3 | ## Build a basic declarative agent with API plugin 4 | 5 | With the declarative agent, you can build a custom version of Copilot that can be used for specific scenarios, such as for specialized knowledge, implementing specific processes, or simply to save time by reusing a set of AI prompts. For example, a grocery shopping Copilot declarative agent can be used to create a grocery list based on a meal plan that you send to Copilot. 6 | 7 | You can extend declarative agents using plugins to retrieve data and execute tasks on external systems. A declarative agent can utilize multiple plugins at the same time. 8 | 9 | ![image](https://github.com/user-attachments/assets/9939972e-0449-410c-b237-d9d748cd6628) 10 | 11 | 12 | ## Get started with the template 13 | 14 | > **Prerequisites** 15 | > 16 | > To run this app template in your local dev machine, you will need: 17 | > 18 | > - [Node.js](https://nodejs.org/), supported versions: 18, 20, 22 19 | > - A [Microsoft 365 account for development](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts). 20 | > - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) version 5.0.0 and higher or [Microsoft 365 Agents Toolkit CLI](https://aka.ms/teamsfx-toolkit-cli) 21 | > - [Microsoft 365 Copilot license](https://learn.microsoft.com/microsoft-365-copilot/extensibility/prerequisites#prerequisites) 22 | 23 | 1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. 24 | 2. In the Account section, sign in with your [Microsoft 365 account](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts) if you haven't already. 25 | 3. Select `Preview Local in Copilot (Edge)` or `Preview Local in Copilot (Chrome)` from the launch configuration dropdown. 26 | 4. Select your declarative agent from the `Copilot` app. 27 | 5. Send a prompt. 28 | 29 | 30 | 31 | ## What's included in the template 32 | 33 | | Folder | Contents | 34 | | ------------ | -------------------------------------------- | 35 | | `.vscode` | VSCode files for debugging | 36 | | `appPackage` | Templates for the application manifest, the plugin manifest and the API specification | 37 | | `env` | Environment files | 38 | 39 | The following files can be customized and demonstrate an example implementation to get you started. 40 | 41 | | File | Contents | 42 | | ------------------------------------ | ------------------------------------------------------------------------------ | 43 | | `appPackage/declarativeCopilot.json` | Define the behaviour and configurations of the declarative agent. | 44 | | `appPackage/manifest.json` | application manifest that defines metadata for your declarative agent. | 45 | 46 | The following are Microsoft 365 Agents Toolkit specific project files. You can [visit a complete guide on Github](https://github.com/OfficeDev/TeamsFx/wiki/Teams-Toolkit-Visual-Studio-Code-v5-Guide#overview) to understand how Microsoft 365 Agents Toolkit works. 47 | 48 | | File | Contents | 49 | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | 50 | | `m365agents.yml` | This is the main Microsoft 365 Agents Toolkit project file. The project file defines two primary things: Properties and configuration Stage definitions. | 51 | 52 | ## Addition information and references 53 | 54 | - [Declarative agents for Microsoft 365](https://aka.ms/teams-toolkit-declarative-agent) 55 | - [Extend Microsoft 365 Copilot](https://aka.ms/teamsfx-copilot-plugin) 56 | - [Message extensions for Microsoft 365 Copilot](https://learn.microsoft.com/microsoft-365-copilot/extensibility/overview-message-extension-bot) 57 | - [Microsoft Copilot connectors for Microsoft 365 Copilot](https://learn.microsoft.com/microsoft-365-copilot/extensibility/overview-graph-connector) 58 | - [Microsoft 365 Copilot extensibility samples](https://learn.microsoft.com/microsoft-365-copilot/extensibility/samples) -------------------------------------------------------------------------------- /src/pythonagenttest/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Remote (Edge)", 6 | "type": "msedge", 7 | "request": "launch", 8 | "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", 9 | "presentation": { 10 | "group": "1-Teams", 11 | "order": 4 12 | }, 13 | "internalConsoleOptions": "neverOpen" 14 | }, 15 | { 16 | "name": "Launch Remote (Chrome)", 17 | "type": "chrome", 18 | "request": "launch", 19 | "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", 20 | "presentation": { 21 | "group": "1-Teams", 22 | "order": 5 23 | }, 24 | "internalConsoleOptions": "neverOpen" 25 | }, 26 | { 27 | "name": "Launch Remote (Desktop)", 28 | "type": "node", 29 | "request": "launch", 30 | "preLaunchTask": "Start Agent in Desktop Client (Remote)", 31 | "presentation": { 32 | "group": "1-Teams", 33 | "order": 6 34 | }, 35 | "internalConsoleOptions": "neverOpen" 36 | }, 37 | { 38 | "name": "Launch Agent (Edge)", 39 | "type": "msedge", 40 | "request": "launch", 41 | "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", 42 | "presentation": { 43 | "group": "all", 44 | "hidden": true 45 | }, 46 | "internalConsoleOptions": "neverOpen" 47 | }, 48 | { 49 | "name": "Launch Agent (Chrome)", 50 | "type": "chrome", 51 | "request": "launch", 52 | "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", 53 | "presentation": { 54 | "group": "all", 55 | "hidden": true 56 | }, 57 | "internalConsoleOptions": "neverOpen" 58 | }, 59 | { 60 | "name": "Start Python", 61 | "type": "debugpy", 62 | "request": "launch", 63 | "program": "${workspaceFolder}/src/app.py", 64 | "cwd": "${workspaceFolder}/src", 65 | "console": "integratedTerminal" 66 | }, 67 | { 68 | "name": "Start Microsoft 365 Agents Playground", 69 | "type": "node", 70 | "request": "launch", 71 | "program": "${workspaceFolder}/devTools/teamsapptester/node_modules/@microsoft/teams-app-test-tool/cli.js", 72 | "args": [ 73 | "start" 74 | ], 75 | "env": { 76 | "PATH": "${workspaceFolder}/devTools/nodejs;${env:PATH}" 77 | }, 78 | "cwd": "${workspaceFolder}", 79 | "console": "integratedTerminal", 80 | "internalConsoleOptions": "neverOpen" 81 | } 82 | ], 83 | "compounds": [ 84 | { 85 | "name": "Debug in Teams (Edge)", 86 | "configurations": ["Launch Agent (Edge)", "Start Python"], 87 | "cascadeTerminateToConfigurations": ["Start Python"], 88 | "preLaunchTask": "Start Agent Locally", 89 | "presentation": { 90 | "group": "1-Teams", 91 | "order": 1 92 | }, 93 | "stopAll": true 94 | }, 95 | { 96 | "name": "Debug in Teams (Chrome)", 97 | "configurations": ["Launch Agent (Chrome)", "Start Python"], 98 | "cascadeTerminateToConfigurations": ["Start Python"], 99 | "preLaunchTask": "Start Agent Locally", 100 | "presentation": { 101 | "group": "1-Teams", 102 | "order": 2 103 | }, 104 | "stopAll": true 105 | }, 106 | { 107 | "name": "Debug in Teams (Desktop)", 108 | "configurations": ["Start Python"], 109 | "preLaunchTask": "Start Agent in Desktop Client", 110 | "presentation": { 111 | "group": "1-Teams", 112 | "order": 3 113 | }, 114 | "stopAll": true 115 | }, 116 | { 117 | "name": "Debug in Microsoft 365 Agents Playground", 118 | "configurations": [ 119 | "Start Python", 120 | "Start Microsoft 365 Agents Playground" 121 | ], 122 | "cascadeTerminateToConfigurations": [ 123 | "Start Microsoft 365 Agents Playground" 124 | ], 125 | "preLaunchTask": "Deploy (Microsoft 365 Agents Playground)", 126 | "presentation": { 127 | "group": "0-TestTool", 128 | "order": 1 129 | }, 130 | "stopAll": true 131 | } 132 | ] 133 | } 134 | -------------------------------------------------------------------------------- /src/advanced_repairs_api/database.py: -------------------------------------------------------------------------------- 1 | """database.py - Acceso a datos para la Repair API usando Azure Cosmos DB.""" 2 | import os 3 | from datetime import datetime, timezone 4 | from typing import Any, Dict, List, Optional 5 | 6 | from dotenv import load_dotenv 7 | from azure.cosmos import CosmosClient, exceptions 8 | 9 | # Cargar variables de entorno en local (.env) 10 | load_dotenv() 11 | 12 | COSMOS_URL = os.getenv("COSMOS_ENDPOINT") 13 | COSMOS_KEY = os.getenv("COSMOS_KEY") 14 | COSMOS_DB_NAME = os.getenv("COSMOS_DATABASE") 15 | COSMOS_CONTAINER_NAME = os.getenv("COSMOS_CONTAINER", "Repairs") 16 | 17 | if not all([COSMOS_URL, COSMOS_KEY, COSMOS_DB_NAME]): 18 | raise RuntimeError( 19 | "Missing one or more Cosmos env variables. " 20 | "Make sure COSMOS_URL, COSMOS_KEY and COSMOS_DB_NAME are set." 21 | ) 22 | 23 | # Crear cliente de Cosmos y obtener referencias a DB y contenedor 24 | try: 25 | client = CosmosClient(COSMOS_URL, credential=COSMOS_KEY) 26 | database = client.get_database_client(COSMOS_DB_NAME) 27 | container = database.get_container_client(COSMOS_CONTAINER_NAME) 28 | except exceptions.CosmosHttpResponseError as e: 29 | raise RuntimeError(f"Error connecting to Cosmos DB: {e}") from e 30 | 31 | 32 | def create_repair_in_db( 33 | item: str, 34 | description: str, 35 | status: str = "New", 36 | assigned_to: Optional[str] = None, 37 | created_by: Optional[str] = None, 38 | ) -> Dict[str, Any]: 39 | """ 40 | Inserta un ticket de reparación en Cosmos DB y devuelve el documento como dict. 41 | 42 | Campos: 43 | - id: GUID generado por la API 44 | - item, description, status, assigned_to: datos funcionales 45 | - created_at: timestamp UTC ISO-8601 46 | - created_by: identificador de quién crea el ticket (tenant|conversation, etc.) 47 | """ 48 | from uuid import uuid4 49 | 50 | repair_id = str(uuid4()) 51 | created_at = datetime.now(timezone.utc).isoformat() 52 | 53 | doc: Dict[str, Any] = { 54 | "id": repair_id, 55 | "item": item, 56 | "description": description, 57 | "status": status, 58 | "assigned_to": assigned_to, 59 | "created_at": created_at, 60 | "created_by": created_by, 61 | } 62 | 63 | container.create_item(doc) 64 | return doc 65 | 66 | 67 | def list_repairs_from_db( 68 | status: Optional[str] = None, 69 | assigned_to: Optional[str] = None, 70 | created_by: Optional[str] = None, 71 | ) -> List[Dict[str, Any]]: 72 | """ 73 | Devuelve una lista de tickets desde Cosmos DB, con filtros opcionales: 74 | 75 | - status: filtra por estado exacto (New, In Progress, Completed, etc.) 76 | - assigned_to: hace un CONTAINS sobre el campo assigned_to (case-insensitive). 77 | - created_by: filtra por el identificador guardado (tenant o tenant|conversation). 78 | """ 79 | query = """ 80 | SELECT c.id, c.item, c.description, c.status, 81 | c.assigned_to, c.created_at, c.created_by 82 | FROM c 83 | WHERE 1 = 1 84 | """ 85 | parameters: List[Dict[str, Any]] = [] 86 | 87 | if status: 88 | query += " AND c.status = @status" 89 | parameters.append({"name": "@status", "value": status}) 90 | 91 | if assigned_to: 92 | # CONTAINS, case-insensitive (tercer parámetro = true) 93 | query += " AND IS_DEFINED(c.assigned_to) " \ 94 | "AND CONTAINS(c.assigned_to, @assigned_to, true)" 95 | parameters.append({"name": "@assigned_to", "value": assigned_to}) 96 | 97 | if created_by: 98 | query += " AND c.created_by = @created_by" 99 | parameters.append({"name": "@created_by", "value": created_by}) 100 | 101 | items = list( 102 | container.query_items( 103 | query=query, 104 | parameters=parameters, 105 | enable_cross_partition_query=True, 106 | ) 107 | ) 108 | 109 | # items ya es una lista de dicts 110 | return items 111 | 112 | 113 | if __name__ == "__main__": 114 | # Pequeño test manual para validar conexión 115 | print("Testing DB connection and insert...") 116 | sample = create_repair_in_db( 117 | item="Test device", 118 | description="Just a test ticket from database.py __main__", 119 | status="New", 120 | assigned_to="Demo User", 121 | created_by="local-test", 122 | ) 123 | print("Inserted document:") 124 | print(sample) 125 | 126 | repairs = list_repairs_from_db() 127 | print(f"Total repairs in DB: {len(repairs)}") 128 | -------------------------------------------------------------------------------- /src/advanced_service_desk_copilot/README.md: -------------------------------------------------------------------------------- 1 | # Overview of the basic declarative agent with API plugin template 2 | 3 | ## Build a basic declarative agent with API plugin 4 | 5 | With the declarative agent, you can build a custom version of Copilot that can be used for specific scenarios, such as for specialized knowledge, implementing specific processes, or simply to save time by reusing a set of AI prompts. For example, a grocery shopping Copilot declarative agent can be used to create a grocery list based on a meal plan that you send to Copilot. 6 | 7 | You can extend declarative agents using plugins to retrieve data and execute tasks on external systems. A declarative agent can utilize multiple plugins at the same time. 8 | 9 | ![image](https://github.com/user-attachments/assets/9939972e-0449-410c-b237-d9d748cd6628) 10 | 11 | 12 | ## Get started with the template 13 | 14 | > **Prerequisites** 15 | > 16 | > To run this app template in your local dev machine, you will need: 17 | > 18 | > - [Node.js](https://nodejs.org/), supported versions: 18, 20, 22 19 | > - A [Microsoft 365 account for development](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts). 20 | > - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) version 5.0.0 and higher or [Microsoft 365 Agents Toolkit CLI](https://aka.ms/teamsfx-toolkit-cli) 21 | > - [Microsoft 365 Copilot license](https://learn.microsoft.com/microsoft-365-copilot/extensibility/prerequisites#prerequisites) 22 | 23 | 1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. 24 | 2. In the Account section, sign in with your [Microsoft 365 account](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts) if you haven't already. 25 | 3. Select `Preview Local in Copilot (Edge)` or `Preview Local in Copilot (Chrome)` from the launch configuration dropdown. 26 | 4. Select your declarative agent from the `Copilot` app. 27 | 5. Send a prompt. 28 | 29 | > [!NOTE] 30 | > Microsoft 365 Agents Toolkit will ask you for your API key during provision. The API key will be securely stored with [Developer Portal](https://dev.teams.microsoft.com/home) and used by Teams client to access your API in runtime. Microsoft 365 Agents Toolkit will not store your API key. 31 | 32 | 33 | ## What's included in the template 34 | 35 | | Folder | Contents | 36 | | ------------ | -------------------------------------------- | 37 | | `.vscode` | VSCode files for debugging | 38 | | `appPackage` | Templates for the application manifest, the plugin manifest and the API specification | 39 | | `env` | Environment files | 40 | 41 | The following files can be customized and demonstrate an example implementation to get you started. 42 | 43 | | File | Contents | 44 | | ------------------------------------ | ------------------------------------------------------------------------------ | 45 | | `appPackage/declarativeCopilot.json` | Define the behaviour and configurations of the declarative agent. | 46 | | `appPackage/manifest.json` | application manifest that defines metadata for your declarative agent. | 47 | 48 | The following are Microsoft 365 Agents Toolkit specific project files. You can [visit a complete guide on Github](https://github.com/OfficeDev/TeamsFx/wiki/Teams-Toolkit-Visual-Studio-Code-v5-Guide#overview) to understand how Microsoft 365 Agents Toolkit works. 49 | 50 | | File | Contents | 51 | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | 52 | | `m365agents.yml` | This is the main Microsoft 365 Agents Toolkit project file. The project file defines two primary things: Properties and configuration Stage definitions. | 53 | 54 | ## Addition information and references 55 | 56 | - [Declarative agents for Microsoft 365](https://aka.ms/teams-toolkit-declarative-agent) 57 | - [Extend Microsoft 365 Copilot](https://aka.ms/teamsfx-copilot-plugin) 58 | - [Message extensions for Microsoft 365 Copilot](https://learn.microsoft.com/microsoft-365-copilot/extensibility/overview-message-extension-bot) 59 | - [Microsoft Copilot connectors for Microsoft 365 Copilot](https://learn.microsoft.com/microsoft-365-copilot/extensibility/overview-graph-connector) 60 | - [Microsoft 365 Copilot extensibility samples](https://learn.microsoft.com/microsoft-365-copilot/extensibility/samples) -------------------------------------------------------------------------------- /src/test-action-agent/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by Microsoft 365 Agents Toolkit. 2 | // The teamsfx tasks defined in this file require Microsoft 365 Agents Toolkit version >= 5.0.0. 3 | // See https://aka.ms/teamsfx-tasks for details on how to customize each task. 4 | { 5 | "version": "2.0.0", 6 | "tasks": [ 7 | { 8 | "label": "Start Agent Locally", 9 | "dependsOn": [ 10 | "Validate prerequisites", 11 | "Start local tunnel", 12 | "Create resources", 13 | "Build project", 14 | "Start application" 15 | ], 16 | "dependsOrder": "sequence" 17 | }, 18 | { 19 | "label": "Validate prerequisites", 20 | "type": "teamsfx", 21 | "command": "debug-check-prerequisites", 22 | "args": { 23 | "prerequisites": [ 24 | "nodejs", 25 | "m365Account", 26 | "portOccupancy" 27 | ], 28 | "portOccupancy": [ 29 | 7071, 30 | 9229 31 | ] 32 | } 33 | }, 34 | { 35 | // Start the local tunnel service to forward public URL to local port and inspect traffic. 36 | // See https://aka.ms/teamsfx-tasks/local-tunnel for the detailed args definitions. 37 | "label": "Start local tunnel", 38 | "type": "teamsfx", 39 | "command": "debug-start-local-tunnel", 40 | "args": { 41 | "type": "dev-tunnel", 42 | "ports": [ 43 | { 44 | "portNumber": 7071, 45 | "protocol": "http", 46 | "access": "public", 47 | "writeToEnvironmentFile": { 48 | "endpoint": "OPENAPI_SERVER_URL", // output tunnel endpoint as OPENAPI_SERVER_URL 49 | } 50 | } 51 | ], 52 | "env": "local" 53 | }, 54 | "isBackground": true, 55 | "problemMatcher": "$teamsfx-local-tunnel-watch" 56 | }, 57 | { 58 | "label": "Create resources", 59 | "type": "teamsfx", 60 | "command": "provision", 61 | "args": { 62 | "env": "local" 63 | } 64 | }, 65 | { 66 | "label": "Build project", 67 | "type": "teamsfx", 68 | "command": "deploy", 69 | "args": { 70 | "env": "local" 71 | } 72 | }, 73 | { 74 | "label": "Start application", 75 | "dependsOn": [ 76 | "Start backend" 77 | ] 78 | }, 79 | { 80 | "label": "Start backend", 81 | "type": "shell", 82 | "command": "npm run dev:teamsfx", 83 | "isBackground": true, 84 | "options": { 85 | "cwd": "${workspaceFolder}", 86 | "env": { 87 | "PATH": "${workspaceFolder}/devTools/func:${env:PATH}" 88 | } 89 | }, 90 | "windows": { 91 | "options": { 92 | "env": { 93 | "PATH": "${workspaceFolder}/devTools/func;${env:PATH}" 94 | } 95 | } 96 | }, 97 | "problemMatcher": { 98 | "pattern": { 99 | "regexp": "^.*$", 100 | "file": 0, 101 | "location": 1, 102 | "message": 2 103 | }, 104 | "background": { 105 | "activeOnStart": true, 106 | "beginsPattern": "^.*(Job host stopped|signaling restart).*$", 107 | "endsPattern": "^.*(Worker process started and initialized|Host lock lease acquired by instance ID).*$" 108 | } 109 | }, 110 | "presentation": { 111 | "reveal": "silent" 112 | }, 113 | "dependsOn": "Watch backend" 114 | }, 115 | { 116 | "label": "Watch backend", 117 | "type": "shell", 118 | "command": "npm run watch:teamsfx", 119 | "isBackground": true, 120 | "options": { 121 | "cwd": "${workspaceFolder}" 122 | }, 123 | "problemMatcher": "$tsc-watch", 124 | "presentation": { 125 | "reveal": "silent" 126 | } 127 | } 128 | ] 129 | } -------------------------------------------------------------------------------- /src/toolkit_agent/README.md: -------------------------------------------------------------------------------- 1 | # Overview of the Declarative Agent template 2 | 3 | With the declarative agent, you can build a custom version of Copilot that can be used for specific scenarios, such as for specialized knowledge, implementing specific processes, or simply to save time by reusing a set of AI prompts. For example, a grocery shopping Copilot declarative agent can be used to create a grocery list based on a meal plan that you send to Copilot. 4 | 5 | ## Get started with the template 6 | 7 | > **Prerequisites** 8 | > 9 | > To run this app template in your local dev machine, you will need: 10 | > 11 | > - [Node.js](https://nodejs.org/), supported versions: 18, 20, 22 12 | > - A [Microsoft 365 account for development](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts). 13 | > - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) version 5.0.0 and higher or [Microsoft 365 Agents Toolkit CLI](https://aka.ms/teamsfx-toolkit-cli) 14 | > - [Microsoft 365 Copilot license](https://learn.microsoft.com/microsoft-365-copilot/extensibility/prerequisites#prerequisites) 15 | 16 | ![image](https://github.com/user-attachments/assets/51a221bb-a2c6-4dbf-8009-d2aa20a1638f) 17 | 18 | 1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. 19 | 2. In the Account section, sign in with your [Microsoft 365 account](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts) if you haven't already. 20 | 3. Select `Preview Local in Copilot (Edge)` or `Preview Local in Copilot (Chrome)` from the launch configuration dropdown. 21 | 4. Select your declarative agent from the `Copilot` app. 22 | 5. Ask a question to your declarative agent and it should respond based on the instructions provided. 23 | 24 | ## What's included in the template 25 | 26 | | Folder | Contents | 27 | | ------------ | ---------------------------------------------------------------------------------------- | 28 | | `.vscode` | VSCode files for debugging | 29 | | `appPackage` | Templates for the application manifest, the GPT manifest and the API specification | 30 | | `env` | Environment files | 31 | 32 | The following files can be customized and demonstrate an example implementation to get you started. 33 | 34 | | File | Contents | 35 | | ---------------------------------- | ---------------------------------------------------------------------------- | 36 | | `appPackage/declarativeAgent.json` | Define the behaviour and configurations of the declarative agent. | 37 | | `appPackage/manifest.json` | application manifest that defines metadata for your declarative agent. | 38 | 39 | The following are Microsoft 365 Agents Toolkit specific project files. You can [visit a complete guide on Github](https://github.com/OfficeDev/TeamsFx/wiki/Teams-Toolkit-Visual-Studio-Code-v5-Guide#overview) to understand how Microsoft 365 Agents Toolkit works. 40 | 41 | | File | Contents | 42 | | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | 43 | | `m365agents.yml` | This is the main Microsoft 365 Agents Toolkit project file. The project file defines two primary things: Properties and configuration Stage definitions. | 44 | 45 | ## Extend the template 46 | 47 | - [Add conversation starters](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=3): Conversation starters are hints that are displayed to the user to demonstrate how they can get started using the declarative agent. 48 | - [Add web content](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=4) for the ability to search web information. 49 | - [Add OneDrive and SharePoint content](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=5) as grounding knowledge for the agent. 50 | - [Add Microsoft Copilot connectors content](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=6) to ground agent with enterprise knowledge. 51 | - [Add API plugins](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=7) for agent to interact with REST APIs. 52 | 53 | ## Addition information and references 54 | 55 | - [Declarative agents for Microsoft 365](https://aka.ms/teams-toolkit-declarative-agent) 56 | -------------------------------------------------------------------------------- /src/pythonagenttest/m365agents.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.11 5 | 6 | environmentFolderPath: ./env 7 | 8 | # Triggered when 'teamsfx provision' is executed 9 | provision: 10 | # Creates an app 11 | - uses: teamsApp/create 12 | with: 13 | # app name 14 | name: pythonagenttest${{APP_NAME_SUFFIX}} 15 | # Write the information of created resources into environment file for 16 | # the specified environment variable(s). 17 | writeToEnvironmentFile: 18 | teamsAppId: TEAMS_APP_ID 19 | 20 | - uses: arm/deploy # Deploy given ARM templates parallelly. 21 | with: 22 | # AZURE_SUBSCRIPTION_ID is a built-in environment variable, 23 | # if its value is empty, TeamsFx will prompt you to select a subscription. 24 | # Referencing other environment variables with empty values 25 | # will skip the subscription selection prompt. 26 | subscriptionId: ${{AZURE_SUBSCRIPTION_ID}} 27 | # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, 28 | # if its value is empty, TeamsFx will prompt you to select or create one 29 | # resource group. 30 | # Referencing other environment variables with empty values 31 | # will skip the resource group selection prompt. 32 | resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}} 33 | templates: 34 | - path: ./infra/azure.bicep # Relative path to this file 35 | # Relative path to this yaml file. 36 | # Placeholders will be replaced with corresponding environment 37 | # variable before ARM deployment. 38 | parameters: ./infra/azure.parameters.json 39 | # Required when deploying ARM template 40 | deploymentName: Create-resources-for-tab 41 | # Microsoft 365 Agents Toolkit will download this bicep CLI version from github for you, 42 | # will use bicep CLI in PATH if you remove this config. 43 | bicepCliVersion: v0.9.1 44 | 45 | # Validate using manifest schema 46 | - uses: teamsApp/validateManifest 47 | with: 48 | # Path to manifest template 49 | manifestPath: ./appPackage/manifest.json 50 | 51 | # Build app package with latest env value 52 | - uses: teamsApp/zipAppPackage 53 | with: 54 | # Path to manifest template 55 | manifestPath: ./appPackage/manifest.json 56 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 57 | outputFolder: ./appPackage/build 58 | 59 | # Validate app package using validation rules 60 | - uses: teamsApp/validateAppPackage 61 | with: 62 | # Relative path to this file. This is the path for built zip file. 63 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 64 | 65 | # Apply the app manifest to an existing app in 66 | # Developer Portal. 67 | # Will use the app id in manifest file to determine which app to update. 68 | - uses: teamsApp/update 69 | with: 70 | # Relative path to this file. This is the path for built zip file. 71 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 72 | 73 | # Triggered when 'teamsfx deploy' is executed 74 | deploy: 75 | # Deploy your application to Azure App Service using the zip deploy feature. 76 | # For additional details, refer to https://aka.ms/zip-deploy-to-app-services. 77 | - uses: azureAppService/zipDeploy 78 | with: 79 | # Deploy base folder 80 | artifactFolder: src 81 | # Ignore file location, leave blank will ignore nothing 82 | ignoreFile: .webappignore 83 | # The resource id of the cloud resource to be deployed to. 84 | # This key will be generated by arm/deploy action automatically. 85 | # You can replace it with your existing Azure Resource id 86 | # or add it to your environment variable file. 87 | resourceId: ${{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} 88 | 89 | # Triggered when 'teamsapp publish' is executed 90 | publish: 91 | # Validate using manifest schema 92 | - uses: teamsApp/validateManifest 93 | with: 94 | # Path to manifest template 95 | manifestPath: ./appPackage/manifest.json 96 | 97 | # Build app package with latest env value 98 | - uses: teamsApp/zipAppPackage 99 | with: 100 | # Path to manifest template 101 | manifestPath: ./appPackage/manifest.json 102 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 103 | outputFolder: ./appPackage/build 104 | 105 | # Validate app package using validation rules 106 | - uses: teamsApp/validateAppPackage 107 | with: 108 | # Relative path to this file. This is the path for built zip file. 109 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 110 | 111 | # Apply the app manifest to an existing app in 112 | # Developer Portal. 113 | # Will use the app id in manifest file to determine which app to update. 114 | - uses: teamsApp/update 115 | with: 116 | # Relative path to this file. This is the path for built zip file. 117 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 118 | # Publish the app to 119 | # Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps) 120 | # for review and approval 121 | - uses: teamsApp/publishAppPackage 122 | with: 123 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 124 | # Write the information of created resources into environment file for 125 | # the specified environment variable(s). 126 | writeToEnvironmentFile: 127 | publishedAppId: TEAMS_APP_PUBLISHED_APP_ID 128 | projectId: 602af5e5-6091-4610-8c54-c71332f5d253 129 | -------------------------------------------------------------------------------- /src/pythonagenttest/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by Microsoft 365 Agents Toolkit. 2 | // The teamsfx tasks defined in this file require Microsoft 365 Agents Toolkit version >= 5.0.0. 3 | // See https://aka.ms/teamsfx-tasks for details on how to customize each task. 4 | { 5 | "version": "2.0.0", 6 | "tasks": [ 7 | { 8 | // Check all required prerequisites. 9 | // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. 10 | "label": "Validate prerequisites (Microsoft 365 Agents Playground)", 11 | "type": "teamsfx", 12 | "command": "debug-check-prerequisites", 13 | "args": { 14 | "prerequisites": [ 15 | "nodejs", // Check if Node.js is installed and the version is >= 12. 16 | "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. 17 | ], 18 | "portOccupancy": [ 19 | 3978, // app service port 20 | 56150, // Microsoft 365 Agents Playground port 21 | ] 22 | } 23 | }, 24 | { 25 | // Build project. 26 | // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. 27 | "label": "Deploy (Microsoft 365 Agents Playground)", 28 | "dependsOn": [ 29 | "Validate prerequisites (Microsoft 365 Agents Playground)" 30 | ], 31 | "type": "teamsfx", 32 | "command": "deploy", 33 | "args": { 34 | "env": "playground", 35 | } 36 | }, 37 | { 38 | "label": "Start Agent Locally", 39 | "dependsOn": [ 40 | "Validate prerequisites", 41 | "Start local tunnel", 42 | "Provision", 43 | "Deploy" 44 | ], 45 | "dependsOrder": "sequence" 46 | }, 47 | { 48 | // Check all required prerequisites. 49 | // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. 50 | "label": "Validate prerequisites", 51 | "type": "teamsfx", 52 | "command": "debug-check-prerequisites", 53 | "args": { 54 | "prerequisites": [ 55 | "m365Account", // Sign-in prompt for Microsoft 365 account, then validate if the account enables the sideloading permission. 56 | "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. 57 | ], 58 | "portOccupancy": [ 59 | 3978 // app service port 60 | ] 61 | } 62 | }, 63 | { 64 | // Start the local tunnel service to forward public URL to local port and inspect traffic. 65 | // See https://aka.ms/teamsfx-tasks/local-tunnel for the detailed args definitions. 66 | "label": "Start local tunnel", 67 | "type": "teamsfx", 68 | "command": "debug-start-local-tunnel", 69 | "args": { 70 | "type": "dev-tunnel", 71 | "ports": [ 72 | { 73 | "portNumber": 3978, 74 | "protocol": "http", 75 | "access": "public", 76 | "writeToEnvironmentFile": { 77 | "endpoint": "BOT_ENDPOINT", // output tunnel endpoint as BOT_ENDPOINT 78 | "domain": "BOT_DOMAIN" // output tunnel domain as BOT_DOMAIN 79 | } 80 | } 81 | ], 82 | "env": "local" 83 | }, 84 | "isBackground": true, 85 | "problemMatcher": "$teamsfx-local-tunnel-watch" 86 | }, 87 | { 88 | // Create the debug resources. 89 | // See https://aka.ms/teamsfx-tasks/provision to know the details and how to customize the args. 90 | "label": "Provision", 91 | "type": "teamsfx", 92 | "command": "provision", 93 | "args": { 94 | "env": "local" 95 | } 96 | }, 97 | { 98 | // Build project. 99 | // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. 100 | "label": "Deploy", 101 | "type": "teamsfx", 102 | "command": "deploy", 103 | "args": { 104 | "env": "local" 105 | } 106 | }, 107 | { 108 | "label": "Start Agent in Desktop Client", 109 | "dependsOn": [ 110 | "Validate prerequisites", 111 | "Start local tunnel", 112 | "Provision", 113 | "Deploy", 114 | "Start desktop client" 115 | ], 116 | "dependsOrder": "sequence" 117 | }, 118 | { 119 | "label": "Start desktop client", 120 | "type": "teamsfx", 121 | "command": "launch-desktop-client", 122 | "args": { 123 | "url": "teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true" 124 | } 125 | }, 126 | { 127 | "label": "Start Agent in Desktop Client (Remote)", 128 | "type": "teamsfx", 129 | "command": "launch-desktop-client", 130 | "args": { 131 | "url": "teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true" 132 | } 133 | } 134 | ] 135 | } -------------------------------------------------------------------------------- /src/test-action-agent/m365agents.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.10/yaml.schema.json 2 | # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file 3 | # Visit https://aka.ms/teamsfx-actions for details on actions 4 | version: v1.10 5 | 6 | environmentFolderPath: ./env 7 | 8 | # Triggered when 'teamsapp provision' is executed 9 | provision: 10 | # Creates an app 11 | - uses: teamsApp/create 12 | with: 13 | # app name 14 | name: test-action-agent${{APP_NAME_SUFFIX}} 15 | # Write the information of created resources into environment file for 16 | # the specified environment variable(s). 17 | writeToEnvironmentFile: 18 | teamsAppId: TEAMS_APP_ID 19 | 20 | - uses: arm/deploy # Deploy given ARM templates parallelly. 21 | with: 22 | # AZURE_SUBSCRIPTION_ID is a built-in environment variable, 23 | # if its value is empty, TeamsFx will prompt you to select a subscription. 24 | # Referencing other environment variables with empty values 25 | # will skip the subscription selection prompt. 26 | subscriptionId: ${{AZURE_SUBSCRIPTION_ID}} 27 | # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, 28 | # if its value is empty, TeamsFx will prompt you to select or create one 29 | # resource group. 30 | # Referencing other environment variables with empty values 31 | # will skip the resource group selection prompt. 32 | resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}} 33 | templates: 34 | - path: ./infra/azure.bicep # Relative path to this file 35 | # Relative path to this yaml file. 36 | # Placeholders will be replaced with corresponding environment 37 | # variable before ARM deployment. 38 | parameters: ./infra/azure.parameters.json 39 | # Required when deploying ARM template 40 | deploymentName: Create-resources-for-sme 41 | # Microsoft 365 Agents Toolkit will download this bicep CLI version from github for you, 42 | # will use bicep CLI in PATH if you remove this config. 43 | bicepCliVersion: v0.9.1 44 | 45 | # Build app package with latest env value 46 | - uses: teamsApp/zipAppPackage 47 | with: 48 | # Path to manifest template 49 | manifestPath: ./appPackage/manifest.json 50 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 51 | outputFolder: ./appPackage/build 52 | 53 | # Validate app package using validation rules 54 | - uses: teamsApp/validateAppPackage 55 | with: 56 | # Relative path to this file. This is the path for built zip file. 57 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 58 | 59 | # Apply the app manifest to an existing app in 60 | # Developer Portal. 61 | # Will use the app id in manifest file to determine which app to update. 62 | - uses: teamsApp/update 63 | with: 64 | # Relative path to this file. This is the path for built zip file. 65 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 66 | 67 | # Extend your app to Outlook and the Microsoft 365 app 68 | - uses: teamsApp/extendToM365 69 | with: 70 | # Relative path to the build app package. 71 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 72 | scope: ${{AGENT_SCOPE}} 73 | # Write the information of created resources into environment file for 74 | # the specified environment variable(s). 75 | writeToEnvironmentFile: 76 | titleId: M365_TITLE_ID 77 | appId: M365_APP_ID 78 | shareLink: SHARE_LINK 79 | 80 | # Triggered when 'teamsapp deploy' is executed 81 | deploy: 82 | # Run npm command 83 | - uses: cli/runNpmCommand 84 | name: install dependencies 85 | with: 86 | args: install 87 | 88 | - uses: cli/runNpmCommand 89 | name: build app 90 | with: 91 | args: run build --if-present 92 | 93 | # Deploy your application to Azure Functions using the zip deploy feature. 94 | # For additional details, see at https://aka.ms/zip-deploy-to-azure-functions 95 | - uses: azureFunctions/zipDeploy 96 | with: 97 | # deploy base folder 98 | artifactFolder: . 99 | # Ignore file location, leave blank will ignore nothing 100 | ignoreFile: .funcignore 101 | # The resource id of the cloud resource to be deployed to. 102 | # This key will be generated by arm/deploy action automatically. 103 | # You can replace it with your existing Azure Resource id 104 | # or add it to your environment variable file. 105 | resourceId: ${{API_FUNCTION_RESOURCE_ID}} 106 | 107 | # Triggered when 'teamsapp publish' is executed 108 | publish: 109 | # Build app package with latest env value 110 | - uses: teamsApp/zipAppPackage 111 | with: 112 | # Path to manifest template 113 | manifestPath: ./appPackage/manifest.json 114 | outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 115 | outputFolder: ./appPackage/build 116 | # Validate app package using validation rules 117 | - uses: teamsApp/validateAppPackage 118 | with: 119 | # Relative path to this file. This is the path for built zip file. 120 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 121 | # Apply the app manifest to an existing app in 122 | # Developer Portal. 123 | # Will use the app id in manifest file to determine which app to update. 124 | - uses: teamsApp/update 125 | with: 126 | # Relative path to this file. This is the path for built zip file. 127 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 128 | # Publish the app to 129 | # Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps) 130 | # for review and approval 131 | - uses: teamsApp/publishAppPackage 132 | with: 133 | appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip 134 | # Write the information of created resources into environment file for 135 | # the specified environment variable(s). 136 | writeToEnvironmentFile: 137 | publishedAppId: TEAMS_APP_PUBLISHED_APP_ID 138 | projectId: 882c8d88-c65f-4ab0-b41d-74a8b4d423ee 139 | -------------------------------------------------------------------------------- /src/repairs_api/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.1.0 2 | info: 3 | title: Repair Service 4 | description: > 5 | A simple service to manage repair tickets for devices so that 6 | Microsoft 365 Copilot agents can list, inspect, and create repairs 7 | on behalf of users. 8 | version: 1.0.0 9 | 10 | servers: 11 | - url: https://fa3abfbb0f86.ngrok-free.app 12 | description: Production Repair Service API 13 | 14 | paths: 15 | /repairs: 16 | get: 17 | operationId: listRepairs 18 | summary: List all repairs 19 | description: > 20 | Returns a list of repair tickets with their details. You can optionally 21 | filter by status or by who the repair is assigned to. 22 | parameters: 23 | - name: status 24 | in: query 25 | description: > 26 | Optional status to filter repairs by. For example, 'New', 27 | 'In Progress', or 'Completed'. 28 | required: false 29 | schema: 30 | type: string 31 | example: "New" 32 | - name: assignedTo 33 | in: query 34 | description: > 35 | Optional name or ID of the person or team the repair is assigned to. 36 | required: false 37 | schema: 38 | type: string 39 | example: "John Doe" 40 | responses: 41 | "200": 42 | description: A list of repairs matching the filters. 43 | content: 44 | application/json: 45 | schema: 46 | type: array 47 | items: 48 | $ref: "#/components/schemas/Repair" 49 | examples: 50 | example1: 51 | summary: Example list of repairs 52 | value: 53 | - id: "1" 54 | item: "Laptop" 55 | description: "Screen is flickering and sometimes goes black." 56 | status: "In Progress" 57 | assigned_to: "John Doe" 58 | created_at: "2024-10-21T09:15:00Z" 59 | - id: "2" 60 | item: "Printer" 61 | description: "Paper jam error on every print job." 62 | status: "New" 63 | assigned_to: null 64 | created_at: "2024-10-22T11:30:00Z" 65 | "500": 66 | description: Server error 67 | post: 68 | operationId: createRepair 69 | summary: Create a new repair 70 | description: Create a new repair ticket for a device that needs to be fixed. 71 | requestBody: 72 | required: true 73 | description: Information about the device and the issue to be repaired. 74 | content: 75 | application/json: 76 | schema: 77 | $ref: "#/components/schemas/RepairCreate" 78 | examples: 79 | example1: 80 | summary: Example create payload 81 | value: 82 | item: "Laptop" 83 | description: "Laptop won't turn on after a power outage." 84 | status: "New" 85 | assigned_to: "Tier 1 Support" 86 | responses: 87 | "201": 88 | description: Repair ticket successfully created. 89 | content: 90 | application/json: 91 | schema: 92 | $ref: "#/components/schemas/Repair" 93 | examples: 94 | example1: 95 | summary: Example created repair 96 | value: 97 | id: "3" 98 | item: "Laptop" 99 | description: "Laptop won't turn on after a power outage." 100 | status: "New" 101 | assigned_to: "Tier 1 Support" 102 | created_at: "2024-10-23T08:00:00Z" 103 | "400": 104 | description: Invalid request body. 105 | "500": 106 | description: Server error 107 | 108 | components: 109 | schemas: 110 | Repair: 111 | type: object 112 | description: A repair ticket representing a device that needs to be fixed. 113 | properties: 114 | id: 115 | type: string 116 | description: Unique identifier of the repair ticket. 117 | example: "1" 118 | item: 119 | type: string 120 | description: Name or type of the item that needs repair. 121 | example: "Laptop" 122 | description: 123 | type: string 124 | description: Short description of the issue reported by the customer. 125 | example: "Screen is flickering and sometimes goes black." 126 | status: 127 | type: string 128 | description: Current status of the repair. 129 | example: "In Progress" 130 | assigned_to: 131 | type: string 132 | nullable: true 133 | description: Name of the person or team assigned to this repair. 134 | example: "John Doe" 135 | created_at: 136 | type: string 137 | format: date-time 138 | description: Date and time when the repair ticket was created (UTC). 139 | example: "2024-10-21T09:15:00Z" 140 | required: 141 | - id 142 | - item 143 | - description 144 | - status 145 | - created_at 146 | 147 | RepairCreate: 148 | type: object 149 | description: Payload for creating a new repair ticket. 150 | properties: 151 | item: 152 | type: string 153 | description: Name or type of the item that needs repair. 154 | example: "Laptop" 155 | description: 156 | type: string 157 | description: Short description of the issue reported by the customer. 158 | example: "Laptop won't turn on after a power outage." 159 | status: 160 | type: string 161 | description: Initial status of the repair. 162 | example: "New" 163 | assigned_to: 164 | type: string 165 | nullable: true 166 | description: Name of the person or team to assign this repair to. 167 | example: "Tier 1 Support" 168 | required: 169 | - item 170 | - description 171 | -------------------------------------------------------------------------------- /src/service-desk-copilot/appPackage/apiSpecificationFile/openapi.yaml.original: -------------------------------------------------------------------------------- 1 | openapi: 3.1.0 2 | info: 3 | title: Repair Service 4 | description: > 5 | A simple service to manage repair tickets for devices so that 6 | Microsoft 365 Copilot agents can list, inspect, and create repairs 7 | on behalf of users. 8 | version: 1.0.0 9 | 10 | servers: 11 | - url: https://fa3abfbb0f86.ngrok-free.app 12 | description: Production Repair Service API 13 | 14 | paths: 15 | /repairs: 16 | get: 17 | operationId: listRepairs 18 | summary: List all repairs 19 | description: > 20 | Returns a list of repair tickets with their details. You can optionally 21 | filter by status or by who the repair is assigned to. 22 | parameters: 23 | - name: status 24 | in: query 25 | description: > 26 | Optional status to filter repairs by. For example, 'New', 27 | 'In Progress', or 'Completed'. 28 | required: false 29 | schema: 30 | type: string 31 | example: "New" 32 | - name: assignedTo 33 | in: query 34 | description: > 35 | Optional name or ID of the person or team the repair is assigned to. 36 | required: false 37 | schema: 38 | type: string 39 | example: "John Doe" 40 | responses: 41 | "200": 42 | description: A list of repairs matching the filters. 43 | content: 44 | application/json: 45 | schema: 46 | type: array 47 | items: 48 | $ref: "#/components/schemas/Repair" 49 | examples: 50 | example1: 51 | summary: Example list of repairs 52 | value: 53 | - id: "1" 54 | item: "Laptop" 55 | description: "Screen is flickering and sometimes goes black." 56 | status: "In Progress" 57 | assigned_to: "John Doe" 58 | created_at: "2024-10-21T09:15:00Z" 59 | - id: "2" 60 | item: "Printer" 61 | description: "Paper jam error on every print job." 62 | status: "New" 63 | assigned_to: null 64 | created_at: "2024-10-22T11:30:00Z" 65 | "500": 66 | description: Server error 67 | post: 68 | operationId: createRepair 69 | summary: Create a new repair 70 | description: Create a new repair ticket for a device that needs to be fixed. 71 | requestBody: 72 | required: true 73 | description: Information about the device and the issue to be repaired. 74 | content: 75 | application/json: 76 | schema: 77 | $ref: "#/components/schemas/RepairCreate" 78 | examples: 79 | example1: 80 | summary: Example create payload 81 | value: 82 | item: "Laptop" 83 | description: "Laptop won't turn on after a power outage." 84 | status: "New" 85 | assigned_to: "Tier 1 Support" 86 | responses: 87 | "201": 88 | description: Repair ticket successfully created. 89 | content: 90 | application/json: 91 | schema: 92 | $ref: "#/components/schemas/Repair" 93 | examples: 94 | example1: 95 | summary: Example created repair 96 | value: 97 | id: "3" 98 | item: "Laptop" 99 | description: "Laptop won't turn on after a power outage." 100 | status: "New" 101 | assigned_to: "Tier 1 Support" 102 | created_at: "2024-10-23T08:00:00Z" 103 | "400": 104 | description: Invalid request body. 105 | "500": 106 | description: Server error 107 | 108 | components: 109 | schemas: 110 | Repair: 111 | type: object 112 | description: A repair ticket representing a device that needs to be fixed. 113 | properties: 114 | id: 115 | type: string 116 | description: Unique identifier of the repair ticket. 117 | example: "1" 118 | item: 119 | type: string 120 | description: Name or type of the item that needs repair. 121 | example: "Laptop" 122 | description: 123 | type: string 124 | description: Short description of the issue reported by the customer. 125 | example: "Screen is flickering and sometimes goes black." 126 | status: 127 | type: string 128 | description: Current status of the repair. 129 | example: "In Progress" 130 | assigned_to: 131 | type: string 132 | nullable: true 133 | description: Name of the person or team assigned to this repair. 134 | example: "John Doe" 135 | created_at: 136 | type: string 137 | format: date-time 138 | description: Date and time when the repair ticket was created (UTC). 139 | example: "2024-10-21T09:15:00Z" 140 | required: 141 | - id 142 | - item 143 | - description 144 | - status 145 | - created_at 146 | 147 | RepairCreate: 148 | type: object 149 | description: Payload for creating a new repair ticket. 150 | properties: 151 | item: 152 | type: string 153 | description: Name or type of the item that needs repair. 154 | example: "Laptop" 155 | description: 156 | type: string 157 | description: Short description of the issue reported by the customer. 158 | example: "Laptop won't turn on after a power outage." 159 | status: 160 | type: string 161 | description: Initial status of the repair. 162 | example: "New" 163 | assigned_to: 164 | type: string 165 | nullable: true 166 | description: Name of the person or team to assign this repair to. 167 | example: "Tier 1 Support" 168 | required: 169 | - item 170 | - description 171 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LinkedIn Learning Exercise Files License Agreement 2 | ================================================== 3 | 4 | This License Agreement (the "Agreement") is a binding legal agreement 5 | between you (as an individual or entity, as applicable) and LinkedIn 6 | Corporation (“LinkedIn”). By downloading or using the LinkedIn Learning 7 | exercise files in this repository (“Licensed Materials”), you agree to 8 | be bound by the terms of this Agreement. If you do not agree to these 9 | terms, do not download or use the Licensed Materials. 10 | 11 | 1. License. 12 | - a. Subject to the terms of this Agreement, LinkedIn hereby grants LinkedIn 13 | members during their LinkedIn Learning subscription a non-exclusive, 14 | non-transferable copyright license, for internal use only, to 1) make a 15 | reasonable number of copies of the Licensed Materials, and 2) make 16 | derivative works of the Licensed Materials for the sole purpose of 17 | practicing skills taught in LinkedIn Learning courses. 18 | - b. Distribution. Unless otherwise noted in the Licensed Materials, subject 19 | to the terms of this Agreement, LinkedIn hereby grants LinkedIn members 20 | with a LinkedIn Learning subscription a non-exclusive, non-transferable 21 | copyright license to distribute the Licensed Materials, except the 22 | Licensed Materials may not be included in any product or service (or 23 | otherwise used) to instruct or educate others. 24 | 25 | 2. Restrictions and Intellectual Property. 26 | - a. You may not to use, modify, copy, make derivative works of, publish, 27 | distribute, rent, lease, sell, sublicense, assign or otherwise transfer the 28 | Licensed Materials, except as expressly set forth above in Section 1. 29 | - b. Linkedin (and its licensors) retains its intellectual property rights 30 | in the Licensed Materials. Except as expressly set forth in Section 1, 31 | LinkedIn grants no licenses. 32 | - c. You indemnify LinkedIn and its licensors and affiliates for i) any 33 | alleged infringement or misappropriation of any intellectual property rights 34 | of any third party based on modifications you make to the Licensed Materials, 35 | ii) any claims arising from your use or distribution of all or part of the 36 | Licensed Materials and iii) a breach of this Agreement. You will defend, hold 37 | harmless, and indemnify LinkedIn and its affiliates (and our and their 38 | respective employees, shareholders, and directors) from any claim or action 39 | brought by a third party, including all damages, liabilities, costs and 40 | expenses, including reasonable attorneys’ fees, to the extent resulting from, 41 | alleged to have resulted from, or in connection with: (a) your breach of your 42 | obligations herein; or (b) your use or distribution of any Licensed Materials. 43 | 44 | 3. Open source. This code may include open source software, which may be 45 | subject to other license terms as provided in the files. 46 | 47 | 4. Warranty Disclaimer. LINKEDIN PROVIDES THE LICENSED MATERIALS ON AN “AS IS” 48 | AND “AS AVAILABLE” BASIS. LINKEDIN MAKES NO REPRESENTATION OR WARRANTY, 49 | WHETHER EXPRESS OR IMPLIED, ABOUT THE LICENSED MATERIALS, INCLUDING ANY 50 | REPRESENTATION THAT THE LICENSED MATERIALS WILL BE FREE OF ERRORS, BUGS OR 51 | INTERRUPTIONS, OR THAT THE LICENSED MATERIALS ARE ACCURATE, COMPLETE OR 52 | OTHERWISE VALID. TO THE FULLEST EXTENT PERMITTED BY LAW, LINKEDIN AND ITS 53 | AFFILIATES DISCLAIM ANY IMPLIED OR STATUTORY WARRANTY OR CONDITION, INCLUDING 54 | ANY IMPLIED WARRANTY OR CONDITION OF MERCHANTABILITY OR FITNESS FOR A 55 | PARTICULAR PURPOSE, AVAILABILITY, SECURITY, TITLE AND/OR NON-INFRINGEMENT. 56 | YOUR USE OF THE LICENSED MATERIALS IS AT YOUR OWN DISCRETION AND RISK, AND 57 | YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE THAT RESULTS FROM USE OF THE 58 | LICENSED MATERIALS TO YOUR COMPUTER SYSTEM OR LOSS OF DATA. NO ADVICE OR 59 | INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM US OR THROUGH OR 60 | FROM THE LICENSED MATERIALS WILL CREATE ANY WARRANTY OR CONDITION NOT 61 | EXPRESSLY STATED IN THESE TERMS. 62 | 63 | 5. Limitation of Liability. LINKEDIN SHALL NOT BE LIABLE FOR ANY INDIRECT, 64 | INCIDENTAL, SPECIAL, PUNITIVE, CONSEQUENTIAL OR EXEMPLARY DAMAGES, INCLUDING 65 | BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA OR OTHER 66 | INTANGIBLE LOSSES . IN NO EVENT WILL LINKEDIN'S AGGREGATE LIABILITY TO YOU 67 | EXCEED $100. THIS LIMITATION OF LIABILITY SHALL: 68 | - i. APPLY REGARDLESS OF WHETHER (A) YOU BASE YOUR CLAIM ON CONTRACT, TORT, 69 | STATUTE, OR ANY OTHER LEGAL THEORY, (B) WE KNEW OR SHOULD HAVE KNOWN ABOUT 70 | THE POSSIBILITY OF SUCH DAMAGES, OR (C) THE LIMITED REMEDIES PROVIDED IN THIS 71 | SECTION FAIL OF THEIR ESSENTIAL PURPOSE; AND 72 | - ii. NOT APPLY TO ANY DAMAGE THAT LINKEDIN MAY CAUSE YOU INTENTIONALLY OR 73 | KNOWINGLY IN VIOLATION OF THESE TERMS OR APPLICABLE LAW, OR AS OTHERWISE 74 | MANDATED BY APPLICABLE LAW THAT CANNOT BE DISCLAIMED IN THESE TERMS. 75 | 76 | 6. Termination. This Agreement automatically terminates upon your breach of 77 | this Agreement or termination of your LinkedIn Learning subscription. On 78 | termination, all licenses granted under this Agreement will terminate 79 | immediately and you will delete the Licensed Materials. Sections 2-7 of this 80 | Agreement survive any termination of this Agreement. LinkedIn may discontinue 81 | the availability of some or all of the Licensed Materials at any time for any 82 | reason. 83 | 84 | 7. Miscellaneous. This Agreement will be governed by and construed in 85 | accordance with the laws of the State of California without regard to conflict 86 | of laws principles. The exclusive forum for any disputes arising out of or 87 | relating to this Agreement shall be an appropriate federal or state court 88 | sitting in the County of Santa Clara, State of California. If LinkedIn does 89 | not act to enforce a breach of this Agreement, that does not mean that 90 | LinkedIn has waived its right to enforce this Agreement. The Agreement does 91 | not create a partnership, agency relationship, or joint venture between the 92 | parties. Neither party has the power or authority to bind the other or to 93 | create any obligation or responsibility on behalf of the other. You may not, 94 | without LinkedIn’s prior written consent, assign or delegate any rights or 95 | obligations under these terms, including in connection with a change of 96 | control. Any purported assignment and delegation shall be ineffective. The 97 | Agreement shall bind and inure to the benefit of the parties, their respective 98 | successors and permitted assigns. If any provision of the Agreement is 99 | unenforceable, that provision will be modified to render it enforceable to the 100 | extent possible to give effect to the parties’ intentions and the remaining 101 | provisions will not be affected. This Agreement is the only agreement between 102 | you and LinkedIn regarding the Licensed Materials, and supersedes all prior 103 | agreements relating to the Licensed Materials. 104 | 105 | Last Updated: March 2019 106 | -------------------------------------------------------------------------------- /src/advanced_repairs_api/main.py: -------------------------------------------------------------------------------- 1 | """Repair Service API (FastAPI + Cosmos DB).""" 2 | import os 3 | from datetime import datetime 4 | from dotenv import load_dotenv 5 | from typing import List, Optional 6 | 7 | from fastapi import FastAPI, Query, Request, Depends, Header, HTTPException, status 8 | from pydantic import BaseModel, Field 9 | 10 | from database import create_repair_in_db, list_repairs_from_db 11 | 12 | app = FastAPI( 13 | title="Repair Service", 14 | description="A simple service to manage repair tickets for devices on behalf of users.", 15 | version="1.0.0", 16 | openapi_url="/openapi.json", 17 | ) 18 | 19 | # --- API Key auth (para el API plugin de Copilot) --- 20 | load_dotenv() 21 | 22 | API_KEY = os.getenv("SECRET_API_KEY") 23 | 24 | print(f"DEBUG: Loaded SECRET_API_KEY = {API_KEY}") 25 | 26 | if API_KEY is None: 27 | # En un entorno real podrías usar logging, aquí hacemos un fallo explícito 28 | raise RuntimeError("SECRET_API_KEY no está configurada en las variables de entorno.") 29 | 30 | def verify_api_key(authorization: str = Header(None)): 31 | """ 32 | Verifica que la petición incluye un header: 33 | Authorization: Bearer 34 | """ 35 | print (f"DEBUG: Verifying API key from Authorization header: {authorization}") 36 | 37 | if not authorization: 38 | # Falta la cabecera Authorization 39 | raise HTTPException( 40 | status_code=status.HTTP_401_UNAUTHORIZED, 41 | detail="Missing Authorization header.", 42 | headers={"WWW-Authenticate": "Bearer"}, 43 | ) 44 | 45 | prefix = "Bearer " 46 | if not authorization.startswith(prefix): 47 | # El formato no es Bearer ... 48 | raise HTTPException( 49 | status_code=status.HTTP_401_UNAUTHORIZED, 50 | detail="Invalid authorization scheme.", 51 | headers={"WWW-Authenticate": "Bearer"}, 52 | ) 53 | 54 | token = authorization[len(prefix):].strip() 55 | 56 | if token != API_KEY: 57 | # Token incorrecto 58 | raise HTTPException( 59 | status_code=status.HTTP_401_UNAUTHORIZED, 60 | detail="Invalid API key.", 61 | headers={"WWW-Authenticate": "Bearer"}, 62 | ) 63 | 64 | # Si todo va bien, no devolvemos nada, simplemente dejamos pasar la request 65 | return True 66 | 67 | 68 | # ---------- Models ---------- 69 | 70 | 71 | class RepairBase(BaseModel): 72 | """Base model for a repair ticket.""" 73 | item: str = Field( 74 | ..., 75 | description="Name or type of the item that needs repair, for example 'Laptop' or 'Printer'.", 76 | ) 77 | description: str = Field( 78 | ..., 79 | description="Short description of the issue reported by the customer.", 80 | ) 81 | status: str = Field( 82 | "New", 83 | description="Current status of the repair, such as 'New', 'In Progress', or 'Completed'.", 84 | ) 85 | assigned_to: Optional[str] = Field( 86 | None, 87 | description="Name of the person or team that this repair is assigned to.", 88 | ) 89 | 90 | 91 | class Repair(RepairBase): 92 | """Model representing a repair ticket with all details.""" 93 | id: str = Field( 94 | ..., 95 | description="Unique identifier of the repair ticket.", 96 | ) 97 | created_at: datetime = Field( 98 | ..., 99 | description="Date and time when the repair ticket was created (UTC).", 100 | ) 101 | created_by: Optional[str] = Field( 102 | None, 103 | description="Identifier of who created this ticket (tenant ID and/or conversation ID).", 104 | ) 105 | 106 | 107 | class RepairCreate(RepairBase): 108 | """Payload for creating a new repair ticket from Copilot.""" 109 | # deliberately no created_by here; we compute it on the server side 110 | 111 | 112 | # ---------- Endpoints ---------- 113 | 114 | 115 | @app.get( 116 | "/repairs", 117 | response_model=List[Repair], 118 | operation_id="listRepairs", 119 | summary="List all repairs", 120 | description=( 121 | "Returns a list of repair tickets with their details. " 122 | "You can optionally filter by status, assigned_to, or created_by." 123 | ), 124 | dependencies=[Depends(verify_api_key)], 125 | ) 126 | async def list_repairs( 127 | status: Optional[str] = Query( 128 | None, 129 | description="Optional status to filter repairs by. Example: 'New' or 'Completed'.", 130 | ), 131 | assigned_to: Optional[str] = Query( 132 | None, 133 | description="Optional name or ID of the person or team the repair is assigned to.", 134 | ), 135 | created_by: Optional[str] = Query( 136 | None, 137 | description=( 138 | "Optional identifier of who created the ticket " 139 | "(for example the tenant ID or tenant|conversation)." 140 | ), 141 | ), 142 | ) -> List[Repair]: 143 | """ 144 | List all repairs, optionally filtered by status, assigned_to and created_by. 145 | Data is retrieved from Azure Cosmos DB. 146 | """ 147 | rows = list_repairs_from_db( 148 | status=status, 149 | assigned_to=assigned_to, 150 | created_by=created_by, 151 | ) 152 | 153 | # Pydantic se encarga de convertir created_at (string ISO) a datetime 154 | return [Repair(**row) for row in rows] 155 | 156 | 157 | @app.post( 158 | "/repairs", 159 | response_model=Repair, 160 | status_code=201, 161 | operation_id="createRepair", 162 | summary="Create a new repair", 163 | description="Create a new repair ticket for a device that needs to be fixed.", 164 | dependencies=[Depends(verify_api_key)], 165 | ) 166 | async def create_repair(payload: RepairCreate, request: Request) -> Repair: 167 | """ 168 | Create a new repair ticket. 169 | 170 | Enriches the ticket with 'created_by' using Microsoft 365 Copilot context headers: 171 | - x-microsoft-tenantid 172 | - x-microsoft-ai-conversationid 173 | """ 174 | headers = request.headers 175 | 176 | tenant_id = headers.get("x-microsoft-tenantid") 177 | conversation_id = headers.get("x-microsoft-ai-conversationid") 178 | 179 | # Construimos un identificador simple de quién creó el ticket 180 | if tenant_id and conversation_id: 181 | created_by = f"{tenant_id}|{conversation_id}" 182 | elif tenant_id: 183 | created_by = tenant_id 184 | else: 185 | created_by = "unknown" # útil en pruebas locales o llamadas directas sin Copilot 186 | 187 | # Guardar en Cosmos DB 188 | data = create_repair_in_db( 189 | item=payload.item, 190 | description=payload.description, 191 | status=payload.status, 192 | assigned_to=payload.assigned_to, 193 | created_by=created_by, 194 | ) 195 | 196 | # Devolver el modelo completo a Copilot 197 | return Repair(**data) 198 | -------------------------------------------------------------------------------- /src/test-action-agent/README.md: -------------------------------------------------------------------------------- 1 | # Overview of the Declarative Agent with API Plugin template 2 | 3 | ## Build a Declarative Agent with API Plugin from a new API with Azure Functions 4 | 5 | With the declarative agent, you can build a custom version of Copilot that can be used for specific scenarios, such as for specialized knowledge, implementing specific processes, or simply to save time by reusing a set of AI prompts. For example, a grocery shopping Copilot declarative agent can be used to create a grocery list based on a meal plan that you send to Copilot. 6 | 7 | You can extend declarative agents using plugins to retrieve data and execute tasks on external systems. A declarative agent can utilize multiple plugins at the same time. 8 | ![image](https://github.com/user-attachments/assets/9939972e-0449-410c-b237-d9d748cd6628) 9 | 10 | ## Get started with the template 11 | 12 | > **Prerequisites** 13 | > 14 | > To run this app template in your local dev machine, you will need: 15 | > 16 | > - [Node.js](https://nodejs.org/), supported versions: 18, 20, 22 17 | > - A [Microsoft 365 account for development](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts) 18 | > - [Microsoft 365 Agents Toolkit Visual Studio Code Extension](https://aka.ms/teams-toolkit) version 5.0.0 and higher or [Microsoft 365 Agents Toolkit CLI](https://aka.ms/teams-toolkit-cli) 19 | > - [Microsoft 365 Copilot license](https://learn.microsoft.com/microsoft-365-copilot/extensibility/prerequisites#prerequisites) 20 | 21 | 1. First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar. 22 | 2. In the Account section, sign in with your [Microsoft 365 account](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts) if you haven't already. 23 | 3. Select `Debug in Copilot (Edge)` or `Debug in Copilot (Chrome)` from the launch configuration dropdown. 24 | 4. Select your declarative agent from the `Copilot` app. 25 | 5. Send a message to Copilot to find a repair record. 26 | 27 | ## What's included in the template 28 | 29 | | Folder | Contents | 30 | | ------------ | ------------------------------------------------------------------------------------------- | 31 | | `.vscode` | VSCode files for debugging | 32 | | `appPackage` | Templates for the application manifest, the plugin manifest and the API specification | 33 | | `env` | Environment files | 34 | | `infra` | Templates for provisioning Azure resources | 35 | | `src` | The source code for the repair API | 36 | 37 | The following files can be customized and demonstrate an example implementation to get you started. 38 | 39 | | File | Contents | 40 | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------- | 41 | | `src/functions/repairs.ts` | The main file of a function in Azure Functions. | 42 | | `src/repairsData.json` | The data source for the repair API. | 43 | | `appPackage/apiSpecificationFile/repair.yml` | A file that describes the structure and behavior of the repair API. | 44 | | `appPackage/manifest.json` | application manifest that defines metadata for your plugin inside Microsoft Teams. | 45 | | `appPackage/ai-plugin.json` | The manifest file for your API Plugin that contains information for your API and used by LLM. | 46 | | `appPackage/repairDeclarativeAgent.json` | Define the behaviour and configurations of the declarative agent. | 47 | | `appPackage/adaptiveCards/listRepairs.json` | Adaptive Card file used to render a result from the plugin response. | 48 | | `appPackage/adaptiveCards/listRepairs.data.json`| Sample mock data file for adaptive card. | 49 | 50 | The following are Microsoft 365 Agents Toolkit specific project files. You can [visit a complete guide on Github](https://github.com/OfficeDev/TeamsFx/wiki/Teams-Toolkit-Visual-Studio-Code-v5-Guide#overview) to understand how Microsoft 365 Agents Toolkit works. 51 | 52 | | File | Contents | 53 | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | 54 | | `m365agents.yml` | This is the main Microsoft 365 Agents Toolkit project file. The project file defines two primary things: Properties and configuration Stage definitions. | 55 | | `m365agents.local.yml` | This overrides `m365agents.yml` with actions that enable local execution and debugging. | 56 | 57 | ## Extend the template 58 | 59 | - [Add conversation starters](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=3): Conversation starters are hints that are displayed to the user to demonstrate how they can get started using the declarative agent. 60 | - [Add web content](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=4) for the ability to search web information. 61 | - [Add OneDrive and SharePoint content](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=5) as grounding knowledge for the agent. 62 | - [Add Microsoft Copilot connectors content](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=6) to ground agent with enterprise knowledge. 63 | - [Add API plugins](https://learn.microsoft.com/microsoft-365-copilot/extensibility/build-declarative-agents?tabs=ttk&tutorial-step=7) for agent to interact with REST APIs. 64 | 65 | 66 | ## Addition information and references 67 | 68 | - [Declarative agents for Microsoft 365](https://aka.ms/teams-toolkit-declarative-agent) 69 | - [Extend Microsoft 365 Copilot](https://aka.ms/teamsfx-copilot-plugin) 70 | - [Message extensions for Microsoft 365 Copilot](https://learn.microsoft.com/microsoft-365-copilot/extensibility/overview-message-extension-bot) 71 | - [Microsoft Copilot connectors for Microsoft 365 Copilot](https://learn.microsoft.com/microsoft-365-copilot/extensibility/overview-graph-connector) 72 | - [Microsoft 365 Copilot extensibility samples](https://learn.microsoft.com/microsoft-365-copilot/extensibility/samples) 73 | --------------------------------------------------------------------------------