[BREAKING] Python: Replace RequestInfoExecutor with request_info API and @response_handler#1466
Conversation
There was a problem hiding this comment.
Pull Request Overview
Introduce a new request/response mechanism (request_info + @response_handler) to replace RequestInfoExecutor, add message typing and internal edge groups, and adjust executor/message routing to support human-in-the-loop scenarios more natively.
- Add WorkflowContext.request_info and response_handler decorator; integrate RequestInfo handling into all executors via RequestInfoMixin.
- Introduce MessageType, internal source IDs, InternalEdgeGroup edges, and routing changes to distinguish regular vs response messages.
- Remove ExecutorDuplicationError path (now plain ValueError) and adapt sample guessing game to new API.
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| guessing_game_with_human_input.py | Updates sample to use request_info / response_handler and simplify loop logic. |
| _workflow_executor.py | Adjust can_handle to unwrap Message objects. |
| _workflow_context.py | Adds request_info API emitting RequestInfoEvent. |
| _workflow.py | Refactors response sending via internal helper and adds internal edge groups on executor registration. |
| _validation.py | Removes duplicate-executor validation & skips type checks for internal edges. |
| _runner_context.py | Adds MessageType, pending request tracking, and response dispatch. |
| _runner.py | Warns/drops messages with no outgoing edges. |
| _request_info_mixin.py | New mixin and @response_handler decorator for response handling. |
| _executor.py | Integrates RequestInfoMixin, routes response messages to response handlers. |
| _events.py | Extends RequestInfoEvent with response_type. |
| _edge_runner.py | Passes full Message objects; supports InternalEdgeGroup. |
| _edge.py | Adds InternalEdgeGroup definition. |
| _const.py | Adds internal source ID helpers. |
| init.pyi / init.py | Exports response_handler; removes ExecutorDuplicationError from public API. |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py
Show resolved
Hide resolved
python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py
Outdated
Show resolved
Hide resolved
python/packages/core/agent_framework/_workflows/_runner_context.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/workflows/human-in-the-loop/guessing_game_with_human_input.py
Show resolved
Hide resolved
python/samples/getting_started/workflows/composition/sub_workflow_request_interception.py
Show resolved
Hide resolved
python/packages/core/agent_framework/_workflows/_request_info_mixin.py
Outdated
Show resolved
Hide resolved
python/packages/core/agent_framework/_workflows/_request_info_mixin.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/workflows/orchestration/magentic_checkpoint.py
Show resolved
Hide resolved
python/samples/getting_started/workflows/composition/sub_workflow_request_interception.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/workflows/composition/sub_workflow_parallel_requests.py
Outdated
Show resolved
Hide resolved
python/packages/core/tests/workflow/test_request_info_event_rehydrate.py
Show resolved
Hide resolved
python/samples/getting_started/workflows/agents/azure_chat_agents_tool_calls_with_feedback.py
Show resolved
Hide resolved
python/packages/core/agent_framework/_workflows/_request_info_mixin.py
Outdated
Show resolved
Hide resolved
|
With this PR, other executors in the same workflow can no longer intercept requests from an executor. This is because requests are directly surfaced to the workflow as events, whereas previously requests are first sends to a We currently don't have a systematic way to work with third party executors yet. However, this could be a potentially scenario as we grow. Here is an issue tracking idea: #1791 |
…API and `@response_handler` (microsoft#1466) * Prototype: Add request_info API and @response_handler * Add original_request as a parameter to the response handler * Prototype: request interception in sub workflows * Prototype: request interception in sub workflows 2 * WIP: Make checkpointing work * checkpointing with sub workflow * Fix function executor * Allow sub-workflow to output directly * Remove ReqeustInfoExecutor and related classes; Debugging checkpoint_with_human_in_the_loop * Fix Handoff and sample * fix pending requests in checkpoint * Fix unit tests * Fix formatting * Resolve comments * Address comment * Add checkpoint tests * Add tests * misc * fix mypy * fix mypy * Use request type as part of the key * Log warning if there is not response handler for a request * Update Internal edge group comments * REcord message type in executor processing span * Update sample * Improve tests
Motivation and Context
Requests & responses (human-in-the-loop) are fundamental to the Workflow system in Agent Framework. This PR attempts to make requests & responses more integrated and easier to use.
Description
RequestInfoExecutorwith a new API calledrequest_infoavailable via theWorkflowContextto send requests, and a new decorator namedresponse_handlerto receive responses.RequestInfoMixinwhich gives all executors the capability to send requests and handle responses.MessageType.InternalEdgeGroup.This will make requests & responses more tightly integrated into the framework, including the special handler type, the special message type, and the dedicated channel for response messages. This will allow users to create cleaner workflow graphs and not to worry about wiring up different executors to achieve human-in-the-loop.
Details
Previously
RequestInfoExecutor.flowchart TD subgraph Workflow Executor RequestInfoExecutor Executor --> | message: RequestInfoMessage | RequestInfoExecutor RequestInfoExecutor --> | message: RequestResponse | Executor end WorkflowRunAPI[Workflow Run API] RequestInfoExecutor --> | event: RequestInfoEvent | WorkflowRunAPI WorkflowRunAPI --> | dict: Responses | RequestInfoExecutorflowchart TD subgraph Executor handler_a handler_b end handler_a --> | message: RequestInfoMessage | RequestInfoExecutor RequestInfoExecutor --> | message: RequestResponse | handler_bRequestInfoMessage.RequestResponse[TRequest, TResponse].RequestInfoMessage, which can be problematic.After this PR
RequestInfoExecutor.flowchart TD subgraph Workflow Executor end WorkflowRunAPI[Workflow Run API] Executor --> | RequestInfoEvent | WorkflowRunAPI WorkflowRunAPI --> | Responses | Executorresponse_handlerfor handling responsesflowchart TD subgraph Executor handler response_handler end handler --> | Requests | WorkflowRunAPI WorkflowRunAPI --> | Responses | response_handlerTODO
Update learn docs
Contribution Checklist