Skip to content

Python: [BREAKING] Fix #3613 chat/agent message typing alignment#3920

Open
eavanvalkenburg wants to merge 10 commits intomicrosoft:mainfrom
eavanvalkenburg:fix-3613-chatclient-message-types
Open

Python: [BREAKING] Fix #3613 chat/agent message typing alignment#3920
eavanvalkenburg wants to merge 10 commits intomicrosoft:mainfrom
eavanvalkenburg:fix-3613-chatclient-message-types

Conversation

@eavanvalkenburg
Copy link
Member

@eavanvalkenburg eavanvalkenburg commented Feb 13, 2026

Summary

  • [BREAKING] update chat client get_response contracts to accept only Sequence[Message]
  • remove chat-side message normalization and keep message normalization at agent run
  • expand agent run inputs to str | Content | Message | Sequence[str | Content | Message] | None
  • align dependent implementations (a2a, claude, github_copilot, copilotstudio, durabletask), existing tests, and AG-UI getting-started samples

Closes #3613

Copilot AI review requested due to automatic review settings February 13, 2026 12:56
@eavanvalkenburg eavanvalkenburg requested a review from a team as a code owner February 13, 2026 12:56
@github-actions github-actions bot changed the title Fix #3613 chat/agent message typing alignment Python: Fix #3613 chat/agent message typing alignment Feb 13, 2026
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Feb 13, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/a2a/agent_framework_a2a
   _agent.py170994%358, 379, 452–453, 494–495, 524–526
packages/ag-ui/agent_framework_ag_ui
   _client.py1491788%85–86, 90–94, 98–102, 265, 293, 460–462
packages/anthropic/agent_framework_anthropic
   _chat_client.py36414859%422, 451, 483, 485, 500, 522–525, 534, 536, 573–577, 579, 581–582, 584, 589–590, 592, 625–626, 635, 637–638, 643, 660–661, 705, 728, 737, 739, 743–744, 787–789, 791, 804–805, 812–814, 818–820, 824–827, 838, 840, 862, 872, 894–900, 907–908, 916–917, 925–928, 935–936, 942–943, 949–950, 956, 964–966, 970, 977–978, 984–985, 991–992, 998, 1006–1009, 1016–1017, 1036, 1043–1044, 1063, 1085, 1087, 1096–1097, 1103, 1125–1126, 1132–1133, 1142–1152, 1159–1165, 1172–1178, 1185–1194, 1201–1204
packages/azure-ai-search/agent_framework_azure_ai_search
   _context_provider.py26513150%103–104, 224, 226, 230, 257–258, 260, 269–270, 273–274, 290, 300, 341–342, 355, 363–368, 371–373, 380–382, 387–390, 392–397, 399–405, 409, 413–418, 422, 424, 427–428, 430, 438–440, 443–445, 451, 453–455, 458, 471–472, 474–475, 477, 479–481, 487–488, 490–497, 499–503, 510, 512, 519, 524, 529, 531, 539–540, 542–543, 552, 554, 559, 561, 567–570, 577, 585, 592–594, 596–604, 606, 616–620, 623
packages/azure-ai/agent_framework_azure_ai
   _chat_client.py4777584%387–388, 390, 573, 578–579, 581–582, 585, 588, 590, 595, 856–857, 859, 862, 865, 868–873, 876, 878, 886, 898–900, 904, 907–908, 916–919, 929, 937–940, 942–943, 945–946, 953, 961–962, 970–971, 976–977, 981–988, 993, 996, 1004, 1010, 1018–1020, 1023, 1045–1046, 1179, 1207, 1222, 1338, 1464
   _client.py2132289%372, 374, 423, 452–457, 500, 535, 537, 570, 778, 781, 784–785, 787–790, 837
   _project_provider.py115496%212, 310, 354, 387
   _shared.py2331792%110, 140, 224, 267, 279–281, 310, 312, 314, 318, 383, 414, 455, 462, 474, 493
packages/azurefunctions/agent_framework_azurefunctions
   _app.py3706981%323–324, 432, 440–441, 461–463, 469–471, 477–479, 512–513, 573–574, 623–624, 629, 711, 714, 723–725, 727–729, 731, 733, 744, 746–749, 751, 753–754, 756, 763–764, 766–767, 769–770, 772, 776, 786–788, 790–791, 793–795, 802, 804–805, 807, 828, 833, 845, 998, 1013–1016, 1041
   _entities.py590100% 
   _orchestration.py610100% 
packages/copilotstudio/agent_framework_copilotstudio
   _agent.py80396%170, 178, 295
packages/core/agent_framework
   _agents.py3113987%474, 874, 910, 987–990, 1054–1056, 1170, 1183, 1196, 1202, 1238, 1240, 1249–1254, 1260, 1262, 1272–1273, 1280, 1282–1283, 1291–1295, 1303–1304, 1306, 1311, 1313
   _clients.py71395%296, 493, 495
   _mcp.py4056484%98–99, 109–114, 125, 130, 176–177, 187–192, 202–203, 255, 264, 327, 335, 356, 470, 537, 572, 574, 578–579, 581–582, 636, 651, 669, 710, 816, 829–834, 856, 902–903, 909–911, 930, 955–956, 960–964, 981–985, 1129
   _middleware.py3281695%60, 63, 68, 775, 777, 779, 900, 927, 929, 954, 1035, 1039, 1163, 1167, 1228, 1302
   _serialization.py106595%290, 494, 510, 520, 588
   _sessions.py1671690%67–69, 71–74, 91–92, 94–98, 539, 553
   _settings.py1061189%92, 99, 115, 126, 142–143, 145, 148, 244–245, 250
   _telemetry.py19194%59
   _tools.py7538488%165–166, 296, 298, 316–318, 325, 343, 357, 369, 374, 376, 383, 420, 443–445, 494–496, 559, 581, 605–631, 666, 674, 915, 1177, 1234, 1238, 1317–1321, 1339, 1341–1342, 1454, 1458, 1508, 1510, 1526, 1528, 1592, 1619, 1676, 1744, 1922–1923, 1950, 1958, 1971, 1981–1982, 2017, 2073, 2105
   _types.py10279690%48, 57–58, 112, 117, 136, 138, 142, 146, 148, 150, 152, 170, 174, 200, 222, 227, 232, 236, 262, 266, 612–613, 984, 1046, 1063, 1081, 1086, 1104, 1114, 1131–1132, 1134, 1152–1153, 1155, 1162–1163, 1165, 1200, 1211–1212, 1214, 1252, 1479, 1536, 1538, 1543, 1571, 1619, 1662–1667, 1689, 1694, 1860, 1872, 2115, 2124, 2145, 2240, 2465, 2672, 2742, 2754, 2761, 2772, 2976–2978, 2981–2983, 2987, 2992, 2996, 3108–3110, 3138, 3192, 3196–3198, 3200, 3211–3212, 3215–3219, 3225
   observability.py6178486%336, 338–340, 343–345, 350–351, 357–358, 364–365, 372, 374–376, 379–381, 386–387, 393–394, 400–401, 408, 677, 680, 688–689, 692–695, 697, 700–702, 705–706, 734, 736, 747–749, 751–754, 758, 766, 867, 869, 1018, 1020, 1024–1029, 1031, 1034–1038, 1040, 1152–1153, 1155, 1212–1213, 1348, 1402–1403, 1519–1521, 1580, 1750, 1904, 1906
packages/core/agent_framework/_workflows
   _agent.py3466880%67, 75–81, 117–118, 208, 252, 308, 354–355, 361–362, 368, 370, 375, 435–436, 445, 452, 478, 511–513, 515, 517, 519, 524, 529, 576, 606, 623, 662–665, 671, 677, 681–682, 685–691, 695–696, 702, 763, 770, 776–777, 788, 820, 827, 848, 857, 861, 863–865, 872
   _checkpoint_encoding.py50296%163–164
   _message_utils.py21576%21, 27, 35, 37, 41
packages/core/agent_framework/azure
   _assistants_client.py400100% 
   _chat_client.py78494%302, 304, 317–318
   _responses_client.py50688%187, 219, 285–288
packages/core/agent_framework/openai
   _assistant_provider.py108991%171, 296, 362, 477–482
   _assistants_client.py2733487%407, 409, 411, 414, 418–419, 422, 425, 430–431, 433, 436–438, 443, 454, 479, 481, 483, 485, 487, 492, 495, 498, 502, 513, 598, 683, 712, 749–752, 822
   _chat_client.py2682391%200, 230–231, 235, 349, 356, 437–444, 446–449, 459, 544, 579, 595, 635
   _exceptions.py330100% 
   _responses_client.py6127987%291–294, 298–299, 302–303, 309–310, 315, 328–334, 355, 363, 386, 549, 552, 607, 611, 613, 615, 617, 693, 703, 708, 751, 828, 845, 858, 914, 1007, 1012, 1016–1018, 1022–1023, 1046, 1115, 1137–1138, 1153–1154, 1172–1173, 1304–1305, 1321, 1323, 1402–1410, 1505, 1560, 1575, 1611–1612, 1614–1616, 1630–1632, 1642–1643, 1649, 1664
   _shared.py1271687%66, 72–75, 150, 152, 154, 161, 163, 176, 251, 275, 334–335, 337
packages/declarative/agent_framework_declarative
   _models.py4673692%16, 19, 51, 56, 225–232, 487, 528–531, 555, 563, 571, 579, 602, 628, 652, 680, 790, 852, 964, 1090, 1092, 1094, 1096, 1098, 1100, 1104, 1106
packages/declarative/agent_framework_declarative/_workflows
   _actions_agents.py31722927%57, 59–60, 62, 64–65, 68–71, 75, 79–81, 83–87, 91, 93–94, 96–106, 108–109, 112–117, 119–120, 122–124, 126–128, 130–132, 134–135, 137–141, 143–151, 153, 155, 158–159, 162, 184, 218, 220–222, 227–228, 242–243, 245, 271–272, 276–277, 287–306, 311, 316–319, 351, 354–355, 361–362, 365–367, 370, 377–378, 381–383, 385–386, 388–390, 395–397, 401, 404–405, 407, 435–436, 439–442, 447–449, 453, 457, 466–467, 469–471, 476–477, 479, 484, 486–487, 500, 506, 509–512, 527, 529–530, 532, 534, 550–557, 560–563, 566, 569, 572, 575–579, 581, 584–586, 588–589, 591, 594–595, 597–598, 600–601, 603–604, 610–612, 614, 616–617, 619–620, 622, 628, 630–632, 634, 636–637, 639–640, 642, 648, 650–652
   _actions_basic.py2419859%53–54, 77–78, 80–82, 85, 88, 90–91, 93, 109, 111, 113, 129–130, 162–164, 167–168, 183–184, 186–189, 207–208, 227–239, 241–242, 244–245, 266–267, 273, 303–304, 327–328, 417–418, 434, 464–466, 468–470, 473–474, 477, 479–480, 483–484, 487–488, 491–496, 498, 505, 520–522, 524–526, 529, 532–534, 537–538, 541–545, 547
   _actions_control_flow.py1685269%45–46, 52–53, 56–57, 72–78, 80–81, 83, 103–104, 122, 147–148, 171, 190–191, 203–210, 212, 215, 220–221, 234–235, 245–246, 277–278, 294, 302, 317, 319–321, 323, 326, 337, 392
   _actions_error.py52786%98, 107–109, 114, 123, 131
   _factory.py1376056%180, 257–258, 322–324, 332, 334, 337–343, 372, 383–384, 393, 428, 441, 466–469, 488–492, 495–496, 499, 502, 507, 616–617, 619–620, 622–624, 627, 641, 644–649, 652–653, 655, 658, 668–669, 671, 675–676, 678
   _handlers.py830100% 
   _human_input.py1241290%108–109, 117, 169–170, 175–176, 196–197, 218–219, 289
   _state.py30916446%22, 25, 141, 165, 179, 201–202, 204, 220, 228, 236, 242, 244, 254, 362, 375–376, 380, 398, 400, 403–406, 409–412, 415–417, 419–425, 428–432, 435–439, 442–458, 461–464, 466–469, 471–474, 476–479, 481–488, 491–494, 496–503, 506–509, 511–517, 519–523, 526–527, 530–535, 538–541, 544, 547–552, 555, 566–570, 572–589, 591, 593–594, 596
packages/purview/agent_framework_purview
   _client.py1200100% 
   _middleware.py1120100% 
   _models.py4579678%222–226, 308, 310, 332, 334, 338, 365, 369, 416–421, 424–431, 442–445, 456–459, 489–490, 493, 495, 497–499, 533, 535, 537, 539, 541, 543, 545, 550–552, 554, 557, 563, 566, 605, 607, 609, 611, 613, 621, 623, 625, 627, 661, 665, 700, 702, 704, 708, 714, 716, 738–739, 764, 766, 768, 772, 791–793, 798–799, 832, 834, 846, 909, 912–916, 918, 946, 977, 979
   _processor.py1711094%177, 257–260, 265, 293, 295, 301, 303
TOTAL20459321684% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
3941 225 💤 0 ❌ 0 🔥 1m 9s ⏱️

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aligns Python chat-client and agent message-input typing to resolve #3613: chat clients now accept Sequence[Message] only (removing chat-side normalization), while agents accept broader “run inputs” including Content (and nullable variants), with downstream implementations, tests, and samples updated accordingly.

Changes:

  • Updated chat client contracts and middleware layers to take messages: Sequence[Message] and removed implicit normalization.
  • Updated agent run() contracts to accept str | Content | Message | Sequence[str | Content | Message] | None.
  • Updated downstream agent packages plus tests/samples to match the new typing.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
python/packages/orchestrations/tests/test_magentic.py Updates agent run() typing in orchestrations tests to include Content.
python/packages/orchestrations/tests/test_group_chat.py Updates agent run() typing in group chat tests to include Content.
python/packages/github_copilot/agent_framework_github_copilot/_agent.py Aligns GitHub Copilot agent run() overloads/impl typing with new agent message union.
python/packages/durabletask/agent_framework_durabletask/_shim.py Updates DurableTask shim run() typing and switches to normalize_messages() for string conversion.
python/packages/core/tests/workflow/test_workflow_kwargs.py Updates workflow test agents’ run() message typing to include Content.
python/packages/core/tests/workflow/test_workflow.py Updates workflow test agent run() message typing to include Content.
python/packages/core/tests/workflow/test_full_conversation.py Updates workflow test agent run() message typing to include Content.
python/packages/core/tests/workflow/test_agent_executor_tool_calls.py Updates executor test agent run() message typing to include Content.
python/packages/core/tests/core/test_function_invocation_logic.py Updates chat client calls to pass Sequence[Message] instead of str.
python/packages/core/tests/core/test_clients.py Updates core client tests to pass Sequence[Message] consistently (streaming and non-streaming).
python/packages/core/tests/core/test_agents.py Adds coverage for agent.run(Content.from_text(...)).
python/packages/core/agent_framework/observability.py Aligns telemetry-layer chat contract to Sequence[Message] and agent contract to new union.
python/packages/core/agent_framework/_workflows/_message_utils.py Extends workflow normalization helper to support Content inputs.
python/packages/core/agent_framework/_workflows/_agent.py Updates workflow agent run() typing to support Content and mixed input sequences.
python/packages/core/agent_framework/_tools.py Updates function-invocation layer to accept Sequence[Message] and removes message prepping.
python/packages/core/agent_framework/_middleware.py Updates middleware-layer chat contract to Sequence[Message] and adjusts context creation.
python/packages/core/agent_framework/_clients.py Updates core chat client protocol/base signatures and examples to require Sequence[Message].
python/packages/core/agent_framework/_agents.py Updates agent contracts to accept Content and mixed sequences for run().
python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py Aligns Copilot Studio agent run() typing with new agent message union.
python/packages/claude/agent_framework_claude/_agent.py Aligns Claude agent run() typing with new agent message union.
python/packages/ag-ui/tests/ag_ui/conftest.py Updates AG-UI test stubs’ typing to include Content.
python/packages/ag-ui/getting_started/client_advanced.py Updates sample usage to pass Sequence[Message] into get_response().
python/packages/ag-ui/getting_started/client.py Updates sample usage to pass Sequence[Message] into get_response().
python/packages/a2a/agent_framework_a2a/_agent.py Aligns A2A agent run() typing with new agent message union.
Comments suppressed due to low confidence (1)

python/packages/ag-ui/tests/ag_ui/conftest.py:103

  • StreamingChatClientStub.get_response is typed to accept str | Content | Message | Sequence[str | Content | Message], but it forwards messages directly to BaseChatClient.get_response, which now requires Sequence[Message] and no longer normalizes inputs. This makes the stub’s signature misleading and will raise at runtime if tests (or future callers) pass a str/Content/Message or Sequence[str|Content]. Either narrow the stub’s messages parameter to Sequence[Message] (matching the new contract) or normalize to Sequence[Message] before calling super().get_response.
    def get_response(
        self,
        messages: str | Content | Message | Sequence[str | Content | Message],
        *,
        stream: bool = False,
        options: OptionsCoT | ChatOptions[Any] | None = None,
        **kwargs: Any,
    ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]:
        self.last_session = kwargs.get("session")
        self.last_service_session_id = self.last_session.service_session_id if self.last_session else None
        return cast(
            Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]],
            super().get_response(
                messages=messages,
                stream=cast(Literal[True, False], stream),
                options=options,
                **kwargs,
            ),
        )

@eavanvalkenburg eavanvalkenburg changed the title Python: Fix #3613 chat/agent message typing alignment [BREAKING] Fix #3613 chat/agent message typing alignment Feb 13, 2026
@eavanvalkenburg eavanvalkenburg changed the title [BREAKING] Fix #3613 chat/agent message typing alignment Python: [BREAKING] Fix #3613 chat/agent message typing alignment Feb 13, 2026
@eavanvalkenburg eavanvalkenburg force-pushed the fix-3613-chatclient-message-types branch from 42aa185 to 8ba0f2f Compare February 13, 2026 14:28
@eavanvalkenburg eavanvalkenburg force-pushed the fix-3613-chatclient-message-types branch from 14469dc to 838571a Compare February 13, 2026 15:21
@markwallace-microsoft markwallace-microsoft added the documentation Improvements or additions to documentation label Feb 13, 2026
from agent_framework._logging import get_logger

logger = get_logger()
logger = logging.getLogger("agent_framework.ag_ui")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to create the logger again?

Comment on lines +1505 to +1506
AgentRunInputs = str | Content | Message | Sequence[str | Content | Message]
AgentRunInputsOrNone = AgentRunInputs | None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really isn't saving much. I wonder if we should just make people do AgentRunInputs | None to make thing more obvious

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot i like this can you replace the current alias with ...None for | None

Co-authored-by: Tao Chen <taochen@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: clients: ChatClientProtocol.get_response messages parameter type

3 participants