Skip to content

Merge main into alpha/v2.0.0#412

Merged
heyitsaamir merged 20 commits intoalpha/v2.0.0from
main
Apr 25, 2026
Merged

Merge main into alpha/v2.0.0#412
heyitsaamir merged 20 commits intoalpha/v2.0.0from
main

Conversation

@heyitsaamir
Copy link
Copy Markdown
Collaborator

Summary

  • Merge latest main into alpha branch for next alpha release
  • Includes deprecation of ai, openai, mcpplugin, a2a, and devtools packages
  • Token validation fixes, proactive messaging updates, agent framework example, and more

Test plan

  • CI passes on alpha branch after merge
  • Trigger publish pipeline on alpha/v2.0.0 in ADO

heyitsaamir and others added 20 commits April 16, 2026 17:01
## Summary
- Simplify `HttpStream` to save the last emitted `MessageActivityInput`
as the final message template (last wins), instead of separately
accumulating attachments, entities, and suggested actions
- Text is still accumulated across all emits; everything else comes from
the last `MessageActivityInput`
- Add suggested action buttons to stream and ai-test examples

## Test plan
- [ ] Run `poe test` — all 11 `test_http_stream.py` tests pass
- [ ] Deploy stream example, verify suggested actions appear after
stream completes
- [ ] Deploy ai-test example, verify suggested actions on both streaming
and non-streaming responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Bumps [authlib](https://github.com/authlib/authlib) from 1.6.9 to
1.6.11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/authlib/authlib/releases">authlib's
releases</a>.</em></p>
<blockquote>
<h2>v1.6.11</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.10...v1.6.11">https://github.com/authlib/authlib/compare/v1.6.10...v1.6.11</a></p>
<ul>
<li>Fix CSRF issue with starlette client</li>
</ul>
<h2>v1.6.10</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.9...v1.6.10">https://github.com/authlib/authlib/compare/v1.6.9...v1.6.10</a></p>
<ul>
<li>Fix redirecting to unvalidated <code>redirect_uri</code> on
<code>UnsupportedResponseTypeError</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/authlib/authlib/blob/v1.6.11/docs/changelog.rst">authlib's
changelog</a>.</em></p>
<blockquote>
<h2>Version 1.6.11</h2>
<p><strong>Released on Apr 16, 2026</strong></p>
<ul>
<li>Fix CSRF vulnerability in the Starlette OAuth client when a
<code>cache</code> is
configured.</li>
</ul>
<h2>Version 1.6.10</h2>
<p><strong>Released on Apr 13, 2026</strong></p>
<ul>
<li>Fix redirecting to unvalidated <code>redirect_uri</code> on
<code>UnsupportedResponseTypeError</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/authlib/authlib/commit/0dc0e5b4dc84f155319518a3732113af6fa47525"><code>0dc0e5b</code></a>
chore: bump to 1.6.11</li>
<li><a
href="https://github.com/authlib/authlib/commit/aa7b8e46e00d0622658666476782042ac00153a5"><code>aa7b8e4</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/authlib/authlib/commit/401a7709c3fe43bce1b2105d16a475b688faa788"><code>401a770</code></a>
fix: CSRF issue with starlette client</li>
<li><a
href="https://github.com/authlib/authlib/commit/ef09aebbba4439dedb22bd15777d1b3458b6f0ab"><code>ef09aeb</code></a>
chore: release 1.6.10</li>
<li><a
href="https://github.com/authlib/authlib/commit/3be08468201a7766a93012ce149ea12822cab096"><code>3be0846</code></a>
fix: redirecting to unvalidated redirect_uri on
UnsupportedResponseTypeError</li>
<li>See full diff in <a
href="https://github.com/authlib/authlib/compare/v1.6.9...v1.6.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=authlib&package-manager=uv&previous-version=1.6.9&new-version=1.6.11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/microsoft/teams.py/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary
- Add `app.reply(conversation_id, message_id, activity)` for proactive
thread sends
- Add `to_threaded_conversation_id()` helper and `supports_threading()`
internal guard
- Update `context.send()` and `context.reply()` doc comments
- Add threading example bot

## Test plan
- [x] Unit tests for `to_threaded_conversation_id()` (9 tests),
`supports_threading()` (8 tests), and `app.reply()` (5 tests)
- [x] E2E: All commands tested in 1:1 and channel (top-level + existing
thread)
- [x] All tests passed, `poe check` clean, pyright 0 errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

Security hardening for token validation, service URL handling, and
development tooling.

- **Service URL validation**: Validate inbound `serviceUrl` against
allowed hostnames from the configured cloud environment preset.
Configurable via `additional_allowed_domains` for non-standard channels
or sovereign clouds without presets.
- **Scope validation**: Use exact set membership instead of substring
matching for JWT scope checks.
- **Issuer validation**: Log a warning when Entra token validation is
configured without a tenant ID, making the silent issuer validation skip
visible.
- **DevTools**: Prevent the DevTools plugin from starting in production
environments.

## Test plan

- Unit tests for domain allowlist (cloud preset FQDNs, rejected domains,
attacker trafficmanager, localhost, custom domains, wildcard,
botframework.com rejected by default)
- Unit tests for exact scope matching
- Unit test for issuer validation warning
- Unit tests for DevTools production guard
- E2E validated in Teams -- no regressions
- E2E validated DevTools blocked on `PYTHON_ENV=production`
… client) (#386)

Adds a new example (examples/ai-agentframework/) showing how to build a
Teams bot using agent framework with tool calling.
The example covers:
- Local tools (datetime, math, random, currency conversion)
  - MCP tools (MSLearn, AdaptiveCards)
  - Streaming responses with citation handling
  - Per-conversation session management
Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from
1.1.1 to 1.2.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/theskumar/python-dotenv/releases">python-dotenv's
releases</a>.</em></p>
<blockquote>
<h2>v1.2.2</h2>
<h3>Added</h3>
<ul>
<li>Support for Python 3.14, including the free-threaded (3.14t) build.
(#)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>The <code>dotenv run</code> command now forwards flags directly to
the specified command by <a
href="https://github.com/bbc2"><code>@​bbc2</code></a> in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/607">theskumar/python-dotenv#607</a></li>
<li>Improved documentation clarity regarding override behavior and the
reference page.</li>
<li>Updated PyPy support to version 3.11.</li>
<li>Documentation for FIFO file support.</li>
<li>Support for Python 3.9.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Improved <code>set_key</code> and <code>unset_key</code> behavior
when interacting with symlinks by <a
href="https://github.com/bbc2"><code>@​bbc2</code></a> in <a
href="https://github.com/theskumar/python-dotenv/commit/790c5c02991100aa1bf41ee5330aca75edc51311">#790c5</a></li>
<li>Corrected the license specifier and added missing Python 3.14
classifiers in package metadata by <a
href="https://github.com/JYOuyang"><code>@​JYOuyang</code></a> in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/590">theskumar/python-dotenv#590</a></li>
</ul>
<h3>Breaking Changes</h3>
<ul>
<li>
<p><code>dotenv.set_key</code> and <code>dotenv.unset_key</code> used to
follow symlinks in some
situations. This is no longer the case. For that behavior to be restored
in
all cases, <code>follow_symlinks=True</code> should be used.</p>
</li>
<li>
<p>In the CLI, <code>set</code> and <code>unset</code> used to follow
symlinks in some situations. This
is no longer the case.</p>
</li>
<li>
<p><code>dotenv.set_key</code>, <code>dotenv.unset_key</code> and the
CLI commands <code>set</code> and <code>unset</code>
used to reset the file mode of the modified .env file to
<code>0o600</code> in some
situations. This is no longer the case: The original mode of the file is
now
preserved. Is the file needed to be created or wasn't a regular file,
mode
<code>0o600</code> is used.</p>
</li>
</ul>
<h3>Misc</h3>
<ul>
<li>skip 000 permission tests for root user by <a
href="https://github.com/burnout-projects"><code>@​burnout-projects</code></a>
in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/561">theskumar/python-dotenv#561</a></li>
<li>Bump actions/checkout from 5 to 6 in the github-actions group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/593">theskumar/python-dotenv#593</a></li>
<li>Add Windows testing to CI by <a
href="https://github.com/bbc2"><code>@​bbc2</code></a> in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/604">theskumar/python-dotenv#604</a></li>
<li>Improve workflow efficiency with best practices by <a
href="https://github.com/theskumar"><code>@​theskumar</code></a> in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/609">theskumar/python-dotenv#609</a></li>
<li>Remove the use of <code>sh</code> in tests by <a
href="https://github.com/bbc2"><code>@​bbc2</code></a> in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/612">theskumar/python-dotenv#612</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/JYOuyang"><code>@​JYOuyang</code></a>
made their first contribution in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/590">theskumar/python-dotenv#590</a></li>
<li><a
href="https://github.com/burnout-projects"><code>@​burnout-projects</code></a>
made their first contribution in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/561">theskumar/python-dotenv#561</a></li>
<li><a
href="https://github.com/cpackham-atlnz"><code>@​cpackham-atlnz</code></a>
made their first contribution in <a
href="https://redirect.github.com/theskumar/python-dotenv/pull/597">theskumar/python-dotenv#597</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/theskumar/python-dotenv/compare/v1.2.1...v1.2.2">https://github.com/theskumar/python-dotenv/compare/v1.2.1...v1.2.2</a></p>
<h2>v1.2.1</h2>
<h2>What's Changed</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md">python-dotenv's
changelog</a>.</em></p>
<blockquote>
<h2>[1.2.2] - 2026-03-01</h2>
<h3>Added</h3>
<ul>
<li>Support for Python 3.14, including the free-threaded (3.14t) build.
(<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/588">#588</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>The <code>dotenv run</code> command now forwards flags directly to
the specified command by [<a
href="https://github.com/bbc2"><code>@​bbc2</code></a>] in <a
href="https://redirect.github.com/theskumar/python-dotenv/issues/607">#607</a></li>
<li>Improved documentation clarity regarding override behavior and the
reference page.</li>
<li>Updated PyPy support to version 3.11.</li>
<li>Documentation for FIFO file support.</li>
<li>Dropped Support for Python 3.9.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Improved <code>set_key</code> and <code>unset_key</code> behavior
when interacting with symlinks by [<a
href="https://github.com/bbc2"><code>@​bbc2</code></a>] in
[790c5c0]</li>
<li>Corrected the license specifier and added missing Python 3.14
classifiers in package metadata by [<a
href="https://github.com/JYOuyang"><code>@​JYOuyang</code></a>] in <a
href="https://redirect.github.com/theskumar/python-dotenv/issues/590">#590</a></li>
</ul>
<h3>Breaking Changes</h3>
<ul>
<li>
<p><code>dotenv.set_key</code> and <code>dotenv.unset_key</code> used to
follow symlinks in some
situations. This is no longer the case. For that behavior to be restored
in
all cases, <code>follow_symlinks=True</code> should be used.</p>
</li>
<li>
<p>In the CLI, <code>set</code> and <code>unset</code> used to follow
symlinks in some situations. This
is no longer the case.</p>
</li>
<li>
<p><code>dotenv.set_key</code>, <code>dotenv.unset_key</code> and the
CLI commands <code>set</code> and <code>unset</code>
used to reset the file mode of the modified .env file to
<code>0o600</code> in some
situations. This is no longer the case: The original mode of the file is
now
preserved. Is the file needed to be created or wasn't a regular file,
mode
<code>0o600</code> is used.</p>
</li>
</ul>
<h2>[1.2.1] - 2025-10-26</h2>
<ul>
<li>Move more config to <code>pyproject.toml</code>, removed
<code>setup.cfg</code></li>
<li>Add support for reading <code>.env</code> from FIFOs (Unix) by [<a
href="https://github.com/sidharth-sudhir"><code>@​sidharth-sudhir</code></a>]
in <a
href="https://redirect.github.com/theskumar/python-dotenv/issues/586">#586</a></li>
</ul>
<h2>[1.2.0] - 2025-10-26</h2>
<ul>
<li>Upgrade build system to use PEP 517 &amp; PEP 518 to use
<code>build</code> and <code>pyproject.toml</code> by [<a
href="https://github.com/EpicWink"><code>@​EpicWink</code></a>] in <a
href="https://redirect.github.com/theskumar/python-dotenv/issues/583">#583</a></li>
<li>Add support for Python 3.14 by [<a
href="https://github.com/23f3001135"><code>@​23f3001135</code></a>] in
<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/579">#579</a></li>
<li>Add support for disabling of <code>load_dotenv()</code> using
<code>PYTHON_DOTENV_DISABLED</code> env var. by [<a
href="https://github.com/matthewfranglen"><code>@​matthewfranglen</code></a>]
in <a
href="https://redirect.github.com/theskumar/python-dotenv/issues/569">#569</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/36004e0e34be7665ff2b11a8a4005144f76f176d"><code>36004e0</code></a>
Bump version: 1.2.1 → 1.2.2</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/eb202520e5933c9daf42501e1e42fdb0144002c8"><code>eb20252</code></a>
docs: update changelog for v1.2.2</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/790c5c02991100aa1bf41ee5330aca75edc51311"><code>790c5c0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/43340da220fb4ca4f95357bbe21a3c7f8f1278b1"><code>43340da</code></a>
Remove the use of <code>sh</code> in tests (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/612">#612</a>)</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/09d7cee32459e7abdcb5c9d8122a552589c06a9c"><code>09d7cee</code></a>
docs: clarify override behavior and document FIFO support (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/610">#610</a>)</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/c8de2887c00198c22842c5ae5e92d1747467363c"><code>c8de288</code></a>
ci: improve workflow efficiency with best practices (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/609">#609</a>)</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/7bd9e3dbfedc0983ad7d56d5570013035242bdf4"><code>7bd9e3d</code></a>
Add Windows testing to CI (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/604">#604</a>)</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/1baaf04f336072e0ee324d5df9563ec767f14f81"><code>1baaf04</code></a>
Drop Python 3.9 support and update to PyPy 3.11 (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/608">#608</a>)</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/4a22cf8993804aeede0c20b75bb1a29d3a99e9dc"><code>4a22cf8</code></a>
ci: enable testing on Python 3.14t (free-threaded) (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/588">#588</a>)</li>
<li><a
href="https://github.com/theskumar/python-dotenv/commit/e2e8e776b42e382ae38b44d3982dd649e7507dd4"><code>e2e8e77</code></a>
Fix license specifier (<a
href="https://redirect.github.com/theskumar/python-dotenv/issues/597">#597</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/theskumar/python-dotenv/compare/v1.1.1...v1.2.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=python-dotenv&package-manager=uv&previous-version=1.1.1&new-version=1.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/microsoft/teams.py/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Looking back, this sample is severely overloaded compared to the other
examples. Simplifying the local tools to have one simple welcome
adaptive card. I think we should include graph and oauth capabilities
with more thought at a later time in a more complex sample.

**Key changes include:**

### Local tool simplification and onboarding improvements
- Replaced all Microsoft Graph-backed local tools (`find_people`,
`get_org_context`, `list_team_members`, `get_presence`) with a single
local tool, `send_welcome_card`, which attaches a capabilities overview
Adaptive Card to greet users. The new tool uses a `ContextVar` to safely
manage per-turn card attachments. (`src/local_tools.py`)
- Updated the agent's system prompt to always greet new users with a
welcome card, aligning agent behavior with the new onboarding
experience. (`src/agent.py`)

### Documentation and environment updates
- Updated the `README.md` to reflect the removal of Microsoft Graph
tools, focusing on the new welcome card tool and simplifying
instructions for environment variables and prerequisites. Microsoft
Graph permissions and related setup steps have been removed.
(`README.md`)
- Removed the `msgraph-sdk` dependency from `pyproject.toml` since
Graph-backed tools are no longer used. (`pyproject.toml`)

### Codebase cleanup and integration
- Removed all code related to binding the Teams App to Microsoft Graph
and cleaned up logging configuration. Updated the message handling flow
to collect and attach Adaptive Cards generated by tools to the Teams
reply.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
**1. Pyright was failing on the `ai-agentframework` example.**
The agent-framework package pulls in a bunch of optional sub-packages
via its [all] extra. One of those —
`agent-framework-azure-ai-search==0.0.0a1` — is a broken placeholder
alpha that accidentally ships an empty agent_framework/__init__.py in
its wheel. When installed, that empty file overwrites the real one from
agent-framework-core, so Python sees an empty agent_framework namespace
and pyright can't find Agent, AgentSession, tool, etc.

Replaced imports with `agent-framework-core` and
`agent-framework-openai` packages, resycned lock file

  **2. CI wasn't running on examples**
Our workflows were only set up to run when files under `packages/`
changed. This bug was undetected when the sample was added, so proposing
to run our examples in CI too.

---------

Co-authored-by: lilydu <lilydu+odspmdb@microsoft.com>
- completely remove `devtools` package

---------

Co-authored-by: lilydu <lilydu+odspmdb@microsoft.com>
`App(additional_allowed_domains=[...])` was silently ignored at the
token-validation layer, rejecting user-approved service URLs (e.g.
`canary.botapi.skype.com`) before they ever reached the allowlist-aware
check in `HttpServer.handle_request`.

Fix threads the allowlist through `TokenValidator.__init__`, both
factory methods (`for_service`, `for_entra`), and the `validate_token`
call site. Updates `HttpServer.initialize` and `App.__init__` to forward
the option.

## Why unit tests missed it

All existing `additional_allowed_domains` tests used `skip_auth=True`,
which bypasses the `TokenValidator` code path entirely. The helper
function `is_allowed_service_url` had direct tests with 3 args, so the
function itself was fine — just no test proved the code *calling* it in
the auth-on path was also using 3 args. E2E validation was against
default service url, which is in the built-in allowlist and doesn't need
the knob. The intersection of "auth on" AND "non-default service URL"
had zero coverage.

  ## Tests

  `test_token_validator.py`:
- `test_validate_token_honors_additional_allowed_domains` — canary
accepted when in allowlist
- `test_validate_token_rejects_when_domain_not_in_allowlist` — baseline:
canary rejected without the knob
- `test_validate_token_wildcard_allows_arbitrary_domain` — `["*"]`
disables the check at the token-validation layer
- `test_for_service_stores_additional_allowed_domains` /
`test_for_entra_stores_additional_allowed_domains` — factory plumbing

  `test_http_server.py`:
- `test_initialize_forwards_allowlist_to_token_validator` — spies
`TokenValidator.for_service` and asserts it's called *with* the
allowlist (catches the exact regression
  class)

  All 67 tests pass.

  ## Test plan

- [x] Unit: `uv run pytest packages/apps/tests/test_token_validator.py
packages/apps/tests/test_http_server.py` — 67/67
  - [x] Lint/format: `uv run poe check` — clean
  - [x] Type check: `uv run pyright` — no new errors
- [x] E2E on canary: verified activity from
`https://canary.botapi.skype.com/amer/...` passes token validation and
reaches `onMessage` (previously 401'd)
  - [x] E2E regression: default `smba.trafficmanager.net` still works
## Summary
- Add Example 3 to the proactive-messaging sample showing how to send a
message and then update it using the ConversationClient
- Demonstrates the send-then-update pattern for proactive messaging
without a running server

## Test plan
- [x] Run `uv run src/main.py <conversation_id>` and verify all 3
examples work
- [x] Confirm the third message shows "Status: Pending..." then updates
to "Status: Complete"
This pull request introduces a new example in `examples/a2a-test`
demonstrating two symmetric Microsoft Teams bots (Alice and Bob) that
relay questions and answers using the official `a2a-sdk` and Adaptive
Cards. The implementation is modularized into clear components for A2A
communication, card construction, bot logic, and state management. The
README and dependencies are updated to reflect the new architecture and
usage.

The most important changes are:

**New A2A Example Architecture and Implementation**
- Added a comprehensive example with two Teams bots (`bot_a.py` and
`bot_b.py`) that can relay questions to each other over A2A, using
Adaptive Cards for human-in-the-loop answers. Each bot can both send and
receive questions, and route replies back to the original asker.
[[1]](diffhunk://#diff-420f24e621487e9551659aeb1b7545dac246a61f6e20fd0ca944ce239eacc4d0R1-R131)
[[2]](diffhunk://#diff-b856f92fbc08301b78465ed1ecd3412a3e285b7156c2d91d2f7cf7f90150e2f6R1-R120)

**A2A Communication Layer**
- Introduced `a2a_client.py` for outbound A2A message sending, which
resolves the peer’s agent card and sends a single message using the
`a2a-sdk`.
- Added `a2a_executor.py` implementing an `AgentExecutor` that routes
incoming A2A `ask` and `reply` messages to the appropriate Teams
conversation, updating bot state as needed.
- Added `a2a_server.py` to wrap the executor in an
`A2AStarletteApplication` for serving A2A requests.

**Adaptive Card Construction**
- Added `cards.py` with builder functions for the "ask" and "reply"
Adaptive Cards, embedding routing metadata so no per-question state is
needed on the receiving bot.

**Documentation and Dependency Updates**
- Overhauled `README.md` to document the new flow, file structure,
operator requirements, and setup instructions.
- Updated `pyproject.toml` to reflect new dependencies (`a2a-sdk`,
`uvicorn`, `httpx`, etc.) and renamed the package for clarity.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
…407)

Bumps [postcss](https://github.com/postcss/postcss) from 8.5.6 to
8.5.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/releases">postcss's
releases</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code>&lt;/style&gt;</code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@​TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's
changelog</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code>&lt;/style&gt;</code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@​TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/postcss/postcss/commit/33b9790263dc1562a46ce45d9532bd63e95b7986"><code>33b9790</code></a>
Release 8.5.10 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/536c79e4b01e58a3a56b09c3c0cf2323f4b9a28b"><code>536c79e</code></a>
Escape &lt;/style&gt; in CSS output (<a
href="https://redirect.github.com/postcss/postcss/issues/2074">#2074</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/afa96b2a139ce625c4d27973313479c7c85f39d4"><code>afa96b2</code></a>
Update dependencies (<a
href="https://redirect.github.com/postcss/postcss/issues/2073">#2073</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/effe88bb87cabdc1876e02adbdd30f392f19f40d"><code>effe88b</code></a>
Typo (<a
href="https://redirect.github.com/postcss/postcss/issues/2072">#2072</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/3ee79a2c4a11e41d52db50b444eebe38299495ad"><code>3ee79a2</code></a>
Thread model (<a
href="https://redirect.github.com/postcss/postcss/issues/2071">#2071</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/2e0683daca4dc2919211b03774f6b2d137136c01"><code>2e0683d</code></a>
Create incident response docs (<a
href="https://redirect.github.com/postcss/postcss/issues/2070">#2070</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/fe88ac29c06b7b218be32994cdc6ca1525bdf2c9"><code>fe88ac2</code></a>
Release 8.5.9 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/c551632496b87ab3f1965bfda5dc386b6c71963e"><code>c551632</code></a>
Avoid RegExp when we can use simple JS</li>
<li><a
href="https://github.com/postcss/postcss/commit/89a6b744060eb8dee743351c785a9fbe37d4525a"><code>89a6b74</code></a>
Move SECURITY.txt for docs folder to keep GitHub page cleaner</li>
<li><a
href="https://github.com/postcss/postcss/commit/6ceb8a46af9f9de821faee98f861bdf84617347b"><code>6ceb8a4</code></a>
Create SECURITY.md</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.6...8.5.10">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=postcss&package-manager=npm_and_yarn&previous-version=8.5.6&new-version=8.5.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/microsoft/teams.py/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary
- These packages were in preview but we've decided to stop maintaining
them before GA
- Added `[!WARNING]` deprecation banners to each package's README with
links to recommended replacements
- Added runtime `DeprecationWarning` on import so users get notified in
their terminal
- Added `Development Status :: 7 - Inactive` trove classifier to each
`pyproject.toml`

**Recommended replacements:**
- `microsoft-teams-ai` → [Agent
Framework](https://microsoft.github.io/teams-sdk/python/in-depth-guides/ai/)
- `microsoft-teams-mcpplugin` → [MCP Python
SDK](https://github.com/modelcontextprotocol/python-sdk)
- `microsoft-teams-a2a` → [A2A Python
SDK](https://github.com/a2aproject/a2a-python)
- `microsoft-teams-openai` → [OpenAI Python
SDK](https://github.com/openai/openai-python)

## Test plan
- [ ] `poe check` passes (ruff + format)
- [ ] pyright passes
- [ ] Verify deprecation warnings show when importing any of the four
packages
- [ ] Verify README banners render correctly on GitHub

---------

Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Restores the devtools package to the workspace (was previously
removed)
- Marks it as deprecated with README warning, `FutureWarning` on import,
and `Development Status :: 7 - Inactive` classifier
- Recommends testing with Teams directly or the [Agents
Playground](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/debug-your-agents-playground)

## Test plan
- [ ] `poe check` passes
- [ ] pyright passes
- [ ] `python -c "import microsoft_teams.devtools"` shows FutureWarning
- [ ] README warning renders on GitHub

Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- `uv.lock` was missing the devtools workspace member after it was
restored in #410
- Ran `uv lock` to regenerate

## Test plan
- [ ] `uv sync` works without errors

Co-authored-by: Claude <noreply@anthropic.com>
@heyitsaamir heyitsaamir merged commit 6230052 into alpha/v2.0.0 Apr 25, 2026
8 checks passed
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.

5 participants