Add ai-file-analysis sample - #727
Open
Corina (corinagum) wants to merge 4 commits into
Open
Conversation
This was referenced Aug 13, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new @examples/ai-file-analysis sample demonstrating the Teams file-receive API in personal (1:1) chat, including a basic “no LLM” path for unsupported files and an Azure OpenAI path that streams analysis for supported text/images.
Changes:
- Introduces
@examples/ai-file-analysisworkspace (bot entrypoint, file classification + guardrails, and an Adaptive Card response for unsupported files). - Adds documentation for the new example (root README link + example README).
- Updates the lockfile to include the new workspace and its dependencies.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds the new example to the repository’s examples list. |
| package-lock.json | Registers the new workspace and dependency graph updates. |
| examples/ai-file-analysis/turbo.json | Defines Turbo build task config for the example workspace. |
| examples/ai-file-analysis/tsconfig.json | TypeScript configuration for building the example. |
| examples/ai-file-analysis/src/index.ts | Main bot message handler: lists files, downloads, classifies, and triggers analysis/guards. |
| examples/ai-file-analysis/src/file-card.ts | Builds an Adaptive Card describing unsupported files (no-LLM path). |
| examples/ai-file-analysis/src/ai/index.ts | Azure OpenAI streaming call + error handling for file analysis. |
| examples/ai-file-analysis/src/ai/file-context.ts | File classification and conversion into OpenAI content parts with size/count guardrails. |
| examples/ai-file-analysis/README.md | Example documentation (setup, manifest requirement, and flow explanation). |
| examples/ai-file-analysis/package.json | Adds the new example as a workspace package with scripts and deps. |
| examples/ai-file-analysis/eslint.config.js | ESLint config wiring for the example workspace. |
Suppressed comments (2)
examples/ai-file-analysis/src/ai/index.ts:45
- After lazily initializing the Azure OpenAI client,
runAnalysisshould use the helper rather than the removed top-levelclient/deploymentconstants.
stream.update('Analyzing files...');
const completion = await client.chat.completions.create({
model: deployment,
messages: [
examples/ai-file-analysis/src/index.ts:58
- If the download loop is capped to 5 files, add a user-facing warning when additional attachments were ignored so the behavior stays traceable (consistent with the sample’s other warnings).
if (analyzable.length === 0) {
return;
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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
Collaborator
Author
|
Copilot resolve the merge conflicts in this pull request |
Copilot stopped work on behalf of
Corina (corinagum) due to an error
August 21, 2026 21:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
@examples/ai-file-analysis, a sample for the file-receive API from #712. It reads files attached in a personal (1:1) chat and sends the ones it understands to Azure OpenAI.One
messagehandler covers two paths:The flow is
files.list(), thendownload()once per file, thenclassifyFileto sort each download intotext,image, orunsupported.classifyFilefalls back to the file's extension when the MIME type does not match, because Teams often misreports source files (.tscomes through asvideo/vnd.dlna.mpeg-tts). Image bytes are inlined as a data URI rather than passing the model the download URL, which carries a short-livedtempauthcredential.Where a block is labeled, the label is either
FILE RECEIVE(the SDK API, the part worth copying) orSAMPLE 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: trueon the bot entry. Without it Teams does not enable the attachment UI in the bot's chat, so there is nothing to receive.Testing
turbo build lint --filter=@examples/ai-file-analysispasses (13/13 tasks including dependencies).Manually tested against a real bot in the Teams web client:
.txt.png.zipThe
.zipcase was checked in the bot log: a SharePoint GET and a card POST, with no call toopenai.azure.com.Other languages: