Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions samples/da-RubberDuck/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# TeamsFx files
env/.env.*.user
env/.env.local
.localConfigs
appPackage/build

# dependencies
node_modules/

# misc
.env
.deployment
.DS_Store
68 changes: 68 additions & 0 deletions samples/da-RubberDuck/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Rubber Duck Debugging Assistant 🐤

![Rubber Duck](assets/da-RubberDuck-screenshot.png)

## Summary

Meet your new debugging companion! This declarative agent acts as a "rubber duck" - inspired by the classic programming practice where developers explain their code problems out loud to uncover issues and clarify their thinking. Instead of talking to an actual rubber duck on your desk, you can now interact with an AI-powered debugging assistant that listens patiently and asks thoughtful questions to guide you toward solutions.

![Rubber Duck in use](assets/da-RubberDuck.gif)

### What is Rubber Duck Debugging?

Rubber duck debugging is a method where programmers explain their code line-by-line to an inanimate object (traditionally a rubber duck) to identify bugs and logical errors. By verbalizing the problem, developers often discover the solution themselves. This agent brings that concept to virtual life with intelligent, guided questioning.

### Version history

| Version | Date | Comments |
| --- | --- | --- |
| 1.0 | 16/04/2026 | Initial release |

## Prerequisites

* Microsoft 365 tenant with Microsoft 365 Copilot
* [Node.js](https://nodejs.org/), supported versions: 18, 20, 22
* A [Microsoft 365 account for development](https://docs.microsoft.com/microsoftteams/platform/toolkit/accounts)
* [VSCode](https://code.visualstudio.com/)
* [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)
* [Microsoft 365 Copilot license](https://learn.microsoft.com/microsoft-365-copilot/extensibility/prerequisites#prerequisites)

## Minimal path to awesome

1. First, select the Teams Toolkit icon on the left in the VS Code toolbar.
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. Ensure that both "Custom App Upload Enabled" and "Copilot Access Enabled" have green checkmarks
3. Create and provision the Teams app by clicking `Provision` in "Lifecycle" section.
4. Select the "Run and Debug" icon in the left sidebar, and then select `Preview in Copilot (Edge)` or `Preview in Copilot (Chrome)` from the launch configuration dropdown.
5. Once the Copilot app is loaded in the browser, click on the "…" menu and select "Copilot agents". You will see your declarative agent on the right rail. Clicking on it will change the experience to showcase the logo and name of the declarative agent.
6. Ask a question to your declarative agent and it should respond based on the instructions provided.

## Contributors

* [Guido Zambarda](https://github.com/guidozam)

## Features

This sample illustrates the following concepts:

Using this sample you can extend Microsoft 365 Copilot with an agent that:

* **Facilitates rubber duck debugging** - Provides a patient virtual companion for explaining code problems
* **Asks guided questions** - Instead of giving direct answers, asks thoughtful questions to guide you toward solutions
* **Encourages systematic thinking** - Helps break down complex problems into manageable parts
* **Creates a judgment-free environment** - Allows developers to think through problems without feeling rushed or judged

## Help

We do not support samples, but this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.

You can try looking at [issues related to this sample](https://github.com/pnp/copilot-pro-dev-samples/issues?q=label%3A%22sample%3A%20da-RubberDuck%22) to see if anybody else is having the same issues.

If you encounter any issues using this sample, [create a new issue](https://github.com/pnp/copilot-pro-dev-samples/issues/new).

Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/copilot-pro-dev-samples/issues/new).

## Disclaimer

**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**

![](https://m365-visitor-stats.azurewebsites.net/copilot-pro-dev-samples/samples/da-RubberDuck)
Binary file added samples/da-RubberDuck/appPackage/color.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions samples/da-RubberDuck/appPackage/declarativeAgent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.6/schema.json",
"version": "v1.6",
"name": "Rubber duck${{APP_NAME_SUFFIX}}",
"description": "Sample declarative agent that acts as a rubber duck to help developers.",
"instructions": "$[file('instruction.txt')]"
}
83 changes: 83 additions & 0 deletions samples/da-RubberDuck/appPackage/instruction.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
You are a “Rubber Duck Debugging Assistant,” inspired by the classic practice where developers explain their code out loud to uncover issues and clarify thinking.

## Mandatory Output Rule

* Every single response MUST begin with the duck emoji: 🐤
* The emoji must be the very first character in your response (no spaces or text before it).
* This rule is strict and applies to ALL replies without exception.

## Core Behavior

* Act as a patient, attentive listener.
* Encourage the developer to explain their problem step-by-step.
* Ask thoughtful, open-ended questions that guide reflection.
* Help break down complex problems into smaller parts.
* Only provide direct suggestions or solutions when the user explicitly asks or is clearly stuck.

## Interaction Style

* Be calm, curious, and non-judgmental.
* Never assume the developer is wrong; instead, explore their reasoning.
* Use prompts like:

* “Can you walk me through what this part of the code is doing?”
* “What do you expect to happen here?”
* “What actually happens instead?”
* “Where do you think things might be going off track?”
* Reflect back what the developer says to confirm understanding.

## Guidance Strategy

1. Clarification First

* Ask the developer to describe the problem in their own words.
* Identify inputs, outputs, and expected behavior.

2. Step-by-Step Exploration

* Guide them through the code flow.
* Encourage them to trace execution mentally or with examples.

3. Hypothesis Building

* Help them form possible explanations for the issue.
* Ask what evidence supports or contradicts each hypothesis.

4. Narrowing Down

* Suggest isolating components or testing smaller parts.
* Encourage debugging techniques (logs, breakpoints, minimal examples).

5. Gentle Nudging

* If they are stuck, provide hints—not full solutions.
* Escalate gradually from hints → partial suggestions → full explanation (only if needed).

## Constraints

* Do NOT immediately provide the final answer unless explicitly requested.
* Avoid overwhelming the user with too many questions at once.
* Keep responses concise but thoughtful.
* Prefer guiding questions over explanations.

## Optional Behaviors

* If the developer seems frustrated, acknowledge it briefly and refocus:

* “This kind of issue can be tricky—let’s break it down together.”
* If they skip steps, gently bring them back:

* “Before we jump ahead, can we look at what this function returns?”

## Example Tone

Developer: “My function isn’t returning the right value.”
You: “🐤 Can you show me the function and tell me what you expect it to return versus what it actually returns?”

## End Goal

Help the developer:

* Understand their own code better
* Discover bugs or gaps in logic independently
* Build stronger problem-solving skills
40 changes: 40 additions & 0 deletions samples/da-RubberDuck/appPackage/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.25/MicrosoftTeams.schema.json",
"manifestVersion": "1.25",
"version": "1.0.0",
"id": "${{TEAMS_APP_ID}}",
"developer": {
"name": "GuidoZam",
"websiteUrl": "https://iamguidozam.blog",
"privacyUrl": "https://iamguidozam.blog/privacy",
"termsOfUseUrl": "https://iamguidozam.blog/term-of-use"
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"name": {
"short": "Rubber duck${{APP_NAME_SUFFIX}}",
"full": "Rubber duck: your personal coding assistant"
},
"description": {
"short": "Rubber duck is your personal coding assistant that helps developers.",
"full": "Rubber duck is your personal coding assistant that helps you debug and understand your code by explaining it in simple terms."
},
"accentColor": "#FFFFFF",
"supportsChannelFeatures": "tier1",
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

supportsChannelFeatures is set to the string value "tier1", which doesn’t match how other Teams app manifests in this repo are structured and is likely to fail schema validation. Consider removing this property or updating it to the correct type/value per the Teams manifest schema you’re targeting.

Suggested change
"supportsChannelFeatures": "tier1",

Copilot uses AI. Check for mistakes.
"composeExtensions": [],
"permissions": [
"identity",
"messageTeamMembers"
],
"copilotAgents": {
"declarativeAgents": [
{
"id": "declarativeAgent",
"file": "declarativeAgent.json"
}
]
},
"validDomains": []
}
Binary file added samples/da-RubberDuck/appPackage/outline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/da-RubberDuck/assets/da-RubberDuck.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions samples/da-RubberDuck/assets/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
{
"name": "pnp-copilot-pro-dev-da-RubberDuck",
"source": "pnp",
"title": "Rubber Duck Debugging Assistant",
"shortDescription": "AI-powered debugging companion for rubber duck debugging methodology",
"url": "https://github.com/pnp/copilot-pro-dev-samples/tree/main/samples/da-RubberDuck",
"downloadUrl": "https://pnp.github.io/download-partial/?url=https://github.com/pnp/copilot-pro-dev-samples/tree/main/samples/da-RubberDuck",
"longDescription": [
"This declarative agent acts as a rubber duck debugging assistant, inspired by the classic programming practice where developers explain their code problems out loud to uncover issues and clarify their thinking. Instead of talking to an actual rubber duck, you can interact with an AI-powered debugging assistant that listens patiently and asks thoughtful questions to guide you toward solutions."
],
"creationDateTime": "2026-04-16",
"updateDateTime": "2026-04-16",
"products": [
"Microsoft 365 Copilot"
],
"metadata": [
{
"key": "PLATFORM",
"value": "Microsoft 365 Agents Toolkit"
},
{
"key": "LANGUAGE",
"value": "N/A"
},
{
"key": "API-PLUGIN",
"value": "No"
},
{
"key": "GRAPH-CONNECTOR",
"value": "No"
}
],
"thumbnails": [
{
"type": "image",
"order": 100,
"url": "https://github.com/pnp/copilot-pro-dev-samples/raw/main/samples/da-RubberDuck/assets/da-RubberDuck-screenshot.png",
"alt": "Rubber Duck Debugging Assistant in action"
},
{
"type": "image",
"order": 101,
"url": "https://github.com/pnp/copilot-pro-dev-samples/raw/main/samples/da-RubberDuck/assets/da-RubberDuck.gif",
"alt": "Rubber Duck Debugging Assistant conversation flow"
}
],
"authors": [
{
"gitHubAccount": "guidozam",
"pictureUrl": "https://github.com/guidozam.png",
"name": "Guido Zambarda"
}
],
"references": [
{
"name": "Microsoft 365 Copilot extensibility",
"description": "Learn more about what Microsoft 365 Copilot and how you can extend it.",
"url": "https://learn.microsoft.com/microsoft-365-copilot/extensibility/"
},
{
"name": "Rubber Duck Debugging",
"description": "Learn more about the rubber duck debugging methodology.",
"url": "https://en.wikipedia.org/wiki/Rubber_duck_debugging"
}
]
}
]
9 changes: 9 additions & 0 deletions samples/da-RubberDuck/env/.env.dev.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# This file includes environment variables that will be committed to git by default.

# Built-in environment variables
TEAMSFX_ENV=dev
APP_NAME_SUFFIX=" dev"
AGENT_SCOPE=shared
# Generated during provision, you can also add your own variables.
TEAMS_APP_ID=
72 changes: 72 additions & 0 deletions samples/da-RubberDuck/m365agents.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
# Visit https://aka.ms/teamsfx-actions for details on actions
version: v1.11

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additionalMetadata.sampleTag is missing from this project config. Other samples include it (e.g., samples/da-CanvasStudent/m365agents.yml:6-8) and it’s used for consistent sample identification/tagging; consider adding additionalMetadata: { sampleTag: pnp-copilot-pro-dev:da-RubberDuck } near the top.

Suggested change
additionalMetadata:
sampleTag: pnp-copilot-pro-dev:da-RubberDuck

Copilot uses AI. Check for mistakes.
environmentFolderPath: ./env

# Triggered when 'teamsapp provision' is executed
provision:
# Creates an app
- uses: teamsApp/create
with:
# app name
name: Rubber duck${{APP_NAME_SUFFIX}}
# Write the information of created resources into environment file for
# the specified environment variable(s).
writeToEnvironmentFile:
teamsAppId: TEAMS_APP_ID

# Build app package with latest env value
- uses: teamsApp/zipAppPackage
with:
# Path to manifest template
manifestPath: ./appPackage/manifest.json
outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
outputFolder: ./appPackage/build
# Update the app manifest to an existing app in Developer Portal.
# Will use the app id in manifest file to determine which app to update.
- uses: teamsApp/update
with:
# Relative path to this file. This is the path for built zip file.
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
# Extend your app to Outlook and the Microsoft 365 app
Comment on lines +20 to +33
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The provision lifecycle is missing a teamsApp/validateAppPackage step after teamsApp/zipAppPackage. All other Agents Toolkit sample configs include this validation (e.g., samples/da-CanvasStudent/m365agents.yml:43-47), and omitting it can allow invalid manifests/app packages to be applied.

Copilot uses AI. Check for mistakes.
- uses: teamsApp/extendToM365
with:
# Relative path to the build app package.
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
scope: ${{AGENT_SCOPE}}
# Write the information of created resources into environment file for
# the specified environment variable(s).
writeToEnvironmentFile:
titleId: M365_TITLE_ID
appId: M365_APP_ID
shareLink: SHARE_LINK

# Triggered when 'teamsapp publish' is executed
publish:
# Build app package with latest env value
- uses: teamsApp/zipAppPackage
with:
# Path to manifest template
manifestPath: ./appPackage/manifest.json
outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
outputFolder: ./appPackage/build
# Apply the app manifest to an existing app in
# Developer Portal.
# Will use the app id in manifest file to determine which app to update.
- uses: teamsApp/update
with:
# Relative path to this file. This is the path for built zip file.
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
# Publish the app to
Comment on lines +48 to +62
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The publish lifecycle also lacks a teamsApp/validateAppPackage step between zipAppPackage and teamsApp/update (and before publishing). This validation is consistently present in other samples and helps catch schema/manifest issues before attempting update/publish.

Copilot uses AI. Check for mistakes.
# Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps)
# for review and approval
- uses: teamsApp/publishAppPackage
with:
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
# Write the information of created resources into environment file for
# the specified environment variable(s).
writeToEnvironmentFile:
publishedAppId: TEAMS_APP_PUBLISHED_APP_ID
projectId: 19e37db5-9021-415c-9718-1e0ac119326a