目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。

前言

咱们先破除一个迷信:做AI Agent必须得用Python?这就像是说"吃火锅必须得去重庆"一样——虽然川渝火锅确实香,但你在家用电火锅煮顿毛肚,照样能吃得满嘴流油,甚至还能精准控温不糊锅。

C#搞AI Agent,那感觉就像是用瑞士军刀削苹果——看似大材小用,实则稳得一批。Python写Agent像开跑车,速度快但颠;C#像开德系SUV,底盘扎实、仪表盘清晰、开着空调跑长途都不带喘的。今天咱们就聊聊,怎么用.NET生态搭建一套工业级稳定的AI Agent系统,代码直接Copy就能跑,不搞那些虚头巴脑的"概念演示"。

一、为什么工业场景偏爱C#搞Agent?

先泼盆冷水:如果你就想做个"提示词套壳"的玩具Agent,那确实Python更快。但要是想把这个Agent塞进7×24小时运转的生产环境,处理订单、监控日志、自动发邮件、对接企业微信——这时候C#的优势就开始暴击了。

类型安全就是防爆胎系统。Python的Agent跑起来,半夜三更突然给你抛个NoneType has no attribute 'split',你找bug找到秃头。C#在编译期就把这些破事掐死了,Agent跑了三个月,内存占用还是稳如老狗,不会像某些脚本语言那样"越跑越胖"。

再说生态。Semantic Kernel这玩意儿是微软亲儿子,GitHub上 star 数已经破两万,更新勤快得跟打卡上班似的。它原生的C#支持比Python还早,Plugins、Planners、Memory这些高级功能,C# API的设计明显是用了心的,不像某些跨语言库,Python是亲生的,其他语言是充话费送的。

二、环境搭建:三行命令上高速

别被那些"先装Conda再配PyTorch"的教程吓到,咱们C#玩家的环境配置简单得令人发指。确保你装了.NET 9 SDK(2025年了,别用.NET Framework 6.x了,性能差一截),然后:

dotnet new console -n IndustrialAgent
cd IndustrialAgent
dotnet add package Microsoft.SemanticKernel --version 1.33.0
dotnet add package Microsoft.SemanticKernel.Agents.Core --version 1.33.0
dotnet add package Microsoft.SemanticKernel.Agents.OpenAI --version 1.33.0

完事儿。没有虚拟环境冲突,没有CUDA版本地狱,NuGet包往csproj里一写,teammates 拉下来直接dotnet restore,整个世界都清净了。

三、核心架构:Agent不是"大模型+while循环"

很多人理解Agent就是"写个死循环,把用户输入扔给GPT,再把输出打印出来"。这顶多算个聊天机器人。真正的Agent得有手(调用工具)、有脑(规划任务)、有记性(上下文记忆)。

Semantic Kernel把这仨抽象得明明白白:

3.1 Plugins:给Agent装上手和脚

Plugin就是一组功能,可以是C#本地方法,也可以是OpenAPI接口。比如咱们要给Agent一个"查天气"和"发邮件"的能力:

using Microsoft.SemanticKernel;
using System.ComponentModel;

public class UtilityPlugin
{
    [KernelFunction("get_weather")]
    [Description("获取指定城市的当前天气")]
    public string GetWeather([Description("城市名称,如'北京'")] string city)
    {
        // 这里接真实天气API,演示用模拟数据
        return $"{city}今天晴,25度,适合写代码";
    }

    [KernelFunction("send_email")]
    [Description("发送邮件给指定收件人")]
    public string SendEmail(
        [Description("收件人邮箱")] string to, 
        [Description("邮件主题")] string subject, 
        [Description("邮件正文")] string body)
    {
        // 真实场景接SMTP或企业微信邮件接口
        Console.WriteLine($"[邮件已发送] To: {to}, Subject: {subject}");
        return "邮件发送成功";
    }
}

看到没?用[KernelFunction][Description]特性一标记,C#的原生方法就变成了Agent能理解的工具。这比Python那种靠字符串匹配函数名的方式靠谱多了,重构的时候Visual Studio直接帮你改全引用,绝不会出现"函数改名了但Agent还在找旧名字"的尴尬。

3.2 多Agent协作:开一场技术评审会

单Agent干活像独角戏,多Agent协作才是工业级的玩法。咱们模拟一个代码评审委员会:产品经理提需求,架构师出方案,开发工程师写代码,测试工程师找bug。

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.OpenAI;
using Microsoft.SemanticKernel.ChatCompletion;
using System.Text;

// 初始化Kernel,这里用OpenAI,实际可换Azure或本地Ollama
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
    modelId: "gpt-4",
    apiKey: "你的APIKey"); // 生产环境用环境变量或Azure Key Vault

// 也支持本地Ollama,零成本测试
// builder.AddOllamaChatCompletion("llama3.2", new Uri("http://localhost:11434"));

var kernel = builder.Build();

// 定义三个专家Agent
var productManager = new ChatCompletionAgent(
    kernel: kernel,
    name: "产品经理",
    description: "负责分析需求,明确业务价值",
    instructions: "你是一位严谨的产品经理。当用户提出需求时,你需要:1)分析需求的合理性 2)指出潜在的业务风险 3)用一句话总结核心功能点。回复控制在100字以内。");

var architect = new ChatCompletionAgent(
    kernel: kernel,
    name: "架构师",
    description: "负责技术方案设计",
    instructions: "你是一位资深.NET架构师。基于产品经理的分析,你需要:1)提出技术实现方案 2)指出技术难点 3)建议使用的设计模式。回复控制在150字以内。");

var developer = new ChatCompletionAgent(
    kernel: kernel,
    name: "开发工程师",
    description: "负责具体代码实现",
    instructions: "你是一位C#开发专家。根据架构师方案,编写可运行的核心代码片段,要求使用最新C# 12语法,包含必要的异常处理。");

// 创建群聊策略
var chat = new AgentGroupChat(productManager, architect, developer);

// 定义终止条件:当开发工程师输出了代码块,且所有人都发言后结束
chat.ExecutionSettings = new ChatHistoryTruncationReducer
{
    TargetCount = 6, // 保留最近6轮对话
};

// 启动话题
var input = "我要做一个能自动监控服务器CPU使用率,超过90%就发微信告警的Windows服务";
await chat.AddChatMessageAsync(new ChatMessageContent(AuthorRole.User, input));

// 执行对话,每轮由LLM决定谁发言
var sb = new StringBuilder();
await foreach (var response in chat.InvokeAsync())
{
    sb.AppendLine($"[{response.AuthorName}]: {response.Content}");
    Console.WriteLine($"[{response.AuthorName}]: {response.Content}");
    Console.WriteLine(new string('-', 40));
}

File.WriteAllText("meeting_minutes.txt", sb.ToString());

这段代码的核心在于AgentGroupChat。它不是一个简单的轮询,而是让大模型自己判断"现在该谁说话"。产品经理说完,模型觉得信息够了就让架构师接,架构师说完再让开发接——这种动态协作比写死流程的代码聪明多了。

而且你看,C#的async/await处理这种流式输出简直丝滑,不会像Python那样在并发高了之后出现诡异的事件循环阻塞。

四、工业级稳定性的秘密武器

4.1 本地模型兜底:断网也能跑

生产环境最怕的就是"OpenAI API超时"或"余额不足"。C#的Semantic Kernel原生支持Ollama,可以把Llama 3.2、Qwen 2.5这些开源模型部署在本地内网,Agent即便断了外网也能降级运行。

// 同一套代码,无缝切换本地模型
builder.AddOllamaChatCompletion(
    modelId: "qwen2.5:7b",
    endpoint: new Uri("http://localhost:11434")
);

// 配合Polly做熔断降级
var pipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(1),
        OnRetry = args =>
        {
            Console.WriteLine($"API挂了,第{args.AttemptNumber}次重试...");
            return ValueTask.CompletedTask;
        }
    })
    .Build();

