Skip to content

Conversation

@TaoChenOSU
Copy link
Contributor

@TaoChenOSU TaoChenOSU commented Oct 14, 2025

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

  1. Replace the RequestInfoExecutor with a new API called request_info available via the WorkflowContext to send requests, and a new decorator named response_handler to receive responses.
  2. Introduce the RequestInfoMixin which gives all executors the capability to send requests and handle responses.
  3. Introduce message types to distinguish between regular executor-to-executor messages and workflow-issued messages: MessageType.
  4. Introduce a new edge group for workflow-issued messages: 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

  1. Executors that need to send requests must be paired up with a 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 | RequestInfoExecutor
Loading
  1. A request and responses are handled by message handlers:
flowchart TD

    subgraph Executor
        handler_a
        handler_b
    end

    handler_a --> | message: RequestInfoMessage | RequestInfoExecutor
    RequestInfoExecutor --> | message: RequestResponse | handler_b
Loading
  1. Requests must be derived from RequestInfoMessage.
  2. Responses must be RequestResponse[TRequest, TResponse].
  3. Checkpoint restoration deserializes the request type and defaults to RequestInfoMessage, which can be problematic.

After this PR

  1. Executors can send requests without a RequestInfoExecutor.
flowchart TD

    subgraph Workflow
        Executor
    end

    WorkflowRunAPI[Workflow Run API]
    Executor --> | RequestInfoEvent | WorkflowRunAPI
    WorkflowRunAPI --> | Responses | Executor
Loading
  1. A new handler type response_handler for handling responses
flowchart TD

    subgraph Executor
        handler

        response_handler
    end

    handler --> | Requests | WorkflowRunAPI
    WorkflowRunAPI --> | Responses | response_handler
Loading
  1. Requests can be any custom type. Doesn't have to derived from anything.
  2. Responses can also be any custom type. Doesn't have to derived from anything.
  3. Checkpoint restoration will fail if deserialization fails.

TODO

Update learn docs

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? If yes, add "[BREAKING]" prefix to the title of the PR.

@TaoChenOSU TaoChenOSU self-assigned this Oct 14, 2025
Copilot AI review requested due to automatic review settings October 14, 2025 22:02
@TaoChenOSU TaoChenOSU added the workflows Related to Workflows in agent-framework label Oct 14, 2025
@github-actions github-actions bot changed the title WIP: Add request_info API and @response_handler Python: WIP: Add request_info API and @response_handler Oct 14, 2025
@TaoChenOSU TaoChenOSU changed the title Python: WIP: Add request_info API and @response_handler [BREAKING] Python: [WIP] Add request_info API and @response_handler Oct 14, 2025
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

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.

