首页
/ AutoGen .NET 创建助手智能体实战:AssistantAgent 与 OpenAIChatAgent 的完整使用指南

AutoGen .NET 创建助手智能体实战:AssistantAgent 与 OpenAIChatAgent 的完整使用指南

2026-09-04 15:46:30作者:卓炯娓

本文以 AutoGen .NET 仓库中的文档 Create-an-agent.md 为核心,讲解在 C# 中创建“助手智能体(Assistant Agent)”的两条主流路径:基于 ConversableAgentConfigAssistantAgent,以及基于 OpenAI V1 SDK 的 OpenAIChatAgent。读完后你将能够独立完成:读取 API Key、配置 LLM 参数、创建助手智能体、发起对话并携带会话历史、以及为智能体注册函数调用(function calling)能力。

一、AutoGen .NET 中的“助手智能体”是什么

官方文档对 AssistantAgent 的定义是:它是 AutoGen 内置的一个 AI 助手型智能体,使用 LLM 对用户的输入生成回复;如果底层 LLM 模型支持函数调用(文档举例 gpt-3.5-turbo-0613),它也支持 function call。

从源码结构看,AutoGen .NET 中存在两代助手智能体 API:

  1. AssistantAgent(位于 AssistantAgent.cs):它只是一个薄封装,直接继承自 ConversableAgent,通过 ConversableAgentConfig 描述 LLM 配置(模型、温度、函数契约等);
  2. OpenAIChatAgent(位于 OpenAIChatAgent.cs):直接基于 OpenAI .NET SDK 的 ChatClient 构建,是后续官方示例(如 Example01_AssistantAgent.cs)采用的方式,支持更多消息类型、流式响应和细粒度参数(seed、JSON mode 等)。

两者都能完成“创建助手并回答用户”的任务,本文按官方文档顺序分别讲解。

二、使用 OpenAI 模型创建 AssistantAgent

官方文档给出的第一个代码片段(来源:CreateAnAgent.cscode_snippet_1 区域)如下:

// get OpenAI Key and create config
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");

// create assistant 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 },
    });

前置条件

  • 设置环境变量 OPENAI_API_KEY
  • 项目引用 AutoGen(核心包)与 AutoGen.OpenAI 相关包,示例位于 AutoGen.Basic.Sample.csproj

关键参数说明

OpenAIConfig(源码:OpenAIConfig.cs)只有两个构造参数:

参数 类型 说明
apiKey string OpenAI API Key,示例中从环境变量 OPENAI_API_KEY 读取
modelId string 模型 ID,示例使用 gpt-3.5-turbo

其内部通过 CreateChatClient() 方法用 new OpenAIClient(this.ApiKey).GetChatClient(this.ModelId) 创建聊天客户端。

ConversableAgentConfig(源码:ConversableAgentConfig.cs)包含 4 个属性:

属性 类型 默认值 说明
Temperature float? 0.7f 采样温度,示例中显式设为 0 以获得更确定的输出
ConfigList IEnumerable<ILLMConfig>? 模型配置列表,支持多个配置组合
FunctionContracts IEnumerable<FunctionContract>? 供该智能体调用的函数契约列表
Timeout int? 超时时间(秒)

源码层面发生了什么

AssistantAgent 的构造函数(AssistantAgent.cs)将 namesystemMessagellmConfig 等参数原样透传给基类 ConversableAgent。在 ConversableAgent 的第二个构造函数中(ConversableAgent.cs),当 llmConfig.ConfigList 非空时,会调用 CreateInnerAgentFromConfigList 根据配置列表创建真正的 LLM 智能体。

CreateInnerAgentFromConfigList 的源码可以看到,当前内置支持三种配置类型:

  • AzureOpenAIConfig → 创建 OpenAIChatAgent(Azure OpenAI 后端);
  • OpenAIConfig → 创建 OpenAIChatAgent(OpenAI 后端);
  • LMStudioConfig → 创建 OpenAIChatAgent(LM Studio 后端,即 OpenAI 兼容接口);

其他类型会抛出 ArgumentException。如果 ConfigList 中包含多个配置,多个内部智能体之间通过中间件串联:当前智能体生成 null 回复时,会回退(fallback)到下一个智能体继续尝试。

此外,构造函数中还有几个值得注意的默认值:systemMessage 默认为 "You are a helpful AI assistant"AssistantAgenthumanInputMode 默认为 HumanInputMode.NEVER(从不提示人工输入),而 ConversableAgent 基类构造函数中该参数默认是 AUTO,使用时需注意二者差异。

三、使用 Azure OpenAI 模型创建助手智能体

官方文档的第二段标题为“使用 Azure OpenAI 模型创建 AssistantAgent”,对应 CreateAnAgent.cscode_snippet_2 区域,实际示例代码如下:

// get OpenAI Key and create config
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
var model = "gpt-4o-mini";

var openAIClient = new OpenAIClient(apiKey);

// create assistant agent
var assistantAgent = new OpenAIChatAgent(
    name: "assistant",
    systemMessage: "You are an assistant that help user to do some tasks.",
    chatClient: openAIClient.GetChatClient(model))
    .RegisterMessageConnector()
    .RegisterPrintMessage();

该示例先创建 OpenAI SDK 的 OpenAIClient,再通过 GetChatClient(model) 获得指定模型(gpt-4o-mini)的 ChatClient,最后以 chatClient 方式构造 OpenAIChatAgent。需要说明:OpenAIClient 支持通过 OpenAIClientOptions.Endpoint 指定自定义端点,因此同样的写法也可以指向 Azure OpenAI 或其他 OpenAI 兼容服务(如 Ollama、LM Studio)。仓库中 LLMConfiguration.csGetAzureOpenAIGPT3_5_Turbo 方法展示了 Azure OpenAI 场景下的环境变量约定:AZURE_OPENAI_API_KEYAZURE_OPENAI_ENDPOINTAZURE_OPENAI_DEPLOY_NAME

OpenAIChatAgent 的完整构造参数

OpenAIChatAgent 提供两个构造函数(源码:OpenAIChatAgent.cs),常用重载的参数如下:

参数 类型 默认值 说明
openAIClient OpenAIClient 必填 OpenAI SDK 客户端
name string 必填 智能体名称
modelName string 必填 模型名,如 gpt-4o-mini
systemMessage string "You are a helpful AI assistant" 系统提示词
temperature float 0.7f 采样温度
maxTokens int 1024 最大生成 token 数
seed int? null 随机种子,设置后输出更具确定性
responseFormat ChatCompletionsResponseFormat? null 设为 JsonObject 可启用 JSON mode
functions IEnumerable<FunctionDefinition>? null 智能体可调用函数

另一个构造函数接收 ChatCompletionsOptions 对象,源码中校验了 options.Messages 不能包含消息("Messages should not be provided in options"),因为消息由 GenerateReplyAsync 在运行时注入。

两个关键扩展方法

示例中的链式调用 .RegisterMessageConnector().RegisterPrintMessage() 分别注册两个中间件:

  • RegisterMessageConnector():定义在 OpenAIAgentExtension.cs,注册 OpenAIChatRequestMessageConnector 流式中间件,负责把 AutoGen 消息体系与 OpenAI 的 ChatRequestMessage 互相转换;
  • RegisterPrintMessage():注册 PrintMessageMiddleware,在控制台打印智能体收发的消息,便于调试观察对话过程。

四、与助手智能体对话:SendAsync 与会话历史

创建智能体后,用 SendAsync 发起对话。Example01_AssistantAgent.cs 展示了完整的对话流程:

var gpt4oMini = LLMConfiguration.GetOpenAIGPT4o_mini();
var assistantAgent = new OpenAIChatAgent(
    chatClient: gpt4oMini,
    name: "assistant",
    systemMessage: "You convert what user said to all uppercase.")
    .RegisterMessageConnector()
    .RegisterPrintMessage();

// talk to the assistant agent
var reply = await assistantAgent.SendAsync("hello world");
reply.Should().BeOfType<TextMessage>();
reply.GetContent().Should().Be("HELLO WORLD");

// to carry on the conversation, pass the previous conversation history to the next call
var conversationHistory = new List<IMessage>
{
    new TextMessage(Role.User, "hello world"), // first message
    reply, // reply from assistant agent
};

reply = await assistantAgent.SendAsync("hello world again", conversationHistory);
reply.Should().BeOfType<TextMessage>();
reply.GetContent().Should().Be("HELLO WORLD AGAIN");

要点:

  1. 智能体本身无状态:第二次调用必须把第一轮的用户消息和助手回复放进 conversationHistory 一并传入,模型才能“记住”上下文;
  2. 回复类型SendAsync 返回 IMessage,助手纯文本回复是 TextMessage,可通过 reply.GetContent() 取出内容;若模型发起函数调用,则返回 ToolCallMessage(见下一节)。

五、让助手支持函数调用(Function Calling)

官方文档指出 AssistantAgent 在底层模型支持时可以进行函数调用。示例工程 CreateAnAgent.cs 后半部分给出了函数调用的完整闭环:

1. 用 [Function] 特性声明函数

/// <summary>
/// convert input to upper case
/// </summary>
/// <param name="input">input</param>
[Function]
public async Task<string> UpperCase(string input)
{
    var result = input.ToUpper();
    return result;
}

AutoGen 的源生成器(FunctionCallGenerator.cs)会为标记 [Function] 的方法生成函数契约 UpperCaseFunctionContract,其中包含供 LLM 理解的 FunctionDefinition(名称、描述、参数 schema,来自方法的 XML 注释)。

2. 方式一:构造时直接传入 functions,模型返回 ToolCallMessage

var assistantAgent = new OpenAIChatAgent(
    chatClient: openAIClient.GetChatClient(model),
    name: "assistant",
    systemMessage: "You are an assistant that convert user input to upper case.",
    functions: [
        this.UpperCaseFunctionContract.ToChatTool(), // The FunctionDefinition object for the UpperCase function
    ])
    .RegisterMessageConnector()
    .RegisterPrintMessage();

var response = await assistantAgent.SendAsync("hello");
response.Should().BeOfType<ToolCallMessage>();
var toolCallMessage = (ToolCallMessage)response;
toolCallMessage.ToolCalls.Count.Should().Be(1);
toolCallMessage.ToolCalls.First().FunctionName.Should().Be("UpperCase");

在这种模式下,SendAsync("hello") 得到的回复是 ToolCallMessage——即模型“想调用函数”但尚未执行,由宿主程序自行取出参数并执行。

3. 方式二:用 FunctionCallMiddleware 自动执行函数

var functionCallMiddleware = new FunctionCallMiddleware(
    functions: [this.UpperCaseFunctionContract],
    functionMap: new Dictionary<string, Func<string, Task<string>>>()
    {
        { this.UpperCaseFunctionContract.Name, this.UpperCase },
    });
var assistantAgent = new OpenAIChatAgent(
    name: "assistant",
    systemMessage: "You are an assistant that convert user input to upper case.",
    chatClient: openAIClient.GetChatClient(model))
    .RegisterMessageConnector()
    .RegisterStreamingMiddleware(functionCallMiddleware);

var response = await assistantAgent.SendAsync("hello");
response.Should().BeOfType<TextMessage>();
response.From.Should().Be("assistant");
var textMessage = (TextMessage)response;
textMessage.Content.Should().Be("HELLO");

这里 FunctionCallMiddleware 通过 functions 向模型声明可用函数,并通过 functionMap 把函数名映射到实际实现。当模型返回工具调用时,中间件自动执行对应函数并把结果回填给模型,最终 SendAsync 直接得到执行完函数后的 TextMessage(内容为 "HELLO")。也就是说:方式一暴露“调用意图”给调用方,方式二在智能体内部闭环完成调用

对于 AssistantAgent 旧 API,则通过构造参数的 functionMapConversableAgentConfig.FunctionContracts 组合实现同样的能力,见 AssistantAgent.cs 的构造函数签名。

六、原理剖析:AssistantAgent 的中间件处理链

理解 ConversableAgent.GenerateReplyAsync 就能理解 AssistantAgent 每次回复的完整处理流程。源码中的注释明确写出处理顺序:

// process order: function_call -> human_input -> inner_agent -> default_reply -> self_execute
// first in, last out

具体步骤:

  1. 系统消息注入:如果消息列表中没有 system 消息,自动把 systemMessage 作为 Role.SystemTextMessage 插到历史最前面;
  2. 构建基础智能体:若 llmConfig 配置了 ConfigList,使用第二节介绍的内部 LLM 智能体;否则回退到 DefaultReplyAgent,只返回 defaultReply 文本(未设置时提示 "Default reply is not set. Please pass a default reply to assistant agent");
  3. HumanInputMiddleware:注册 HumanInputMiddleware,其行为由 HumanInputMode 三档控制:
    • NEVERAssistantAgent 默认):直接透传给下一层,不提示人工输入;
    • ALWAYS:每次都打印提示并读取控制台输入作为该轮“回复”,输入 exit 时返回群聊终止消息;
    • AUTOConversableAgent 基类默认):仅当 isTermination 判定为非终止消息时提示人工输入;
  4. FunctionCallMiddleware:最外层注册函数调用中间件,负责解析 ToolCallMessage 并执行 functionMap 中映射的函数;
  5. 按“先进后出”的顺序执行整条中间件链。

这套设计意味着:创建助手智能体只是“填参数”,而消息转换、人工介入、函数执行等能力都通过中间件按需叠加,这也是 AutoGen .NET 与直接用 LLM SDK 调用的主要区别。

七、实践建议与验证路径

  • 新项目优先用 OpenAIChatAgent:仓库的官方示例(如 Example01_AssistantAgent.cs)均采用此 API,参数更完整(seed、JSON mode、maxTokens),且天然支持流式(IStreamingAgent);AssistantAgent 适合需要 ConversableAgentConfig 多模型 fallback 或 functionMap 简写风格的场景;
  • 无状态设计:务必自己维护 conversationHistory,不要假设智能体记住了上一轮对话;
  • 函数调用二选一:需要宿主程序控制执行时机时用 functions 构造参数(拿 ToolCallMessage),需要智能体自主闭环时用 FunctionCallMiddleware

可参考的仓库内验证路径:

文件 作用
CreateAnAgent.cs 本文全部代码片段的来源(code_snippet_1code_snippet_5
Example01_AssistantAgent.cs 助手智能体对话与会话历史的最小可运行示例
AssistantAgent.cs AssistantAgent 实现
ConversableAgent.cs 中间件处理链与多模型 fallback 逻辑
OpenAIChatAgent.cs OpenAIChatAgent 参数与消息转换实现
FunctionCallMiddleware.cs 函数调用自动执行中间件
AutoGen.csproj AssistantAgent/ConversableAgent 所在核心包

运行上述示例前,请先按各代码片段注释设置 OPENAI_API_KEY(以及 Azure 场景的 AZURE_OPENAI_API_KEY / AZURE_OPENAI_ENDPOINT)环境变量,并确认所用模型版本支持函数调用(文档示例为 gpt-3.5-turbo-0613 及之后的模型)。

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

项目优选

收起
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