Principle:Microsoft Agent framework Human in the Loop Response
| Property | Value |
|---|---|
| Principle Name | Human-in-the-Loop Response |
| SDK | Microsoft Agent Framework |
| Repository | Microsoft Agent Framework |
| Source Reference | python/packages/core/agent_framework/_workflows/_request_info_mixin.py:L114-133
|
| Import | from agent_framework import response_handler
|
| Domains | Workflow_Engine, Human_in_the_Loop |
Overview
Human-in-the-Loop Response is the principle governing how responses to human-in-the-loop requests are routed back into a running workflow. When a workflow emits a request_info event to solicit input from a human operator, the workflow pauses and waits for a response. The @response_handler decorator marks executor methods that process these responses. When workflow.run(responses={request_id: data}) is called, the framework matches the supplied request_id to the corresponding handler and invokes it with the original request and the response data.
Description
Request-Response Lifecycle
The human-in-the-loop response pattern follows a well-defined lifecycle:
- Request emission: During workflow execution, an
Executormethod callsctx.request_info(prompt, response_type, request_id=...)to emit arequest_infoevent. This signals that the workflow requires input from a human operator before it can proceed. - Workflow suspension: After emitting the request, the workflow suspends execution. The request is surfaced to the calling application, which is responsible for presenting it to the user and collecting their response.
- Response submission: The calling application resumes the workflow by invoking
workflow.run(responses={request_id: data}), passing a dictionary that maps request IDs to their corresponding response values. - Response routing: The framework matches each
request_idin the responses dictionary to the executor method decorated with@response_handler. The matching handler is invoked with the original request payload, the response data, and the currentWorkflowContext. - Workflow continuation: The response handler processes the data and the workflow resumes normal execution, potentially emitting outputs via
ctx.yield_output()or issuing furtherrequest_infoevents.
The @response_handler Decorator
The @response_handler decorator marks a method on an Executor subclass as the designated handler for responses to request_info events. The decorated method receives three arguments:
original_request: The original request payload that was passed toctx.request_info(). This is typed asRequestTypeand allows the handler to recall what was originally asked.response: The response data provided by the human operator, typed asResponseType. This corresponds to the value associated with therequest_idin the responses dictionary.ctx: The currentWorkflowContext, providing access to workflow operations such asyield_output(),request_info(), and state management.
The handler method must be an async method (i.e., defined with async def) and returns None.
Routing Mechanism
The response routing mechanism uses the request_id as the correlation key. When a workflow is resumed with responses, the framework:
- Iterates over each
(request_id, data)pair in the responses dictionary. - Looks up the pending request associated with that
request_id. - Resolves the executor and method that originally emitted the request.
- Invokes the
@response_handler-decorated method on that executor with the matched request and response.
This design ensures that responses are always delivered to the correct handler, even in workflows with multiple executors or multiple concurrent request_info events.
Multiple Requests and Iterative Loops
A workflow may emit multiple request_info events before suspending, and the calling application can supply responses for all of them in a single workflow.run(responses={...}) call. Additionally, a response handler may itself emit further request_info events, creating an iterative human-in-the-loop loop:
- Workflow emits request_info events
- Application collects responses from human
- Application resumes workflow with responses
- Response handlers process data, potentially emitting new request_info events
- Repeat until workflow completes
This iterative pattern supports complex multi-step data collection workflows where each step depends on the results of previous human inputs.
Type Safety
The @response_handler decorator preserves type information from the method signature. The RequestType and ResponseType generic parameters are inferred from the method's type annotations, ensuring that the framework can validate response data against the expected types at runtime.
Theoretical Basis
The Human-in-the-Loop Response principle implements a coroutine-style suspension and resumption model for workflows. Rather than blocking a thread while waiting for human input, the workflow yields control back to the calling application and resumes only when a response is available. This maps naturally to the async/await paradigm in Python.
The pattern is an instance of the Request-Response communication model, where the request and response are correlated by a shared identifier (request_id). This correlation mechanism is essential in systems where multiple requests may be outstanding simultaneously.
From a safety perspective, this pattern enforces a mandatory human checkpoint at designated points in the workflow. The workflow cannot proceed past a request_info call without receiving explicit human input, ensuring that critical decisions remain under human control.
Related Pages
- Implementation:Microsoft_Agent_framework_Response_Handler_Decorator
- Principle: Approval Response Handling -- related human-in-the-loop pattern for tool approval
- Principle: Approval Request Detection -- detecting when approval is needed
Sources
| Type | Name | URL |
|---|---|---|
| Repo | Microsoft Agent Framework | https://github.com/microsoft/agent-framework |