首页
/ AutoGen .NET Core 实战指南:从 BaseAgent 事件处理到分布式运行时与 Aspire 编排

AutoGen .NET Core 实战指南:从 BaseAgent 事件处理到分布式运行时与 Aspire 编排

2026-09-03 19:55:39作者:翟萌耘Ralph

AutoGen .NET 版本(AutoGen Core for .NET)的编程模型与其 Python 版本保持一致:以“消息 + 主题 + 事件处理”为核心,通过 BaseAgent 派生实现自定义智能体,再用 AgentsAppBuilder 把智能体挂载到进程内或分布式运行时上运行。读完本篇,你将掌握 .NET 版 AutoGen 的完整上手路径:NuGet 包安装、编写并注册 Agent、用 AgentsAppBuilder 启动应用并投递消息、配置日志,以及通过 Microsoft.AutoGen.AgentHost 与 .NET Aspire 编排跨进程、跨语言(Python/.NET)的分布式 Agent 系统。

核心概念:与 Python 版本对齐的编程模型

AutoGen Core for .NET 沿用了其 Python 对应版本的相同概念与约定。官方文档的建议是:在理解 .NET 版本的概念之前,可先阅读 Python 版本文档;除特别说明外,Python 版本中的概念均可映射到 .NET 版本。两个语言版本之间的重要差异记录在 Differences from Python 一节中,而只影响某一语言的内容(例如依赖注入、Host Builder 模式)则不在差异文档中赘述。

一个值得注意的差异(同样在差异文档中说明):当一个 Agent 向自己订阅的主题发布消息时,默认不会收到自己发出的消息——这与 Python 运行时行为一致;但在 .NET 的 InProcessRuntime 中,可将 DeliverToSelf 属性设为 true 以允许 Agent 收到自己发布的消息(对应 AgentsAppBuilder.UseInProcessRuntime(deliverToSelf: true) 的第二个参数)。

安装:获取 .NET SDK 包

AutoGen .NET SDK 可以以 NuGet 包形式获取(NuGet 上的包名为 Microsoft.AutoGen),也可以直接克隆仓库使用。最小安装只需要以下两个包:

dotnet add package Microsoft.AutoGen.Contracts
dotnet add package Microsoft.AutoGen.Core
  • Microsoft.AutoGen.Contracts:定义 IAgentRuntimeBaseAgentIHandle<T>AgentIdTopicIdMessageContext 等核心契约类型,源码位于 Contracts 项目
  • Microsoft.AutoGen.Core:提供 InProcessRuntime(进程内运行时)、AgentsAppBuilderAgentsApp 等运行时实现,源码位于 Core 项目

更完整的安装说明(包括各相关包的取舍)见 Installation。快速上手的最佳途径是浏览仓库 samples 目录下的示例代码,其中 dotnet/samples/Hellodotnet/samples/GettingStarted 是本文后续示例的直接来源。

创建 Agent:继承 BaseAgent 并实现 IHandle<T>

创建 Agent 的方式是继承 BaseAgent 并为你关心的事件实现事件处理器。文档给出的最小示例如下:

public class MyAgent : BaseAgent, IHandle<MyMessage>
{
    // ...
    public async ValueTask HandleAsync(MyMessage item, MessageContext context)
    {
        // ...logic here...
    }
}

通过继承 BaseAgent,你获得了运行时(Runtime)与日志(_logger)等基础设施;通过实现 IHandle<T>,可以简洁地为自定义消息类型定义事件处理方法。

源码视角:事件处理器是如何被发现与分发的

