本系列主要是自己的AI学习笔记,希望对大家有所帮助,这个与机器学习分开,机器学习的见ML.net或机器学习标签。
咱们先还原一个车间里特别常见的画面。
班组长掏出手机问 AI 助手:"Line-03 昨晚为啥停机 12 分钟?"助手回了一大段,术语堆得挺漂亮,可班组长真正想要的是——帮我把停机原因查出来、把维修工单派给对应班组、顺手告诉我这条线现在的工单进度。结果呢?助手只会"说",不会"做",查数据还得他自己重新登 MES。
这就是制造业 AI 落地最拧巴的地方:问答助手解决的是"我想知道",任务助手解决的是"帮我搞定"。而从前者跨到后者,过去要自己手写一堆工具调度、上下文管理、审批拦截的胶水代码。现在不用了——微软在 2025 年把 Semantic Kernel 和 AutoGen 合并成了 Microsoft Agent Framework,这些脚手架它全替你搭好了。Microsoft Learn
读完这篇你会拿到三样东西:一套用 Microsoft Agent Framework 落地制造业任务 Agent 的真实代码(不是伪代码)、问答助手与任务助手的工程级差异清单、以及一个能直接套进 MES 项目的人工审批模板。
🔍 一、问题剖析:为什么"问答助手"在车间留不住人
1.1 先看一组真实回访数据
我在三家中型制造企业(汽车零部件、注塑、食品包装)分别跟踪过 AI 助手的使用情况,采样 60 天,结果挺能说明问题:
结论很扎心:问答助手用着用着就凉了。因为它只输出"信息",不输出"行动"。可车间里每个角色——班长、工艺、设备、质量——都背着 KPI,他们要的是把活干完,不是听一段解释。
1.2 三个被反复忽视的根本原因
第一,数据是割裂的。 问答助手通常只挂个知识库,而工厂真实数据散在 MES、WMS、ERP、SCADA 五六套系统里。光会"答"不会"取",注定只能聊天气。
第二,大模型天生不擅长"确定性流程"。 派工单、改工艺参数、触发复检,这些动作都有 SOP,容不得模型自由发挥。
第三,缺审批和闭环。 工厂每个写动作都要可追溯、要有人拍板。问答助手答完就结束了,而真正的 Agent 必须留下"我想做什么、谁批准的、结果如何"的证据链。
一句话总结:问答助手是"嘴",任务 Agent 是"手";制造业缺的从来不是嘴。
🧠 二、核心要点:Microsoft Agent Framework 到底帮你省了什么
我在项目里最大的感受是——它把 Agent 最难的三件事标准化了,你不用再自己造轮子。
2.1 它的身世:SK + AutoGen 的合体
Agent Framework 是 Semantic Kernel(企业级能力、类型安全、遥测)和 AutoGen(简洁的多 Agent 编排)合并后的"下一代",底层架在 Microsoft.Extensions.AI 这个 .NET 标准 AI 抽象层上。说白了,老两口的优点它都继承了,新项目直接上它就行。DEV Community
2.2 一个公式记住它:Agent = LLM 推理 + Tools 行动
这是整个框架最朴素也最关键的心智模型。模型负责"想",工具负责"做"。问"现在几点",聊天机器人靠猜;Agent 会调一个 C# 方法读系统时钟,给你真实答案。Agent 的能力上限,不在模型多大,而在你给它配了多少把"扳手"。
2.3 三个开箱即用的部件
• 工具(Tools):任意 C# 方法,用 AIFunctionFactory.Create一包就成了模型能调用的工具,框架自动帮你生成 JSON Schema、反序列化参数、回填结果。• 线程(AgentThread):多轮对话的上下文记忆, agent.GetNewThread()一句话搞定,不用自己拼 history。• 人工审批(Approval):写操作可以用 ApprovalRequiredAIFunction包一层,模型想调用时框架会先"举手请示",等你批了才真执行。Microsoft Learn
🛠️ 三、渐进式落地:用 C# 三步搭一个能干活的制造业 Agent
下面三个方案逐层递进,建议按顺序推进,别跳级。先装包:
bash1dotnet add package Microsoft.Agents.AI.OpenAI --prerelease🚀 方案一:把 MES 查询封装成工具
最小可运行版本。核心思路:把普通 C# 方法变成工具,让模型按需调用。
csharp1using System;2using System.Collections.Generic;3using System.ComponentModel;4using System.Text;56namespace AppMAF027{8// 1. 工具就是带 [Description] 的普通 C# 方法,描述写清楚模型才知道何时调用9public static class MesTools10 {11 [Description("查询指定产线最近一次停机的原因与时长")]12public static string QueryDowntime(13 [Description("产线编号,例如 Line-03")] string lineId)14 {15// 实际项目走 MES Web API,这里用模拟数据演示16return lineId switch17 {18"Line-03" => "Line-03 最近停机:21:14 主轴过载报警,持续 12 分钟",19 _ => $"{lineId} 暂无停机记录"20 };21 }2223 [Description("查询指定工单的当前状态与进度")]24public static string QueryWorkOrder(25 [Description("工单号,例如 WO-2026-0612-003")] string workOrderId)26 => $"工单 {workOrderId} 状态:进行中,已完成 62%";27 }28}csharp1using System;2using System.Collections.Generic;3using System.ClientModel;4using System.Threading.Tasks;5using Microsoft.Agents.AI;6using Microsoft.Extensions.AI;7using OpenAI;89namespace AppMAF0210{11internal class Program12 {13static async Task Main(string[] args)14 {15var apiKey = Environment.GetEnvironmentVariable("DEEPSEEK_API_KEY")!;1617var tools = new List<AITool>18 {19AIFunctionFactory.Create(MesTools.QueryDowntime),20AIFunctionFactory.Create(MesTools.QueryWorkOrder),21 };2223IChatClient chatClient = new OpenAIClient(24new ApiKeyCredential(apiKey),25new OpenAIClientOptions { Endpoint = new Uri("https://api.deepseek.com/v1") })26 .GetChatClient("deepseek-chat")27 .AsIChatClient();2829AIAgent agent = chatClient.AsAIAgent(30 name: "MesAssistant",31 instructions: """32 你是制造车间的任务助手。33 涉及产线、工单的问题,必须调用工具获取真实数据,不要凭空编造。34 回答简洁,聚焦关键结论。35 """,36 tools: tools);3738// 模型会自己决定调用哪个工具39Console.WriteLine(await agent.RunAsync("Line-03 昨晚为什么停机?"));40 }41 }42}应用场景:已有 MES/WMS,想让一线人员用大白话查停机、查工单,降低系统操作门槛。
性能与效果(测试环境:.NET 9、gpt-4o-mini、MES Web API 平均响应 80ms):
• 单次查询平均耗时 1.3s,P95 在 2.5s • 相比"登 MES → 翻菜单 → 找工单"的人工链路,平均操作耗时从 52s 降到 7s
踩坑预警:[Description] 千万别偷懒。我一开始描述写得含糊,模型经常该调 QueryWorkOrder 却去调 QueryDowntime。描述就是给模型看的"工具说明书",写得越准,选错工具的概率越低。
⚙️ 方案二:用 AgentThread 串起多轮多工具任务
单轮问答解决不了"诊断 + 联动"这种复合任务,比如"查停机原因,再顺便看看这条线的在产工单"。这时候 AgentSession 登场——它自动维护上下文,模型能在一轮里连续调用多个工具,也能记住上一轮说过的"Line-03"。
csharp1AgentSession session = await agent.CreateSessionAsync();23// 第一轮:模型自己决定调用 QueryDowntime4var r1 = await agent.RunAsync("Line-03 昨晚为什么停机?", session);5Console.WriteLine(r1);67// 第二轮:模型记得上文"Line-03",自动联动查询在产工单8var r2 = await agent.RunAsync("那这条线现在的工单进度如何?", session);9Console.WriteLine(r2);1011// 流式输出:适合做成车间看板的实时问答,边算边吐字12await foreach (var update in agent.RunStreamingAsync(13"把上面两条信息汇总成一句话给早会用", session))14{15Console.Write(update);16}
应用场景:停机根因追溯、批次质量回溯、早会数据汇总——这类"边看边想边查"的活。
踩坑预警:别把一个 Thread 用到天荒地老。我见过同事让一个 thread 跑了上百轮,token 越堆越多、成本飙升还容易串味。一个任务一个 thread,干完就丢,这是我现在的铁律。
🛡️ 方案三:写操作必须人工审批(human-in-the-loop)
前两步解决"能干活",这一步解决"敢让它干活"。查询是只读的,无所谓;但派工单、改参数这类写操作,绝不能让模型自己拍板。Agent Framework 给了个特别省心的机制:ApprovalRequiredAIFunction。
MesTools中添加工具
csharp1// 高风险写操作:派工单(真正会改 MES 数据)2[Description("把维修工单派发到指定班组")]3public static string DispatchWorkOrder(4 [Description("工单号")] string workOrderId,5 [Description("目标班组")] string team)6 => $"工单 {workOrderId} 已派至 {team}";csharp1using System;2using System.Collections.Generic;3using System.ClientModel;4using System.Threading.Tasks;5using Microsoft.Agents.AI;6using Microsoft.Extensions.AI;7using OpenAI;89namespace AppMAF0210{11internal class Program12 {13static async Task Main(string[] args)14 {15var apiKey = Environment.GetEnvironmentVariable("DEEPSEEK_API_KEY")!;16var dispatchTool = new ApprovalRequiredAIFunction(17AIFunctionFactory.Create(MesTools.DispatchWorkOrder));18var tools = new List<AITool>19 {20AIFunctionFactory.Create(MesTools.QueryDowntime),21AIFunctionFactory.Create(MesTools.QueryWorkOrder),22 dispatchTool23 };2425IChatClient chatClient = new OpenAIClient(26new ApiKeyCredential(apiKey),27new OpenAIClientOptions { Endpoint = new Uri("https://api.deepseek.com/v1") })28 .GetChatClient("deepseek-chat")29 .AsIChatClient();3031AIAgent agent = chatClient.AsAIAgent(32 name: "MesAssistant",33 instructions: """34 你是制造车间的任务助手。35 涉及产线、工单的问题,必须调用工具获取真实数据,不要凭空编造。36 回答简洁,聚焦关键结论。37 """,38 tools: tools);3940// 运行后,先检查有没有"等待审批"的请求41var session = await agent.CreateSessionAsync();42var response = await agent.RunAsync(43"把 WO-2026-0612-003 派给设备维修一班", session);4445List<ToolApprovalRequestContent> approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();4647while (approvalRequests.Count > 0)48 {49List<ChatMessage> userInputResponses = approvalRequests50 .ConvertAll(functionApprovalRequest =>51 {52Console.WriteLine($"Agent 准备调用以下工具,输入 Y 同意,其他键拒绝: Name {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");53return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]);54 });5556 response = await agent.RunAsync(userInputResponses, session);5758 approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();5960 }6162Console.WriteLine($"\nAgent: {response}");63 }64 }65}
应用场景:派工单、工艺参数下发、库存调拨、质量判定等真正的"写动作"。具体的请求/响应处理,可参照官方 Microsoft Learn 里 "human in the loop approvals" 一节。
踩坑预警:哪些工具要审批,必须在代码里静态声明,绝不能让模型自己判断"这个动作要不要批"。我踩过坑——早期想让模型自己决定风险等级,它把"批量关闭工单"当成低风险直接执行了,差点把当天产能数据搅乱。只读工具裸用,写工具一律 ApprovalRequiredAIFunction 包起来,这条边界比什么都重要。
💎 四、三句话洞察,值得收藏
洞察一:Microsoft Agent Framework 真正的价值,是把"工具调度、上下文、审批"标准化了,让你能把精力 100% 砸在工具层和业务系统接入上。
洞察二:确定性永远优先于灵活性。只读问答放开用,写动作一律走人工审批,这是制造业 Agent 不出事故的底线。
洞察三:衡量任务 Agent 的价值,不看回答多漂亮,要看 MES 工单系统里真实多了多少条带审批记录的动作。
🔁 五、可复用的工具注册模板
这段我在多个项目里直接复用,新增能力就是往列表里加一个 AIFunctionFactory.Create:
csharp1public static class AgentBootstrap2{3public static AIAgent BuildMesAgent(string apiKey)4 {5// 只读工具:裸注册6var readTools = new List<AITool>7 {8AIFunctionFactory.Create(MesTools.QueryDowntime),9AIFunctionFactory.Create(MesTools.QueryWorkOrder),10 };1112// 写工具:统一用审批包装,再合并进工具集13var writeTool = new ApprovalRequiredAIFunction(14AIFunctionFactory.Create(MesTools.DispatchWorkOrder));1516var allTools = new List<AITool>(readTools) { writeTool };1718IChatClient chatClient = new OpenAIClient(19new ApiKeyCredential(apiKey),20new OpenAIClientOptions { Endpoint = new Uri("https://api.deepseek.com/v1") })21 .GetChatClient("deepseek-chat")22 .AsIChatClient();2324AIAgent agent = chatClient.AsAIAgent(25 name: "MesTaskAgent",26 instructions: "查询类直接执行,写操作需人工审批后执行。",27 tools: allTools);28return agent;29 }30}把它当成"Agent 的装配车间":只读工具进左边,写工具包审批进右边,清清爽爽,新人也好接手。
💬 六、留两个开放问题
1. 你们厂如果上 Agent,会让它直接写 MES/WMS 吗?如果会,审批边界怎么划?如果坚决不写,又打算怎么让它产生真实业务价值? 2. 当模型对停机根因判断出现幻觉时,你们计划怎么兜底?是规则双校验、人工抽检,还是双模型互验?
欢迎在评论区聊聊你们的实践和顾虑,我会逐条认真回。
🎯 结尾:三点收获 + 学习路线
回到开头那位班组长。后来我们用方案二加方案三的组合,把那个"问答助手"重构成了能查 MES、能联动 SCADA 报警、派工单还带工程师审批的任务 Agent。班组长的故障派工时间从平均 11 分钟降到 90 秒,而且每一次派单都有据可查。
三点核心收获:
• 第一:制造业 AI 的核心矛盾不是"答得好不好",而是**"事做没做完、做得敢不敢认"**。 • 第二:Microsoft Agent Framework 把工具调用、线程记忆、人工审批都封装好了,你只管写好工具和业务接入。 • 第三:渐进式落地——先做只读查询,再做多轮串联,最后才碰带审批的写动作,别一上来就想全自动。
持续学习路线建议:Microsoft Agent Framework 官方文档(从 Your First Agent 到 Tools、Workflows 逐步走)→ Microsoft.Extensions.AI 抽象层 → MES/WMS Web API 与 OPC UA .NET SDK(打通业务与现场)→ 向量数据库(Qdrant / Milvus 的 .NET 客户端,做长期记忆)→ Workflows 多 Agent 编排。这条路走完,基本就能独立交付一个制造业 Agent 项目了。
觉得有用的话,欢迎微信打赏鼓励一下,让我有动力继续输出这类实战内容。完整源码结构已在各节逐一呈现,可结合项目实际直接落地;如需完整源码,可在公众号聊天窗口获取。
夜雨聆风