首页
/ AutoGen .NET Hello 示例深度解析:用 .NET Aspire App Host 编排跨语言 gRPC 多智能体应用

AutoGen .NET Hello 示例深度解析:用 .NET Aspire App Host 编排跨语言 gRPC 多智能体应用

2026-09-05 18:30:46作者:史锋燃Gardner

本篇以 dotnet/samples/Hello/README.md 为切入点,讲解 AutoGen 仓库中 "Hello" 示例的 .NET Aspire App Host 是如何一次性拉起 HelloAgent、智能体后端(AgentHost)与一个 Python 智能体,形成跨语言(C#/Python)的事件驱动消息链路,并如何在 Aspire Dashboard 中查看遥测与日志。读完后你可以直接在本地运行该多项目示例、理解 AGENT_HOSTSTAY_ALIVE_ON_GOODBYE 等关键环境变量的作用,并掌握从 proto 定义消息类型到进程内/gRPC 两种运行时切换的完整方法。

1. 这个示例在 AutoGen .NET 中的定位

dotnet/samples/Hello 目录是 AutoGen 0.4 .NET SDK 的 "Hello World" 级示例集合,其核心文档 dotnet/samples/Hello/README.md 说明:这是一个基于 .NET Aspire 的 App Host,负责启动 HelloAgent 工程与 agents backend(智能体后端),项目启动后可通过控制台输出的链接在 Aspire Dashboard 中查看遥测数据与日志,运行方式只有两条命令:

cd Hello.AppHost
dotnet run

整个目录的组织如下,每个子工程各司其职:

目录 角色 关键文件
Hello.AppHost .NET Aspire 编排入口(App Host) Program.csHello.AppHost.csproj
HelloAgent C# 智能体:订阅 HelloTopic,处理消息并回话 HelloAgent.csProgram.cs
HelloAIAgents 带 LLM 的扩展变体(继承 HelloAgent,调用 ChatClient) HelloAIAgent.cs
HelloAgentState 演示智能体状态持久化的变体 README.md
protos 共享的事件消息 schema(ProtoBuf) agent_events.proto

运行前置条件(参考 HelloAgent 的 README):.NET 8.0 或更高版本;由于 App Host 还会拉起一个 Python 智能体,本地还需为 Python 端准备好虚拟环境(见第 4 节)。

2. App Host 如何编排三个进程

Hello.AppHost/Program.cs 是理解本示例的关键。它通过 DistributedApplication.CreateBuilder 声明了一个分布式应用的资源拓扑(第 6~27 行):

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();

从这段编排代码可以确认三个事实:

  1. backend 是分布式消息网关AddProject<Projects.Microsoft_AutoGen_AgentHost>("backend") 引用的工程是 dotnet/src/Microsoft.AutoGen/AgentHost,即仓库中的 gRPC 智能体后端;WithExternalHttpEndpoints() 让它对外暴露 HTTP(S) 端点,供其余进程连接。
  2. HelloAgent 以 gRPC 客户端身份接入 backendWithReference(backend) 注入连接信息,AGENT_HOST 环境变量被显式设置为 backend 的 https 端点。HelloAgent 的入口程序会依据 AGENT_HOST 决定使用 gRPC 运行时还是进程内运行时(见第 3 节),因此这里它走的是分布式路径。
  3. Python 智能体跨语言加入同一事件总线AddPythonApp 的工作目录指向 python/samples/core_xlang_hello_python_agent,入口脚本为 hello_python_agent.py;第 4 个参数 ../../.venv 从该工作目录相对解析后,指向 python 包根目录下的 .venv 虚拟环境——可以推断需要在 python 目录下预先创建装好本地包的虚拟环境。Python 端通过 GrpcWorkerAgentRuntime 连接同一个 backend,从而实现 C# 与 Python 智能体在同一 topic 上收发消息。源码中的注释也提示:xlang 目前走 http,生产环境容器间应使用 TLS。

2.1 关键环境变量一览

环境变量 设置位置 作用
AGENT_HOST App Host 通过 WithEnvironment 注入 智能体据此连接 gRPC 后端(C# 端取自 HelloAgent/Program.cs;Python 端在 hello_python_agent.py 中默认回退到 http://localhost:50673
STAY_ALIVE_ON_GOODBYE App Host 对两个智能体均设为 true 控制 HelloAgent 在发出 ConversationClosed 后是否自行关停:见 HelloAgent.cs,若该变量不为 true,则会再发布 Shutdown 消息并停止应用。在 Aspire 托管场景下保持 true,进程不因一次对话结束而退出
GRPC_DNS_RESOLVER 仅 Python 端设为 native 指定 gRPC 使用原生 DNS 解析器,配合容器化环境下的主机名解析

2.2 启动顺序与依赖等待

WaitFor 声明了显式依赖链:backend 先就绪 → HelloAgent 启动 → Python 智能体最后启动backend.WaitForclientHelloAgentsPython)。启动完成后 App Host 会打印 Backend URL 并等待关闭信号,此时控制台同时提供 Aspire Dashboard 的访问链接。

Hello.AppHost.csproj 声明了编排所需的基础设施:使用 Aspire.AppHost.Sdk(9.0.0),目标框架 net8.0,标记 IsAspireHost 为 true,并引用 Aspire.Hosting.AppHostAspire.HostingAspire.Hosting.Python(Python 应用支持)三个包;项目引用则精确指向 AgentHost 后端与 HelloAgent 两个工程。

3. HelloAgent 的消息处理流程

理解 App Host 编排后,再看被编排的 HelloAgent 本身。其消息类型定义在 protos/agent_events.protopackage HelloAgents,C# 命名空间为 Microsoft.AutoGen.Contracts),其中示例用到的三个消息为:

message NewMessageReceived {
      string message = 1;
}
message ConversationClosed {
  string user_id = 1;
  string user_message = 2;
}
message Shutdown {
      string message = 1;
}

HelloAgent/HelloAgent.cs 展示了一个最小智能体的完整形态:通过 [TypeSubscription("HelloTopic")] 订阅 topic HelloTopic,并通过实现 IHandle<NewMessageReceived>IHandle<ConversationClosed>IHandle<Shutdown> 三个接口声明它能处理哪些消息:

public async ValueTask HandleAsync(NewMessageReceived item, MessageContext messageContext)
{
    Console.Out.WriteLine(item.Message);
    ConversationClosed goodbye = new ConversationClosed
    {
        UserId = this.Id.Type,
        UserMessage = "Goodbye"
    };
    // This will publish the new message type which will be handled by the ConversationClosed handler
    await this.PublishMessageAsync(goodbye, new TopicId("HelloTopic"));
}

处理链是典型的事件链式编排:收到 NewMessageReceived → 打印消息并发布 ConversationClosedConversationClosed 处理器打印告别语,并在 STAY_ALIVE_ON_GOODBYE 不为 true 时发布 ShutdownShutdown 处理器调用 hostApplicationLifetime.StopApplication() 结束进程。

HelloAgent/Program.cs 则展示了同一工程支持两种运行模式,这正是 README 中 "使用 SDK 的 App Runtime 在本地启动智能体" 的落地方式:

  • 进程内模式(默认):没有 AGENT_HOST 时,appBuilder.UseInProcessRuntime(deliverToSelf: true).AddAgent<HelloAgent>("HelloAgent"),随后直接 app.PublishMessageAsync(message, new TopicId("HelloTopic")) 发送 NewMessageReceived { Message = "Hello World!" } 给自己。
  • gRPC 分布式模式:设置了 --host <address> 命令行参数或 AGENT_HOST 环境变量时,改用 appBuilder.AddGrpcAgentWorker(agentHost) 连接到网关(Aspire 场景即此模式)。

命令行参数语义(来自 Program.cs 的参数解析与帮助文本):

HelloAgent [--host <hostAddress>] [--nosend]
  --host     使用 <hostAddress> 处的 gRPC 网关;也可通过 AGENT_HOST 环境变量设置
  --nosend   不发送初始消息,等待其他智能体发送。注意:在 InProcessRuntime 下该参数无效(会挂起),程序会直接退出

在 Aspire 编排中,Python 智能体(WaitFor(client) 之后启动)会向 HelloTopic 发布 NewMessageReceived { message = "Hello from Python!" },HelloAgent 打印后回发 ConversationClosed,整条 C# ↔ Python 链路即由此贯通。

4. 在 Aspire Dashboard 中查看遥测与日志

README 的核心承诺是:启动后在控制台给出的链接进入 Aspire Dashboard,即可查看各进程的遥测与日志。相关配置位于 launchSettings.json,包含三个配置文件(profile):

Profile 应用地址 关键点
https(默认) https://localhost:15887;http://localhost:15888 DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL=https://localhost:16038DOTNET_RESOURCE_SERVICE_ENDPOINT_URL=https://localhost:17037,并开启 DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES=true
http http://localhost:15888 对应 Dashboard 端口 16032 / 17031,额外设置 ASPIRE_ALLOW_UNSECURED_TRANSPORT=true
generate-manifest 不启动应用 --publisher manifest --output-path aspire-manifest.json 生成部署清单,用于容器化等场景

在 Dashboard 中可以看到 backendHelloAgentsDotNETHelloAgentsPython 三个资源的日志流与跟踪数据;Python 端因配置了 .WithOtlpExporter(),其 OpenTelemetry 导出同样汇入 Dashboard。此外 appsettings.json 将日志级别默认设为 WarningMicrosoft 命名空间为 Information,用于控制各进程日志输出粒度。

5. 消息类型的扩展方式

示例展示了消息类型由 ProtoBuf schema 驱动的模式:.proto 文件在构建时由 gRPC 工具转为 C# 类。HelloAgent.csproj 的做法是引用 Google.ProtobufGrpc.Tools 包,并用 <Protobuf Include="..\..\..\src\Microsoft.AutoGen\Agents\protos\agent_events.proto" /> 纳入 proto 文件;AgentHost 相关工程与测试 中同样维护了 agent_events.proto。若要新增自定义消息,可按 HelloAgent README 的说明:新建 .proto 文件并在 .csproj 中加入 Grpc.Tools<Protobuf Include="..."/>,然后像示例中 PublishMessageAsync 那样把消息包装后投递到事件总线即可。

6. 同目录的变体工程

  • HelloAIAgentsHelloAIAgent.cs 继承自本地定义的 HelloAgent 基类([TopicSubscription("agents")]),用 new 重写 Handle(NewMessageReceived),通过注入的 IChatClient 调用大模型写一首 limerick 问候诗并回发 Output。其 Program.cs 从配置读取 HelloAIAgents:ModelType(azureopenai)与 HelloAIAgents:LlmModelName,要求设置 AZURE_OPENAI_CONNECTION_STRING 环境变量;未设置时直接抛出 InvalidOperationException。注意:该工程未被 Hello.AppHost 的 csproj 引用,属于独立运行的变体示例,不参与 Aspire 编排。
  • HelloAgentState:演示智能体状态持久化 API 的变体,可查阅其 README 了解用法。

7. 关键文件索引

内容 路径
本示例总览文档(本文依据) dotnet/samples/Hello/README.md
App Host 编排逻辑 dotnet/samples/Hello/Hello.AppHost/Program.cs
Aspire 启动配置 dotnet/samples/Hello/Hello.AppHost/Properties/launchSettings.json
C# 智能体与消息处理器 dotnet/samples/Hello/HelloAgent/HelloAgent.cs
进程内/gRPC 双模式启动 dotnet/samples/Hello/HelloAgent/Program.cs
事件消息 schema dotnet/samples/Hello/protos/agent_events.proto
Python 侧跨语言智能体 python/samples/core_xlang_hello_python_agent/hello_python_agent.py
gRPC 后端工程 dotnet/src/Microsoft.AutoGen/AgentHost

综上,dotnet/samples/Hello 用一个最小闭环完整呈现了 AutoGen .NET 的分布式智能体模型:Aspire App Host 负责进程编排与依赖管理,智能体通过 TypeSubscription 订阅 topic、通过 IHandle<T> 注册消息处理器、通过 ProtoBuf 定义跨语言消息契约,最终 C# 与 Python 智能体经由 AgentHost 网关在同一事件总线上协作,全部运行状态可经 Aspire Dashboard 观测。

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