BaseAgent.cs 的实现可以看到这套机制的细节:

  • BaseAgent 构造函数在初始化时调用 ReflectInvokers(),扫描当前类实现的所有 IHandle<> / IHandle<,> 泛型接口,为每种消息类型创建一个 HandlerInvoker,存入 Dictionary<Type, HandlerInvoker>(见 BaseAgent.cs#L60-L81)。
  • 运行时收到消息后,OnMessageAsync 按消息类型查表分发到对应处理器,未注册的消息类型直接返回 null(见 BaseAgent.cs#L83-L93)。
  • BaseAgent 本身提供 SendMessageAsync(点对点发送)与 PublishMessageAsync(向主题发布)两个方法,均委托给注入的 IAgentRuntime,发送方身份自动填充为 this.Id(见 BaseAgent.cs#L95-L104)。
  • 此外 BaseAgent 实现了 ISaveState,并内置 ActivitySourceMicrosoft.AutoGen.Core.Agent)用于 OpenTelemetry 追踪。

一个更完整的真实示例是 HelloAgent:它通过 [TypeSubscription("HelloTopic")] 属性订阅主题,并实现了三个处理器——NewMessageReceived(收到消息后转发一条 ConversationClosed)、ConversationClosed(打印告别语,若未设置 STAY_ALIVE_ON_GOODBYE=true 则发布 Shutdown)、Shutdown(调用 IHostApplicationLifetime.StopApplication() 关闭宿主)。这展示了 AutoGen 中“一切皆消息”的编排风格:Agent 间的状态推进完全由消息流驱动。

在应用里运行 Agent:AgentsAppBuilder

在应用内运行 Agent 使用 AgentsAppBuilder。文档示例展示了如何在应用中运行一个 HelloAgent

AgentsAppBuilder appBuilder = new AgentsAppBuilder()
    .UseInProcessRuntime(deliverToSelf: true)
    .AddAgent<HelloAgent>("HelloAgent");

var app = await appBuilder.BuildAsync();

// start the app by publishing a message to the runtime
await app.PublishMessageAsync(new NewMessageReceived
{
    Message = "Hello from .NET"
}, new TopicId("HelloTopic"));

// Wait for shutdown
await app.WaitForShutdownAsync();

源码视角:AgentsAppBuilder 的构建流程

AgentsApp.cs 揭示了该 API 的底层行为:

  • AgentsAppBuilder 内部封装了一个 HostApplicationBuilder(.NET Generic Host),因此你可以直接访问 appBuilder.ServicesIServiceCollection)与 appBuilder.Configuration,把 Agent 所需的依赖注册进去(见 AgentsApp.cs#L13-L26)。
  • UseInProcessRuntime(bool deliverToSelf = false)InProcessRuntime 注册为 IAgentRuntime 单例,并将其作为 IHostedService 托管,从而随宿主启动(见 AgentsApp.cs#L32-L41)。
  • AddAgent<TAgent>(agentType, ...) 只是登记一个注册委托;BuildAsync() 阶段才真正执行 RegisterAgentTypeAsyncRegisterImplicitAgentSubscriptionsAsync,把 Agent 类型及其隐式订阅(如 [TypeSubscription])写入运行时(见 AgentsApp.cs#L75-L86)。
  • AgentsApp.PublishMessageAsync 具有“按需自启动”特性:如果应用尚未运行,会先调用 StartAsync() 再向运行时发布消息(见 AgentsApp.cs#L127-L136)——这就是文档示例中省略显式 StartAsync() 的原因。

完整示例:GettingStarted 计数器

仓库中的 GettingStarted 示例 演示了“多 Agent + 依赖注入”的完整流程:CheckerModifier 两个 Agent 协作,从 10 开始递减直到 1。关键代码如下:

using Microsoft.AutoGen.Contracts;
using Microsoft.AutoGen.Core;
using Microsoft.Extensions.DependencyInjection.Extensions;

// 把业务依赖注入到宿主
appBuilder.Services.TryAddSingleton(modifyFunc);
appBuilder.Services.TryAddSingleton(runUntilFunc);

// 注册两个 Agent(key 即 AgentType)
appBuilder.AddAgent<Checker>("Checker");
appBuilder.AddAgent<Modifier>("Modifier");

var app = await appBuilder.BuildAsync();
await app.StartAsync();

// 向 "default" 主题发布初始消息,触发整条消息链
await app.PublishMessageAsync(new CountMessage
{
    Content = 10
}, new TopicId("default"));

// Run until application shutdown
await app.WaitForShutdownAsync();

该示例中 Checker/Modifier 分别订阅消息类型并发布下一条消息(CountUpdate),体现了与 Hello 示例一致的消息链模式。

.NET SDK 的两种运行时

.NET SDK 提供两类运行时:

  1. InMemory Single Process Runtime(进程内运行时):即 InProcessRuntime,适合单进程应用;
  2. Remote Distributed Runtime(分布式运行时):面向云端部署,支持 Python 与 .NET 编写的 Agent 在同一个分布式系统中互相通信。分布式运行时基于 Microsoft Orleans 提供弹性、持久化以及与 Azure Event Hubs 等消息服务的集成;跨语言(xlang)通信要求 Agent 的消息可序列化为 CloudEvents,消息通过 gRPC 以 CloudEvents 格式交换,运行时负责保证消息被投递到正确的 Agent。

客户端侧:接入分布式运行时

要在应用中使用分布式运行时,需要添加:

dotnet add package Microsoft.AutoGen.Core.Grpc

这是运行在你应用内、连接分布式系统的包(源码位于 Core.Grpc 项目)。

服务端侧:运行 Agent Host 后端

运行后端/服务端需要两个包:

dotnet add package Microsoft.AutoGen.RuntimeGateway
dotnet add package Microsoft.AutoGen.AgentHost

可以独立以后端进程方式运行:

dotnet run --project Microsoft.AutoGen.AgentHost

也可以把后端嵌入到自己的应用中:

using Microsoft.AutoGen.RuntimeGateway;
using Microsoft.AutoGen.AgentHost;

var autogenBackend = await Microsoft.AutoGen.RuntimeGateway.Grpc.Host.StartAsync(local: false, useGrpc: true);

此外,还可以把运行时作为 dotnet tool 安装使用:

dotnet pack --no-build --configuration Release --output './output/release' -bl
dotnet tool install --add-source ./output/release Microsoft.AutoGen.AgentHost
# run the tool
# dotnet agenthost
# or just...
agenthost

相关源码可参考 RuntimeGateway.Grpc 项目AgentHost 项目

使用 .NET Aspire 编排多进程分布式系统

Hello.AppHost 示例 展示了如何用 .NET Aspire 把“多个 Agent + 运行时”编排为独立进程组成的分布式系统,并同时拉起一个 Python Agent 演示跨语言协作(对应 core_xlang_hello_python_agent 示例):

using Microsoft.Extensions.Hosting;

var builder = DistributedApplication.CreateBuilder(args);
var backend = builder.AddProject<Projects.Microsoft_AutoGen_AgentHost>("backend").WithExternalHttpEndpoints();
var client = builder.AddProject<Projects.HelloAgent>("HelloAgentsDotNET")
    .WithReference(backend)
    .WithEnvironment("AGENT_HOST", backend.GetEndpoint("https"))
    .WithEnvironment("STAY_ALIVE_ON_GOODBYE", "true")
    .WaitFor(backend);
// xlang is over http for now - in prod use TLS between containers
builder.AddPythonApp("HelloAgentsPython", "../../../../python/samples/core_xlang_hello_python_agent", "hello_python_agent.py", "../../.venv")
    .WithReference(backend)
    .WithEnvironment("AGENT_HOST", backend.GetEndpoint("http"))
    .WithEnvironment("STAY_ALIVE_ON_GOODBYE", "true")
    .WithEnvironment("GRPC_DNS_RESOLVER", "native")
    .WithOtlpExporter()
    .WaitFor(client);
using var app = builder.Build();
await app.StartAsync();
var url = backend.GetEndpoint("http").Url;
Console.WriteLine("Backend URL: " + url);
await app.WaitForShutdownAsync();

要点解读:

  • backendMicrosoft.AutoGen.AgentHost 项目,作为 Orleans 网关对外暴露 HTTP 端点;
  • .NET 客户端 HelloAgentsDotNET 通过环境变量 AGENT_HOST 指向后端端点(此示例中走 https),并用 WaitFor(backend) 声明启动顺序;
  • Python 应用通过 AddPythonApp 注册,当前 xlang 走 http(示例注释提醒:生产环境容器间应使用 TLS),并额外设置 GRPC_DNS_RESOLVER=native
  • 更丰富的 Aspire + XLang 示例可在 Microsoft.AutoGen.Integration.Tests.AppHosts 目录中找到。

配置日志

SDK 使用 Microsoft.Extensions.Logging 框架进行日志输出。文档推荐了一个包含实用默认值的 appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Microsoft.AspNetCore": "Information",
      "Microsoft": "Information",
      "Microsoft.Orleans": "Warning",
      "Orleans.Runtime": "Error",
      "Grpc": "Information"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }
}

各配置项的作用:默认日志级别为 Warning 以降噪;Orleans.Runtime 提到 Error 避免 Orleans 内部日志刷屏;Grpc 保持 Information 便于观察分布式消息通道;Kestrel 端点强制 Http2 协议是 gRPC 传输的前提。

用 Protocol Buffers 定义消息类型

如果消息要走 InProcessRuntime 以外的运行时,则必须以 Protocol Buffers 消息形式定义,因为跨进程消息使用 Protocol Buffers 进行序列化/反序列化(未来可能放宽为支持转换器或自定义序列化机制)。要点是:将 .proto 文件纳入项目后会自动生成对应的 C# 消息类,具体做法(引入 Grpc.Tools、配置 <Protobuf Include="..."/>、定义 message、对生成类编程)详见 Using Protocol Buffers to Define Message Types。仓库中的 messages.protoGettingStartedGrpc 示例 可作为对照参考。

小结与延伸阅读

本篇围绕 AutoGen Core for .NET 入口文档 覆盖了 .NET 版 AutoGen 的完整主线:

主题 关键 API / 包 源码位置
Agent 定义 BaseAgent + IHandle<T> + [TypeSubscription] dotnet/src/Microsoft.AutoGen/Core/BaseAgent.cs
应用装配 AgentsAppBuilder / AgentsApp dotnet/src/Microsoft.AutoGen/Core/AgentsApp.cs
进程内运行时 UseInProcessRuntime(deliverToSelf:) dotnet/src/Microsoft.AutoGen/Core/InProcessRuntime.cs
分布式客户端 Microsoft.AutoGen.Core.Grpc dotnet/src/Microsoft.AutoGen/Core.Grpc
分布式后端 Microsoft.AutoGen.RuntimeGateway + Microsoft.AutoGen.AgentHost dotnet/src/Microsoft.AutoGen/AgentHost
示例 Hello / GettingStarted / Aspire AppHost dotnet/samples

继续深入可阅读:Differences from PythonInstallationTutorialUsing Protocol Buffers to Define Message Types,以及跨语言互通的 xlang Python Agent 示例

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