[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
@@ -140,7 +140,7 @@ class ExclamationAdder(Executor):
super().__init__(id=id)
@handler(input=str, output=str)
async def add_exclamation(self, message: str, ctx: WorkflowContext) -> None:
async def add_exclamation(self, message, ctx) -> None: # type: ignore
"""Add exclamation marks to the input.
Note: The input=str and output=str are explicitly specified on @handler,
@@ -149,7 +149,7 @@ class ExclamationAdder(Executor):
on @handler take precedence.
"""
result = f"{message}!!!"
await ctx.send_message(result)
await ctx.send_message(result) # type: ignore
async def main():
@@ -57,7 +57,6 @@ async def main():
# of `AgentResponse` from the agents in the workflow.
outputs = cast(list[AgentResponse], outputs)
for output in outputs:
# TODO: author_name should be available in AgentResponse
print(f"{output.messages[0].author_name}: {output.text}\n")
# Summarize the final run state (e.g., COMPLETED)
@@ -66,7 +65,7 @@ async def main():
"""
writer: "Charge Ahead: Affordable Adventure Awaits!"
reviewer: - Consider emphasizing both affordability and fun in a more dynamic way.
reviewer: - Consider emphasizing both affordability and fun in a more dynamic way.
- Try using a catchy phrase that includes a play on words, like “Electrify Your Drive: Fun Meets Affordability!”
- Ensure the slogan is succinct while capturing the essence of the car's unique selling proposition.
@@ -3,7 +3,6 @@
import asyncio
from agent_framework import AgentResponseUpdate, ChatMessage, WorkflowBuilder
from agent_framework._workflows._events import WorkflowOutputEvent
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
@@ -58,7 +57,7 @@ async def main():
):
# The outputs of the workflow are whatever the agents produce. So the events are expected to
# contain `AgentResponseUpdate` from the agents in the workflow.
if isinstance(event, WorkflowOutputEvent) and isinstance(event.data, AgentResponseUpdate):
if event.type == "output" and isinstance(event.data, AgentResponseUpdate):
update = event.data
author = update.author_name
if author != last_author:
@@ -8,7 +8,6 @@ from agent_framework import (
Executor,
WorkflowBuilder,
WorkflowContext,
WorkflowOutputEvent,
executor,
handler,
)
@@ -87,7 +86,7 @@ async def main():
async for event in workflow.run("hello world", stream=True):
# The outputs of the workflow are whatever the agents produce. So the events are expected to
# contain `AgentResponseUpdate` from the agents in the workflow.
if isinstance(event, WorkflowOutputEvent) and isinstance(event.data, AgentResponseUpdate):
if event.type == "output" and isinstance(event.data, AgentResponseUpdate):
update = event.data
if first_update:
print(f"{update.author_name}: {update.text}", end="", flush=True)