Skip to content

.NET: [Feature Request] Function Invocation Middleware for Nested Tools (HITL Support) #4158

Description

Use Case

We need to intercept MCP tool invocations within nested agents (e.g., FinancialAgent called via handoff from TriageAgent) to implement Human-in-the-Loop (HITL) approval workflows.

Our application requires user confirmation before executing write operations (create transactions, update budgets, delete records). The workflow involves:

  1. User sends message to TriageAgent
  2. TriageAgent hands off to FinancialAgent (or other specialized agent)
  3. FinancialAgent invokes MCP tools (e.g., register_expense)
  4. Before tool execution, we need to suspend workflow and request user approval
  5. Resume workflow after approval with same context

Current Limitation

  • response.Messages only exposes top-level handoffs (e.g., handoff_to_1)
  • MCP tool invocations within handoffed agents are hidden from the response
  • No callback API available to intercept tool execution before it occurs
  • Documentation references CallbackMiddleware<AgentFunctionInvocationCallbackContext> but classes don't exist in preview

Evidence from our investigation:

// What we receive in response.Messages:
FunctionCallContent { Name: "handoff_to_1" }  // ❌ Handoff, not tool name

// What we need to intercept:
FunctionCallContent { Name: "register_expense" }  // ✅ Actual MCP tool

Package version tested: Microsoft.Agents.AI 1.0.0-preview.260212.1

Requested API

1. Function Invocation Callback Middleware

public class AgentFunctionInvocationCallbackContext
{
    public AIFunction Function { get; set; }
    public AIFunctionArguments Arguments { get; set; }
    public bool Terminate { get; set; }  // Suspend workflow before execution
}

public abstract class CallbackMiddleware<TContext>
{
    public abstract Task OnProcessAsync(
        TContext context,
        Func<TContext, Task> next,
        CancellationToken cancellationToken);
}

2. Expose Nested Tool Calls in Response

Either:

  • Option A: Include nested tool invocations in response.Messages (e.g., register_expense alongside handoff_to_1)
  • Option B: Invoke callbacks BEFORE tool execution (even for nested tools within handoffs)

3. Checkpoint Resumption with Context

  • Resume workflow from suspended state after approval
  • Restore exact context at suspension point
  • Execute approved tool with original arguments

Workaround Impact

Without this API:

  • ❌ ALL write operations execute without user confirmation
  • ❌ Violates GDPR/LGPD compliance (no explicit consent for data mutations)
  • ❌ Cannot implement HITL workflows for 22 critical operations
  • ❌ Users may create accidental transactions/deletions

Business Impact: Cannot deploy to production without HITL compliance.

Related Documentation

Proposed Timeline

This is a blocking issue for production deployment. We have prepared code for callback implementation and are ready to integrate as soon as the API is available.

Thank you for considering this feature request!

Activity

  1. added
    .NETUsage: [Issues, PRs], Target: .Net
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Feb 22, 2026
  2. changed the title [-][Feature Request] Function Invocation Middleware for Nested Tools (HITL Support)[/-] [+].NET: [Feature Request] Function Invocation Middleware for Nested Tools (HITL Support)[/+] on Feb 22, 2026
  3. arturteplov commented on Oct 18, 2026

    @arturteplov

    LI (@ktz03) How are you currently handling MCP tool permissions across nested agent handoffs, particularly when execution needs to pause for approval and resume with the same context?

  4. ktz03 commented on Oct 19, 2026

    @ktz03
    Contributor

    Artur Teplov (@arturteplov) I’d use the current .NET approval sample as a starting point: it resumes with the matching approval response and the same AgentSession. I haven’t checked the nested MCP handoff/restart case yet. Which SDK/version and handoff setup are you using, and should the approval survive a process restart? We can work through a small example together.

  5. arturteplov commented on Oct 20, 2026

    @arturteplov

    LI (@ktz03) I looked through the sample. I’d like to extend it to nested MCP tool approvals and test whether authorization and context survive a process restart.

    I haven’t picked an SDK version yet. Which version and persistence approach would you use?

    Happy to put together a minimal repro.

  6. ktz03 commented on Oct 20, 2026

    @ktz03
    Contributor

    Artur Teplov (@arturteplov) I'd pin the repro to .NET 10 and Agent Framework 1.25.0, using that release's session serialization sample with a local JSON file first.
    I'd save each participating agent's session and the app's pending-request correlation, then reload the sessions and recreate the same tool bindings and MCP authentication after restart; session persistence and human tool approval do not preserve MCP credentials or server-side authorization.
    I haven't verified that nested restart path, and the same-version approval sample notes that unanswered requests are rejected on the next run, so the matching decision needs to accompany continuation.
    Could you share a one-parent/one-child/one-tool repro with the model provider and MCP transport pinned; I'll check the approval/session routing against the no-restart control, with context preserved, no tool execution before approval or after rejection, and one execution after approval as the initial checks?

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: .Net

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions