首页
/ AutoGen .NET 集成 Semantic Kernel 实战:两个 Agent、两个中间件与消息桥接原理

AutoGen .NET 集成 Semantic Kernel 实战:两个 Agent、两个中间件与消息桥接原理

2026-09-04 09:53:10作者:毕习沙Eudora

本文围绕 AutoGen .NET(AutoGen.Net)的 AutoGen.SemanticKernel 包展开,系统讲解 SemanticKernelAgentSemanticKernelChatCompletionAgent 两类封装 Agent 的构造参数、行为差异,以及 SemanticKernelChatMessageContentConnectorKernelPluginMiddleware 两个中间件的桥接机制,并结合仓库中的示例与测试用例给出可直接运行的接入代码。读完本文,你可以把 Semantic Kernel 的 Kernel/ChatCompletionAgent 无缝嵌入 AutoGen 的消息体系与编排框架,甚至把 Kernel 插件函数挂载到 OpenAIChatAgent 这类非 SK 系 Agent 上。

包定位与组件总览

AutoGen.SemanticKernel 是 AutoGen.Net 与 Semantic Kernel 之间的官方集成包,对应 安装指南 中列出的“provides the integration agents over semantic kernel”的包之一。从工程配置看,该包依赖 Microsoft.SemanticKernelMicrosoft.SemanticKernel.Agents.CoreMicrosoft.SemanticKernel.Connectors.AzureOpenAI,并引用 AutoGen.Core(见 AutoGen.SemanticKernel.csproj),因此它复用的是 AutoGen 核心消息与中间件抽象,而非 AutoGen 全家桶。

按照 AutoGen.SemanticKernel Overview,该包提供 2 个 Agent 与 2 个中间件:

组件 类型 作用
SemanticKernelAgent Agent 对 Semantic Kernel Kernel 的瘦封装,仅原生支持 IMessage<ChatMessageContent>;配合 Connector 中间件后可支持 AutoGen 内置消息类型
SemanticKernelChatCompletionAgent Agent Microsoft.SemanticKernel.Agents.ChatCompletionAgent 的瘦封装
SemanticKernelChatMessageContentConnector 中间件 在 AutoGen 内置消息类型(TextMessage/ImageMessage/MultiModalMessage)与 ChatMessageContent 之间双向转换;目前不支持 ToolCallMessageToolCallResultMessage 等函数调用消息
KernelPluginMiddleware 中间件 让你在其他 AutoGen Agent(如 OpenAIChatAgent)中使用 Semantic Kernel 插件函数

所有类型均位于 AutoGen.SemanticKernel 命名空间,源码集中在 dotnet/src/AutoGen.SemanticKernel 目录下。

SemanticKernelAgent:基于 Kernel 的流式 Agent

SemanticKernelAgent 是文档中推荐的核心入口,其构造函数签名与参数语义如下(见 SemanticKernelAgent.cs):

public SemanticKernelAgent(
    Kernel kernel,
    string name,
    string systemMessage = "You are a helpful AI assistant",
    string? modelServiceId = null,
    PromptExecutionSettings? settings = null)
  • kernel:承载模型连接与插件的 Semantic Kernel 实例;
  • name:Agent 名称,同时作为回复消息的 from 字段;
  • systemMessage:系统提示词,默认 "You are a helpful AI assistant"
  • modelServiceId:可选的 keyed service id,用于在 Kernel 注册了多个 IChatCompletionService 时按 id 选取;
  • settings:可选的 PromptExecutionSettings

