Merge branch 'main' into crickman/dotnet-sample-improvements

This commit is contained in:
Chris
2026-02-19 13:49:56 -08:00
committed by GitHub
32 changed files with 2605 additions and 123 deletions
@@ -2,8 +2,9 @@
// This sample shows multiple middleware layers working together with Azure OpenAI:
// chat client (global/per-request), agent run (PII filtering and guardrails),
// function invocation (logging and result overrides), and human-in-the-loop
// approval workflows for sensitive function calls.
// function invocation (logging and result overrides), human-in-the-loop
// approval workflows for sensitive function calls, and MessageAIContextProvider
// middleware for injecting additional context messages into the agent pipeline.
using System.ComponentModel;
using System.Text.RegularExpressions;
@@ -96,6 +97,20 @@ var response = await originalAgent // Using per-request middleware pipeline with
Console.WriteLine($"Per-request middleware response: {response}");
// MessageAIContextProvider middleware that injects additional messages into the agent request.
// This allows any AIAgent (not just ChatClientAgent) to benefit from MessageAIContextProvider-based
// context enrichment. Multiple providers can be passed to Use and they are called in sequence,
// each receiving the output of the previous one.
Console.WriteLine("\n\n=== Example 5: MessageAIContextProvider middleware ===");
var contextProviderAgent = originalAgent
.AsBuilder()
.Use([new DateTimeContextProvider()])
.Build();
var contextResponse = await contextProviderAgent.RunAsync("Is it almost time for lunch?");
Console.WriteLine($"Context-enriched response: {contextResponse}");
// Function invocation middleware that logs before and after function calls.
async ValueTask<object?> FunctionCallMiddleware(AIAgent agent, FunctionInvocationContext context, Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next, CancellationToken cancellationToken)
{
@@ -259,3 +274,23 @@ async Task<ChatResponse> PerRequestChatClientMiddleware(IEnumerable<ChatMessage>
return response;
}
/// <summary>
/// A <see cref="MessageAIContextProvider"/> that injects the current date and time into the agent's context.
/// This is a simple example of how to use a MessageAIContextProvider to enrich agent messages
/// via the <see cref="AIAgentBuilder.Use(MessageAIContextProvider[])"/> extension method.
/// </summary>
internal sealed class DateTimeContextProvider : MessageAIContextProvider
{
protected override ValueTask<IEnumerable<ChatMessage>> ProvideMessagesAsync(
InvokingContext context,
CancellationToken cancellationToken = default)
{
Console.WriteLine("DateTimeContextProvider - Injecting current date/time context");
return new ValueTask<IEnumerable<ChatMessage>>(
[
new ChatMessage(ChatRole.User, $"For reference, the current date and time is: {DateTimeOffset.Now}")
]);
}
}
@@ -14,6 +14,7 @@ This sample demonstrates how to add middleware to intercept:
5. Perrequest chat client middleware
6. Perrequest function pipeline with approval
7. Combining agentlevel and perrequest middleware
8. MessageAIContextProvider middleware via `AIAgentBuilder.Use(...)` for injecting additional context messages
## Function Invocation Middleware
@@ -146,11 +146,11 @@ namespace SampleApp
}
/// <summary>
/// An <see cref="AIContextProvider"/> which searches for upcoming calendar events and adds them to the AI context.
/// A <see cref="MessageAIContextProvider"/> which searches for upcoming calendar events and adds them to the AI context.
/// </summary>
internal sealed class CalendarSearchAIContextProvider(Func<Task<string[]>> loadNextThreeCalendarEvents) : AIContextProvider
internal sealed class CalendarSearchAIContextProvider(Func<Task<string[]>> loadNextThreeCalendarEvents) : MessageAIContextProvider
{
protected override async ValueTask<AIContext> ProvideAIContextAsync(InvokingContext context, CancellationToken cancellationToken = default)
protected override async ValueTask<IEnumerable<MEAI.ChatMessage>> ProvideMessagesAsync(InvokingContext context, CancellationToken cancellationToken = default)
{
var events = await loadNextThreeCalendarEvents();
@@ -161,10 +161,7 @@ namespace SampleApp
outputMessageBuilder.AppendLine($" - {calendarEvent}");
}
return new AIContext
{
Messages = [new MEAI.ChatMessage(ChatRole.User, outputMessageBuilder.ToString())]
};
return [new MEAI.ChatMessage(ChatRole.User, outputMessageBuilder.ToString())];
}
}
}