### Ollama Quick Setup and API Test Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/models/oss-openai-compatible-ts.md This bash script provides a quick setup guide for Ollama, including installation, pulling models, listing installed models, and testing the API with a sample request. It also shows how to pull additional models. ```bash # Install Ollama curl -fsSL https://ollama.com/install.sh | sh # Pull a model ollama pull llama3.2 # List installed models ollama list # Test the API curl http://localhost:11434/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"llama3.2","messages":[{"role":"user","content":"Hello!"}]}' # Pull more models ollama pull mistral ollama pull phi4 ollama pull deepseek-r1:1.5b ``` -------------------------------- ### Setup Project Dependencies Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/api/CONTRIBUTING.md After cloning, set up the project by installing and linking dependencies using pnpm. This command should be run from the root folder of the monorepo. ```bash npm run setup ``` ```bash pnpm install && npm run build ``` -------------------------------- ### Example workflow for running npm install Source: https://github.com/officedev/microsoft-365-agents-toolkit/wiki/Available-actions-in-Microsoft-365-Agents-Toolkit This YAML workflow demonstrates checking out a repository and running 'npm install' within a specified directory using the cli/runNpmCommand action. ```yaml jobs: build: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 - name: Run npm install uses: cli/runNpmCommand with: args: "install" workingDirectory: "./my-project" ``` -------------------------------- ### Database-backed Installation Store for Slack OAuth Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/slack/bolt-oauth-distribution-ts.md Implement a database-backed installation store for multi-workspace OAuth apps. This example shows how to store, fetch, and delete installation data for teams and enterprises. ```typescript import { App, type Installation, type InstallationQuery } from "@slack/bolt"; const app = new App({ signingSecret: process.env.SLACK_SIGNING_SECRET!, clientId: process.env.SLACK_CLIENT_ID!, clientSecret: process.env.SLACK_CLIENT_SECRET!, stateSecret: process.env.SLACK_STATE_SECRET!, scopes: ["chat:write", "commands", "channels:history", "app_mentions:read"], installationStore: { storeInstallation: async (installation: Installation) => { if (installation.isEnterpriseInstall && installation.enterprise) { await db.set(`install:${installation.enterprise.id}`, installation); return; } if (installation.team) { await db.set(`install:${installation.team.id}`, installation); return; } throw new Error("Failed saving installation: no team or enterprise ID"); }, fetchInstallation: async (query: InstallationQuery) => { if (query.isEnterpriseInstall && query.enterpriseId) { return await db.get(`install:${query.enterpriseId}`); } if (query.teamId) { return await db.get(`install:${query.teamId}`); } throw new Error("Failed fetching installation"); }, deleteInstallation: async (query: InstallationQuery) => { if (query.isEnterpriseInstall && query.enterpriseId) { await db.delete(`install:${query.enterpriseId}`); return; } if (query.teamId) { await db.delete(`install:${query.teamId}`); return; } throw new Error("Failed deleting installation"); }, }, }); // Clean up on uninstall app.event("app_uninstalled", async ({ context, body }) => { const teamId = body.team_id; const enterpriseId = body.enterprise_id; console.log(`App uninstalled from team ${teamId}`); // deleteInstallation is called automatically by the built-in authorize }); // Clean up on token revocation app.event("tokens_revoked", async ({ event, context }) => { console.log(`Tokens revoked: ${JSON.stringify(event.tokens)}`); }); (async () => { await app.start(3000); console.log("OAuth app running — visit http://localhost:3000/slack/install"); })(); ``` -------------------------------- ### Basic MCP Server with Two Tools Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/mcp.server-basics-ts.md Sets up an MCP server with 'greet' and 'echo' tools. Use this as a starting point for exposing bot functionalities as MCP tools. Ensure you have the required packages installed: '@microsoft/teams.mcp', '@modelcontextprotocol/sdk', and 'zod'. ```typescript import { App } from '@microsoft/teams.apps'; import { McpPlugin } from '@microsoft/teams.mcp'; import { ConsoleLogger } from '@microsoft/teams.common'; import { DevtoolsPlugin } from '@microsoft/teams.dev'; import { z } from 'zod'; const mcpPlugin = new McpPlugin({ name: 'my-mcp-server', description: 'Exposes greeting and echo tools', }) .tool( 'greet', 'Greet a user by name', { name: z.string().describe('Name to greet') }, { readOnlyHint: true, idempotentHint: true }, async ({ name }) => ({ content: [{ type: 'text', text: `Hello, ${name}!` }], }) ) .tool( 'echo', 'Echoes back the input text', { input: z.string().describe('The text to echo') }, { readOnlyHint: true, idempotentHint: true }, async ({ input }) => ({ content: [{ type: 'text', text: `You said: "${input}"` }], }) ); const app = new App({ logger: new ConsoleLogger('mcp-bot', { level: 'debug' }), plugins: [new DevtoolsPlugin(), mcpPlugin], }); app.on('message', async ({ reply, activity }) => { await reply(`Echo: ${activity.text}`); }); app.start(3978); // MCP endpoint: http://localhost:3978/mcp ``` -------------------------------- ### Configure Middleware, Install Handlers, and Invoke Routes in Teams.js Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/runtime.routing-handlers-ts.md Set up middleware to run before all route handlers, define handlers for installation and uninstallation events, and create routes for dialogs, card actions, and messages. This example also includes a catch-all message handler and starts the application on a specified port. ```typescript import { App } from '@microsoft.apps'; import { ConsoleLogger } from '@microsoft.common'; import { DevtoolsPlugin } from '@microsoft.dev'; const app = new App({ logger: new ConsoleLogger('full-bot', { level: 'debug' }), plugins: [new DevtoolsPlugin()], }); // --- Middleware: runs before all route handlers --- app.use(async (ctx) => { ctx.log.info(`Received: ${ctx.activity.type}`); await ctx.next(); }); // --- Install routes --- app.on('install.add', async ({ send }) => { await send('Thanks for installing me!'); }); app.on('install.remove', async ({ activity, log }) => { log.info(`Uninstalled from ${activity.conversation.id}`); }); // --- Dialog invoke routes (return response objects) --- app.on('dialog.open', async ({ send }) => { return { status: 200, body: { task: { type: 'continue', value: { title: 'My Dialog', card: { contentType: 'application/vnd.microsoft.card.adaptive', content: { type: 'AdaptiveCard', version: '1.5', body: [{ type: 'TextBlock', text: 'Enter data below' }], }, }, }, }, }, }; }); app.on('dialog.submit', async ({ activity }) => { const formData = activity.value.data; return { status: 200, body: { task: { type: 'message', value: 'Form submitted successfully!' }, }, }; }); // --- Card action handler --- app.on('card.action', async ({ activity, send }) => { const data = activity.value; await send(`Card action received: ${JSON.stringify(data)}`); }); // --- Feedback handler --- app.on('message.submit.feedback', async ({ activity, log }) => { const feedback = { messageId: activity.replyToId || activity.id, reaction: activity.value.actionValue.reaction, feedback: activity.value.actionValue.feedback, }; log.info('Feedback received:', feedback); return { status: 200 }; }); // --- Catch-all fallback --- app.on('message', async ({ send, activity }) => { await send(`Echo: ${activity.text}`); }); app.start(3978); ``` -------------------------------- ### Start Local Development Server Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/slack/cli.local-dev-deploy.md Use `slack run` to start a local development server. This command installs a development version of your app, starts the bot process, and tunnels traffic from Slack to your machine. It automatically rebuilds on code changes and uses Socket Mode for a direct connection without needing a public URL or ngrok. ```bash # Start local dev server (creates dev app, watches for changes) slack run ``` ```bash # With activity level for debugging slack run --activity-level debug ``` ```bash # Auto-cleanup dev app when stopping (Ctrl+C) slack run --cleanup ``` ```bash # Target a specific workspace slack run --team T0123456789 ``` ```bash # Typical terminal output: # ⚡ App is running in development mode # Connected, awaiting events # my-bot (dev) A0123456789 T0123456789 # SDK: deno-slack-sdk 2.x # Visit https://app.slack.com/client/T0123456789 to use your app ``` -------------------------------- ### Install and Verify CLI Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/cli/README.md Install the CLI globally using npm and verify the installation by checking the help command. ```powershell $ npm install -g @microsoft/m365agentstoolkit-cli $ atk -h ``` -------------------------------- ### Quick Start: Start Agents Playground Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/test-playground/test-playground.md In a new terminal, start the Agents Playground and connect it to your bot service endpoint. ```bash # 3. Use a NEW/separate terminal to start Agents Playground agentsplayground -e http://localhost:3978/api/messages -c msteams ``` -------------------------------- ### Build Verification and Debugging Workflow (Manual) Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/dev.debug-test-ts.md This section outlines the manual workflow for setting up and running your Teams agent without the ATK. It covers dependency installation, environment variable configuration, type-checking, starting the development server, setting up dev tunnels, and sideloading the application in Teams. ```bash # === Option B: Manual workflow (no ATK) === # 1. npm install # 2. Create .env: CLIENT_ID, CLIENT_SECRET, TENANT_ID, PORT=3978 # (Register bot manually -- see azure-bot-deploy-ts.md) # 3. npx tsc --noEmit # 4. npm run dev # 5. devtunnel host -p 3978 --allow-anonymous → update Azure Bot messaging endpoint # 6. Sideload: zip appPackage/ → upload in Teams ``` -------------------------------- ### Build Verification and Debugging Workflow (ATK-Provisioned) Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/dev.debug-test-ts.md Follow this recommended workflow for provisioning, deploying, and verifying your Teams agent using the ATK. This includes installing dependencies, setting up dev tunnels, provisioning resources, generating local configurations, type-checking, starting the dev server, and accessing DevTools. It also details steps for real Teams testing with dev tunnels and sideloading. ```bash # === Option A: ATK-provisioned workflow (recommended) === # 1. Install dependencies # npm install # 2. Start a dev tunnel (must be running BEFORE provisioning) # devtunnel host -p 3978 --allow-anonymous # Copy the tunnel URL and set BOT_ENDPOINT in env/.env.local # 3. Provision bot resources via ATK (creates Entra ID app + Bot Framework + Teams app) # atk provision --env local -i false # 4. Generate .localConfigs with credentials # atk deploy --env local -i false # Verify .localConfigs contains CLIENT_ID, CLIENT_SECRET, TENANT_ID, PORT. # If TENANT_ID is missing, copy the value of TEAMS_APP_TENANT_ID from env/.env.local into TENANT_ID in .localConfigs. # 5. Type-check the project (build gate) # npx tsc --noEmit # 6. Start dev server with file watching # npm run dev # 7. Open DevTools in browser # http://localhost:3979/devtools # 7. For real Teams testing, start a dev tunnel and provision: # devtunnel host -p 3978 --allow-anonymous # Set BOT_ENDPOINT in env/.env.local to the tunnel URL # atk provision --env local -i false # atk deploy --env local -i false # Open Teams sideload URL (TEAMS_APP_ID from env/.env.local): # https://teams.microsoft.com/l/app/$TEAMS_APP_ID?installAppPackage=true&webjoin=true&appTenantId=$TENANT_ID # (TEAMS_APP_ID from env/.env.local; TENANT_ID from .localConfigs, mapped from TEAMS_APP_TENANT_ID in env/.env.local) ``` -------------------------------- ### Install SDK and Hosting Packages Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/sdk/README.md Install the necessary packages for TeamsFx and agents hosting. For TypeScript projects, also install the Node.js types. ```sh npm install @microsoft/teamsfx npm install @microsoft/agents-hosting@^0.2.14 // For TS projects only npm install --save-dev @types/node ``` -------------------------------- ### Install Foundry Local Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/models/foundry-local-ts.md Install Foundry Local using your system's package manager. Verify the installation by checking the version. ```bash winget install Microsoft.FoundryLocal ``` ```bash brew tap microsoft/foundrylocal && brew install foundrylocal ``` ```bash foundry --version ``` -------------------------------- ### Install and Verify Slack CLI Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/slack/cli.getting-started.md Install the Slack CLI using package managers or scripts based on your operating system. Verify the installation by checking the CLI version. ```bash # Step 1: Install the CLI # macOS: brew install slack-cli # Windows (PowerShell as admin): # irm https://downloads.slack-edge.com/slack-cli/install-windows.ps1 | iex # Linux: # curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash # Step 2: Verify installation slack version ``` -------------------------------- ### Run Local Project Setup Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/cli/CONTRIBUTING.md Navigate to the project directory and run setup commands to prepare the local environment for development. ```bash cd TeamsFx npm run setup npm link ``` -------------------------------- ### Example arm/deploy action configuration Source: https://github.com/officedev/microsoft-365-agents-toolkit/wiki/Available-actions-in-Microsoft-365-Agents-Toolkit This example demonstrates a typical input configuration for the `arm/deploy` action, specifying deployment details and template paths. ```yaml with: subscriptionId: "your-subscription-id" resourceGroupName: "your-resource-group" bicepCliVersion: "0.4.1008" # optional templates: - deploymentName: "template1-deployment" path: "./templates/template1.bicep" parameters: "./parameters/template1-parameters.json" # optional - deploymentName: "template2-deployment" path: "./templates/template2.json" ``` -------------------------------- ### Start Backend Service Task Source: https://github.com/officedev/microsoft-365-agents-toolkit/wiki/{Debug}-Teams-Toolkit-VS-Code-Tasks Configures a background shell task to start the backend service. It includes environment variable setup for the PATH and specific patterns to detect task start and end. ```json { "label": "Start backend", "type": "shell", "command": "npm run dev:teamsfx", "isBackground": true, "options": { "cwd": "${workspaceFolder}/api", "env": { "PATH": "${command:fx-extension.get-func-path}${env:PATH}" } }, "problemMatcher": { "pattern": { "regexp": "^.*$", "file": 0, "location": 1, "message": 2 }, "background": { "activeOnStart": true, "beginsPattern": "^.*(Job host stopped|signaling restart).*$", "endsPattern": "^.*(Worker process started and initialized|Host lock lease acquired by instance ID).*$" } }, "presentation": { "reveal": "silent" } } ``` -------------------------------- ### Start Local Web Server and Side-load Add-in Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/templates/unused/js/office-xml-addin-excel-sso/README.md Commands to build the project, start the local web server, and side-load the add-in into an Office client application. Ensure Office applications are closed before running. ```shell npm run start ``` -------------------------------- ### Example botFramework/create Input Source: https://github.com/officedev/microsoft-365-agents-toolkit/wiki/Available-actions-in-Microsoft-365-Agents-Toolkit Provides a concrete example of how to configure the input parameters for the botFramework/create action, including optional fields like description, iconUrl, and channels. ```yaml with: botId: "123e4567-e89b-12d3-a456-426614174000" name: "SampleBot" messagingEndpoint: "https://example.com/api/messages" description: "This is a sample bot." iconUrl: "https://example.com/icon.png" channels: - name: "MicrosoftTeams" callingWebhook: "https://example.com/webhook" - name: "M365Extensions" ``` -------------------------------- ### Retrieve Paged Installations for Notifications Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/dotnet-sdk/MIGRATION.md In Trigger.cs, use the ConversationBot's Notification property to get a paginated list of bot installations. Requires a ConversationReference. ```csharp var pagedInstallations = await _conversation.Notification.GetPagedInstallationsAsync(pageSize, continuationToken, req.HttpContext.RequestAborted); ``` -------------------------------- ### Provisioning and Deploying a New Environment Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/toolkit/environments.md Steps to provision a new environment, set overrides, and deploy your agent. This process creates environment files and cloud resources. ```bash # Step 1: Provision creates the env files and cloud resources atk provision --env staging -i false # This creates: # env/.env.staging (with APP_ENV=staging, resource IDs) # env/.env.staging.user (with SECRET_* values) # Step 2: Set environment-specific overrides # Edit env/.env.staging to adjust resource names, domains, etc. # Step 3: Deploy to the new environment atk deploy --env staging -i false # Step 4: Test against the new environment # Use agentsplayground CLI or sideload in Teams ``` -------------------------------- ### Test Different Channels with Agents Playground Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/test-playground/test-playground.md Examples of starting the Agents Playground to test different communication channels. ```bash agentsplayground -e http://localhost:3978/api/messages -c webchat ``` ```bash agentsplayground -e http://localhost:3978/api/messages -c emulator ``` -------------------------------- ### Quick Start: Deploy and Run Bot Service Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/test-playground/test-playground.md Deploy playground configuration and start your bot service. The bot service is expected to hang the terminal and should be run as a background process. ```bash # 1. For ATK projects, deploy playground config first atk deploy --env playground -i false # 2. Start your bot service (this will HANG the terminal — expected!) # Run as a background process since the server keeps running cd my-bot npm run dev:teamsfx:playground # For ATK projects # npm run dev # For customized projects ``` -------------------------------- ### Deploy M365 Agent with Automatic GUID Encoding Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/templates/vs/csharp/foundry-proxy-agent/infra/modules/GUID_ENCODER_GUIDE.md Use this command to deploy the M365 Agent infrastructure, including the automatic GUID encoding process via deployment scripts. Ensure you have the Azure CLI installed and are logged in. ```powershell az deployment group create \ --resource-group "rg-m365agent-dev" \ --template-file M365Agent/infra/azure.bicep \ --parameters resourceBaseName="m365agent" \ botDisplayName="M365 Agent" \ tenantId="671740f0-0ce9-4b51-bae5-4096de8b66d3" ``` -------------------------------- ### Launch Local Testing with `atk preview` Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/toolkit/lifecycle-cli.md Start the Agents Playground for local testing without deploying to Teams. Consider using the `agentsplayground` CLI for a similar experience that requires no provisioning. ```bash atk preview ``` -------------------------------- ### Create and Initialize Slack Projects Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/slack/cli.getting-started.md Scaffold new Slack projects using an interactive wizard or a specific template URL. Initialize an existing codebase as a Slack project or list available sample templates. ```bash # Interactive wizard — pick template and runtime slack create my-bot # From a specific template URL slack create my-bot --template https://github.com/slack-samples/deno-hello-world # Create an AI agent app slack project create agent my-agent # Initialize existing code as a Slack project cd existing-app/ slack project init # List available sample templates slack project samples ``` -------------------------------- ### Teams Event Handling (After Migration) Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/bridge/events-activities-ts.md Example of handling conversation updates (member join/leave), message reactions, and install events in Microsoft Teams. ```typescript import { App } from "@microsoft/teams.apps"; import { ConsoleLogger } from "@microsoft/teams.common"; import { DevtoolsPlugin } from "@microsoft/teams.dev"; const app = new App({ logger: new ConsoleLogger("my-bot", { level: "info" }), plugins: [new DevtoolsPlugin()], }); // Member joined -- conversationUpdate with membersAdded app.on("conversationUpdate", async ({ activity, send }) => { if (activity.membersAdded?.length) { for (const member of activity.membersAdded) { // Skip the bot itself if (member.id !== activity.recipient?.id) { await send(`Welcome to the channel, ${member.name}!`); } } } // Member left -- conversationUpdate with membersRemoved if (activity.membersRemoved?.length) { for (const member of activity.membersRemoved) { if (member.id !== activity.recipient?.id) { await send(`${member.name} has left the channel.`); } } } }); // Reaction events -- messageReaction route app.on("messageReaction" as any, async ({ activity, send }) => { if (activity.reactionsAdded?.length) { for (const reaction of activity.reactionsAdded) { if (reaction.type === "like") { await send("Someone liked a message!"); } } } }); // Install event (no Slack equivalent) -- good for welcome messages app.on("install.add", async ({ send, activity }) => { await send("Thanks for installing me! Type 'help' to get started."); }); app.start(3978); ``` -------------------------------- ### Send Notification Message Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/dotnet-sdk/README.md Implement logic to send notifications to users or channels. This example demonstrates iterating through installations and sending a simple message, with a placeholder for sending adaptive cards. ```csharp public async Task NotifyAsync(ConversationBot conversation, CancellationToken cancellationToken) { var pageSize = 100; string continuationToken = null; do { var pagedInstallations = await conversation.Notification.GetPagedInstallationsAsync(pageSize, continuationToken, cancellationToken); continuationToken = pagedInstallations.ContinuationToken; var installations = pagedInstallations.Data; foreach (var installation in installations) { await installation.SendMessage("Hello.", cancellationToken); // Or, send adaptive card (need to build your own card object) // await installation.SendAdaptiveCard(cardObject, cancellationToken); } } while (!string.IsNullOrEmpty(continuationToken)); } ``` -------------------------------- ### Start Agents Playground CLI Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/toolkit/playground.md Use the `agentsplayground` CLI to start the local test harness. Option 1 starts the bot in the background and then the playground. Option 2 includes authentication credentials for testing authenticated agents. ```bash # Option 1: agentsplayground CLI (recommended — no provisioning needed) npm run dev # Start bot in background agentsplayground -e http://localhost:3978/api/messages -c msteams # New terminal # Option 2: With authentication credentials agentsplayground -e http://localhost:3978/api/messages -c msteams \ --client-id --client-secret --tenant-id ``` -------------------------------- ### Minimal Socket Mode Setup in TypeScript Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/slack/runtime.socket-mode-ts.md This snippet demonstrates the basic setup for a Slack Bolt TypeScript app using Socket Mode. Ensure you have `@slack/bolt` and `@slack/socket-mode` installed. Provide your bot token and app-level token (prefixed with 'xapp-') via environment variables. The app listens for 'hello' messages and responds. ```typescript import { App } from "@slack/bolt"; const app = new App({ token: process.env.SLACK_BOT_TOKEN!, appToken: process.env.SLACK_APP_TOKEN!, socketMode: true, }); app.message("hello", async ({ message, say }) => { await say(`Hey there <@${message.user}>!`); }); (async () => { await app.start(); console.log("⚡️ Bolt app is running in Socket Mode"); })(); ``` -------------------------------- ### Manual MCP Server Configuration in VS Code Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/mcp-server/README.md Add this JSON configuration to your .vscode/mcp.json file to manually set up the M365AgentsToolkit Server. This command installs and starts the latest version of the MCP server. ```json { "servers": { "M365AgentsToolkit Server": { "command": "npx", "args": [ "-y", "@microsoft/m365agentstoolkit-mcp@latest", "server", "start" ] } } } ``` -------------------------------- ### Teams SDK v2 Handler Registration Examples Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/docs/middleware-and-handlers.md Illustrates handler registration in the Teams SDK v2, covering messages, events, actions, dialog submissions, message extensions, and install events. ```typescript app.message(pattern, handler) or app.on("message", handler) ``` ```typescript app.on("routeName", handler) ``` ```typescript app.on("card.action", handler) — route by data.action ``` ```typescript app.on("dialog.submit", handler) ``` ```typescript app.on("message.ext.open", handler) ``` ```typescript app.on("install.add", handler) ``` -------------------------------- ### Build the Project Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/function-extension/CONTRIBUTING.md Use this command to build the .NET project. Ensure you have the .NET Core SDK installed. ```shell dotnet build Microsoft.Azure.WebJobs.Extensions.TeamsFx.sln ``` -------------------------------- ### Scaffold a new project with Agents Toolkit CLI Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/toolkit/lifecycle-cli.md Create a new Agents Toolkit project. Use interactive mode for a guided setup or provide flags for non-interactive scaffolding with specified parameters. ```bash atk new # Interactive wizard ``` ```bash atk new -c ai-bot -l typescript -i false # Non-interactive ``` -------------------------------- ### GitHub Actions CI/CD pipeline for deploying Teams Bot Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/toolkit/lifecycle-cli.md Example GitHub Actions workflow for deploying a Teams Bot. It includes checking out code, setting up Node.js, installing dependencies, and provisioning/deploying the agent. ```yaml name: Deploy Teams Bot on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - name: Install Agents Toolkit CLI run: npm install -g @microsoft/m365agentstoolkit-cli - name: Provision run: atk provision --env production -i false env: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} AZURE_RESOURCE_GROUP_NAME: ${{ secrets.AZURE_RESOURCE_GROUP_NAME }} # M365 credentials for app registration M365_ACCOUNT_NAME: ${{ secrets.M365_ACCOUNT_NAME }} M365_ACCOUNT_PASSWORD: ${{ secrets.M365_ACCOUNT_PASSWORD }} - name: Deploy run: atk deploy --env production -i false env: AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} ``` -------------------------------- ### Basic MCP Client Setup and Connection Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/mcp.client-basics-ts.md Demonstrates setting up a ChatPrompt with the McpClientPlugin and connecting to a single MCP server. Tools from the server are automatically discovered and made available to the LLM. ```typescript import { App } from '@microsoft/teams.apps'; import { ChatPrompt } from '@microsoft/teams.ai'; import { OpenAIChatModel } from '@microsoft/teams.openai'; import { McpClientPlugin } from '@microsoft/teams.mcpclient'; import { ConsoleLogger } from '@microsoft/teams.common'; import { DevtoolsPlugin } from '@microsoft/teams.dev'; const logger = new ConsoleLogger('mcp-client-bot', { level: 'debug' }); const model = new OpenAIChatModel({ apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o', }); const prompt = new ChatPrompt( { model, instructions: 'You are a helpful assistant. Use available tools to answer questions.', }, [new McpClientPlugin({ logger })], // Pass as ChatPrompt plugin ) // Connect to an MCP server -- tools are auto-discovered .usePlugin('mcpClient', { url: 'http://localhost:3978/mcp', }); const app = new App({ logger, plugins: [new DevtoolsPlugin()], }); // Tools from the MCP server are automatically available to the LLM app.on('message', async ({ send, activity }) => { const result = await prompt.send(activity.text); if (result.content) { await send(result.content); } }); app.start(4000); ``` -------------------------------- ### Custom Thread Context Store with Database (TypeScript) Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/slack/bolt-assistant-ts.md Implement a custom thread context store for persistent storage using a database. This example demonstrates `get` and `save` methods for managing thread context. ```typescript import { type AssistantThreadContextStore, type AllAssistantMiddlewareArgs, type AssistantThreadContext } from "@slack/bolt"; const contextStore: AssistantThreadContextStore = { async get({ payload }: AllAssistantMiddlewareArgs): Promise { const threadTs = "assistant_thread" in payload ? payload.assistant_thread.thread_ts : payload.thread_ts; const row = await db.query("SELECT context FROM assistant_threads WHERE thread_ts = $1", [threadTs]); return row?.context ?? {}; }, async save({ payload }: AllAssistantMiddlewareArgs): Promise { const threadTs = "assistant_thread" in payload ? payload.assistant_thread.thread_ts : payload.thread_ts; const context = "assistant_thread" in payload ? payload.assistant_thread.context : {}; await db.query( "INSERT INTO assistant_threads (thread_ts, context) VALUES ($1, $2) ON CONFLICT (thread_ts) DO UPDATE SET context = $2", [threadTs, context] ); }, }; const assistant = new Assistant({ threadContextStore: contextStore, threadStarted: async ({ saveThreadContext, say }) => { await saveThreadContext(); // uses custom store await say("Hello! I'm ready to help."); }, userMessage: async ({ getThreadContext, say, setStatus }) => { await setStatus("Processing..."); const ctx = await getThreadContext(); // reads from custom store await say(`Context channel: ${ctx?.channel_id}`); }, }); ``` -------------------------------- ### List Installations and Continue Conversation (.NET) Source: https://github.com/officedev/microsoft-365-agents-toolkit/wiki/ZZZ-‐-[Archived]-‐-Send-notification-to-Teams Iterates through all installation targets and uses Bot Framework's adapter to continue the conversation, allowing custom bot logic to be executed. Requires a cancellation token for asynchronous operations. ```csharp /** .NET **/ // list all installation targets foreach (var target in await _conversation.Notification.GetInstallationsAsync()) { // call Bot Framework's adapter.ContinueConversationAsync() await target.Adapter.ContinueConversationAsync( target.BotAppId, target.ConversationReference, async (context, ctx) => { // your own bot logic await context... }, cancellationToken); } ``` -------------------------------- ### Environment File Structure Example Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/toolkit/environments.md Illustrates the directory structure for environment files, including shared configuration and user-specific secrets for different environments. ```tree project-root/ ├── m365agents.yml ├── env/ │ ├── .env.dev # Shared dev config (committed) │ ├── .env.dev.user # Dev secrets (gitignored) │ ├── .env.staging # Shared staging config (committed) │ ├── .env.staging.user # Staging secrets (gitignored) │ ├── .env.production # Shared production config (committed) │ └── .env.production.user # Production secrets (gitignored) └── appPackage/ └── manifest.json # Uses ${{VAR}} placeholders ``` -------------------------------- ### Expose Chat Prompt Functions and Direct MCP Tools Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/mcp.expose-chatprompt-tools-ts.md This example demonstrates how to expose functions defined in a ChatPrompt as MCP tools, alongside directly defined MCP tools. It shows the setup for an application that uses both bridged and direct tools. ```typescript import { App } from '@microsoft/teams.apps'; import { ChatPrompt } from '@microsoft/teams.ai'; import { OpenAIChatModel } from '@microsoft/teams.openai'; import { McpPlugin } from '@microsoft/teams.mcp'; import { DevtoolsPlugin } from '@microsoft/teams.dev'; import { z } from 'zod'; const model = new OpenAIChatModel({ apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o', }); // Functions used by the LLM internally const prompt = new ChatPrompt({ model, instructions: 'You are a helpful assistant.', }) .function('searchDocs', 'Search documentation', { type: 'object', properties: { query: { type: 'string', description: 'Search query' }, }, required: ['query'], }, async ({ query }: { query: string }) => { return [{ title: 'Getting Started', snippet: 'How to set up...' }]; }); const mcpPlugin = new McpPlugin({ name: 'hybrid-server', description: 'Documentation search and admin tools', }); // Expose LLM functions as MCP tools (searchDocs) mcpPlugin.use(prompt); // Add MCP-only tools with authInfo and hints mcpPlugin.tool( 'adminReset', 'Reset a user session (admin only)', { userId: z.string().describe('User ID to reset'), }, // No readOnlyHint -- this is a mutating operation async ({ userId }, { authInfo }) => { if (!authInfo) { return { content: [{ type: 'text', text: 'Unauthorized' }] }; } // Perform reset... return { content: [{ type: 'text', text: `Session reset for ${userId}` }], }; } ); const app = new App({ plugins: [new DevtoolsPlugin(), mcpPlugin], }); app.start(3978); // MCP exposes both "searchDocs" (from prompt) and "adminReset" (direct) ``` -------------------------------- ### Quick Reference Commands Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/provision-deploy/provision-deploy.md A quick reference for common ATK commands, including provisioning, deployment, and authentication for both local and cloud environments. ```bash Provision local: atk provision --env local -i false Deploy local: atk deploy --env local -i false Provision cloud: atk provision --env dev --resource-group --region -i false Deploy cloud: atk deploy --env dev -i false Login M365: atk auth login m365 Login Azure: atk auth login azure Check login: atk auth list ``` -------------------------------- ### Define Weather Function with Enum and Optional Units Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/ai.function-calling-design-ts.md This example demonstrates defining a function to get weather information. It uses JSON Schema to define parameters, including an enum for units and an optional units parameter. The handler function fetches data and returns it as JSON. ```typescript import { ChatPrompt } from '@microsoft/teams.ai'; const prompt = new ChatPrompt({ model, instructions: 'You help users find weather information.' }) .function( 'getWeather', 'Get the current weather for a city. Use celsius unless the user specifies fahrenheit.', { type: 'object', properties: { city: { type: 'string', description: 'The city name, e.g. "London" or "New York"', }, units: { type: 'string', description: 'Temperature units', enum: ['celsius', 'fahrenheit'], }, }, required: ['city'], }, async ({ city, units }: { city: string; units?: string }) => { const u = units || 'celsius'; const res = await fetch(`https://api.weather.example.com/${city}?units=${u}`); return await res.json(); } ); ``` -------------------------------- ### Recommended Project Structures Source: https://github.com/officedev/microsoft-365-agents-toolkit/blob/dev/packages/vscode-extension/skills/microsoft-365-agents-toolkit/experts/teams/project.scaffold-files-ts.md Illustrates two recommended project structures: a minimal setup for simple bots and an expanded structure for complex agents. Includes an alternative CLI scaffolding command. ```typescript // Minimal project (simple bot) // my-teams-bot/ // ├── appPackage/ // │ ├── manifest.json # Teams app manifest // │ ├── color.png # 192x192 app icon // │ └── outline.png # 32x32 outline icon // ├── src/ // │ └── index.ts # App entry point (all logic here) // ├── .env # Environment variables // ├── package.json // └── tsconfig.json // Expanded project (complex agent) // my-teams-bot/ // ├── appPackage/ // │ ├── manifest.json // │ ├── color.png // │ └── outline.png // ├── src/ // │ ├── index.ts # App entry point, App init, start // │ ├── handlers/ # Message and invoke handlers // │ │ ├── messages.ts // │ │ └── cardActions.ts // │ ├── prompts/ # AI prompt configurations // │ │ └── mainPrompt.ts // │ ├── functions/ # AI function definitions // │ │ ├── weather.ts // │ │ └── search.ts // │ ├── cards/ # Adaptive Card templates // │ │ ├── welcomeCard.ts // │ │ └── feedbackCard.ts // │ └── services/ # API clients, business logic // │ └── apiClient.ts // ├── .env // ├── package.json // └── tsconfig.json // CLI scaffolding (alternative to manual creation): // npx @microsoft/teams.cli@latest new typescript my-teams-bot --template echo // cd my-teams-bot // npm install ``` -------------------------------- ### Start Services Task Configuration Source: https://github.com/officedev/microsoft-365-agents-toolkit/wiki/{Debug}-Teams-Toolkit-VS-Code-Tasks This task configuration is used to start multiple services for your Teams application. It depends on other tasks like 'Start frontend', 'Start backend', and 'Start bot'. ```json { "label": "Start services", "dependsOn": [ "Start frontend", "Start backend", "Start bot" ] } ```