从源码结构看,它实现了 IStreamingAgent 接口,同时支持 GenerateReplyAsyncGenerateStreamingReplyAsync。几个关键实现细节值得注意:

  1. 系统消息自动补齐BuildChatHistory 会先转换历史消息,若其中不存在 System 角色消息,则把 systemMessage 自动拼接到历史开头(SemanticKernelAgent.cs)。也就是说,你既可以在构造时传 systemMessage,也可以在消息序列里显式携带一条 System 消息,二者取其一即可,不会重复注入。
  2. 执行参数默认值:若未提供 settingsBuildOption 会构造 OpenAIPromptExecutionSettings,默认 Temperature = 0.7MaxTokens = 1024,并透传 options.StopSequence;同时强制设置 ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctionsSemanticKernelAgent.cs)。这意味着挂在 Kernel 上的插件函数(如 Bing 搜索插件)会被自动调用,无需额外配置。
  3. 消息类型约束ProcessMessage 只接受 IMessage<ChatMessageContent>,其余类型直接抛 ArgumentExceptionSemanticKernelAgent.cs)。这是“瘦封装”的体现——要使用 TextMessage 等内置类型,必须注册 Connector 中间件。
  4. 单结果约束:无论流式还是非流式,ResultsPerPrompt 大于 1 或流式响应中出现 ChoiceIndex > 0 都会抛 InvalidOperationException

另外,包内还提供了一个便捷扩展方法 ToSemanticKernelAgentKernelExtension.cs),可以在 Kernel 实例上一行完成 Agent 创建:

using AutoGen.SemanticKernel.Extension;

var skAgent = kernel.ToSemanticKernelAgent(name: "assistant");

最小可运行示例

仓库示例 Create_Semantic_Kernel_Agent.cs 展示了完整的接入流程:

using AutoGen.Core;
using AutoGen.SemanticKernel.Extension;
using Microsoft.SemanticKernel;

var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
    ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
var modelId = "gpt-3.5-turbo";
var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(modelId: modelId, apiKey: openAIKey)
    .Build();

var skAgent = new SemanticKernelAgent(
    kernel: kernel,
    name: "assistant",
    systemMessage: "You are a helpful AI assistant")
    .RegisterMessageConnector() // 注册消息桥接中间件,支持 TextMessage 等 AutoGen 内置类型
    .RegisterPrintMessage();     // 控制台打印消息

await skAgent.SendAsync("Hey tell me a long tedious joke");

其中 RegisterMessageConnector 是包内扩展方法(SemanticKernelAgentExtension.cs),若未传入 connector 实例则自动 new SemanticKernelChatMessageContentConnector(),最终注册为流式中间件,因此 skAgent 的类型变为 MiddlewareStreamingAgent<SemanticKernelAgent>

结合 Kernel 插件:以 Bing 搜索为例

SemanticKernelAgent 的最大优势在于直接复用 Kernel 的插件体系。仓库示例 Use_Bing_Search_With_Semantic_Kernel_Agent.cs 演示了把 WebSearchEnginePlugin 挂进 Kernel 后,Agent 自动具备联网搜索能力:

var bingApiKey = Environment.GetEnvironmentVariable("BING_API_KEY")
    ?? throw new Exception("BING_API_KEY environment variable is not set");
var bingSearch = new BingConnector(bingApiKey);
var webSearchPlugin = new WebSearchEnginePlugin(bingSearch);

var kernelBuilder = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(modelId: "gpt-3.5-turbo", apiKey: openAIKey);
kernelBuilder.Plugins.AddFromObject(webSearchPlugin);
var kernel = kernelBuilder.Build();

var skAgent = new SemanticKernelAgent(kernel, "assistant", "You are a helpful AI assistant")
    .RegisterMessageConnector()
    .RegisterPrintMessage();

await skAgent.SendAsync("Tell me more about gpt-4-o");

这里没有手动写任何函数调用逻辑——如前所述,默认执行参数中的 ToolCallBehavior.AutoInvokeKernelFunctions 会让 SK 自动完成“模型请求插件 → 执行插件 → 回传结果”的闭环。仓库测试 SemanticKernelAgentTest.cs 中的 SemanticKernelPluginTestAsync 用天气函数验证了同样路径:向 builder.Plugins.AddFromFunctions 注册 GetWeatherAsync 后,SendAsync("What is the weather in Seattle?") 的回复断言包含 "seattle" 与 "sunny",证实插件调用确实发生。

modelServiceId 参数也有对应测试佐证:BasicConversationTestWithKeyedServiceAsyncSemanticKernelAgentTest.cs)通过 AddAzureOpenAIChatCompletion(deploymentName, endpoint, key, modelServiceId) 注册 keyed service,再用 new SemanticKernelAgent(kernel, "assistant", modelServiceId: modelServiceId) 精确选中该服务,适用于一个 Kernel 中并存多个模型服务(例如不同部署或不同供应商)的场景。

SemanticKernelChatCompletionAgent:封装 SK 官方 Agent

第二个 Agent SemanticKernelChatCompletionAgent 是对 Microsoft.SemanticKernel.Agents.ChatCompletionAgent 的封装(SemanticKernelChatCompletionAgent.cs)。与 SemanticKernelAgent 不同,它只实现了 IAgent 接口(不支持流式),且构造时不接收 name——Name 直接取自被包装 Agent 的 Name 属性,若为空则抛 ArgumentNullExceptionSemanticKernelChatCompletionAgent.cs)。

其回复流程是:把历史消息转成 ChatHistory,包装为 ChatHistoryAgentThread 后调用底层 InvokeAsync,再把首条结果包成 MessageEnvelope<ChatMessageContent> 返回;同样保留 ResultsPerPrompt > 1 抛异常的单结果约束(SemanticKernelChatCompletionAgent.cs)。输入消息约束与 SemanticKernelAgent 一致:仅接受 IMessage<ChatMessageContent>,其余类型抛 ArgumentException

示例代码来自 Create_Semantic_Kernel_Chat_Agent.cs

using AutoGen.Core;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;

var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(modelId: "gpt-3.5-turbo", apiKey: openAIKey)
    .Build();

// Semantic Kernel 内置的 ChatCompletionAgent
var chatAgent = new ChatCompletionAgent()
{
    Kernel = kernel,
    Name = "assistant",
    Description = "You are a helpful AI assistant",
};

var messageConnector = new SemanticKernelChatMessageContentConnector();
var skAgent = new SemanticKernelChatCompletionAgent(chatAgent)
    .RegisterMiddleware(messageConnector) // 支持 TextMessage 等 AutoGen 内置类型
    .RegisterPrintMessage();

await skAgent.SendAsync("Hey tell me a long tedious joke");

测试 SemanticKernelAgentTest.cs 中还有两个值得参考的写法:一是直接发送 ChatMessageContent 包裹消息的“零中间件”用法(BasicSkChatCompletionAgentConversationTestAsync);二是在底层 ChatCompletionAgentArguments 中显式设置 OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions } 来启用插件(SkChatCompletionAgentPluginTestAsync)——这是它区别于 SemanticKernelAgent 的一点:后者默认就开启了自动调用,前者需要你在创建 SK Agent 时自行配置。

两个 Agent 的选型可以概括为:需要流式输出、想沿用 AutoGen 的 GenerateReplyOptions 语义(温度、最大 token、停止序列),用 SemanticKernelAgent;已经持有 SK 官方 ChatCompletionAgent 实例(例如配置了 SK 侧的指令模板、运行参数),用 SemanticKernelChatCompletionAgent 包一层即可。

SemanticKernelChatMessageContentConnector:消息桥接中间件

这是文档明确点名的关键中间件。两个 SK Agent 原生只认 ChatMessageContent,而 AutoGen 生态的消息(TextMessageImageMessageMultiModalMessage)需要通过它在进入 Agent 前转换、在返回后反向转换。从 SemanticKernelChatMessageContentConnector.cs 的 XML 文档注释与实现可以确认其能力边界:

  • 支持的消息类型:输入侧支持 TextMessageImageMessageMultiModalMessage 以及已废弃的 Message 类型;输出侧同样映射回这三类(多条内容时合成 MultiModalMessage),流式输出则统一转为 TextMessageUpdate
  • 不支持ToolCallMessageToolCallResultMessage 等函数调用类消息——这与 Overview 文档中“Function call message type … are not supported yet”的描述一致,源码中对应分支会抛 InvalidOperationException(如 SemanticKernelChatMessageContentConnector.cs 对函数调用消息的处理)。

