Skip to content

.NET: Handoff workflow raises two approval requests for one tool call, and resuming reports an error after the tool has executed #8577

Description

Versions

  • Microsoft.Agents.AI.Foundry.Hosting 1.22.0-preview.260918.1 (also 1.21.0-preview)
  • Microsoft.Agents.AI.Workflows 1.22.0
  • Deployed to Foundry with azd code deploy, runtime dotnet_10, protocol responses 2.0.0

Setup

Two agents in a handoff workflow built with AgentWorkflowBuilder.CreateHandoffBuilderWith(...), exposed as a single agent with workflow.AsAIAgent(...) and served with AddFoundryResponses(...). One tool is wrapped in ApprovalRequiredAIFunction:

tools: [
    AIFunctionFactory.Create(GetRestaurants, nameof(GetRestaurants)),
    new ApprovalRequiredAIFunction(AIFunctionFactory.Create(BookTable, nameof(BookTable)))
]

What happens

1. One tool call produces two approval requests. The response contains two mcp_approval_request items with different ids and identical arguments, for a single BookTable call:

mcpr_E41E3C55A3EF084A2EE2339780FE661F4219A723CCDEE141E6  BookTable  {"restaurant":"The Domain Kitchen", ...}
mcpr_A3C8F9317B062E63C739D44A10DA0DE19C79BF37FBFB2A1869  BookTable  {"restaurant":"The Domain Kitchen", ...}

The same agent without a handoff workflow produces one.

2. Answering fails the run, after the tool has already executed. Posting mcp_approval_response for both ids (answering only one behaves the same) returns HTTP 200 with:

{
  "status": "failed",
  "error": { "code": "server_error", "message": "An error occurred while executing the workflow." },
  "output": [
    { "type": "function_call", "name": "BookTable" },
    { "type": "function_call_output", "output": "{\"reference\":\"BK-4651\", ... }" },
    { "type": "message", "role": "assistant", "content": [ { "type": "output_text",
      "text": "Booked: The Domain Kitchen (Auckland) for 2 people on 2026-09-26 at 19:00. Booking reference: BK-4651" } ] }
  ]
}

So the side effect happens and the caller is told the run failed. A client that retries on failure would book twice.
Image

3. Nothing is logged. Container logs for the session show no exception and all four POST /responses completing HTTP 200. The failure exists only in the response payload, which makes this hard to diagnose from logs.

4. The response carrying the approval is marked completed. Not incomplete, so a client cannot use the status to tell that something is waiting on a human; it has to look for the item.

Expected

One mcp_approval_request per tool call, and answering it completes the run.

Note

In-process the same workflow behaves correctly: the run pauses with ToolApprovalRequestContent, CreateResponse(approved) resumes it, and the tool runs only after approval.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETUsage: [Issues, PRs], Target: .NettriageUsage: [Issues], Target: All issues that still need to be triaged

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions