Skip to content

Add AIFileAnalysisBot sample - #651

Merged
Corina (corinagum) merged 4 commits into
mainfrom
cg/ai-file-analysis-sample
Aug 19, 2026
Merged

Add AIFileAnalysisBot sample#651
Corina (corinagum) merged 4 commits into
mainfrom
cg/ai-file-analysis-sample

Conversation

@corinagum

Copy link
Copy Markdown
Collaborator

Adds AIFileAnalysisBot, a sample for the file-receive API from #645. It reads files attached in a personal (1:1) chat and sends the ones it understands to Azure OpenAI.

One OnMessage handler covers two paths:

  • Basic (no LLM) replies with an Adaptive Card for files the sample cannot analyze, showing the metadata the file API exposes and the bytes that were downloaded.
  • AI converts text files and images into model content parts, sends them in a single request, and streams the analysis back.

The flow is context.Files.ListAsync(), then DownloadAsync() once per file, then FileContext.Classify to sort each download into Text, Image, or Unsupported. Classify falls back to the file's extension when the MIME type does not match, because Teams often misreports source files (.ts comes through as video/vnd.dlna.mpeg-tts). Image bytes are inlined as a data URI rather than passing the model the download URL, which carries a short-lived tempauth credential.

Where a block is labeled, the label is either FILE RECEIVE (the SDK API, the part worth copying) or SAMPLE GUARDRAIL (limits this sample picked). The guardrails: 5 files per message, 100 KB text per file, 250 KB text per message, 1 MB per image, PNG/JPEG/GIF/WebP only, and no conversation state. Anything dropped or truncated sends the user a message saying why.

Prerequisites

The manifest needs supportsFiles: true on the bot entry. Without it Teams does not enable the attachment UI in the bot's chat, so there is nothing to receive.

Testing

dotnet build succeeds with 0 warnings and 0 errors, and dotnet format --verify-no-changes is clean.

Manually tested against a real bot in the Teams web client:

Case Result
No attachment Prompts for a file
Text .txt Analyzed and streamed
JSON .json Analyzed and streamed
Image .png Analyzed and streamed
Two images in one message Both files reached the model in one request
Mixed text + image in one message Both files reached the model in one request
Unsupported .zip Basic card, no model call
192 KB text file Truncated at the 100 KB cap with a warning

Other languages:

Copilot AI lite review requested due to automatic review settings August 13, 2026 22:06
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new AIFileAnalysisBot sample demonstrating the personal-scope file-receive API (context.Files.ListAsync() + DownloadAsync()) and an Azure OpenAI analysis path that streams results back to Teams, with explicit “FILE RECEIVE” vs “SAMPLE GUARDRAIL” labeling.

Changes:

  • Introduces the samples/AIFileAnalysisBot project, including file classification, guardrails, an unsupported-file Adaptive Card path, and a streaming LLM analysis path.
  • Adds sample documentation and local configuration templates (appsettings + launchSettings.TEMPLATE.json).
  • Registers the new sample in the repo root README and solution (Microsoft.Teams.slnx).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
samples/AIFileAnalysisBot/README.md Documents the sample’s purpose, prerequisites (manifest supportsFiles), and behavior/limits.
samples/AIFileAnalysisBot/Properties/launchSettings.TEMPLATE.json Provides a template for required env vars (Azure AD + Azure OpenAI).
samples/AIFileAnalysisBot/Program.cs Wires Teams app + message handler flow: list files, download, classify, prepare request, stream analysis.
samples/AIFileAnalysisBot/FileContext.cs Implements file classification + request construction and guardrail enforcement.
samples/AIFileAnalysisBot/FileCard.cs Builds an Adaptive Card for unsupported files showing metadata + download facts.
samples/AIFileAnalysisBot/appsettings.json Sets default logging levels and AllowedHosts for the sample.
samples/AIFileAnalysisBot/AnalysisRunner.cs Runs a single stateless LLM request and streams incremental output to Teams.
samples/AIFileAnalysisBot/AIFileAnalysisBot.csproj Adds the new sample project with Teams project references + AI packages.
README.md Adds the new sample to the repository samples list.
Microsoft.Teams.slnx Adds the new sample project to the solution index.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread samples/AIFileAnalysisBot/FileContext.cs Outdated
Comment thread samples/AIFileAnalysisBot/FileContext.cs Outdated
Comment thread samples/AIFileAnalysisBot/Program.cs

@singhk97 Kavin (singhk97) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm!

@corinagum
Corina (corinagum) added this pull request to the merge queue Aug 19, 2026
Merged via the queue into main with commit 19d2d66 Aug 19, 2026
6 checks passed
@corinagum
Corina (corinagum) deleted the cg/ai-file-analysis-sample branch August 19, 2026 22:33
Corina (corinagum) added a commit to microsoft/teams.py that referenced this pull request Aug 20, 2026
Adds the `ai-file-analysis` example, a sample for the file-receive API
from #550. It reads files attached in a personal (1:1) chat and sends
the ones it understands to Azure OpenAI.

One `@app.on_message` handler covers two paths:

- **Basic (no LLM)** replies with an Adaptive Card for files the sample
cannot analyze, showing the metadata the file API exposes and the bytes
that were downloaded.
- **AI** converts text files and images into OpenAI content parts, sends
them in a single request, and streams the analysis back.

The flow is `ctx.files.list()`, then `download()` once per file, then
`classify_file` to sort each download into `text`, `image`, or
`unsupported`. `classify_file` falls back to the file's extension when
the MIME type does not match, because Teams often misreports source
files (`.ts` comes through as `video/vnd.dlna.mpeg-tts`). Image bytes
are inlined as a data URI rather than passing the model the download
URL, which carries a short-lived `tempauth` credential.

Where a block is labeled, the label is either `FILE RECEIVE` (the SDK
API, the part worth copying) or `SAMPLE GUARDRAIL` (limits this sample
picked). The guardrails: 5 files per message, 100 KB text per file, 250
KB text per message, 1 MB per image, PNG/JPEG/GIF/WebP only, and no
conversation state. Anything dropped or truncated sends the user a
message saying why.

## Prerequisites

The manifest needs `supportsFiles: true` on the bot entry. Without it
Teams does not enable the attachment UI in the bot's chat, so there is
nothing to receive.

## Testing

`ruff format --check`, `ruff check`, and `pyright` are all clean on the
example (5 files formatted, 0 errors).

Manually tested against a real bot in the Teams web client:

| Case | Result |
| --- | --- |
| No attachment | Prompts for a file |
| Text `.txt` | Analyzed and streamed |
| Image `.png` | Analyzed and streamed |
| Mixed text + image in one message | Both files reached the model in
one request |
| Unsupported `.zip` | Basic card, no model call |
| 192 KB text file | Truncated at the 100 KB cap with a warning |

The `.zip` case was checked in the bot log: a SharePoint GET and a card
POST, with no call to `openai.azure.com`.

Other languages:

- TypeScript: microsoft/teams.ts#727
- .NET: microsoft/teams.net#651
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants