Skip to content

Python: [Bug]: Workflow build rejects a list[T] output sent to a Sequence[T] handler #9449

Closed

Description

Observed Behavior

An executor that sends list[str] can't be wired to a handler that takes Sequence[str]. WorkflowBuilder.build() raises TypeCompatibilityError.

The same check breaks Workflow.as_agent(): if the start executor's handler takes Sequence[Message], it raises ValueError: Workflow's start executor cannot handle list[Message].

At runtime the message would be delivered fine. is_instance_of(["a"], Sequence[str]) is True. Only the build-time check says no.

It's also inconsistent with the bare case. list[str] -> Sequence passes since #8731, but list[str] -> Sequence[str] doesn't.

Expected Behavior

list[str] is a Sequence[str], so the edge builds. Same for dict[str, int] -> Mapping[str, int], list[str] -> Iterable[str], set[int] -> collections.abc.Set[int]. Element types still have to fit, so list[int] -> Sequence[str] stays rejected.

Steps to Reproduce

  1. Executor A has WorkflowContext[list[str]] and sends a list.
  2. Executor B handles words: Sequence[str].
  3. WorkflowBuilder(start_executor=a).add_edge(a, b).build()

Minimal Reproduction

from collections.abc import Sequence

from agent_framework import Executor, Message, WorkflowBuilder, WorkflowContext, handler


class Splitter(Executor):
    @handler
    async def split(self, text: str, ctx: WorkflowContext[list[str]]) -> None:
        await ctx.send_message(text.split())


class Counter(Executor):
    @handler
    async def count(self, words: Sequence[str], ctx: WorkflowContext[None, int]) -> None:
        await ctx.yield_output(len(words))


splitter, counter = Splitter(id="splitter"), Counter(id="counter")
workflow = WorkflowBuilder(start_executor=splitter).add_edge(splitter, counter).build()  # raises


class Chat(Executor):
    @handler
    async def chat(self, messages: Sequence[Message], ctx: WorkflowContext[None, str]) -> None:
        await ctx.yield_output(messages[-1].text)


WorkflowBuilder(start_executor=Chat(id="chat")).build().as_agent()  # raises

Error Messages and Stack Traces

is_type_compatible(list[str], Sequence[str]): False
is_type_compatible(list[str], Sequence):      True

1. build: TypeCompatibilityError - [TYPE_COMPATIBILITY] Type incompatibility between executors 'splitter' -> 'counter'. Source executor outputs types ['list[str]'] but target executor can only handle types ['collections.abc.Sequence[str]'].
2. as_agent(): ValueError - Workflow's start executor cannot handle list[Message]

Package Versions

agent-framework-core: 1.22.0 (main at bfc4fdb)

Python Version

Python 3.12

Operating System

macOS

Regression

No

Additional Context

Cause: is_type_compatible in python/packages/core/agent_framework/_workflows/_typing_utils.py. Origins are list and collections.abc.Sequence, so Case 5 ("different container types are not compatible") returns False before any argument check.

#8731 handled the bare target (list[str] -> Sequence) and its description mentions list[Message] -> Sequence[Message] as left out. I didn't find an issue for it.

Fix I have: when the source is a builtin container, the target is a collections.abc class it implements, and both have the same number of type arguments, compare the arguments pairwise. 13 lines plus a unit test. Happy to open the PR.

Acknowledgements

  • I searched existing issues and did not find a duplicate.
  • I personally verified this behavior and the reproduction details are authentic.
  • I will wait for explicit maintainer agreement before starting implementation of a non-trivial change.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 16, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 16, 2026
  3. github-actions commented on Oct 16, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    The bug is in python/packages/core/agent_framework/_workflows/_typing_utils.py::is_type_compatible at lines 551-553, where differing parameterized container origins are rejected before generic arguments are checked. It triggers for assignable pairs such as list[str] and Sequence[str], affecting edge validation and workflow-agent construction. Minimal repro: assert is_type_compatible(list[str], Sequence[str]) and build a workflow edge with those output/input annotations.

    • Failing test: python/packages/core/tests/workflow/test_typing_utils.py
    • Files examined: python/packages/core/agent_framework/_workflows/_typing_utils.py, python/packages/core/agent_framework/_workflows/_validation.py, python/packages/core/agent_framework/_workflows/_agent.py, python/packages/core/tests/workflow/test_typing_utils.py, python/packages/core/pyproject.toml
    • Tests run: python/packages/core/tests/workflow/test_typing_utils.py::test_type_compatibility_parameterized_container_abc
    • Reported version: 1.22.0
    • Current version: 1.22.0
  4. added
    workflowsUsage: [Issues, PRs], Target: Workflows
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 16, 2026
  5. added a commit that references this issue on Oct 24, 2026
    c3fb3ae
  6. Somay-kousis commented on Oct 24, 2026

    @Somay-kousis
    ContributorAuthor

    Eduard van Valkenburg (@eavanvalkenburg) is a PR welcome for this one? The fix is on my fork, rebased on main today: main...Somay-kousis:agent-framework:fix/edge-abc-container-types (879d77d).

    is_type_compatible gets one case: a builtin container whose collections.abc target it implements, with the same number of type arguments, compares the arguments pairwise. So list[str] -> Sequence[str] and dict[str, int] -> Mapping[str, int] build, and list[int] -> Sequence[str] is still rejected. 3 of the 4 new tests fail on main (the type check, a workflow that builds and runs with a Sequence[str] handler, and as_agent() with a Sequence[Message] start executor); the mismatch test passes on both. tests/workflow: 1441 passed.

    I'll open the PR as soon as you're OK with the direction.

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

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Pythonready-for-implementationMaintainers agree the problem and direction are ready for implementation.reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowworkflowsUsage: [Issues, PRs], Target: Workflows

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions