AutoGen .NET:使用 Protocol Buffers 定义跨进程 Agent 消息类型

发布时间:2026/9/7 14:47:40
AutoGen .NET:使用 Protocol Buffers 定义跨进程 Agent 消息类型 AutoGen .NET使用 Protocol Buffers 定义跨进程 Agent 消息类型【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogenAutoGen .NET 的 Agent 可以在进程内InProcessRuntime直接用普通 C# 类通信但要接入 gRPC 等分布式运行时所有消息类型就必须以 Protocol Buffersproto3定义。本文基于仓库文档 protobuf-message-types.md 讲解这一硬性要求的来源给出完整的.proto集成步骤与 C# 代码写法并结合 GettingStartedGrpc 示例源码剖析消息在跨进程运行时的完整流转过程。为什么跨运行时消息必须是 Protocol Buffers 消息文档 protobuf-message-types.md 开篇即给出约束For a message to be sent using a runtime other than theInProcessRuntime, it must be defined as a Protocol Buffers message. This is because the message is serialized and deserialized using Protocol Buffers.也就是说只要消息要离开当前进程例如通过Microsoft.AutoGen.Core.Grpc的 gRPC 运行时发送到远程 Worker消息在传输前会被 Protocol Buffers 序列化、在接收端被反序列化因此消息类型本身必须由.proto文件定义并在构建期生成 C# 类。文档同时说明这一限制未来可能通过允许 converter、自定义序列化等机制放宽但在当前版本中它是刚性要求。可以对比仓库中两个 GettingStarted 示例来验证这一点进程内示例 GettingStarted/CountMessage.cs 直接用普通 C# POCO 定义消息namespace GettingStartedSample; public class CountMessage { public int Content { get; set; } }该示例通过appBuilder.UseInProcessRuntime()见 Program.cs运行全程不发生网络序列化所以不需要 protobuf。而 gRPC 示例 GettingStartedGrpc/message.proto 将同样的消息改为 proto 定义syntax proto3; option csharp_namespace GettingStartedGrpcSample.Events; message CountMessage { int32 content 1; } message CountUpdate { int32 new_count 1; }其宿主 Program.cs 使用appBuilder.AddGrpcAgentWorker(http://localhost:50051)接入远程 Worker此时消息类型必须来自 proto 生成代码。在 .NET 项目中集成 Protocol Buffers 的四个步骤以下是文档给出的完整操作路径四步缺一不可。第 1 步在 .csproj 中引入 Grpc.Tools 包PackageReference IncludeGrpc.Tools PrivateAssetsAll /Grpc.Tools负责在构建期执行protoc把.proto文件编译为 C# 消息类以及可选的 gRPC 客户端/服务端桩代码。PrivateAssetsAll表示这是一个纯构建期依赖它只在当前项目编译时生效不会传递给引用方也不会出现在 NuGet 包的依赖列表中。仓库示例 GettingStartedGrpc.csproj 使用了完全相同的写法ItemGroup PackageReference IncludeGrpc.Tools PrivateAssetsAll / /ItemGroup第 2 步在项目中声明 .proto 文件ItemGroup Protobuf Includemessages.proto GrpcServicesClient;Server Linkmessages.proto / /ItemGroupInclude指定要编译的 proto 文件Link仅影响解决方案资源管理器中的显示路径不影响实际位置。GrpcServices控制是否生成 gRPC 服务代码Client/Server。如果你只定义消息类型、不需要服务桩可以像 GettingStartedGrpc.csproj 那样只写GrpcServicesClient甚至可省略该属性仅生成消息类。第 3 步编写 proto3 消息定义文档给出的最小示例syntax proto3; package HelloAgents; option csharp_namespace MyAgentsProtocol; message TextMessage { string Source 1; string Content 2; }按文档指引字段定义需遵循 Protocol Buffers Language Guide 中引用的 proto3 规范几个关键点syntax proto3必须声明 proto3 语法这是当前 .NET gRPC 工具链支持的版本。option csharp_namespace指定生成 C# 类的命名空间。文档示例中使用MyAgentsProtocol真实示例 message.proto 使用option csharp_namespace GettingStartedGrpcSample.Events;因此后续 C# 代码中可以直接写Events.CountMessage这样的限定名与示例代码 Checker.cs 中的IHandleEvents.CountUpdate一致。字段编号从 1 开始且不能重复Source 1、Content 2是 wire format 的标签一经发布即不可更改新增字段只能追加新编号。proto 类型映射string、int32等基础类型会映射为 C# 的string、int例如 proto 中int32 content 1;生成 C# 属性int Content { get; set; }这保证了生成的类可以直接作为业务消息使用。第 4 步针对生成的类编写 Agent 代码文档示例using Microsoft.AutoGen.Contracts; using Microsoft.AutoGen.Core; using MyAgentsProtocol; [TypeSubscription(default)] public class Checker( AgentId id, IAgentRuntime runtime, ) : BaseAgent(id, runtime, MyAgent, null), IHandleTextMessage { public async ValueTask HandleAsync(TextMessage item, MessageContext messageContext) { Console.WriteLine($Received message from {item.Source}: {item.Content}); } }要点解析TextMessage不是手写的而是构建期由messages.proto自动生成的 C# 类位于option csharp_namespace指定的MyAgentsProtocol命名空间。IHandleT是 AutoGen 的通用消息处理契约定义在 IHandle.cspublic interface IHandlein T { ValueTask HandleAsync(T item, MessageContext messageContext); }Agent 只要实现该接口T为 proto 生成的消息类型运行时就会把匹配的消息分发进来。由于T位于逆变位置in Thandler 也可以接受更宽泛的基类型。HandleAsync的第二个参数MessageContext携带消息元数据定义见 MessageContext.cs核心属性包括MessageId消息唯一标识、CancellationToken取消令牌、Sender发送方AgentId未指定时为null、Topic消息所属话题、IsRpc是否为 RPC 调用。这些属性在调试跨进程消息流向时非常有用。[TypeSubscription(default)]声明该 Agent 订阅default话题下TextMessage类型的所有消息。实战示例GettingStartedGrpc 的完整消息流仓库中的 GettingStartedGrpc 是这套机制的最小可运行示例完整复现了“修改—校验”循环消息全程经过 gRPC 序列化。消息定义message.protoCountMessage携带当前计数与CountUpdate携带更新后的计数均生成到GettingStartedGrpcSample.Events命名空间。Modifier AgentModifier.cs实现IHandleEvents.CountMessage收到消息后对计数执行注入的modifyFunc再发布CountUpdate回default话题[TypeSubscription(default)] public class Modifier( AgentId id, IAgentRuntime runtime, ModifyF modifyFunc ) : BaseAgent(id, runtime, Modifier, null), IHandleEvents.CountMessage { public async ValueTask HandleAsync(Events.CountMessage item, MessageContext messageContext) { int newValue modifyFunc(item.Content); var updateMessage new Events.CountUpdate { NewCount newValue }; await this.PublishMessageAsync(updateMessage, topic: new TopicId(default)); } }Checker AgentChecker.cs实现IHandleEvents.CountUpdate若new_count 1则把计数重新包装为CountMessage发布回去形成循环否则调用hostApplicationLifetime.StopApplication()终止应用public async ValueTask HandleAsync(Events.CountUpdate item, MessageContext messageContext) { if (!runUntilFunc(item.NewCount)) { await this.PublishMessageAsync(new Events.CountMessage { Content item.NewCount }, new TopicId(default)); } else { hostApplicationLifetime.StopApplication(); } }宿主程序Program.csAgentsAppBuilder appBuilder new AgentsAppBuilder(); appBuilder.AddGrpcAgentWorker(http://localhost:50051); // 连接远程 gRPC Worker appBuilder.AddAgentChecker(Checker); appBuilder.AddAgentModifier(Modifier); var app await appBuilder.BuildAsync(); await app.StartAsync(); await app.PublishMessageAsync(new GettingStartedGrpcSample.Events.CountMessage { Content 10 }, new TopicId(default)); await app.WaitForShutdownAsync();与进程内版本 GettingStarted/Program.cs 相比唯一本质差异是UseInProcessRuntime()换成了AddGrpcAgentWorker(...)——Agent 代码Checker/Modifier几乎逐行相同只是消息类型从 POCO 换成了 proto 生成类。这说明只要消息类型按本文方式定义同一套 Agent 逻辑可以在进程内与 gRPC 运行时之间平移代价仅仅是把消息类改为 proto 定义。项目依赖上GettingStartedGrpc.csproj 额外引用了三个项目Microsoft.AutoGen.ContractsIHandleT、TypeSubscription、MessageContext等契约、Microsoft.AutoGen.CoreAgent 基础类型与进程内能力、Microsoft.AutoGen.Core.GrpcgRPC 运行时与 Worker 接入。关键限制与注意事项适用范围protobuf 消息要求仅针对InProcessRuntime之外的运行时。纯进程内应用可继续使用普通 C# 类参见 GettingStarted/CountUpdate.cs 等 POCO不必引入 proto 工具链。未来可能放宽文档明确提示该要求“may be relaxed in future by allowing for converters, custom serialization, or other mechanisms”即官方预留了 converter / 自定义序列化机制的扩展方向。当前版本请以 proto 定义为唯一合规做法。csharp_namespace决定代码组织所有 C# 端引用using、IHandle...泛型参数都依赖该选项示例将其设为GettingStartedGrpcSample.Events后Agent 代码得以用Events.CountMessage这类短限定名引用生成类型。字段编号是 wire 契约proto 字段的数字标签参与二进制编码修改或复用编号会导致跨版本反序列化错乱扩展消息时只应追加新字段。GrpcServices 按需选择仅定义消息类型时可只生成客户端代码或完全不生成服务桩示例使用GrpcServicesClient文档示例中的GrpcServicesClient;Server适用于 proto 文件中同时定义service的场景。按以上方式你就可以在 AutoGen .NET 项目中定义一套跨进程可传输的强类型消息构建期由Grpc.Tools生成 C# 类运行期由 gRPC 运行时完成序列化与分发Agent 通过IHandleT[TypeSubscription]以类型安全的方式订阅并处理消息。【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考