Skip to content

Python: fix: resolve string annotations in FunctionExecutor#2308

Merged
eavanvalkenburg merged 4 commits intomicrosoft:mainfrom
madebygps:fix/issue-1808-pep-563-annotations
Nov 19, 2025
Merged

Python: fix: resolve string annotations in FunctionExecutor#2308
eavanvalkenburg merged 4 commits intomicrosoft:mainfrom
madebygps:fix/issue-1808-pep-563-annotations

Conversation

@madebygps
Copy link
Member

Enhance type hint validation in FunctionExecutor by importing typing and using get_type_hints to correctly resolve annotations.

This fixes validation failures when from __future__ import annotations is enabled, which stores annotations as strings.

Fixes #1808

Motivation and Context

This change is required to support Python codebases that use from __future__ import annotations (PEP 563).

  1. Why is this change required?
    When from __future__ import annotations is enabled, type annotations are stored as strings rather than type objects. The current implementation of FunctionExecutor inspects param.annotation directly, which fails when it encounters a string (e.g., "WorkflowContext[str]") instead of the actual type object.

  2. What problem does it solve?
    It solves the ValueError that occurs during FunctionExecutor initialization when users enable future annotations. The error looks like this:

    ValueError: Function instance parameter 'ctx' must be annotated as WorkflowContext, WorkflowContext[T], or WorkflowContext[T, U], got WorkflowContext
    
  3. What scenario does it contribute to?
    It enables developers to use modern Python typing practices (PEP 563) and forward references within their agent workflows without runtime errors.

  4. Issue Link: Fixes Python: Type checking fails for WorkflowContext annotation with from __future__ import annotations in Python 3.14 #1808

Description

The fix involves updating _validate_function_signature in _function_executor.py to correctly resolve type hints.

  • Approach: Instead of relying solely on inspect.signature(...).parameters[...].annotation, I now use typing.get_type_hints(func) to resolve the annotations into their actual type objects.
  • Implementation:
    • Imported typing.
    • Added type_hints = typing.get_type_hints(func) inside _validate_function_signature.
    • Updated the logic to retrieve both the message and ctx parameter annotations from the resolved type_hints dictionary.
    • Added a new test file test_function_executor_future.py that explicitly uses from __future__ import annotations to verify the fix and prevent regression.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? No

Enhance type hint validation in FunctionExecutor by importing `typing` and
using `get_type_hints` to correctly resolve annotations.

This fixes validation failures when `from __future__ import annotations`
is enabled, which stores annotations as strings.

Fixes microsoft#1808
Copilot AI review requested due to automatic review settings November 18, 2025 20:24
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 fixes type hint validation in FunctionExecutor to support Python's from __future__ import annotations (PEP 563), which stores type annotations as strings rather than type objects.

Key Changes:

  • Updates _validate_function_signature to use typing.get_type_hints() for resolving string annotations to actual type objects
  • Adds comprehensive test coverage for future annotations with both simple and complex type hints

Reviewed Changes

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

File Description
python/packages/core/agent_framework/_workflows/_function_executor.py Imports typing module and modifies signature validation to resolve stringified annotations using get_type_hints()
python/packages/core/tests/workflow/test_function_executor_future.py Adds new test suite with from __future__ import annotations to verify the fix works with stringified type hints

@github-actions github-actions bot changed the title fix: resolve string annotations in FunctionExecutor Python: fix: resolve string annotations in FunctionExecutor Nov 18, 2025
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Nov 18, 2025

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework/_workflows
   _function_executor.py59493%82, 88, 94, 111
TOTAL14990220785% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
2041 127 💤 0 ❌ 0 🔥 40.904s ⏱️

@eavanvalkenburg eavanvalkenburg added this pull request to the merge queue Nov 19, 2025
Merged via the queue into microsoft:main with commit f83c39f Nov 19, 2025
23 checks passed
arisng pushed a commit to arisng/agent-framework that referenced this pull request Feb 2, 2026
…t#2308)

* fix: resolve string annotations in FunctionExecutor

Enhance type hint validation in FunctionExecutor by importing `typing` and
using `get_type_hints` to correctly resolve annotations.

This fixes validation failures when `from __future__ import annotations`
is enabled, which stores annotations as strings.

Fixes microsoft#1808

* Update python/packages/core/tests/workflow/test_function_executor_future.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* ran pre commit

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
moonbox3 added a commit to moonbox3/agent-framework that referenced this pull request Feb 26, 2026
microsoft#3898)

Use typing.get_type_hints() in _validate_handler_signature to resolve
string annotations from `from __future__ import annotations`. This
mirrors the fix applied to FunctionExecutor in microsoft#2308.

When __future__ annotations are enabled, type annotations are stored as
strings. The handler decorator was passing these strings directly to
validate_workflow_context_annotation, which uses typing.get_origin and
returns None for strings, causing a ValueError.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-merge-queue bot pushed a commit that referenced this pull request Feb 27, 2026
…e__ import annotations` (#4317)

* Python: Fix Executor handler type checking with __future__ annotations (#3898)

Use typing.get_type_hints() in _validate_handler_signature to resolve
string annotations from `from __future__ import annotations`. This
mirrors the fix applied to FunctionExecutor in #2308.

When __future__ annotations are enabled, type annotations are stored as
strings. The handler decorator was passing these strings directly to
validate_workflow_context_annotation, which uses typing.get_origin and
returns None for strings, causing a ValueError.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback for #3898: improve error handling and test coverage

- Wrap typing.get_type_hints() in try/except to provide a descriptive
  ValueError mentioning the handler name when annotations cannot be resolved
- Strengthen bare context test to assert output_types and workflow_output_types
- Add test for @handler(input=..., output=...) with future annotations
  covering the skip_message_annotation branch
- Add test for union-type context annotations with future annotations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Narrow exception catch and add test for unresolvable annotations (#3898)

- Narrow except clause from bare Exception to (NameError, AttributeError,
  TypeError) to avoid masking unexpected errors.
- Add test_handler_unresolvable_annotation_raises to verify that a handler
  with a forward-reference to a non-existent type raises ValueError with
  the expected message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix #3898: fall back to raw annotations when get_type_hints fails

When typing.get_type_hints(func) raises NameError (unresolvable forward
ref), AttributeError, RecursionError, or any other exception, fall back
to the raw parameter annotations instead of raising a ValueError.
This matches the suggestion from @moonbox3 on PR #4317.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix test to match new fallback behavior when get_type_hints fails (#3898)

The code now falls back to raw string annotations instead of raising
'Failed to resolve type annotations'. A ValueError is still raised when
the raw string ctx annotation is not a valid WorkflowContext type, so
update the test to match on ValueError without checking the message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply pyupgrade: remove unnecessary string annotation quote

* Add noqa for intentionally undefined name in annotation test

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Type checking fails for WorkflowContext annotation with from __future__ import annotations in Python 3.14

5 participants