Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jannik Reinhard — Driving AI with passion

Microsoft Foundry Agent Tab

Chat with your Microsoft Foundry agents from a Microsoft Teams tab. Streaming answers, tool chips, citations, real errors. Sample code for the book 'Microsoft Foundry'.

Website GitHub LinkedIn X YouTube

Driving AI with passion · Microsoft Foundry · Intune · Azure

Overview

A Microsoft Teams personal tab for chatting with the agents in a Microsoft Foundry project. It lists the agents the project actually exposes, streams answers token by token, shows which tools the agent ran, and puts a source under every grounded claim.

Companion sample for the book Microsoft Foundry by Jannik Reinhard. Everything here runs against a real Foundry project — there is no mock mode and no canned data.

The tab answering a question, with the web search chip and its sources

Why This Exists

Publishing an agent to Teams through the Foundry portal gives you a bot. That is the right answer for most people. This is the other answer: a tab you own, where you decide what the surface shows — including the parts a bot chat hides. The tool the agent ran, the sources behind the sentence, the token cost of the turn, and the real reason a call failed are all first-class here, because those are the things you need when an agent misbehaves in front of a user.

What It Does

  • Agent picker built from GET /agents on the project. No hardcoded agent list — what you see is what the project has, including model and tools per agent.
  • Streaming answers over Server-Sent Events. The caret keeps moving, so a slow grounded answer never looks like a hang.
  • Tool chips. When the service runs web search, file search, or a function, the tab says so. Agent behaviour stops being a black box.
  • Citations with real, clickable URLs from the response annotations.
  • Real errors. 401 (not signed in), 403 (no role), 404 (wrong endpoint), 429 (quota), and content-filter blocks each get their own honest sentence instead of "Something went wrong."
  • Three Teams themes — default, dark, and high contrast — driven by the Teams client, not by the tab.
  • No secrets in the browser. The token lives on the server. See Architecture.

Screenshots

Empty state — teaches the agent and offers starters that actually run
Streaming — tokens arrive, caret alive
Dark theme — the Teams client decides, the tab follows
Error — the real cause, not a shrug

Architecture

Teams client
    │  loads the tab over HTTPS, hands it the theme
    ▼
app/           static page — no framework, no build step, no token
    │  GET /api/agents          POST /api/chat  (Server-Sent Events)
    ▼
server/        Express — holds the credential, talks to Foundry
    │  Authorization: Bearer <token for https://ai.azure.com/.default>
    ▼
Microsoft Foundry project
    ├── GET  {project}/agents?api-version=v1        control surface
    ├── POST {project}/openai/v1/conversations      OpenAI-compatible surface
    └── POST {project}/openai/v1/responses          (streams SSE back)

The backend exists for exactly one reason: a Teams tab is a web page, and anything a web page holds, the user holds. Put a Foundry key in the frontend and you have handed every user of the tab full access to the project. The server keeps the credential and exposes two narrow endpoints instead.

Auth is DefaultAzureCredential, so the same code runs under az login on your laptop and under a managed identity in App Service. There is no API key anywhere in this repo.

Three things the API will trip you on

These cost real time to find. They are documented here so they cost you none.

1. One project endpoint, two surfaces, two versioning rules.

{project}/agents?api-version=v1     ✅ control surface — wants api-version
{project}/openai/v1/responses       ✅ OpenAI-compatible — rejects it outright
{project}/openai/v1/responses?api-version=v1
                                    ❌ "api-version=v1 is not allowed. Use /v1 path instead."

2. agent is deprecated; it is agent_reference — and type is required inside it.

// ❌ rejected as deprecated
{ "agent": "MyAgent" }

// ❌ rejected: type is missing
{ "agent_reference": { "name": "MyAgent" } }

//
{ "agent_reference": { "name": "MyAgent", "type": "agent_reference" } }

3. Two roles look like one. Azure AI Agent Consumer grants .../endpoints/interact/action. Azure AI Project Runtime User grants .../responses/*. Reading the agent list and calling the agent are separate permissions — a tab that lists agents but 403s on send is almost always this.

Run it locally

Requires Node 20+, the Azure CLI, and a Foundry project with at least one agent.

az login                       # the identity needs a Foundry role on the project
cd server
npm install
cp .env.example .env           # then set FOUNDRY_PROJECT_ENDPOINT
npm start

Open http://localhost:3978. Outside Teams the tab falls back to your OS colour scheme; append ?theme=dark or ?theme=contrast to force one.

FOUNDRY_PROJECT_ENDPOINT is the project endpoint from the Foundry portal overview:

https://<resource>.services.ai.azure.com/api/projects/<project>

Roles you need

Role Why
Azure AI Foundry User read the project
Azure AI Agent Consumer list agents
Azure AI Project Runtime User create conversations and responses

Run it in Teams

Teams only loads a tab over HTTPS, so during development point a tunnel at port 3978:

devtunnel host -p 3978 --allow-anonymous     # or ngrok http 3978
cd teams
./package.sh <your-tunnel-host>              # bare hostname, no scheme

Then in Teams: Apps → Manage your apps → Upload an app → Upload a custom app, and pick teams/foundry-agent-tab.zip. Uploading custom apps must be allowed by your tenant's app setup policy.

The manifest ships with a __TAB_DOMAIN__ placeholder that package.sh substitutes, so nobody accidentally commits their tunnel hostname.

Layout

app/                the tab — index.html, styles.css, app.js, favicon.svg
server/             Express backend + Foundry calls
teams/              manifest.json, icons, package.sh
docs/screenshots/   the screenshots above
PRODUCT.md          who this is for and what it refuses to be
DESIGN.md           the visual system: themes, colour, type, motion

No build step, no bundler, no framework. The tab is three files a reader of the book can open and understand in one sitting, which is the whole point.

Related

License

MIT — see LICENSE.


Built and maintained by Jannik Reinhard · Microsoft MVP for Security and AI Platform.

Support the open-source work

Stay healthy, Cheers Jannik

About

Chat with your Microsoft Foundry agents from a Microsoft Teams tab. Streaming answers, tool chips, citations, real errors. Sample code for the book 'Microsoft Foundry'.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages