微软的代理框架拯救圣诞节
简介
寻找完美的圣诞礼物可能会带来压力。在集思广益的礼物创意、比较各商店的价格以及确保所有物品准时到达之间,假日购物很快就会变得势不可挡。如果我们可以将这些任务委托给协同工作的专门人工智能代理会怎么样?在这篇文章中,我们将探讨如何使用 Microsoft 的代理框架构建一个多代理系统,其中每个代理专门从事特定任务,从生成礼物创意到比较价格,所有这些都通过工作流程进行协调。
2025 年科技节日日历
<p对齐=“中心”>

该项目是我在 2025 年节日科技日历 会议的一部分,这是一场在节日期间庆祝科技的精彩社区活动。您可以在 Sessionize 上找到有关该活动的更多信息。
什么是微软的代理框架?
Agent Framework 是 Microsoft 用于构建、编排和部署 AI 代理和多代理系统的解决方案。它为创建可以顺序、并发或通过切换模式工作的代理提供了灵活的基础。该框架支持 OpenAI、Azure OpenAI 和 Microsoft Foundry 模型,使其具有令人难以置信的多功能性。
主要特点包括:
- 多代理编排:群聊、顺序、并发和切换模式
- 插件生态系统:使用本机功能、OpenAPI 和模型上下文协议 (MCP) 进行扩展
- 工作流支持:使用执行器和边缘构建复杂的代理管道
先决条件
在深入研究代码之前,请确保您拥有:
- .NET 9
- Azure OpenAI 访问(或 OpenAI API 密钥)
- Visual Studio 或 Visual Studio Code
安装所需的软件包(请注意,在预览中需要 --prerelease 标志):
dotnet add package Microsoft.Agents.AI.OpenAI --prerelease
dotnet add package Microsoft.Agents.AI.Workflows --prerelease
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity
dotnet add package Azure.AI.Agents.Persistent --prerelease
礼品代购
我们的圣诞礼物搜寻器将由三个专业代理组成:
- 礼品创意代理 - 根据收件人的个人资料生成创意礼品建议
- 价格比较代理 - 查找不同商店的最优惠价格
- Summary Agent - 编译最终建议
模型
让我们首先定义将流经代理管道的数据模型:
public class GiftRecipient
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public List<string> Interests { get; set; } = [];
public decimal Budget { get; set; }
}
public class GiftIdea
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string Category { get; set; } = string.Empty;
public decimal EstimatedPrice { get; set; }
}
public class PriceResult
{
public string GiftName { get; set; } = string.Empty;
public string Store { get; set; } = string.Empty;
public decimal Price { get; set; }
public string Url { get; set; } = string.Empty;
}
public class GiftRecommendation
{
public GiftIdea Gift { get; set; } = new();
public List<PriceResult> Prices { get; set; } = [];
public PriceResult? BestDeal { get; set; }
}
构建代理
代理框架的优点在于创建专用代理是多么容易。每个代理只是一个 ChatClientAgent,具有定义其专业知识的特定系统提示。
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
public static class ChristmasAgentFactory
{
public static AIAgent CreateGiftIdeaAgent(IChatClient chatClient)
{
return new ChatClientAgent(
chatClient,
@"You are a creative Christmas gift advisor. When given information about a person
(age, interests, budget), you suggest thoughtful and personalized gift ideas.
For each suggestion, provide:
- Gift name
- Brief description of why it's a good fit
- Category (Electronics, Books, Fashion, Home, Experience, etc.)
- Estimated price range
Always suggest 3-5 gift options within the specified budget.
Format your response as a structured list.");
}
public static AIAgent CreatePriceComparisonAgent(IChatClient chatClient)
{
return new ChatClientAgent(
chatClient,
@"You are a price comparison specialist. Given a list of gift ideas,
you research and compare prices from different online retailers.
For each gift, provide:
- Store name (Amazon, Best Buy, Target, Walmart, etc.)
- Current price
- Any available discounts or deals
Always highlight the best deal for each item.
Consider shipping costs and delivery times for Christmas.");
}
public static AIAgent CreateSummaryAgent(IChatClient chatClient)
{
return new ChatClientAgent(
chatClient,
@"You are a gift recommendation summarizer. Take the gift ideas and price
comparisons and create a final recommendation report.
Your summary should:
- Rank gifts by value (quality vs price)
- Highlight the top pick with reasoning
- Include total cost estimate
- Add any tips for holiday shopping
Make the summary cheerful and festive!");
}
}
创建工作流程
现在到了有趣的部分,将我们的代理连接到顺序工作流程中。 Agent 框架提供了 WorkflowBuilder 和 AgentWorkflowBuilder 将代理组成不同的模式。
public static class ChristmasGiftWorkflow
{
public static async Task RunAsync()
{
// Set up the Azure OpenAI client
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME")
?? "gpt-4o-mini";
var chatClient = new AzureOpenAIClient(
new Uri(endpoint),
new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsIChatClient();
// Create our specialized agents
AIAgent giftIdeaAgent = ChristmasAgentFactory.CreateGiftIdeaAgent(chatClient);
AIAgent priceAgent = ChristmasAgentFactory.CreatePriceComparisonAgent(chatClient);
AIAgent summaryAgent = ChristmasAgentFactory.CreateSummaryAgent(chatClient);
// Build a sequential workflow: Ideas -> Prices -> Summary
var workflow = AgentWorkflowBuilder.BuildSequential(
"ChristmasGiftFinder",
[giftIdeaAgent, priceAgent, summaryAgent]);
// Define our gift recipient
var recipient = new GiftRecipient
{
Name = "Mom",
Age = 55,
Interests = ["gardening", "cooking", "reading", "yoga"],
Budget = 100
};
var prompt = $@"Find Christmas gifts for {recipient.Name},
age {recipient.Age}, who enjoys {string.Join(", ", recipient.Interests)}.
Budget: ${recipient.Budget}";
// Execute the workflow with streaming
await using StreamingRun run = await InProcessExecution.StreamAsync(
workflow,
new ChatMessage(ChatRole.User, prompt));
// Send the turn token to start processing
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
// Watch for workflow events
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
if (evt is AgentRunUpdateEvent agentUpdate)
{
Console.Write(agentUpdate.Data);
}
else if (evt is WorkflowOutputEvent outputEvent)
{
Console.WriteLine("\n🎄 Final Recommendations:");
Console.WriteLine(outputEvent.Data);
}
}
}
}
同时运行代理
如果我们想同时为多人寻找礼物怎么办? Agent框架支持并发执行,非常适合这种场景:
public static async Task FindGiftsForEveryoneAsync(IChatClient chatClient, List<GiftRecipient> recipients)
{
// Create an agent for each recipient
var agents = recipients.Select(r => new ChatClientAgent(
chatClient,
$@"Find the perfect Christmas gift for {r.Name} (age {r.Age}),
who loves {string.Join(", ", r.Interests)}. Budget: ${r.Budget}.
Provide one well-researched recommendation with price."
)).ToList();
// Build a concurrent workflow - all agents run in parallel
var workflow = AgentWorkflowBuilder.BuildConcurrent(
"FamilyGiftFinder",
agents);
await using StreamingRun run = await InProcessExecution.StreamAsync(
workflow,
new ChatMessage(ChatRole.User, "Find gifts now!"));
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
if (evt is WorkflowOutputEvent output)
{
Console.WriteLine("🎁 All gift recommendations ready!");
Console.WriteLine(output.Data);
}
}
}
自定义执行器以实现更多控制对于更复杂的场景,您可以创建自定义执行器,以便对工作流程进行细粒度控制:
public sealed class GiftValidatorExecutor : Executor<List<ChatMessage>, List<ChatMessage>>
{
public GiftValidatorExecutor() : base("GiftValidator") { }
public override async ValueTask<List<ChatMessage>> HandleAsync(
List<ChatMessage> messages,
IWorkflowContext context,
CancellationToken cancellationToken = default)
{
var lastMessage = messages.LastOrDefault()?.Text ?? "";
// Validate that suggestions are within budget
if (lastMessage.Contains("over budget", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("⚠️ Some suggestions exceeded budget, filtering...");
// Add validation logic here
}
Console.WriteLine("✅ Gift suggestions validated!");
return messages;
}
}
然后,您可以将此执行器插入到您的工作流程中:
var validator = new GiftValidatorExecutor();
var workflow = new WorkflowBuilder(giftIdeaAgent)
.AddEdge(giftIdeaAgent, validator)
.AddEdge(validator, priceAgent)
.AddEdge(priceAgent, summaryAgent)
.WithOutputFrom(summaryAgent)
.Build();
使用 Bing 基础添加真实的 Web 搜索
到目前为止,我们的代理根据人工智能模型的知识生成响应。但是,如果我们想在网络上搜索实际产品价格和库存情况该怎么办?这就是 Grounding with Bing Search 的用武之地。它是 Microsoft Foundry(以前称为 Azure AI Foundry)中提供的工具,允许您的代理在生成响应时合并实时公共 Web 数据。
首先,您需要在 Azure 门户 中创建 Grounding with Bing Search 资源。确保将其创建在与您的 AI 项目相同的资源组中。
使用 Bing 搜索设置基础
Grounding with Bing Search 的优点在于它直接与 Azure AI Agent 集成。代理根据用户的查询决定何时使用搜索工具,搜索网络,并使用结果生成接地响应。
using Azure.AI.Agents.Persistent;
using Azure.Identity;
public static class BingGroundingSetup
{
public static async Task<PersistentAgent> CreateAgentWithBingGroundingAsync(
string projectEndpoint,
string modelDeploymentName,
string bingConnectionId)
{
// Create the Persistent Agents client
var agentClient = new PersistentAgentsClient(projectEndpoint, new DefaultAzureCredential());
// Configure the Bing Grounding tool
var bingGroundingTool = new BingGroundingToolDefinition(
new BingGroundingSearchToolParameters(
[new BingGroundingSearchConfiguration(bingConnectionId)]
)
);
// Create the agent with Bing Grounding enabled
var agent = await agentClient.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "ChristmasPriceHunter",
instructions: @"You are a Christmas gift price comparison specialist.
When given gift ideas, use Bing to search for:
- Current prices at major retailers (Amazon, Best Buy, Target, Walmart)
- Available discounts and holiday deals
- Shipping times to ensure delivery before Christmas
Always provide URLs to the products you find.
Highlight the best deals and recommend where to buy.",
tools: [bingGroundingTool]
);
return agent;
}
}
创建具有真实搜索的价格比较代理
现在让我们创建一个完整的价格比较代理,用于在网络上搜索真实的产品信息:
using Azure.AI.Agents.Persistent;
using Azure.Identity;
public class ChristmasPriceAgent
{
private readonly PersistentAgentsClient _client;
private readonly string _modelDeployment;
private readonly string _bingConnectionId;
public ChristmasPriceAgent(string projectEndpoint, string modelDeployment, string bingConnectionId)
{
_client = new PersistentAgentsClient(projectEndpoint, new DefaultAzureCredential());
_modelDeployment = modelDeployment;
_bingConnectionId = bingConnectionId;
}
public async Task<string> FindGiftPricesAsync(string giftIdeas)
{
// Create agent with Bing Grounding
var bingTool = new BingGroundingToolDefinition(
new BingGroundingSearchToolParameters(
[new BingGroundingSearchConfiguration(_bingConnectionId)]
)
);
var agent = await _client.Administration.CreateAgentAsync(
model: _modelDeployment,
name: "PriceHunter",
instructions: @"Search the web for current prices on the given gift ideas.
For each gift, find prices from at least 2-3 different stores.
Include direct links to the products.
Note any Christmas sales or discounts available.",
tools: [bingTool]
);
try
{
// Create a thread for the conversation
var thread = await _client.Threads.CreateThreadAsync();
// Add the gift ideas as a message
await _client.Messages.CreateMessageAsync(
thread.Id,
MessageRole.User,
$"Find current prices for these gift ideas: {giftIdeas}"
);
// Run the agent
var run = await _client.Runs.CreateRunAsync(thread.Id, agent.Id);
// Wait for completion
do
{
await Task.Delay(500);
run = await _client.Runs.GetRunAsync(thread.Id, run.Id);
}
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress);
// Get the response
var messages = _client.Messages.GetMessages(thread.Id);
var response = messages
.Where(m => m.Role == MessageRole.Agent)
.SelectMany(m => m.ContentItems)
.OfType<MessageTextContent>()
.FirstOrDefault();
// Clean up
await _client.Threads.DeleteThreadAsync(thread.Id);
return response?.Text ?? "No results found.";
}
finally
{
// Clean up the agent
await _client.Administration.DeleteAgentAsync(agent.Id);
}
}
}
将 Bing Grounding 集成到工作流程中
以下是如何在完整的礼品搜寻工作流程中使用 Bing 支持的价格代理:
public static async Task RunWithBingGroundingAsync()
{
var projectEndpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT")!;
var modelDeployment = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4o";
var bingConnectionId = Environment.GetEnvironmentVariable("BING_CONNECTION_ID")!;
// Connection ID format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}/projects/{project}/connections/{connection}
Console.WriteLine("🔍 Searching the web for real prices with Bing Grounding...\n");
var priceAgent = new ChristmasPriceAgent(projectEndpoint, modelDeployment, bingConnectionId);
// First, generate gift ideas (could come from another agent)
var giftIdeas = "1. Milwaukee cordless drill set, 2. Weber portable grill, 3. Carhartt beanie";
// Search for real prices
var priceResults = await priceAgent.FindGiftPricesAsync(giftIdeas);
Console.WriteLine("📊 Price Comparison Results:");
Console.WriteLine(priceResults);
Console.WriteLine("\n🎁 Happy Shopping! 🎁");
}
处理来自 Bing 结果的引用
Bing 搜索扎根的一个重要方面是回复中包含带有源网站链接的引用。以下是提取和显示它们的方法:
public static void ProcessBingGroundingResponse(IEnumerable<PersistentThreadMessage> messages)
{
foreach (var message in messages.Where(m => m.Role == MessageRole.Agent))
{
foreach (var content in message.ContentItems)
{
if (content is MessageTextContent textContent)
{
var response = textContent.Text;
// Process URL citations
if (textContent.Annotations != null)
{
foreach (var annotation in textContent.Annotations)
{
if (annotation is MessageTextUriCitationAnnotation uriAnnotation)
{
// Replace citation placeholder with markdown link
response = response.Replace(
uriAnnotation.Text,
$" [{uriAnnotation.UriCitation.Title}]({uriAnnotation.UriCitation.Uri})"
);
}
}
}
Console.WriteLine(response);
}
}
}
}
现在,当价格比较代理运行时,它使用 Grounding with Bing Search 从实时网络中查找真实的产品列表、当前价格和可用交易。代理根据查询自动决定何时进行搜索,并返回带有正确引用的接地响应。
完整的程序
以下是 Program.cs 中所有内容的组合方式:
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
Console.WriteLine("🎄 Christmas Gift Finder - Powered by AI Agents 🎄\n");
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!;
var deployment = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetChatClient(deployment)
.AsIChatClient();
// Create the agent team
var ideaAgent = ChristmasAgentFactory.CreateGiftIdeaAgent(chatClient);
var priceAgent = ChristmasAgentFactory.CreatePriceComparisonAgent(chatClient);
var summaryAgent = ChristmasAgentFactory.CreateSummaryAgent(chatClient);
// Build the workflow
var workflow = AgentWorkflowBuilder.BuildSequential(
"ChristmasGiftWorkflow",
[ideaAgent, priceAgent, summaryAgent]);
Console.Write("Who are you shopping for? ");
var recipientName = Console.ReadLine() ?? "Someone special";
Console.Write("What are their interests? ");
var interests = Console.ReadLine() ?? "general";
Console.Write("What's your budget? $");
var budget = Console.ReadLine() ?? "50";
var prompt = $"Find Christmas gifts for {recipientName} who enjoys {interests}. Budget: ${budget}";
Console.WriteLine("\n🔍 Searching for the perfect gifts...\n");
await using var run = await InProcessExecution.StreamAsync(
workflow,
new ChatMessage(ChatRole.User, prompt));
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
await foreach (var evt in run.WatchStreamAsync())
{
switch (evt)
{
case AgentRunUpdateEvent update:
Console.Write(update.Update.Text);
break;
case WorkflowOutputEvent output:
Console.WriteLine("\n\n🎁 Happy Shopping! 🎁");
break;
}
}
结论
Microsoft 的代理框架使构建多代理系统变得异常容易,其中每个代理专门从事特定任务。通过通过工作流程协调这些代理,我们可以以结构化且高效的方式解决圣诞节购物等复杂问题。
让它变得更加强大的是通过工具添加现实世界功能的能力。通过将 Grounding 与 Microsoft Foundry 的 Bing Search 集成,我们的价格比较代理实际上可以在网络上搜索当前价格、交易和库存情况,将简单的 AI 聊天机器人转变为具有正确引用的真正有用的购物助手。
该框架对顺序、并发和切换模式的支持意味着您可以设计符合您确切需求的代理系统。无论是寻找礼物、计划旅行还是任何其他多步骤任务,代理框架都提供了实现这些目标的构建块。这个假期,让人工智能代理来处理研究,而您则专注于包装礼物并享受与家人共度的时光!
源代码
本文中显示的概念基于官方代理框架示例。您可以在 Microsoft Agent Framework GitHub 存储库 上探索更多示例。
节日快乐,编码愉快! 🎄