@markwallace-microsoft markwallace-microsoft added the documentation Improvements or additions to documentation label Oct 22, 2025
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Oct 25, 2025

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   observability.py60410981%238, 264–266, 268, 270–274, 282, 288–293, 316–318, 320–321, 327, 411, 421, 443, 449, 468–470, 478–480, 503–505, 515–517, 650, 652, 739–743, 746–750, 759–762, 772–775, 777, 864–867, 1042, 1190–1192, 1347, 1354, 1356, 1358, 1360, 1362, 1364, 1366, 1368, 1370, 1372, 1376–1378, 1380, 1390, 1418–1419, 1429, 1432–1435, 1449, 1454–1456, 1458–1461, 1463–1464, 1468, 1471, 1491, 1529, 1545, 1549, 1683, 1685
packages/core/agent_framework/_workflows
   _checkpoint.py121298%182–183
   _checkpoint_encoding.py1856664%36–37, 46–54, 56, 62–64, 70–71, 91–92, 107–108, 125–126, 144–146, 152–159, 170, 175–177, 195–196, 209, 213, 222–223, 228–242, 244–250
   _checkpoint_summary.py27485%36–39
   _const.py50100% 
   _edge.py2182688%36, 58–59, 61, 413–414, 419, 423–428, 430–432, 542, 656, 663–665, 712, 740, 766, 820, 834
   _edge_runner.py1581391%53, 58, 71, 136–137, 141, 148, 202, 207, 349–350, 354, 395
   _events.py1211587%59–60, 78, 86, 90, 180–181, 234, 259, 289, 302, 310, 318, 345, 357
   _executor.py138695%203, 319, 334, 336, 451, 461
   _function_executor.py57492%81, 87, 93, 110
   _handoff.py45614568%61–63, 70–71, 73, 75, 80–81, 83, 133, 141–146, 149–150, 164, 173, 192–195, 204–206, 217, 220, 230–241, 243, 249, 255, 282, 296–298, 333, 338–340, 376, 385–390, 392–393, 404, 421, 449, 456, 458–460, 472, 500, 531–533, 536–539, 541–543, 776, 782, 786, 792, 796, 808, 856, 859, 947, 952, 962, 968–971, 979–980, 984–986, 988–998, 1000–1001, 1003, 1005, 1020–1021, 1024–1025, 1028, 1048–1054, 1056, 1062, 1096–1097, 1150–1151, 1262, 1270, 1279–1282, 1337, 1350, 1354, 1359–1360
   _magentic.py94027370%69–78, 83, 87–98, 322, 327, 344, 346, 361, 369–378, 456, 460, 474, 480, 495, 575, 588, 605, 614–615, 617–619, 621, 632, 699–703, 706–710, 790–793, 796–800, 802–804, 811, 850, 897, 933–935, 937, 1004, 1077, 1079–1080, 1088, 1124, 1133–1135, 1154, 1165, 1175–1176, 1178–1179, 1198, 1251, 1271, 1274, 1303, 1306, 1314–1318, 1324, 1352–1354, 1356, 1358, 1366–1369, 1371, 1375–1376, 1379–1382, 1384–1385, 1391–1393, 1396–1397, 1402–1403, 1411, 1419, 1434, 1446, 1458–1461, 1490–1491, 1496–1498, 1529, 1555, 1570, 1586, 1603, 1673, 1679–1680, 1694, 1696, 1699, 1701–1702, 1705–1706, 1710, 1713, 1734, 1771–1772, 1774, 1778–1780, 1796, 1807, 1817, 1861, 1866–1867, 2193–2194, 2198, 2213, 2218, 2221, 2275, 2286, 2297–2299, 2312–2313, 2318, 2329–2331, 2342–2344, 2356–2363, 2365–2366, 2374, 2382–2383, 2385–2387, 2389–2392, 2396–2404, 2408–2409, 2412–2416, 2418–2419, 2421–2423, 2425–2428, 2430–2432, 2434–2435, 2437–2439, 2451–2453, 2464–2467, 2478–2481, 2493–2496, 2504–2507, 2514–2515, 2522, 2526
   _request_info_mixin.py77593%54, 99, 220, 227, 234
   _runner.py2072985%111, 113–116, 155–158, 162, 202–204, 225, 231, 261–262, 264–265, 299–301, 310, 314, 316, 320, 328, 334, 374
   _runner_context.py154994%76–77, 79–80, 82, 342, 361, 457, 461
   _typing_utils.py1365559%23–24, 28–30, 32–34, 36, 38, 41, 43–45, 47–50, 57–58, 63–67, 70–71, 118, 142, 221, 223–224, 233, 235, 242, 244, 264, 266, 268, 273–280, 283–284, 286–290, 292
   _validation.py208796%89, 138, 160, 255, 336, 339, 476
   _workflow.py2441793%94, 249–251, 253–254, 272, 296, 298, 505, 577, 582, 585, 619–621, 686
   _workflow_builder.py142894%139, 281–285, 287, 359
   _workflow_context.py1611391%60–61, 69, 73, 87, 163, 188, 295, 398, 407, 412, 427, 440
   _workflow_executor.py1764872%90, 395, 414, 418, 424, 428, 441, 445, 469–470, 473–475, 482–485, 488–490, 493–494, 496, 499–501, 504–508, 512–513, 522, 527, 531, 577, 601–606, 609, 612, 620, 625, 636
TOTAL11966183584% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
1446 98 💤 0 ❌ 0 🔥 28.397s ⏱️

@TaoChenOSU TaoChenOSU requested review from ekzhu and moonbox3 October 27, 2025 20:41
@markwallace-microsoft markwallace-microsoft added the lab Agent Framework Lab label Oct 27, 2025
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

Copilot reviewed 53 out of 54 changed files in this pull request and generated 17 comments.

@TaoChenOSU TaoChenOSU enabled auto-merge October 29, 2025 23:31
@TaoChenOSU TaoChenOSU added this pull request to the merge queue Oct 29, 2025
Merged via the queue into microsoft:main with commit 943d926 Oct 29, 2025
21 checks passed
@TaoChenOSU
Copy link
Contributor Author

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 RequestInfoExecutor as a message and the RequestInfoExecutor raises an event. Being able to intercept requests from an executor is particularly useful if people are using third party executors and want to handle the requests with another executor that they own without surfacing the requests to an external system.

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

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

Labels

documentation Improvements or additions to documentation lab Agent Framework Lab python workflows Related to Workflows in agent-framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants