Summary
microsoft-teams-common imports from httpx's private modules while declaring an unbounded httpx requirement. httpx 1.0 removes those modules, so once 1.0 is released as stable, a fresh pip install microsoft-teams-apps will resolve to httpx 1.0 and fail at import time.
This is not yet affecting users: current httpx stable is 0.28.1, and dev releases aren't selected by default resolvers. Filing it now because httpx 1.0 is actively moving (1.0.dev4 was published 2026-08-19) and this breaks the moment it ships.
The two halves of the problem
1. Private API imports in packages/common/src/microsoft_teams/common/http/client.py:
from httpx._models import Request, Response
from httpx._types import QueryParamTypes, RequestContent, RequestData, RequestFiles
2. No upper bound on the requirement:
| File |
Constraint |
packages/common/pyproject.toml |
httpx>=0.28.1 |
packages/apps/pyproject.toml |
httpx>=0.27.0 |
examples/a2a/pyproject.toml |
httpx>=0.27 |
Either alone would be survivable. Together they mean the next httpx major silently becomes an install-time failure.
Reproduction
$ uv pip install --prerelease=allow "httpx==1.0.dev4" "microsoft-teams-api==2.1.0a2"
$ python -c "import microsoft_teams.api"
...
File ".../microsoft_teams/common/http/client.py", line 13, in <module>
from httpx._models import Request, Response
ModuleNotFoundError: No module named 'httpx._models'
I hit this accidentally while verifying the 2.1.0a2 release: --prerelease=allow applied globally, pulled httpx 1.0.dev4, and every import microsoft_teams.* failed.
Why 1.0 breaks it
httpx 1.0 is a significant restructure. _models.py and _types.py no longer exist; the module layout is now _request.py, _response.py, _client.py, _content.py, and friends.
httpx 0.28.1 : httpx._models OK, httpx._types OK
httpx 1.0.dev4: httpx._models -> ModuleNotFoundError
httpx._types -> ModuleNotFoundError
Fixing the imports
The two lines are not equally easy.
Request and Response are public in both 0.x and 1.0, so that import has a direct public replacement:
from httpx import Request, Response
The _types aliases (QueryParamTypes, RequestContent, RequestData, RequestFiles) are the harder half. They are not exported publicly in 0.x or 1.0, so there is no drop-in swap. Options: define our own type aliases in common/http, or loosen those annotations. Worth a deliberate decision rather than a mechanical edit, since they appear in public method signatures.
Suggested actions
- Switch
Request/Response to the public from httpx import ... (safe, works on both).
- Decide how to replace the
_types aliases, most likely SDK-owned aliases in common/http.
- Add an upper bound (
httpx>=0.28.1,<1.0) as a stopgap so a future httpx release can't break installs before 1 and 2 land.
Doing 3 alone is enough to stop the bleeding, but it shouldn't be the permanent answer: the underlying issue is depending on private API.
Affected
main, release/v2.0 (2.0.16), and release/v2.1 (2.1.0a2) all carry both private imports and the unbounded constraint.
Summary
microsoft-teams-commonimports from httpx's private modules while declaring an unbounded httpx requirement. httpx 1.0 removes those modules, so once 1.0 is released as stable, a freshpip install microsoft-teams-appswill resolve to httpx 1.0 and fail at import time.This is not yet affecting users: current httpx stable is 0.28.1, and dev releases aren't selected by default resolvers. Filing it now because httpx 1.0 is actively moving (
1.0.dev4was published 2026-08-19) and this breaks the moment it ships.The two halves of the problem
1. Private API imports in
packages/common/src/microsoft_teams/common/http/client.py:2. No upper bound on the requirement:
packages/common/pyproject.tomlhttpx>=0.28.1packages/apps/pyproject.tomlhttpx>=0.27.0examples/a2a/pyproject.tomlhttpx>=0.27Either alone would be survivable. Together they mean the next httpx major silently becomes an install-time failure.
Reproduction
I hit this accidentally while verifying the 2.1.0a2 release:
--prerelease=allowapplied globally, pulled httpx1.0.dev4, and everyimport microsoft_teams.*failed.Why 1.0 breaks it
httpx 1.0 is a significant restructure.
_models.pyand_types.pyno longer exist; the module layout is now_request.py,_response.py,_client.py,_content.py, and friends.Fixing the imports
The two lines are not equally easy.
RequestandResponseare public in both 0.x and 1.0, so that import has a direct public replacement:The
_typesaliases (QueryParamTypes,RequestContent,RequestData,RequestFiles) are the harder half. They are not exported publicly in 0.x or 1.0, so there is no drop-in swap. Options: define our own type aliases incommon/http, or loosen those annotations. Worth a deliberate decision rather than a mechanical edit, since they appear in public method signatures.Suggested actions
Request/Responseto the publicfrom httpx import ...(safe, works on both)._typesaliases, most likely SDK-owned aliases incommon/http.httpx>=0.28.1,<1.0) as a stopgap so a future httpx release can't break installs before 1 and 2 land.Doing 3 alone is enough to stop the bleeding, but it shouldn't be the permanent answer: the underlying issue is depending on private API.
Affected
main,release/v2.0(2.0.16), andrelease/v2.1(2.1.0a2) all carry both private imports and the unbounded constraint.