You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #88 lands native Teams DM streaming as a hand-rolled implementation of the Bot Framework REST streaming wire format (channelData.streamType, streamSequence, streamId, streaminfo entity, 1 req/sec throttle). Upstream vercel/chat#416 (in chat@4.27.0) achieves the same UX by delegating to IStreamer.emit() from @microsoft/teams.apps — an SDK that handled the wire format and throttling under the hood.
When PR #88 was started, the equivalent Python SDK didn't exist. It does now: Microsoft shipped microsoft-teams-apps as GA on May 1, 2026 (announcement), with the same ctx.stream.emit(text) primitive upstream uses in TS:
Migrate chat_sdk/adapters/teams off our hand-rolled Bot Framework REST loop and onto microsoft-teams-apps. After migration, we no longer own the streaming wire format, the throttle gate, or the activity-routing layer — all delegated to the SDK.
src/chat_sdk/adapters/teams/cards.py (~440 LOC — keep ours for the divider-rendering parity fix per UPSTREAM_SYNC.md row, or migrate if SDK behavior matches)
tests/test_teams_*.py (~4,800 LOC across 6 files — large reduction expected as wire-format assertions become SDK-internal)
docs/UPSTREAM_SYNC.md — rows 482, 488, 489, 490, 491, 492 reference the hand-rolled implementation; rewrite or delete each after migration
What changes structurally
Webhook entry: today we own HTTP + JWT verification (handle_webhook). With the SDK, we plug into App via HttpServerAdapter (FastAPI/Starlette/aiohttp wrapper).
Activity handlers (_handle_message_activity, _handle_message_action, _handle_adaptive_card_action, _handle_reaction_activity): receive ctx: ActivityContext[...] from the SDK instead of building Message + thread_id from raw activity dicts. Delegate into our Chat.process_* from the SDK callbacks.
Streaming (_stream_via_emit, _close_stream_session, _active_streams, _TeamsStreamSession): delete entirely (~150 lines + supporting class). Replace with ctx.stream.emit(chunk) inside the message handler. Cumulative-text snapshot + throttle gate become SDK-internal.
Send/edit/delete/reactions/typing (post_message, edit_message, delete_message, add_reaction, remove_reaction, start_typing): replace _teams_send HTTP loop with ctx.send() + app.send(conversation_id, activity) for proactive messages.
Optional dep: chat-sdk-python[teams] switches from aiohttp>=3.9 (hand-rolled HTTP) to microsoft-teams-apps.
Required prerequisites
Python version floor bump: microsoft-teams-apps requires Python >=3.12. Our current floor is 3.10. Need to bump pyproject and update python_requires / CI matrix. Coordinate timing with downstream consumers.
Audit microsoft-teams-apps API stability: GA on 2026-05-01 — confirm semver guarantees and that there's no breaking churn expected in 2.x.
Validate against an integration test: stand up a real Teams bot using the SDK + chat-sdk-python to confirm the streaming UX and webhook routing work end-to-end before deleting our HTTP layer.
Out of scope for 4.27
Per discussion on PR #88, this migration is too large to land inside the 4.27 sync cycle (4-6 focused days; would block waves 2 & 3; SDK is only 2 weeks GA so carries early-adopter risk).
For 4.27 we landed the bounded P1 fixes (PR #88, commit b29efe0):
streamId placement on the streaminfo entity (Bot Framework REST contract)
1 req/sec emit throttle with native_stream_min_emit_interval_ms config + StreamOptions.update_interval_ms override
Re-raise on send failure so Thread.stream history matches user-visible text
This issue tracks the broader migration as the headline feature for 0.4.28 (or a 0.4.27.x point release if SDK adoption goes faster than expected).
Acceptance criteria
src/chat_sdk/adapters/teams/adapter.py no longer imports aiohttp for Bot Framework REST calls; all webhook + send/edit/stream paths go through microsoft-teams-apps
All wire-format-specific tests removed (TestNativeStreamingWireFormat, TestNativeStreamingThrottle, TestStreamInfoEntityContract) — the SDK owns these contracts
Background
PR #88 lands native Teams DM streaming as a hand-rolled implementation of the Bot Framework REST streaming wire format (
channelData.streamType,streamSequence,streamId,streaminfoentity, 1 req/sec throttle). Upstreamvercel/chat#416(in chat@4.27.0) achieves the same UX by delegating toIStreamer.emit()from@microsoft/teams.apps— an SDK that handled the wire format and throttling under the hood.When PR #88 was started, the equivalent Python SDK didn't exist. It does now: Microsoft shipped
microsoft-teams-appsas GA on May 1, 2026 (announcement), with the samectx.stream.emit(text)primitive upstream uses in TS:Goal
Migrate
chat_sdk/adapters/teamsoff our hand-rolled Bot Framework REST loop and ontomicrosoft-teams-apps. After migration, we no longer own the streaming wire format, the throttle gate, or the activity-routing layer — all delegated to the SDK.Scope
src/chat_sdk/adapters/teams/adapter.py(~2,300 LOC)src/chat_sdk/adapters/teams/cards.py(~440 LOC — keep ours for the divider-rendering parity fix per UPSTREAM_SYNC.md row, or migrate if SDK behavior matches)tests/test_teams_*.py(~4,800 LOC across 6 files — large reduction expected as wire-format assertions become SDK-internal)docs/UPSTREAM_SYNC.md— rows 482, 488, 489, 490, 491, 492 reference the hand-rolled implementation; rewrite or delete each after migrationWhat changes structurally
handle_webhook). With the SDK, we plug intoAppviaHttpServerAdapter(FastAPI/Starlette/aiohttp wrapper)._handle_message_activity,_handle_message_action,_handle_adaptive_card_action,_handle_reaction_activity): receivectx: ActivityContext[...]from the SDK instead of building Message + thread_id from raw activity dicts. Delegate into ourChat.process_*from the SDK callbacks._stream_via_emit,_close_stream_session,_active_streams,_TeamsStreamSession): delete entirely (~150 lines + supporting class). Replace withctx.stream.emit(chunk)inside the message handler. Cumulative-text snapshot + throttle gate become SDK-internal.post_message,edit_message,delete_message,add_reaction,remove_reaction,start_typing): replace_teams_sendHTTP loop withctx.send()+app.send(conversation_id, activity)for proactive messages.chat-sdk-python[teams]switches fromaiohttp>=3.9(hand-rolled HTTP) tomicrosoft-teams-apps.Required prerequisites
microsoft-teams-appsrequires Python >=3.12. Our current floor is 3.10. Need to bump pyproject and updatepython_requires/ CI matrix. Coordinate timing with downstream consumers.microsoft-teams-appsAPI stability: GA on 2026-05-01 — confirm semver guarantees and that there's no breaking churn expected in 2.x.Out of scope for 4.27
Per discussion on PR #88, this migration is too large to land inside the 4.27 sync cycle (4-6 focused days; would block waves 2 & 3; SDK is only 2 weeks GA so carries early-adopter risk).
For 4.27 we landed the bounded P1 fixes (PR #88, commit b29efe0):
streamIdplacement on thestreaminfoentity (Bot Framework REST contract)native_stream_min_emit_interval_msconfig +StreamOptions.update_interval_msoverrideThread.streamhistory matches user-visible textThis issue tracks the broader migration as the headline feature for 0.4.28 (or a 0.4.27.x point release if SDK adoption goes faster than expected).
Acceptance criteria
src/chat_sdk/adapters/teams/adapter.pyno longer importsaiohttpfor Bot Framework REST calls; all webhook + send/edit/stream paths go throughmicrosoft-teams-apps_stream_via_emit,_close_stream_session,_active_streams,_TeamsStreamSessiondeletedTestNativeStreamingWireFormat,TestNativeStreamingThrottle,TestStreamInfoEntityContract) — the SDK owns these contractsUPSTREAM_SYNC.mdrows 482, 488, 489, 490, 491, 492 rewritten or deletedchat-sdk-python[teams]extras switched fromaiohttptomicrosoft-teams-appspyproject.toml, CI matrix, READMEReferences
microsoft-teams-appson PyPImicrosoft/teams.pyGitHubed46bae(vercel/chat#416) — the TS port we're aligning with