Skip to content

.NET Workflows: RequestPort in Subworkflow (AsAgent) included in Parentworkflow (Handoff) never receives SendResponseAsync response #3766

@MichaelWilliamBaumann

Description

@MichaelWilliamBaumann

Scenario
I have a Human-in-the-Loop (HITL) workflow with a RequestPort that is wrapped via AsAgent() and integrated into a Handoff workflow. The nested workflow should request external input from the user, but the response never reaches the RequestPort, causing downstream executors to never be invoked.

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                        Handoff Workflow                             │
│  ┌──────────────┐     ┌─────────────────────────────────────────┐   │
│  │ HandoffStart │ ──▶ │            Main Agent                   │   │
│  └──────────────┘     │ (Triage/Router)                         │   │
│                       └────────────────┬────────────────────────┘   │
│                                        │ handoff_to_X               │
│                       ┌────────────────▼────────────────────────┐   │
│                       │   WorkflowHostExecutor (AsAgent)        │   │
│                       │  ┌────────────────────────────────────┐ │   │
│                       │  │       Inner HITL Workflow          │ │   │
│                       │  │  ┌──────────┐    ┌─────────────┐   │ │   │
│                       │  │  │RequestPort│ ──▶│ JudgeExecutor│  │ │   │
│                       │  │  └────┬─────┘    └──────┬──────┘   │ │   │
│                       │  │       │ ◀───────────────┘          │ │   │
│                       │  └───────│────────────────────────────┘ │   │
│                       └──────────│──────────────────────────────┘   │
│                                  │ RequestInfoEvent                 │
│                       ┌──────────▼──────────────────────────────┐   │
│                       │            HandoffEnd                    │   │
│                       └─────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘

Workflow Structure

Parent Workflow: Handoff workflow with a Main Agent (router/triage)
Sub-Agent: HITL workflow wrapped via AsAgent()
Contains a ChatToSignalAdapter (converts ChatMessages to signals)
Contains a RequestPort<NumberSignal, int> for external input
Contains a JudgeExecutor that processes the input
Integration: Main Agent calls handoff_to_X to invoke the HITL sub-agent

Expected Behavior

Main Agent routes to HITL sub-agent
RequestPort emits RequestInfoEvent (forwarded as FunctionCallContent)
User provides response via SendResponseAsync() with qualified PortId
RequestPort receives response and forwards it to downstream executor (JudgeExecutor)
JudgeExecutor processes the input and sends feedback or result
Loop continues until workflow completes

Actual Behavior

  1. Main Agent routes to HITL sub-agent
  2. RequestPort emits RequestInfoEvent (appears in AgentResponseUpdateEvent.RawRepresentation)
  3. User provides response via SendResponseAsync() (no error, returns successfully)
  4. RequestPort completes WITHOUT output
  5. WorkflowHostExecutor emits ExecutorCompleted prematurely
  6. JudgeExecutor is NEVER invoked
  7. Handoff workflow terminates the sub-agent
    Key observation: SendResponseAsync() accepts the response without error, but the response never reaches the inner workflow's RequestPort.

Root Cause Analysis
The WorkflowHostExecutor treats the inner workflow as "finished" as soon as it has no more events to emit. The RequestPort is waiting for the response, but the WorkflowHostExecutor interprets this as "workflow paused/ended" and signals ExecutorCompleted.

Lifecycle Issue:

  1. Inner workflow starts
  2. RequestPort emits RequestInfoEvent
  3. WorkflowHostExecutor forwards event to parent
  4. Inner workflow has no more immediate events
  5. WorkflowHostExecutor emits ExecutorCompleted (TOO EARLY!)
  6. Handoff workflow terminates sub-agent
  7. User code calls SendResponseAsync()
  8. Response goes nowhere → RequestPort never receives it

What can I do to use HITL correctly in a workflow AsAgent within a parent handoff workflow, including the request/response system? Is there a plan to handle such a scenario? How i understand the RequestInfoEvent is parsed as FunctionCallContent, and because of the workflow isolation level the PendingRequests from the wf AsAgent doesnt exists in the Parent Handoff Workflow Level.

Metadata

Metadata

Assignees

Labels

.NETagent orchestrationIssues related to agent orchestrationv1.1Fast follow up items post v1.0 release.

Type

Projects

Status

In Review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions