[BREAKING] Python: Refactor workflow events to unified discriminated union pattern (#3690)

* Refactor events

* Merge main

* Fixes

* Cleanup

* Update samples and tests

* Remove unused imports

* PR feedback

* Merge main. Add properties for events to help typing

* Formatting

* Cleanup

* use builtins.type to avoid shadowing by WorkflowEvent.type attribute

* Final improvements
This commit is contained in:
Evan Mattson
2026-02-06 16:47:20 +09:00
committed by GitHub
Unverified
parent 09f59b21ad
commit 0f3f4dbcaf
127 changed files with 1646 additions and 1703 deletions
@@ -16,7 +16,6 @@ from agent_framework import (
WorkflowBuilder,
WorkflowContext,
WorkflowEvent,
WorkflowOutputEvent,
executor,
)
from agent_framework.azure import AzureOpenAIChatClient
@@ -279,7 +278,7 @@ async def main() -> None:
async for event in workflow.run(email, stream=True):
if isinstance(event, DatabaseEvent):
print(f"{event}")
elif isinstance(event, WorkflowOutputEvent):
elif event.type == "output":
print(f"Workflow output: {event.data}")
"""
@@ -7,7 +7,6 @@ from agent_framework import (
Executor,
WorkflowBuilder,
WorkflowContext,
WorkflowOutputEvent,
handler,
)
from typing_extensions import Never
@@ -77,7 +76,7 @@ async def main() -> None:
outputs: list[str] = []
async for event in workflow.run("hello world", stream=True):
print(f"Event: {event}")
if isinstance(event, WorkflowOutputEvent):
if event.type == "output":
outputs.append(cast(str, event.data))
if outputs:
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import WorkflowBuilder, WorkflowContext, WorkflowOutputEvent, executor
from agent_framework import WorkflowBuilder, WorkflowContext, executor
from typing_extensions import Never
"""
@@ -14,7 +14,8 @@ The second reverses the text and yields the workflow output. Events are printed
Purpose:
Show how to declare executors with the @executor decorator, connect them with WorkflowBuilder,
pass intermediate values using ctx.send_message, and yield final output using ctx.yield_output().
Demonstrate how streaming exposes ExecutorInvokedEvent and ExecutorCompletedEvent for observability.
Demonstrate how streaming exposes executor_invoked events (type='executor_invoked') and
executor_completed events (type='executor_completed') for observability.
Prerequisites:
- No external services required.
@@ -67,17 +68,17 @@ async def main():
async for event in workflow.run("hello world", stream=True):
# You will see executor invoke and completion events as the workflow progresses.
print(f"Event: {event}")
if isinstance(event, WorkflowOutputEvent):
if event.type == "output":
print(f"Workflow completed with result: {event.data}")
"""
Sample Output:
Event: ExecutorInvokedEvent(executor_id=upper_case_executor)
Event: ExecutorCompletedEvent(executor_id=upper_case_executor)
Event: ExecutorInvokedEvent(executor_id=reverse_text_executor)
Event: ExecutorCompletedEvent(executor_id=reverse_text_executor)
Event: WorkflowOutputEvent(data='DLROW OLLEH', executor_id=reverse_text_executor)
Event: executor_invoked event (type='executor_invoked', executor_id=upper_case_executor)
Event: executor_completed event (type='executor_completed', executor_id=upper_case_executor)
Event: executor_invoked event (type='executor_invoked', executor_id=reverse_text_executor)
Event: executor_completed event (type='executor_completed', executor_id=reverse_text_executor)
Event: output event (type='output', data='DLROW OLLEH', executor_id=reverse_text_executor)
Workflow completed with result: DLROW OLLEH
"""
@@ -9,7 +9,6 @@ from agent_framework import (
ChatAgent,
ChatMessage,
Executor,
ExecutorCompletedEvent,
WorkflowBuilder,
WorkflowContext,
handler,
@@ -143,7 +142,7 @@ async def main():
# Step 2: Run the workflow and print the events.
iterations = 0
async for event in workflow.run(NumberSignal.INIT, stream=True):
if isinstance(event, ExecutorCompletedEvent) and event.executor_id == "guess_number":
if event.type == "executor_completed" and event.executor_id == "guess_number":
iterations += 1
print(f"Event: {event}")