// 在KernelFunction里套一层熔断保护
kernel.FunctionInvocationFilters.Add(new PollyFilter(pipeline));

这就像是给Agent配了个"备用发电机",主电源断了自动切换,业务不中断。Python虽然也能用Ollama,但C#的强类型让你在切换模型时,编译器会强制你检查所有接口兼容性,不会出现"本地模型不支持某个参数导致运行时崩溃"的情况。

4.2 内存管理:别让Agent变成"内存黑洞"

Python的Agent跑久了内存泄露是常态,C#有GC把关,但也要注意Kernel和ChatHistory的生命周期。上面代码里的ChatHistoryTruncationReducer就是关键——它自动裁剪对话历史,防止上下文无限增长撑爆显存(如果是本地模型)或Token费用(如果是云端API)。

// 自定义更激进的内存控制
public class CompactHistoryReducer : IChatHistoryReducer
{
    public int? TargetCount => 4; // 只保留最近4轮

    public Task ReduceAsync(ChatHistory history, CancellationToken ct = default)
    {
        // 把老旧对话压缩成摘要,而不是直接删除
        if (history.Count > TargetCount)
        {
            var oldMessages = history.Take(history.Count - TargetCount.Value).ToList();
            var summary = $"[历史摘要]{string.Join(";", oldMessages.Select(m => m.Content))}";
            
            history.RemoveRange(0, oldMessages.Count);
            history.Insert(0, new ChatMessageContent(AuthorRole.System, summary));
        }
        return Task.CompletedTask;
    }
}

这种细粒度的内存控制,在C#里写起来就是几行LINQ,放到Python里你得自己管理列表切片和字符串拼接,还容易出索引越界错误。

五、实战:写一个能操作Excel的Agent

光说不练假把式,咱们来个能实际干活的:让Agent读取Excel报表,分析数据,生成图表,最后把报告发邮件给老板。全程不用Python的pandas,就用C#的EPPlus库,速度比Python快,内存占用还低。

using OfficeOpenXml; // dotnet add package EPPlus
using Microsoft.SemanticKernel;
using System.Data;

public class ExcelAnalysisPlugin
{
    [KernelFunction("analyze_sales_excel")]
    [Description("分析销售Excel文件,返回关键指标")]
    public string AnalyzeExcel([Description("Excel文件路径")] string filePath)
    {
        ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
        using var package = new ExcelPackage(new FileInfo(filePath));
        var worksheet = package.Workbook.Worksheets[0];

        // 读取数据到DataTable
        var dt = new DataTable();
        foreach (var firstRowCell in worksheet.Cells[1, 1, 1, worksheet.Dimension.End.Column])
        {
            dt.Columns.Add(firstRowCell.Text);
        }

        for (int rowNum = 2; rowNum <= worksheet.Dimension.End.Row; rowNum++)
        {
            var row = worksheet.Cells[rowNum, 1, rowNum, worksheet.Dimension.End.Column];
            var newRow = dt.NewRow();
            foreach (var cell in row) 
                newRow[cell.Start.Column - 1] = cell.Text;
            dt.Rows.Add(newRow);
        }

        // 简单分析:计算总销售额
        var totalSales = dt.AsEnumerable().Sum(r => 
            decimal.TryParse(r["销售额"].ToString(), out var d) ? d : 0);
    
        return $"分析完成:共{dt.Rows.Count}条记录,总销售额{totalSales:C},平均客单价{totalSales/dt.Rows.Count:C}";
    }

    [KernelFunction("generate_chart")]
    [Description("生成销售趋势图")]
    public string GenerateChart([Description("输出图片路径")] string outputPath)
    {
        // 这里接SkiaSharp或System.Drawing生成图表
        // 演示简化,实际可生成真实PNG
        File.WriteAllText(outputPath, "[图表数据占位]");
        return $"图表已保存至{outputPath}";
    }
}

