microsoft / microsoft/agent-framework

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

Open
#4,158 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

.NET
Dominant language
Python
Stars
13.6k
Forks
2.3k
Avg merge
2d 45m
Merged PRs (30d)
358

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` but classes don't exist in preview

**Evidence from our investigation:**

```csharp
// 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

```csharp
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
{
public abstract Task OnProcessAsync(
TContext context,
Func 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

- ADR-0007 mentions callback patterns: https://github.com/microsoft/agent-framework/blob/main/docs/decisions/0007-agent-filtering-middleware.md
- `.UseCallbacks()` exists but requires `CallbackMiddleware` (not available)

## 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!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with docs/decisions/0007-agent-filtering-middleware.md and the existing .UseCallbacks() reference, then inspect the Microsoft.Agents.AI preview API mentioned in the issue. Define how callbacks reach nested MCP tool invocations, suspend before execution, and resume with the original context and arguments; done means a nested write tool can be intercepted for HITL approval without executing prematurely.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
ai, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.