Skip to content

Conversation

@eavanvalkenburg
Copy link
Member

Summary

This PR addresses all type-related sub-issues from the Python Single Agent API Review (#3575).

Changes

Replace Role and FinishReason with NewType + Literal

  • Removed EnumLike metaclass
  • Replaced Role and FinishReason classes with NewType + Literal
  • Type hints use RoleLiteral | str for IDE autocomplete while accepting custom values

Simplify ChatResponse/AgentResponse type hints

  • Changed messages parameter to accept ChatMessage | Sequence[ChatMessage] | None
  • Removed text parameter and **kwargs from __init__

Remove text parameter from ChatResponseUpdate/AgentResponseUpdate

  • Removed text parameter (use contents=[Content.from_text(...)] instead)
  • Removed **kwargs from both classes

Rename from_chat_response_updates

  • from_chat_response_updatesfrom_updates on ChatResponse
  • from_chat_response_generatorfrom_update_generator on ChatResponse
  • from_agent_run_response_updatesfrom_updates on AgentResponse

Remove try_parse_value method

  • Removed from ChatResponse and AgentResponse
  • Users should use try/except with .value property instead

Documentation clarification

  • Added agent_id parameter to AgentResponse and AgentResponseUpdate
  • Documented that author_name is on ChatMessage objects, not responses

Simplify ChatMessage.init signature

  • Made contents a positional argument: ChatMessage("role", ["text"])
  • Auto-convert strings in contents to TextContent
  • Kept text kwarg for backward compatibility with serialization

Allow Content as input on run/get_response

  • Updated prepare_messages and normalize_messages to accept Content
  • Updated type signatures in agents and clients

Breaking Changes

  • Role and FinishReason are now NewType instead of classes (no .value access)
  • ChatMessage signature changed: use ChatMessage("role", ["text"]) instead of ChatMessage(role="role", text="text")
  • try_parse_value removed - use try/except with .value property
  • text parameter removed from ChatResponseUpdate and AgentResponseUpdate
  • Method renames: from_chat_response_updatesfrom_updates, etc.

Closes

Closes #3591
Closes #3592
Closes #3593
Closes #3595
Closes #3596
Closes #3597
Closes #3615
Closes #3618

Testing

  • All 1639 tests pass
  • Linting: All checks passed
  • Type checking: 0 errors, 0 warnings

@eavanvalkenburg eavanvalkenburg requested a review from a team as a code owner February 3, 2026 16:05
Copilot AI review requested due to automatic review settings February 3, 2026 16:05
@markwallace-microsoft markwallace-microsoft added python lab Agent Framework Lab labels Feb 3, 2026
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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@markwallace-microsoft markwallace-microsoft added the documentation Improvements or additions to documentation label Feb 3, 2026
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Feb 3, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/a2a/agent_framework_a2a
   _agent.py139794%351–352, 389–390, 419–421
packages/ag-ui/agent_framework_ag_ui
   _client.py1371092%84–88, 234, 264, 419–421
   _event_converters.py690100% 
   _message_adapters.py4428979%64, 74–75, 84–87, 116–117, 120, 124–126, 135–137, 146–157, 159–161, 191, 204–205, 215–216, 253, 256, 258, 261, 264, 280, 297, 319, 350, 355, 366–367, 418, 434–435, 495–498, 500, 506, 514–515, 517, 521–524, 537, 626–629, 631, 696, 731–733, 735–738, 741–742, 744, 750, 753, 755, 758, 760, 766–767, 769
   _run.py43212171%151–158, 301, 320–321, 336–337, 348, 351–352, 354–355, 357–359, 369, 379–382, 386–388, 390, 400, 403–406, 408–409, 412–418, 421–423, 426, 442–444, 451, 457–458, 460–461, 475–481, 492, 505, 507–508, 542–543, 595–597, 609–611, 635, 640–642, 758, 769–770, 777, 824–826, 841, 847, 855, 857, 893–899, 902–905, 907–916, 919, 926–927, 932, 938–940, 953–955
   _utils.py101397%72, 257, 262
packages/anthropic/agent_framework_anthropic
   _chat_client.py36215058%365, 388, 390, 405, 427–430, 439, 441, 472–476, 478, 480–481, 483, 488–489, 491, 524–525, 534, 536–537, 542, 559–560, 602, 617, 621–622, 638, 647, 649, 653–654, 697–699, 701, 714–715, 722–724, 728–730, 734–737, 748, 750, 772, 782, 804–810, 817–818, 826–827, 835–838, 845–846, 852–853, 859–860, 866, 874–876, 880, 887–888, 894–895, 901–902, 908, 916–919, 926–927, 946, 953–954, 973, 995, 997, 1006–1007, 1013, 1035–1036, 1042–1043, 1052–1062, 1069–1075, 1082–1088, 1095–1104, 1111–1114
packages/azure-ai/agent_framework_azure_ai
   _chat_client.py4806786%376, 637–638, 640, 643, 646, 649–654, 657, 659, 667, 679–681, 685, 688–689, 697–700, 710, 718–721, 723–724, 726–727, 734, 742–743, 751–752, 757–758, 762–769, 774, 777, 785, 791, 799–801, 804, 826–827, 960, 988, 1003, 1124, 1150, 1159, 1168, 1301
   _client.py1951393%345, 347, 396, 425–430, 473, 510, 512, 588
packages/chatkit/agent_framework_chatkit
   _converter.py1334665%115, 120, 168, 170, 340, 393, 395, 414–416, 418, 436, 438, 440, 443, 455, 465, 483, 503–527, 529–531
packages/copilotstudio/agent_framework_copilotstudio
   _agent.py75494%153–154, 189, 197
packages/core/agent_framework
   _agents.py3104087%456, 855, 858–860, 985–987, 992–994, 1093, 1134, 1136, 1145–1150, 1156, 1158, 1168–1169, 1176, 1178–1179, 1187–1191, 1199–1200, 1202, 1207, 1209, 1243, 1283, 1303
   _clients.py57492%286, 330, 478, 480
   _mcp.py3885386%111, 173, 182, 245, 253, 274, 364, 431, 466, 468, 472–473, 475–476, 530, 545, 563, 604, 710, 723–728, 750, 771, 774–776, 791–792, 798–800, 819, 828, 831–833, 848–849, 853–857, 874–878, 1018
   _middleware.py404798%810, 826, 873–874, 1079–1080, 1125
   _serialization.py105496%516, 532, 542, 610
   _threads.py136397%343, 474–475
   _tools.py7677690%226, 272, 323, 325, 353, 523, 558–559, 661, 663, 683, 701, 715, 727, 732, 734, 741, 774, 845–847, 888, 913–922, 928–937, 973, 981, 1222, 1559, 1646–1650, 1672–1673, 1789, 1791, 1856, 1948, 1954, 1995–1996, 2009–2010, 2053, 2137, 2175–2176, 2214–2216, 2254–2255, 2265, 2322–2323, 2330–2331
   _types.py8773496%88, 262, 292, 296, 1162, 1182–1183, 1185, 1193, 1230, 1242, 1282, 1621, 1720–1725, 1747, 1881, 1893, 2129, 2138, 2256, 2477, 2762–2764, 2854, 2865–2866, 2872–2873
   observability.py6267687%323, 325–327, 330–332, 337–338, 344–345, 351–352, 359, 361–363, 366–368, 373–374, 380–381, 387–388, 395, 651, 654, 662–663, 666–669, 671, 674–676, 679–680, 708, 710, 721–723, 725–728, 732, 740, 841, 843, 992, 994, 998–1003, 1005, 1008–1012, 1014, 1289, 1614, 1617, 1676, 1850, 2004, 2006
packages/core/agent_framework/_workflows
   _agent.py2804583%61, 69–75, 103–104, 260, 316, 330, 343, 392–395, 401, 407, 411–412, 415–421, 425–426, 495, 502, 508–509, 520, 552, 559, 580, 589, 593, 595–597, 604
   _agent_executor.py1712386%95, 117, 151, 167–168, 219–220, 222–223, 255–257, 265–267, 277–279, 281, 285, 289, 293–294
   _base_group_chat_orchestrator.py1701292%135, 301, 316, 350–352, 356, 375, 436, 480–482
   _concurrent.py1872885%53, 62–63, 71–72, 91–92, 97, 124, 129, 134–135, 141, 163, 173, 180, 347, 350, 378, 434, 446, 485, 487–488, 490, 495, 517, 521
   _conversation_state.py36586%40, 45, 47, 49, 64
   _group_chat.py2853787%172, 333, 340, 367, 378–379, 385, 390, 406, 433–438, 440, 473–476, 478, 483–487, 648, 653, 667, 748, 754, 799, 819, 915, 934, 953, 963
   _handoff.py3825785%110–111, 113, 142–143, 163–173, 175, 177, 179, 184, 284, 338, 363, 389, 397–398, 412, 461–462, 492, 539–541, 724, 731, 736, 823, 826, 835–838, 848, 853, 860, 866–869, 904, 909, 1106, 1109, 1117, 1135, 1142, 1217
   _magentic.py6149185%68–77, 82, 86–97, 262, 273, 277, 297, 358, 367, 369, 411, 428, 437–438, 440–442, 444, 455, 597, 599, 639, 689, 725–727, 729, 737–740, 744–747, 790, 817–820, 911, 917, 923, 962, 1000, 1029, 1046, 1057, 1111–1112, 1116–1118, 1142, 1163–1164, 1177, 1193, 1215, 1263–1264, 1302–1303, 1459, 1468, 1471, 1476, 1872, 1914, 1929, 1958
   _message_utils.py18383%22, 33, 37
   _orchestration_request_info.py540100% 
   _orchestrator_helpers.py21290%90–91
   _workflow.py2481793%89, 259–261, 263–264, 282, 310, 411, 688, 722, 727, 730, 749–751, 816
packages/core/agent_framework/openai
   _assistants_client.py2742989%347, 361, 364, 366–367, 370, 373, 376–377, 388, 413, 415, 417, 419, 421, 426, 429, 432, 436, 447, 532, 617, 652, 689–692, 744, 761
   _chat_client.py2682192%181–182, 186, 272, 279, 360–367, 369–372, 382, 467, 504, 520
   _responses_client.py5626488%257, 262, 264–265, 276, 294, 302, 325, 387, 419, 444, 450, 468–469, 491, 496, 552, 566, 583, 596, 651, 730, 735, 739–741, 745–746, 769, 838, 860–861, 876–877, 895–896, 1027–1028, 1044, 1046, 1121–1129, 1177, 1232, 1247, 1283–1284, 1286–1288, 1302–1304, 1314–1315, 1321, 1336
packages/mem0/agent_framework_mem0
   _provider.py83396%170–171, 174
packages/purview/agent_framework_purview
   _middleware.py930100% 
packages/redis/agent_framework_redis
   _chat_message_store.py1491490%199, 232, 322–323, 326, 329, 485, 575–579, 588, 592
   _provider.py188995%255, 257, 265, 270–271, 274, 329, 386, 398
TOTAL16255191888% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
3929 221 💤 0 ❌ 0 🔥 1m 7s ⏱️

@eavanvalkenburg eavanvalkenburg changed the title Python: Types API Review improvements Python: [BREAKING] Types API Review improvements Feb 4, 2026
- Remove EnumLike metaclass from _types.py
- Replace Role class with NewType('Role', str) + RoleLiteral
- Replace FinishReason class with NewType('FinishReason', str) + FinishReasonLiteral
- Update all usages across codebase to use string literals
- Remove .value access patterns (direct string comparison now works)
- Add backward compatibility for legacy dict serialization format
- Update tests to reflect new string-based types

Addresses microsoft#3591, microsoft#3615
- Remove overloads from ChatResponse.__init__
- Remove text parameter from ChatResponse.__init__
- Remove | dict[str, Any] from finish_reason and usage_details params
- Remove **kwargs from AgentResponse.__init__
- Both now accept ChatMessage | Sequence[ChatMessage] | None for messages
- Update docstrings and examples to reflect changes
- Fix tests that were using removed kwargs
- Fix Role type hint usage in ag-ui utils
…microsoft#3597)

- Remove text parameter from ChatResponseUpdate.__init__
- Remove text parameter from AgentResponseUpdate.__init__
- Remove **kwargs from both update classes
- Simplify contents parameter type to Sequence[Content] | None
- Update all usages to use contents=[Content.from_text(...)] pattern
- Fix imports in test files
- Update docstrings and examples
- ChatResponse.from_chat_response_updates → ChatResponse.from_updates
- ChatResponse.from_chat_response_generator → ChatResponse.from_update_generator
- AgentResponse.from_agent_run_response_updates → AgentResponse.from_updates
…crosoft#3595)

- Remove try_parse_value method from ChatResponse
- Remove try_parse_value method from AgentResponse
- Remove try_parse_value calls from from_updates and from_update_generator methods
- Update samples to use try/except with response.value instead
- Update tests to use response.value pattern
- Users should now use response.value with try/except for safe parsing
…icrosoft#3596)

- Add agent_id parameter to AgentResponse class
- Document that author_name is on ChatMessage objects, not responses
- Update ChatResponse docstring with author_name note
- Update AgentResponse docstring with author_name note
- Make contents a positional argument accepting Sequence[Content | str]
- Auto-convert strings in contents to TextContent
- Remove overloads, keep text kwarg for backward compatibility with serialization
- Update _parse_content_list to handle string items
- Update all usages across codebase to use new format: ChatMessage("role", ["text"])
- Update prepare_messages and normalize_messages to accept Content
- Update type signatures in _agents.py and _clients.py
- Add tests for Content input handling
Update all remaining ChatMessage(role=..., text=...) to use new
ChatMessage('role', ['text']) signature.
- Fix redis provider: remove .value access on string literals
- Fix durabletask ensure_response_format: set _response_format before accessing .value
- Fix ollama _chat_client: remove .value on string literals
- Fix ollama _chat_client: rename ai_model_id to model_id
- Fix _parse_content_list: skip None values gracefully
@eavanvalkenburg eavanvalkenburg added this pull request to the merge queue Feb 4, 2026
Merged via the queue into microsoft:main with commit 838a7fd Feb 4, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment