AutoGen.Net Agent 核心机制详解:从创建、对话、流式输出到中间件与群聊编排
本文围绕 AutoGen.Net 中最基础的抽象 Agent(智能体)展开,系统讲解其接口契约(IAgent/IStreamingAgent)、如何创建各类内置 Agent、如何发起普通与流式对话、如何通过中间件扩展 Agent 行为,以及如何用群聊(GroupChat)构建多智能体工作流。读完本文后,你能够基于 AutoGen.sln 中的 AutoGen.Core 等程序集搭建一个可对话、可流式输出、可挂接工具调用与消息转换逻辑的 Agent,并将其组织为顺序或动态编排的多 Agent 流程。
Agent 是什么:一个最小接口契约
在 AutoGen.Net 中,Agent 是处理特定任务的基本单元:单个 Agent 负责处理一项具体任务;通过中间件(Middlewares)扩展 Agent 的行为;通过群聊(GroupChat)把多个 Agent 组织成多智能体工作流。
从源码看,所有 Agent 都实现同一个接口契约:
- 每个 Agent 都实现 IAgent,支持流式回复的 Agent 额外实现 IStreamingAgent;
IAgent继承自IAgentMetaInformation,因此每个 Agent 都有Name属性,这是后续群聊编排、消息来源追踪(IMessage.From)的基础。
IAgent 的核心方法签名为:
public interface IAgent : IAgentMetaInformation
{
public Task<IMessage> GenerateReplyAsync(
IEnumerable<IMessage> messages, // 会话历史
GenerateReplyOptions? options = null, // 可选的补全选项,提供时覆盖已有选项
CancellationToken cancellationToken = default);
}
也就是说,一次 Agent 调用就是"输入一个消息序列,产出一条 IMessage 回复"。GenerateReplyOptions 允许在调用时临时覆盖默认行为,其字段定义见 IAgent.cs:
| 属性 | 类型 | 说明 |
|---|---|---|
Temperature |
float? |
采样温度,可空表示沿用 Agent 默认值 |
MaxToken |
int? |
生成 token 上限 |
StopSequence |
string[]? |
停止序列 |
Functions |
FunctionContract[]? |
临时注入的函数调用契约 |
OutputSchema |
JsonSchema? |
输出结构约束(JSON Schema),仅对部分 LLM 生效 |
IStreamingAgent 则在此基础上多出一个流式入口,返回 IAsyncEnumerable<IMessage>:
public interface IStreamingAgent : IAgent
{
public IAsyncEnumerable<IMessage> GenerateStreamingReplyAsync(
IEnumerable<IMessage> messages,
GenerateReplyOptions? options = null,
CancellationToken cancellationToken = default);
}
创建 Agent
AutoGen.Net 提供了多套可直接使用的内置 Agent,分别对应不同的 LLM 后端。以下是官方文档给出的四类典型创建路径(对应 Agent-overview.md 中的链接集合):
| Agent 类型 | 适用场景 | 参考文档 |
|---|---|---|
AutoGen.AssistantAgent |
通用助手,支持 OpenAI/Azure OpenAI/LM Studio 配置 | Create an assistant agent |
AutoGen.OpenAI.OpenAIChatAgent |
基于 OpenAI .NET SDK 的 Chat Client | Create an OpenAI chat agent |
AutoGen.SemanticKernel.SemanticKernelAgent |
复用 Semantic Kernel 的 Kernel 与函数体系 | Create a semantic kernel agent |
AutoGen.LMStudio.LMStudioAgent |
连接本地 LM Studio 服务 | Connect to LM Studio |
使用 AssistantAgent(配置驱动)
AssistantAgent 是内置的"AI 助手" Agent。它接收名称、系统提示词、LLM 配置(ConversableAgentConfig)、终止判定函数、人工输入模式等参数。示例代码来自 CreateAnAgent.cs:
// 从环境变量读取 OpenAI Key 并创建配置
var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
var llmConfig = new OpenAIConfig(openAIKey, "gpt-3.5-turbo");
// 创建助手 Agent
var assistantAgent = new AssistantAgent(
name: "assistant",
systemMessage: "You are an assistant that help user to do some tasks.",
llmConfig: new ConversableAgentConfig
{
Temperature = 0,
ConfigList = new[] { llmConfig },
});
从 ConversableAgent 的实现可以看到其内部机制:AssistantAgent 继承自 ConversableAgent,后者会根据 ConversableAgentConfig.ConfigList 中的配置类型自动构造底层 Agent——AzureOpenAIConfig/OpenAIConfig/LMStudioConfig 都会被映射为带 RegisterMessageConnector() 的 OpenAIChatAgent。若 ConfigList 中包含多个配置,还会用中间件把它们串成"主 Agent 失败则回退到下一个 Agent"的降级链。
ConversableAgent 的构造函数参数还体现了几个关键行为开关(见 AssistantAgent.cs):
isTermination:终止判定函数,返回true时结束会话;humanInputMode:人工输入模式,取值为NEVER/ALWAYS/AUTO(定义于 ConversableAgent.cs);functionMap:函数名到异步委托的映射,用于函数调用;defaultReply:无法走 LLM 时的兜底回复。
在 GenerateReplyAsync 中,ConversableAgent 会先检查消息序列中是否已有 system 消息,若没有则把自身的 systemMessage 作为第一条系统消息注入,随后按 function_call -> human_input -> inner_agent -> default_reply 的处理顺序组装中间件管道(源码注释见 ConversableAgent.cs)。
使用 OpenAIChatAgent(SDK 驱动)
如果你更习惯直接使用 OpenAI .NET SDK,可以创建 OpenAIChatAgent 并通过扩展方法注册消息连接器与打印中间件,示例来自 CreateAnAgent.cs:
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
var model = "gpt-4o-mini";
var openAIClient = new OpenAIClient(apiKey);
var assistantAgent = new OpenAIChatAgent(
name: "assistant",
systemMessage: "You are an assistant that help user to do some tasks.",
chatClient: openAIClient.GetChatClient(model))
.RegisterMessageConnector() // 注册消息类型转换中间件
.RegisterPrintMessage(); // 注册控制台打印中间件
.RegisterMessageConnector() 与 .RegisterPrintMessage() 都是"注册中间件"的快捷扩展方法,这正是下一节中间件机制的典型用法。
与 Agent 对话
与 Agent 对话的最直接方式是调用 IAgent.GenerateReplyAsync;此外,AutoGen.Core.AgentExtension 提供了一组快捷扩展方法(实现见 AgentExtension.cs),可以简化消息构造与多轮会话管理。官方示例代码见 AgentCodeSnippet.cs。
方式一:GenerateReplyAsync
var message = new TextMessage(Role.User, "Hello");
IMessage reply = await agent.GenerateReplyAsync([message]);
这里直接以 IMessage 列表(即会话历史)作为输入,返回值是单条 IMessage 回复。
方式二:SendAsync 扩展方法
reply = await agent.SendAsync("Hello");
从 AgentExtension.cs 的实现看,字符串重载 SendAsync(string message, ...) 会先构造一条 TextMessage(Role.User, message),再委托给 IMessage 重载:后者把可选的 chatHistory 与新消息拼成完整序列后调用 GenerateReplyAsync。因此 SendAsync 本质上只是"自动帮你把消息追加到会话历史末尾"的语法糖。
AgentExtension 还提供了两个 Agent 之间对话的能力:SendAsync(this IAgent agent, IAgent receiver, ...) 会自动把两个 Agent 包进一个 RoundRobinGroupChat 来回对话(默认最多 10 轮,见 AgentExtension.cs);InitiateChatAsync 则是把整个对话过程收集完毕后一次性返回完整历史。
内置消息类型
AutoGen.Net 提供了一组内置消息类型,可用它们与 Agent 交互(详见 Built-in-messages.md)。从 AutoGen.Core/Message 目录可以确认实际可用的类型包括:
TextMessage:纯文本消息,是最常用的对话载体;ImageMessage:图片消息;MultiModalMessage:多模态组合消息;ToolCallMessage:工具调用请求;ToolCallResultMessage:工具执行结果;AggregateMessage/ToolCallAggregateMessage:聚合型消息(用于合并多条消息的场景);MessageEnvelope:消息信封结构。
消息的 Role(User/Assistant/System)与 From(消息来自哪个 Agent)共同构成了会话历史的语义基础,群聊中按"谁说了什么"路由正是依赖这两个字段。
流式对话
如果 Agent 实现了 IStreamingAgent,就可以使用 GenerateStreamingReplyAsync 以流式方式与 Agent 对话。注意:流式返回的是 IAsyncEnumerable<IMessage>,需要调用方自行消费这些增量更新。官方示例(同样位于 AgentCodeSnippet.cs)展示了把流式更新逐段打印到控制台的写法:
var textMessage = new TextMessage(Role.User, "Hello");
await foreach (var streamingReply in agent.GenerateStreamingReplyAsync([message]))
{
if (streamingReply is TextMessageUpdate update)
{
Console.Write(update.Content);
}
}
示例中用类型模式匹配 streamingReply is TextMessageUpdate update 过滤出文本增量并打印 Content。这说明流式管道中的每个 IMessage 并不都是"最终回复",而可能是增量更新类型的消息,消费方需要根据消息类型做不同的处理。
为 Agent 注册中间件
IMiddleware 与 IStreamingMiddleware 用于扩展 IAgent.GenerateReplyAsync 与 IStreamingAgent.GenerateStreamingReplyAsync 的行为。你可以向 Agent 注册中间件,以自定义函数调用支持、不同消息类型之间的转换、消息打印、收集用户输入等行为。
两个接口的定义分别在 IMiddleware.cs 与 IStreamingMiddleware.cs:
public interface IMiddleware
{
public string? Name { get; }
public Task<IMessage> InvokeAsync(
MiddlewareContext context,
IAgent agent,
CancellationToken cancellationToken = default);
}
public interface IStreamingMiddleware : IMiddleware
{
public IAsyncEnumerable<IMessage> InvokeAsync(
MiddlewareContext context,
IStreamingAgent agent,
CancellationToken cancellationToken = default);
}
中间件的语义是"环绕"(wrap):每个中间件持有 MiddlewareContext(封装了消息与选项)、下一个 IAgent,以及一个 CancellationToken,可以读取/改写上下文,然后决定是否调用 agent.GenerateReplyAsync 继续向管道深处传递——这与 ASP.NET Core 中间件模型一致。
承载中间件的容器是 MiddlewareAgent。它的 Use 方法会把新中间件包装成 DelegateAgent 并替换内部 Agent,形成洋葱模型;源码注释明确指出:多个中间件按 LIFO(后注册先执行)顺序运行。此外,MiddlewareAgent 还支持用委托直接注册匿名中间件(Use(Func<IEnumerable<IMessage>, GenerateReplyOptions?, IAgent, CancellationToken, Task<IMessage>>)),以及通过 ToString() 打印出 middleware1 -> middleware2 -> AgentName 形式的管道结构,便于调试。
围绕中间件的进一步主题,可参考以下文档(均来自 Agent-overview.md 的导航):
- 中间件总览:Middleware overview
- 打印消息到控制台:Print message middleware
- 消息类型转换:SemanticKernelChatMessageContentConnector 与 OpenAIChatRequestMessageConnector
- 编写自己的中间件:Create your own middleware
用群聊构建多智能体工作流
你可以使用 AutoGen.Core.IGroupChat 构建多智能体工作流。AutoGen.Net 中有两种群聊类型(定义于 AutoGen.Core/GroupChat 目录):
SequentialGroupChat:按固定、确定的顺序依次编排群聊中的 Agent。从源码看它继承自RoundRobinGroupChat(见 RoundRobinGroupChat.cs),即按成员列表轮转发言;GroupChat:以"更动态但依然可控"的方式编排群聊中的 Agent。
GroupChat 的构造函数接受成员列表、可选的管理者 Agent(admin)、初始消息与可选的工作流图(Graph),其编排策略(IOrchestrator)按优先级自动选择:
- 提供了
admin时使用RolePlayOrchestrator(由 LLM 管理者基于角色扮演提示词决定下一位发言者,可叠加Graph工作流先缩小候选集); - 仅提供
workflow时使用WorkflowOrchestrator(按图结构转移发言权); - 两者都没有时退化为
RoundRobinOrchestrator(轮询)。
构造函数中的 Validation() 还强制了群聊约束:所有成员必须有名字、名字必须唯一、工作流图中出现的 Agent 必须都在群聊成员中(见 GroupChat.cs)。其主循环 CallAsync 在每一轮中由编排器选出下一位发言人、执行 GenerateReplyAsync、把回复追加到历史,遇到群聊终止消息或达到 maxRound(默认 10)即结束(见 GroupChat.cs)。
更多群聊细节可参阅 Group chat overview。
小结
| 能力 | 关键 API | 源码位置 |
|---|---|---|
| 基本对话 | IAgent.GenerateReplyAsync |
IAgent.cs |
| 流式对话 | IStreamingAgent.GenerateStreamingReplyAsync |
IStreamingAgent.cs |
| 快捷发送 | AgentExtension.SendAsync / InitiateChatAsync |
AgentExtension.cs |
| 行为扩展 | IMiddleware / IStreamingMiddleware + MiddlewareAgent.Use |
IMiddleware.cs、MiddlewareAgent.cs |
| 多 Agent 编排 | SequentialGroupChat / GroupChat(Orchestrator) |
GroupChat.cs |
理解了"Agent 就是 GenerateReplyAsync 这一契约"之后,创建(选后端)、对话(消息类型)、流式(消费增量)、中间件(扩展管道)与群聊(编排策略)五个维度就都能在同一套抽象上组合起来,构成 AutoGen.Net 的完整编程模型。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00