// 主程序
var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4", Environment.GetEnvironmentVariable("OPENAI_API_KEY"))
    .Build();

kernel.Plugins.AddFromType<ExcelAnalysisPlugin>();
kernel.Plugins.AddFromType<UtilityPlugin>(); // 之前的发邮件插件

var agent = new ChatCompletionAgent(
    kernel: kernel,
    instructions: "你是数据分析助手。当用户要求分析Excel时,先调用analyze_sales_excel获取数据,然后调用generate_chart生成图表,最后调用send_email发送结果。每步都要确认上一步成功。"
);

// 运行
await foreach (var msg in agent.InvokeAsync("帮我分析C:\\data\\sales.xlsx,然后把结果发给manager@company.com"))
{
    Console.WriteLine(msg.Content);
}

看到没?Agent自己规划了"读取→分析→可视化→发送"的流程,而且用的是原生C#生态的EPPlus,不需要像Python那样装一堆科学计算包还担心版本冲突。这套代码编译成exe,扔到Windows Server上设个定时任务,每天自动跑报表,稳得一批。

六、部署:从控制台到Windows服务

写完代码别只会dotnet run,工业级Agent得包装成Windows服务,开机自启,后台运行,带日志切割。

// Program.cs 改造为Worker Service
using Microsoft.SemanticKernel;
using System.ServiceProcess; // dotnet add package System.ServiceProcess.ServiceController

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddWindowsService(options => options.ServiceName = "AI Agent Service");
builder.Services.AddHostedService<AgentWorker>();

// 依赖注入Kernel
builder.Services.AddSingleton(serviceProvider =>
{
    var k = Kernel.CreateBuilder()
        .AddOpenAIChatCompletion("gpt-4", builder.Configuration["OpenAI:Key"])
        .Build();
    k.Plugins.AddFromType<ExcelAnalysisPlugin>();
    return k;
});

var host = builder.Build();
await host.RunAsync();

// Worker实现
public class AgentWorker : BackgroundService
{
    private readonly Kernel _kernel;
    private readonly ILogger<AgentWorker> _logger;

    public AgentWorker(Kernel kernel, ILogger<AgentWorker> logger)
    {
        _kernel = kernel;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Agent服务启动,开始监控...");
    
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // 每小时检查一次数据库或消息队列
                await CheckPendingTasks(stoppingToken);
                await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Agent执行任务时挂了");
                // 异常了等5分钟重试,防止疯狂报错打爆日志
                await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
            }
        }
    }

    private async Task CheckPendingTasks(CancellationToken ct)
    {
        // 查数据库找待处理任务,交给Agent处理
        // 真实业务代码...
    }
}

sc.exe create "AIAgent" binPath= "你的exe路径"装成服务,配合Windows事件查看器查日志,这才是工业级玩法。Python你想做成服务?要么用nssm这种第三方工具,要么写一堆SystemD配置,还得小心GIL锁导致的并发问题。

七、结语:C#的Agent开发,是降维打击

说到底,C#做AI Agent不是"能不能"的问题,而是"值不值"的问题。如果你就想搞个原型骗投资,Python确实快;但如果你想让Agent在企业防火墙内稳定跑三年,处理千万级数据不丢包,对接SAP、用友、金蝶这些老古董系统——C#就是最优解。

Semantic Kernel生态在2025年已经相当成熟,NuGet包每周更新,社区示例丰富。更重要的是,C#的强类型、完善的异步模型、出色的内存管理,让Agent从"玩具"变成了"生产工具"。

下次再有小白问你"做AI必须用Python吗",你可以把这篇文章拍他脸上:看好了,这才叫工业级的AI Agent开发,稳得就像你写的单元测试——虽然写的时候麻烦点,但跑起来从来不出幺蛾子。

代码都给你了,环境配置就三步,还等啥?今晚就开始把你的第一个C# Agent部署到服务器上,明天上班就能跟老板吹牛:“咱这系统,用C#写的,比隔壁组Python的那个稳定十倍。”

目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。

在这里插入图片描述

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