-
Notifications
You must be signed in to change notification settings - Fork 1.5k
.NET: Approval requests handling in workflows #1973
Copy link
Copy link
Open
Labels
.NETrequested-infoworkflowsRelated to Workflows in agent-frameworkRelated to Workflows in agent-framework
Description
I couldn't find a way to handle user input requests (human in the loop) in the workflow event loop. I was expecting this could be as simple as just type checking for a type extending WorkflowEvent but I don't see one being returned.
If I just let the loop run, I see an ExecutorFailedEvent with the error:
[Event: ExecutorFailedEvent(Executor = 4c39304655fc445bbee8b75ab7d09ca9, Data: System.InvalidOperationException = System.InvalidOperationException: FunctionApprovalRequestContent found with FunctionCall.CallId(s) 'call_tzJTA2K8mNGedRAc4aSjDxst' that have no matching FunctionApprovalResponseContent.
I tried to send the approval response with TrySendMessageAsync but it didn't reach the IChatClient, aditionally, in a non-streaming case, this is not available. I'm not sure if I'm missing a piece in the puzzle but I think it should have a better UX if that's the case.
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Azure.Identity;
using Azure.AI.OpenAI;
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var endpoint = "https://<my-endpoint>.openai.azure.com";
var deploymentName = "gpt-4o-mini";
IChatClient client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetOpenAIResponseClient(deploymentName)
.AsIChatClient();
AIAgent agentA = new ChatClientAgent(client, options:
new ChatClientAgentOptions
{
ChatOptions = new ChatOptions
{
Tools = [new HostedMcpServerTool("deep-wiki", "https://mcp.deepwiki.com/sse")
{
// hosted MCP requires tool approval by default,
// uncommenting this would workaround the approval shortcoming
// but that's not the point of the sample
// ApprovalMode = HostedMcpServerToolApprovalMode.NeverRequire
},
// Similarly, using below line would avoid approval requirement for client functions.
//AIFunctionFactory.Create((object e) => $"Echo {e}", "echo_tool")
new ApprovalRequiredAIFunction(AIFunctionFactory.Create((object e) => $"Echo {e}", "echo_tool")),
]},
Instructions = "Use your tools to address user petitions, truncate the response to 20 words."
});
AIAgent agentB = new ChatClientAgent(client, options:
new ChatClientAgentOptions
{
Instructions = "You are an expert translator, translate the input text to Spanish and only the text provided, truncate the response to 20 words."
});
WorkflowBuilder builder = new(agentA);
builder.AddEdge(agentA, agentB);
Workflow workflow = builder.Build();
await using StreamingRun run = await InProcessExecution.StreamAsync(workflow,
new List<ChatMessage> { new ChatMessage(ChatRole.User,
"Use the echo_tool to echo the value 42") });
//"Where's the README file for Microsoft.Extensions.AI package located in the dotnet/extensions repository?") }); // for MCP testing
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
Console.WriteLine($"[Event: {evt}]");
if (evt is AgentRunUpdateEvent runUpd)
{
foreach (var userInputRequest in runUpd.Update.UserInputRequests)
{
Console.WriteLine($"Approval request id: {userInputRequest.Id}");
if (userInputRequest is FunctionApprovalRequestContent farc)
{
// Create the approval response
FunctionApprovalResponseContent response = farc.CreateResponse(approved: true);
await run.TrySendMessageAsync(new ChatMessage(ChatRole.User, [response])); // didn't work.
}
else
{
// Handle MCP approval request
}
}
}
}
Console.WriteLine("Done.");cc @lokitoth @westey-m @stephentoub @jeffhandley
Related: #938, although that issue focuses on orchestration (AgentWorkflowBuilder).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
.NETrequested-infoworkflowsRelated to Workflows in agent-frameworkRelated to Workflows in agent-framework
Type
Projects
Status
Planned