Skip to content

Python: handle Literal annotations in is_instance_of - #8351

Open
Manohar Paturi (ManoharPaturi) wants to merge 4 commits into
microsoft:mainfrom
ManoharPaturi:fix/is-instance-of-literal
Open

Manohar Paturi (ManoharPaturi) wants to merge 4 commits into
microsoft:mainfrom
ManoharPaturi:fix/is-instance-of-literal

Conversation

@ManoharPaturi

@ManoharPaturi Manohar Paturi (ManoharPaturi) commented Sep 13, 2026

Copy link
Copy Markdown

Motivation & Context

Workflows with a Literal message annotation on a handler crash at the first message delivery: Executor.can_handle() / _find_handler() call is_instance_of() directly on the annotation, which has no Literal case and raises TypeError: typing.Literal cannot be used with isinstance(). Registration and the builder type validation both accept Literal, and the sibling helper _matches_annotation() already implements the intended semantics, so the two validators disagree. Reported in #8350.

Description & Review Guide

  • What are the major changes? Adds a Literal case to is_instance_of() that matches by allowed values with strict member types, aligned with _matches_annotation(), so registration, validation, and delivery agree on Literal annotations.
  • What is the impact of these changes? Literal-annotated handlers work end to end; no change for any other annotation type.
  • What do you want reviewers to focus on? The member-type strictness in the new case (booleans vs integers in Literal[0, 1]-style annotations) and the three new tests.

Related Issue

Fixes #8350

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue
  • This is not a breaking change.

…tance_of

Executor handlers annotated with a Literal message type (e.g.
`message: Literal["yes", "no"]`) pass @handler registration, executor
construction, and WorkflowBuilder type validation, but crashed at
message-delivery time with:

    TypeError: typing.Literal cannot be used with isinstance()

is_instance_of() had no case for Literal origins and fell through to
isinstance(data, Literal), which always raises. Executor.can_handle()
and Executor._find_handler() call is_instance_of() directly, so any
workflow containing such an executor failed on the first delivery.

Add a Literal case that matches by allowed values with strict member
types (bool never matches an int member), mirroring the existing
_matches_annotation() semantics used by try_coerce_to_type.

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Sep 13, 2026
Comment thread python/packages/core/agent_framework/_workflows/_typing_utils.py Outdated
Comment thread python/packages/core/agent_framework/_workflows/_typing_utils.py Outdated
…hes_annotation to is_instance_of

- Reorder Literal evaluation to check type(data) is type(member) before data == member to prevent __eq__ side effects on mismatched types
- Remove duplicate Literal check in _matches_annotation to delegate directly to is_instance_of
- Add test verifying mismatched type with throwing __eq__ returns False without raising

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good—thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Literal handler annotations crash workflows at delivery (is_instance_of has no Literal case)

4 participants