它的角色区分逻辑比较精巧,直接决定了转换出的 SK 角色:

  • 来自 Agent 自身的消息m.From == agent.Name):TextMessage 中 System 角色转为 AuthorRole.System,其余一律转为 AuthorRole.Assistant;自身的 MultiModalMessage 则抛出“not supported if it's from self”的异常(SemanticKernelChatMessageContentConnector.cs);
  • 来自其他参与者的消息:System 角色转 AuthorRole.SystemTextMessageAuthorRole.UserImageMessage 按优先级取 UrlBuildDataUri() 构造 ImageContentSemanticKernelChatMessageContentConnector.cs),MultiModalMessage 逐项展开为 TextContent/ImageContent 集合。

这一设计的意义在于:AutoGen 里 Role.Assistant 标记的是“某个 Agent 的历史发言”,但在 SK 的 ChatHistory 语义中需要严格区分 System/User/Assistant 三角色。Connector 按“是否本 Agent 所发”来还原正确的 SK 角色,使多 Agent 对话历史能无失真地喂给 SK。

反向转换(PostProcessMessage)同样有规则:SK 返回的 TextContent 转为 TextMessageImageContent 分别按 Uri 或二进制数据转为 ImageMessage;单条内容直接返回对应消息,多条则组装为 MultiModalMessageSemanticKernelChatMessageContentConnector.cs)。流式场景下,每个 StreamingChatMessageContent 片段转为一条 TextMessageUpdate,并强制校验 ChoiceIndex == 0

测试 SemanticKernelAgentTest.csSemanticKernelChatMessageContentConnectorTestAsync 覆盖了这条链路:对 ChatMessageContentTextMessageMultiModalMessage 三种输入分别断言回复为 TextMessageFrom == "assistant",并对流式路径断言产出 TextMessageUpdate

KernelPluginMiddleware:让非 SK Agent 使用 Kernel 插件

KernelPluginMiddleware 解决了另一个方向的集成问题:Agent 不是 SK 的,但想用 SK 的插件。Overview 文档的原话是“allows you to use semantic kernel plugins in other AutoGen agents like OpenAIChatAgent”。

其实现(KernelPluginMiddleware.cs)相当直接:

public KernelPluginMiddleware(Kernel kernel, KernelPlugin kernelPlugin)
{
    _kernelPlugin = kernelPlugin;
    var functionContracts = kernelPlugin.Select(k => k.Metadata.ToFunctionContract());
    var functionMap = kernelPlugin.ToDictionary(kv => kv.Metadata.Name, kv => InvokeFunctionPartial(kernel, kv));
    _functionCallMiddleware = new FunctionCallMiddleware(functionContracts, functionMap, Name);
}

可以看到它把 KernelPlugin 内每个 KernelFunction 的元数据通过 ToFunctionContractKernelExtension.cs)翻译成 AutoGen 的 FunctionContract,再把“解析 JSON 参数 → 补默认值 → 校验必填参数 → 调用 KernelFunction”的回调注册进 FunctionCallMiddleware。因此它的本质是适配层:函数调用协议由 AutoGen 侧驱动,执行时再落到 Kernel 上。参数解析细节上,InvokeFunctionAsync 会把模型给出的 JSON 字符串反序列化后按 KernelParameterMetadata 声明的类型逐项转换,缺失参数走 DefaultValue,缺必填参数则抛 ArgumentExceptionKernelPluginMiddleware.cs)。

仓库示例 Use_Kernel_Functions_With_Other_Agent.cs 展示了典型用法——插件来自 Kernel,Agent 却是 OpenAIChatAgent

using AutoGen.Core;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;
using Microsoft.SemanticKernel;
using OpenAI;

// 1. 创建 Kernel 插件(这里只是普通 Kernel,无需模型服务)
var kernel = Kernel.CreateBuilder().Build();
var getWeatherFunction = KernelFunctionFactory.CreateFromMethod(
    method: (string location) => $"The weather in {location} is 75 degrees Fahrenheit.",
    functionName: "GetWeather",
    description: "Get the weather for a location.");
var plugin = kernel.CreatePluginFromFunctions("my_plugin", [getWeatherFunction]);

// 2. 用插件构造中间件
var kernelPluginMiddleware = new KernelPluginMiddleware(kernel, plugin);

// 3. 注册到任意 AutoGen Agent 上
var openAIAgent = new OpenAIChatAgent(
    chatClient: openAIClient.GetChatClient("gpt-4o-mini"),
    name: "assistant")
    .RegisterMessageConnector()
    .RegisterMiddleware(kernelPluginMiddleware) // 关键:插件挂载在这里
    .RegisterPrintMessage();

// 4. 发送消息,第一轮返回聚合的工具调用消息
var toolAggregateMessage = await openAIAgent.SendAsync("Tell me the weather in Seattle");

// 5. 把聚合消息回灌给 Agent,生成最终自然语言回复
var finalReply = await openAIAgent.SendAsync(toolAggregateMessage);

注意示例中的两步 SendAsync:第一次请求时 Agent 返回的是聚合了 ToolCallMessageToolCallResultMessage 的消息(示例注释说明了这一点),把它再发回 Agent 才会由 LLM 生成最终答复。这反映了 AutoGen 侧函数调用消息流的通用形态,与 SemanticKernelAgent 内部由 SK 自动闭环调用插件的模式形成对照。

安装与版本

按照 AutoGen.SemanticKernel Overview 的入门指引,接入分两步:

  1. 先按 安装指南 配置 NuGet feed(稳定版走 NuGet 官方源,nightly 构建需添加 AutoGen 专用 feed 到 NuGet.config);
  2. 在项目中引用包:
<ItemGroup>
    <PackageReference Include="AutoGen.SemanticKernel" Version="AUTOGEN_VERSION" />
</ItemGroup>

Version 需替换为你要使用的实际版本号(文档中以 AUTOGEN_VERSION 占位)。若你只想引入 AutoGen 核心抽象并自行实现 Agent,可以只装 AutoGen.Core;而 AutoGen 全家桶包本身就依赖了 AutoGen.SemanticKernel(见 Installation.md 中的包说明),安装全家桶时无需重复添加。

小结:组件能力速查

场景 推荐组件 关键注意点
快速接入 SK Kernel,需要流式 SemanticKernelAgent + RegisterMessageConnector() 默认 Temperature=0.7MaxTokens=1024,插件自动调用已开启
已持有 SK ChatCompletionAgent 实例 SemanticKernelChatCompletionAgent IAgent,无流式;Name 取自被包装 Agent
使用 TextMessage/ImageMessage/MultiModalMessage SemanticKernelChatMessageContentConnector 不支持函数调用类消息;自身 MultiModalMessage 不被接受
OpenAIChatAgent 等使用 Kernel 插件 KernelPluginMiddleware 函数调用由 AutoGen 侧驱动,需自行回灌工具结果消息
一个 Kernel 多个模型服务 SemanticKernelAgentmodelServiceId 参数 注册时用同 id 的 keyed service

综合来看,AutoGen.SemanticKernel 包的设计思路是“双向桥接”:向外,把 AutoGen 的内置消息体系与中间件框架引入 SK Agent(Connector 负责消息转换,KernelPluginMiddleware 负责反向输出函数能力);向内,让 SK 的 Kernel、插件与官方 ChatCompletionAgent 都能成为 AutoGen 编排(单 Agent、多 Agent、群聊)中的一等公民。当前阶段的边界也很明确——函数调用消息暂不参与 Connector 的双向转换,SK 内部插件调用则依赖 AutoInvokeKernelFunctions 自动闭环。对于希望以 Semantic Kernel 作为模型与插件底座、同时享受 AutoGen 消息抽象与编排能力的 .NET 团队,这是当前仓库提供的标准集成路径。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384