Skip to content

Python: [BREAKING] Redesign Python exception hierarchy - #4082

Merged
Eduard van Valkenburg (eavanvalkenburg) merged 3 commits into
microsoft:mainfrom
eavanvalkenburg:eavanvalkenburg/exception-hierarchy-redesign
Feb 19, 2026
Merged

Eduard van Valkenburg (eavanvalkenburg) merged 3 commits into
microsoft:mainfrom
eavanvalkenburg:eavanvalkenburg/exception-hierarchy-redesign

Conversation

@eavanvalkenburg

Copy link
Copy Markdown
Member

Summary

Replaces the flat ServiceException family with domain-scoped exception branches, giving callers precise except targets and clear error semantics.

Fixes #3410

New Hierarchy

AgentFrameworkException
├── AgentException
│   ├── AgentInvalidAuthException
│   ├── AgentInvalidRequestException
│   ├── AgentInvalidResponseException
│   ├── AgentContentFilterException
│   └── DeclarativeLoaderError → ProviderLookupError
├── ChatClientException
│   ├── ChatClientInvalidAuthException
│   ├── ChatClientInvalidRequestException
│   ├── ChatClientInvalidResponseException
│   └── ChatClientContentFilterException
├── IntegrationException
│   ├── IntegrationInitializationError
│   ├── IntegrationInvalidAuthException
│   ├── IntegrationInvalidRequestException
│   ├── IntegrationInvalidResponseException
│   └── IntegrationContentFilterException
├── ContentError
│   └── AdditionItemMismatch
├── WorkflowException
│   ├── WorkflowRunnerException
│   │   ├── WorkflowConvergenceException
│   │   └── WorkflowCheckpointException
│   ├── WorkflowValidationError (+ Edge/Type/Graph suberrors)
│   ├── WorkflowActionError
│   └── DeclarativeWorkflowError
├── ToolException → ToolExecutionException
├── MiddlewareException → MiddlewareTermination
└── SettingNotFoundError

Breaking Changes

  • Removed: ServiceException, ServiceInitializationError, ServiceResponseException, ServiceContentFilterException, ServiceInvalidAuthError, ServiceInvalidExecutionSettingsError, ServiceInvalidRequestError, ServiceInvalidResponseError
  • Removed: AgentExecutionException (split → AgentInvalidRequestException / AgentInvalidResponseException)
  • Removed: AgentInvocationError (split → AgentInvalidRequestException / AgentInvalidResponseException)
  • Removed: AgentInitializationError, AgentSessionException, ChatClientInitializationError (0 callsites)
  • Removed: CheckpointDecodingError (merged → WorkflowCheckpointException)
  • Re-parented: Purview exceptions under IntegrationException hierarchy
  • Re-parented: Workflow exceptions under WorkflowException (moved from _workflows/_exceptions.py to exceptions.py)
  • Changed: Init validation errors now use built-in ValueError/TypeError instead of custom exceptions

Design Principles

  1. Domain-scoped branches: Agent, ChatClient, Integration, Content, Workflow, Tool, Middleware
  2. Consistent suberror pattern: InvalidAuth, InvalidRequest, InvalidResponse, ContentFilter across Agent/ChatClient/Integration
  3. Built-ins for validation: ValueError/TypeError for config checks; AF exceptions only for domain-level failures
  4. Catch-all still works: except AgentFrameworkException catches everything

Other Changes

  • _workflows/__init__.py emptied; main __init__.py imports directly from submodules
  • CODING_STANDARD.md updated with hierarchy design, rationale, and branch selection guide
  • 87 files changed across all packages (production + tests)
  • All 3729 tests pass, all 66 lint+pyright tasks pass

Copilot AI review requested due to automatic review settings February 19, 2026 12:38
@markwallace-microsoft Mark Wallace (markwallace-microsoft) added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Feb 19, 2026
@github-actions github-actions Bot changed the title [BREAKING] Redesign Python exception hierarchy Python: [BREAKING] Redesign Python exception hierarchy Feb 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 implements a comprehensive redesign of the Python exception hierarchy to replace the flat ServiceException family with domain-scoped exception branches. This provides callers with precise exception targets and clear error semantics.

Changes:

  • Redesigned exception hierarchy with domain-specific branches (Agent, ChatClient, Integration, Workflow, Content, Tool, Middleware)
  • Removed old flat ServiceException family and replaced with semantically meaningful exceptions
  • Migrated initialization validation errors to use built-in Python exceptions (ValueError, TypeError, RuntimeError)
  • Consolidated workflow exceptions from _workflows/_exceptions.py into main exceptions.py
  • Updated comprehensive documentation in CODING_STANDARD.md with hierarchy diagrams, design principles, and usage guidance

Reviewed changes

Copilot reviewed 87 out of 87 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/packages/core/agent_framework/exceptions.py Complete redesign of exception hierarchy with 6 domain branches, each with consistent suberror patterns
python/CODING_STANDARD.md Comprehensive documentation of new hierarchy including design rationale, full tree diagram, and usage guide
python/packages/core/agent_framework/_workflows/_exceptions.py Deleted - workflow exceptions moved to main exceptions.py
python/packages/core/agent_framework/workflows/*.py Updated imports to use exceptions from main module instead of local _exceptions.py
python/packages/core/agent_framework/init.py Workflow imports changed from single _workflows import to individual submodule imports; workflow exceptions now exported from main exceptions module
python/packages/core/agent_framework/openai/* ServiceInitializationError → ValueError; ServiceInvalidRequestError → ChatClientInvalidRequestException; ServiceResponseException → ChatClientException
python/packages/core/agent_framework/azure/* Same pattern as OpenAI - init errors → ValueError, runtime errors → ChatClient* exceptions
python/packages/redis/agent_framework_redis/_context_provider.py ServiceInitializationError → ValueError; ServiceInvalidRequestError → IntegrationInvalidRequestException
python/packages/mem0/agent_framework_mem0/_context_provider.py ServiceInitializationError → ValueError for filter validation
python/packages/purview/agent_framework_purview/_exceptions.py PurviewServiceError now inherits from IntegrationException; PurviewAuthenticationError from IntegrationInvalidAuthException
python/packages/ollama/agent_framework_ollama/_chat_client.py ServiceInvalidRequestError → ChatClientInvalidRequestException; ServiceResponseException → ChatClientException
python/packages/foundry_local/agent_framework_foundry_local/_foundry_local_client.py ServiceInitializationError → ValueError for model validation
python/packages/declarative/agent_framework_declarative/_workflows/_executors_agents.py AgentInvocationError removed; replaced with AgentInvalidRequestException (not found) and AgentInvalidResponseException (invocation failure)
python/packages/declarative/agent_framework_declarative/_workflows/_factory.py DeclarativeWorkflowError now inherits from WorkflowException
python/packages/declarative/agent_framework_declarative/_workflows/_actions_error.py WorkflowActionError now inherits from WorkflowException
python/packages/declarative/agent_framework_declarative/_loader.py DeclarativeLoaderError now inherits from AgentException (was AgentFrameworkException)
python/packages/github_copilot/agent_framework_github_copilot/_agent.py ServiceException → AgentException; client not initialized → RuntimeError
python/packages/copilotstudio/agent_framework_copilotstudio/* ServiceException → AgentException; ServiceInitializationError → ValueError
python/packages/claude/agent_framework_claude/_agent.py ServiceException → AgentException; client not initialized → RuntimeError
python/packages/azure-ai/agent_framework_azure_ai/* ServiceInitializationError → ValueError; ServiceInvalidRequestError → IntegrationInvalidRequestException
python/packages/bedrock/agent_framework_bedrock/_chat_client.py ServiceInitializationError → ValueError; ServiceInvalidResponseError → ChatClientInvalidResponseException
python/packages/anthropic/agent_framework_anthropic/_chat_client.py ServiceInitializationError → ValueError for missing API key
All test files Updated to expect new exception types; ValueError for validation, domain-specific exceptions for runtime failures

@markwallace-microsoft

Mark Wallace (markwallace-microsoft) commented Feb 19, 2026 •

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/ag-ui/agent_framework_ag_ui
   _run.py51012375%156–163, 209–210, 217, 340, 359–360, 375–376, 391, 419–421, 446, 449–452, 454–455, 458–464, 467–469, 472, 488–490, 497, 503–505, 509, 514–516, 518–519, 535–539, 550, 562, 566, 568–569, 585, 612–613, 668–670, 682–684, 887, 898–899, 906, 955–957, 974, 980, 988, 990, 998, 1028–1034, 1037–1040, 1042–1051, 1054, 1062–1065, 1072, 1075–1076, 1081, 1087–1089, 1093, 1098–1101, 1115–1117
packages/anthropic/agent_framework_anthropic
   _chat_client.py3863690%457, 544, 546, 689–690, 753, 774–775, 818–820, 822, 835–836, 843–845, 849–851, 855–858, 971, 981, 1015, 1037, 1158, 1185–1186, 1203, 1216, 1229, 1254–1255
packages/azure-ai-search/agent_framework_azure_ai_search
   _context_provider.py266398%103–104, 273
packages/azure-ai/agent_framework_azure_ai
   _agent_provider.py109199%249
   _chat_client.py4787584%391–392, 394, 578, 583–584, 586–587, 590, 593, 595, 600, 861–862, 864, 867, 870, 873–878, 881, 883, 891, 903–905, 909, 912–913, 921–924, 934, 942–945, 947–948, 950–951, 958, 966–967, 975–976, 981–982, 986–993, 998, 1001, 1009, 1015, 1023–1025, 1028, 1050–1051, 1184, 1212, 1227, 1343, 1465
   _client.py2743786%379, 381, 424, 432–444, 457, 517, 532–537, 580, 615, 617, 650, 858, 861, 864–865, 867–870, 913
   _project_provider.py116496%209, 303, 343, 376
   _shared.py2332190%109, 139, 187, 189–191, 223, 266, 278–280, 309, 311, 313, 317, 382, 413, 454, 461, 473, 492
packages/azurefunctions/agent_framework_azurefunctions
   _app.py50017265%261–262, 265, 267–269, 275, 277–280, 282–283, 285–287, 291, 294, 296, 298–299, 302–304, 306, 308, 316, 324–327, 330, 333, 338–339, 342–345, 348, 351–353, 364–367, 373, 375, 383–384, 387, 392–393, 395–396, 398, 401, 404, 406, 408, 410–412, 416–419, 421, 423–424, 426, 437–439, 443–444, 446–447, 449, 460–465, 473, 475, 481–483, 489–490, 492–493, 495–498, 502, 508, 527, 626–627, 735, 743–744, 764–766, 772–774, 780–782, 815–816, 876–877, 926–927, 932, 1014, 1017, 1026–1028, 1030–1032, 1034, 1036, 1047, 1049–1052, 1054, 1056–1057, 1059, 1066–1067, 1069–1070, 1072–1073, 1075, 1079, 1089–1091, 1093–1094, 1096–1098, 1105, 1107–1108, 1110, 1131, 1136, 1148, 1220, 1310, 1325–1328, 1353
   _context.py66690%98, 102, 153–154, 162, 169
   _serialization.py431174%40–46, 114–115, 129–130
packages/copilotstudio/agent_framework_copilotstudio
   _acquire_token.py420100% 
   _agent.py80396%170, 178, 295
packages/core/agent_framework
   _agents.py3314486%425, 429, 481, 846, 882, 898, 969, 974–977, 1038–1040, 1161, 1177, 1179, 1192, 1198, 1234, 1236, 1245–1250, 1255, 1257, 1263–1264, 1271, 1273–1274, 1282–1283, 1286–1288, 1296–1297, 1299, 1304, 1306
   _settings.py1161388%92, 99, 115, 126, 142–143, 145, 148, 251–252, 260–261, 266
   exceptions.py620100% 
packages/core/agent_framework/_workflows
   _agent.py3547080%66, 74–80, 116–117, 207, 253, 255, 313, 315, 361–362, 368–369, 375, 377, 382, 442–443, 452, 459, 485, 518–520, 522, 524, 526, 531, 536, 583, 613, 630, 669–672, 678, 684, 688–689, 692–698, 702–703, 711, 772, 779, 785–786, 797, 829, 836, 857, 866, 870, 872–874, 881
   _checkpoint.py157596%115–116, 274, 331–332
   _checkpoint_encoding.py50296%161–162
   _runner.py171298%276–277
   _validation.py152596%129, 150, 245, 326, 329
packages/core/agent_framework/azure
   _assistants_client.py370100% 
   _chat_client.py77494%298, 300, 313–314
   _entra_id_authentication.py220100% 
   _responses_client.py48687%184, 216, 276–279
   _shared.py71494%174, 177, 188, 198
packages/core/agent_framework/openai
   _assistant_provider.py106991%162, 288, 354, 469–474
   _assistants_client.py2753587%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, 684, 687, 716, 753–756, 826
   _chat_client.py2692291%201, 231–232, 236, 354, 361, 442–449, 451–454, 464, 549, 584, 600
   _exceptions.py330100% 
   _responses_client.py6247887%290–293, 297–298, 301–302, 308–309, 314, 327–333, 354, 362, 385, 548, 551, 606, 610, 612, 614, 616, 692, 702, 707, 750, 829, 846, 859, 1013, 1018, 1022–1024, 1028–1029, 1052, 1121, 1143–1144, 1159–1160, 1178–1179, 1317–1318, 1334, 1336, 1415–1423, 1542, 1597, 1612, 1651–1652, 1654–1656, 1670–1672, 1682–1683, 1689, 1704
   _shared.py1261687%65, 71–74, 148, 150, 152, 159, 161, 174, 249, 273, 332–333, 335
packages/declarative/agent_framework_declarative
   _loader.py24011552%311–317, 481–486, 517, 550–553, 556–558, 561–567, 594–600, 644–653, 655, 658, 660, 671, 675–681, 690, 692, 694, 700, 702, 704, 706, 708, 721–726, 733–738, 740, 744–754, 756–761, 769, 771, 776, 779–782, 785–786, 789–790, 804–805, 808–809, 827, 834–838
packages/declarative/agent_framework_declarative/_workflows
   _actions_error.py53786%100, 109–111, 116, 125, 133
   _declarative_base.py3784089%43, 46, 129–130, 133, 207, 221, 235, 246, 263, 398, 426, 509–511, 513–515, 517, 520, 527, 553, 577–581, 583–591, 612–613, 615–616
   _declarative_builder.py3422492%166, 223, 314, 336, 346, 397, 399, 407, 422, 458, 461, 487–488, 507–508, 584, 589, 633–635, 659–660, 882, 950
   _executors_agents.py4658681%95–96, 113–115, 156–157, 164, 192, 195–196, 204–205, 215, 226–231, 487, 525–527, 530, 546, 562–566, 590, 595, 685, 691–696, 703, 727–728, 737–739, 788–789, 797, 816, 923–926, 933–934, 943–944, 956–961, 965–966, 968, 973, 975, 979–982, 985, 987–988, 991, 999–1001, 1003, 1006–1007, 1009, 1036–1037
   _executors_basic.py2813786%32, 307, 382, 384, 389–391, 404–410, 433, 438–441, 508, 513, 520–522, 526, 529, 533, 535, 540–542, 546, 548, 553–555, 558
   _executors_control_flow.py169696%81, 89, 152, 342–343, 347
   _executors_external_input.py1082675%131, 133–134, 136–137, 139, 192, 194, 197–198, 201–202, 204–205, 207, 259, 261, 263–264, 266, 326, 328, 331–333, 335
   _factory.py1386056%181, 258–259, 323–325, 333, 335, 338–344, 373, 384–385, 394, 429, 442, 467–470, 489–493, 496–497, 500, 503, 508, 617–618, 620–621, 623–625, 628, 642, 645–650, 653–654, 656, 659, 669–670, 672, 676–677, 679
packages/mem0/agent_framework_mem0
   _context_provider.py77198%128
packages/purview/agent_framework_purview
   _exceptions.py70100% 
packages/redis/agent_framework_redis
   _context_provider.py1795668%220, 238, 241, 247–248, 250–251, 253–255, 257–259, 261–263, 265–276, 278–279, 281–287, 315, 317, 321–326, 347, 358, 368–369, 382–383, 405, 407–408, 412–413
TOTAL21230330484% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
4183 239 💤 0 ❌ 0 🔥 1m 14s ⏱️

Comment thread python/CODING_STANDARD.md Resolved
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Feb 19, 2026
Replace the flat ServiceException family with domain-scoped branches:
- AgentException (with InvalidAuth, InvalidRequest, InvalidResponse, ContentFilter)
- ChatClientException (same consistent suberrors)
- IntegrationException (same + InitializationError)
- WorkflowException (Runner, Convergence, Checkpoint, Validation, Action, Declarative)
- ContentError (AdditionItemMismatch)
- ToolException / ToolExecutionException (unchanged)
- MiddlewareException / MiddlewareTermination (unchanged)

Key changes:
- All Service* exceptions removed (ServiceException, ServiceInitializationError, etc.)
- AgentExecutionException split into AgentInvalidRequest/ResponseException
- AgentInvocationError removed, split into AgentInvalidRequest/ResponseException
- Workflow exceptions moved from _workflows/_exceptions.py into main exceptions.py
- _workflows/__init__.py emptied; main __init__.py imports directly from submodules
- Purview exceptions re-parented under IntegrationException hierarchy
- Init validation errors use built-in ValueError/TypeError instead of custom exceptions
- CODING_STANDARD.md updated with hierarchy design and rationale

Fixes microsoft#3410

Co-authored-by: Copilot <[email protected]>
ToolException: base class for all tool-related exceptions (preconditions,
connection/init failures).
ToolExecutionException: runtime call failures (tool call failed, reconnect
failed, MCP errors).

Co-authored-by: Copilot <[email protected]>
- azurefunctions: _context.py, _app.py, _serialization.py, test_func_utils.py
  used 'from agent_framework._workflows import X' which broke after
  emptying _workflows/__init__.py; changed to direct submodule imports
- azure-ai-search: test still referenced ServiceInitializationError;
  updated to ValueError to match production code

Co-authored-by: Copilot <[email protected]>
Merged via the queue into microsoft:main with commit 5ee0685 Feb 19, 2026
26 checks passed
@eavanvalkenburg
Eduard van Valkenburg (eavanvalkenburg) deleted the eavanvalkenburg/exception-hierarchy-redesign branch June 30, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: all: Review and standardize exception documentation

5 participants