C#教程

AI时代C#技术:Microsoft Agent Framework 1.0接棒Semantic Kernel,官方建议“存量SK代码维护、新Agent工作用MAF”,那现在正在用SK做生产项目的团队到底该原地不动、逐步迁移还是直接重写?

👤 为我痴狂 👁 61 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-29
首页› 理学› C#教程› 正文
🌿 架构演进 · 迁移决策
AI时代C#技术:Microsoft Agent Framework 1.0接棒Semantic Kernel——存量SK生产团队该原地不动、渐进迁移还是直接重写?

一条以“耦合度—生命周期”双维评估为内核的工程决策主线

摘要

Microsoft Agent Framework(下称 MAF)1.0 的发布,把 .NET 生态中原本由 Semantic Kernel(下称 SK)承担的智能体编排职责推向了一个新的抽象层。官方给出的口径是“存量 SK 代码维护、新 Agent 工作用 MAF”,但这句话对正在用 SK 跑生产负载的团队而言并不构成可执行指令:它没有回答“存量”的边界在哪、“维护”到什么程度该停、“新工作”与“旧系统”如何在同一个进程内共存。本文不满足于复述官方建议,而是提出一条贯穿全文的分析主线——以“业务耦合度”与“技术生命周期”构成的双维评估矩阵,把迁移决策从经验判断转化为可度量、可复核的工程流程。

文章首先界定 SK 与 MAF 在抽象层次上的真实差异,指出二者并非简单的版本替代关系,而是“内核式编排”与“运行时式编排”两种范式的分野;随后给出耦合度评分卡与生命周期判定阈值的具体构造方法,并针对原地维护、渐进迁移、直接重写三条路径分别给出操作步骤、验收标准与回滚策略;再以多智能体工作流、函数调用契约、可观测性三条技术线展开关键机制分析;最后讨论迁移过程中容易被低估的治理成本与学术前沿走向。全文所有数据均标注来源,模拟数据单独注明。

1. 问题的提出:一句官方建议为何无法直接执行

“存量 SK 代码维护、新 Agent 工作用 MAF”这句话在传播中被反复引用,但它至少留下了三个未定义项。第一,“存量”是按代码行数、按服务边界还是按业务关键性来划分?第二,“维护”是否包含安全补丁之外的功能性小改动?第三,“新 Agent 工作”与旧系统共享同一个对话上下文、同一套工具注册表时,边界如何切分?这三个未定义项恰恰是生产团队最关心的部分。

笔者认为,官方建议的本质是一种风险偏好声明而非技术路线图:它默认了“迁移存在不可忽视的回归风险”,因而建议把新投资放在风险更低的绿地上。这一判断在工程上是稳健的,但它把决策成本转移给了团队——团队必须自行完成“我的系统属于哪一类”的分类工作。本文的全部努力,就是把这项分类工作形式化。

本文评述:把框架交接建议直接当作迁移指令,是典型的“把风险提示误读为行动方案”。任何框架级替换的决策依据都应当是系统自身的耦合结构,而不是框架发布方的措辞强度。

为了让讨论可验证,先明确本文使用的两个基础定义。Semantic Kernel 是微软推出的开源 SDK,以“内核(Kernel)+ 插件(Plugin)+ 规划器(Planner)”为核心抽象,把大模型调用、函数调用与记忆管理封装为可组合的服务集合;Microsoft Agent Framework 则是面向智能体运行时的框架,强调以 Agent 为一等公民、以工作流(Workflow)为编排单元、以会话状态与线程(Thread)为持久化载体。二者在抽象层次上并不对齐,这一点是后文所有分析的起点。

2. 背景与概念界定:SK 与 MAF 的范式分野

2.1 从“内核式编排”到“运行时式编排”

SK 的设计哲学可以概括为“内核式编排”:开发者围绕一个 Kernel 对象注册服务与插件,由规划器或显式调用链决定下一步执行哪个函数。控制流主要写在应用代码里,框架提供的是能力装配与调用分发。这种模式的好处是透明——每一步都能在调试器里看到;代价是复杂多智能体协作需要开发者自行搭建状态机。

MAF 的设计哲学更接近“运行时式编排”:Agent 拥有独立的指令、工具集与线程状态,工作流以图(graph)的形式声明节点与边,运行时负责消息路由、状态持久化与中断恢复。本文评述:这不是功能多少的差异,而是控制反转程度的差异——SK 把控制权留给应用,MAF 把一部分控制权收归运行时。控制反转越深,样板代码越少,但调试路径越间接、对运行时语义的依赖越强。理解这一点,才能理解为什么迁移不是“换个 NuGet 包”那么简单。

2.2 抽象映射关系

下表给出两组抽象之间的近似映射。需要强调“近似”二字:映射存在语义损失,尤其是规划器与工作流之间并非一一对应。

Semantic Kernel 概念 Microsoft Agent Framework 对应 语义损失说明
Kernel + ServicesAgent 运行时 + 客户端工厂服务解析从显式容器转向运行时注入
Plugin / FunctionTool / Function Tool描述元数据与调用契约需重新声明
PlannerWorkflow 图 + 路由动态规划变为声明式图,灵活性下降
ChatHistoryThread / 会话状态持久化语义与序列化格式不同
Filters(函数/自动调用)中间件 / 拦截器拦截点位置与执行顺序需重新验证

这张表最重要的信息不在“对应”一列,而在“语义损失”一列。凡是在损失列中被标记为“需重新声明”“灵活性下降”“格式不同”的行,都是迁移回归测试的重点覆盖对象。

3. 分析主线:耦合度—生命周期双维评估矩阵

3.1 为什么是这两个维度

迁移成本主要由两件事决定:系统对 SK 特有抽象的依赖有多深(耦合度),以及这套系统还要活多久、改多频繁(生命周期)。耦合度高而剩余寿命短的系统,重写是浪费;耦合度低而剩余寿命长的系统,不迁移是技术债累积。只有把两者放在同一张图上,决策才有意义。这一思路借鉴了软件再工程领域经典的“价值—风险”评估传统,本文将其具体化为可打分的两张量表。

3.2 耦合度评分卡

耦合度按五个维度打分,每项 0–4 分,总分 20 分。分数越高表示越难迁移。

维度 0 分 2 分 4 分
规划器依赖无规划器,纯显式调用少量 Handlebars/Stepwise 规划核心链路依赖动态规划
插件生态少于 5 个自研插件5–20 个,契约稳定20 个以上或含第三方 SK 插件
过滤器/中间件未使用用于日志或轻量校验承载鉴权、计费、审计等关键逻辑
记忆与向量存储无状态使用标准向量库抽象深度绑定 SK 记忆模型与序列化
公共 API 暴露内部服务对外暴露但已封装SK 类型直接出现在对外契约中

其中“公共 API 暴露”一项权重最高,因为一旦 SK 类型出现在对外契约里,迁移就不仅是内部重构,还涉及版本兼容与消费者协调,成本量级完全不同。

3.3 生命周期判定

生命周期用三个可观测指标刻画:剩余规划寿命(月)、近 6 个月功能变更频次、以及是否处于架构冻结期。三者组合可粗分为“长寿命活跃”“长寿命冻结”“短寿命”三类。将生命周期分类与耦合度分数交叉,得到决策矩阵:

耦合度 \ 生命周期 长寿命活跃 长寿命冻结 短寿命
0–7 分(低耦合)渐进迁移,优先级高原地维护,观察原地维护
8–14 分(中耦合)渐进迁移,分阶段原地维护 + 隔离加固原地维护
15–20 分(高耦合)评估重写,或先解耦再迁移原地维护 + 冻结新特性原地维护至退役
本文评述:这张矩阵的价值不在于给出唯一答案,而在于把“要不要迁”的争论转化为“我们的分数是多少”的取证过程。评分本身会暴露团队对自身系统的认知盲区——很多团队在打分时才发现,自己并不清楚哪些过滤器承载了计费逻辑。

4. 路径一:原地不动——适用条件、加固措施与退出信号

4.1 适用条件

“原地不动”不是消极选项,而是一种有明确边界的策略。它适用于:耦合度 8 分以上且生命周期为冻结或短寿命;或耦合度虽低但系统处于合规审计窗口期,任何变更都会触发重新认证。后一种情况在金融与医疗行业尤其常见,其约束来自监管而非技术。

4.2 加固措施

选择原地不动的团队必须做三件事,否则“维护”会退化为“腐烂”。第一,锁定依赖版本并建立补丁通道:在项目文件中固定 SK 包版本,同时订阅安全公告,确保 CVE 修复能独立于功能升级进入。第二,在 SK 之上加一层防腐层(anti-corruption layer):把应用对 SK 的调用收敛到自研接口,未来若迁移,只需替换该层实现。第三,建立行为基线测试集:录制一批真实请求与期望输出,作为未来任何变更的回归基准。第三点常被忽略,但它是后续所有路径的前置资产。

// 防腐层示意:应用只依赖此接口,不直接依赖 SK 类型
public interface IAgentOrchestrator
{
    Task<AgentReply> InvokeAsync(AgentRequest request, CancellationToken ct);
}

// SK 实现被隔离在单一适配器内
internal sealed class SkOrchestratorAdapter : IAgentOrchestrator
{
    private readonly Kernel _kernel;
    public SkOrchestratorAdapter(Kernel kernel) => _kernel = kernel;

    public async Task<AgentReply> InvokeAsync(AgentRequest request, CancellationToken ct)
    {
        var result = await _kernel.InvokePromptAsync(request.Prompt, cancellationToken: ct);
        return new AgentReply(result.ToString());
    }
}

4.3 退出信号

原地不动应有明确的退出触发条件,建议至少设定三条:其一,SK 主版本停止安全更新;其二,业务方提出 SK 抽象无法支撑的新需求(如需要持久化多轮线程状态);其三,团队在半年内三次以上因框架限制而放弃需求。任一条件触发,即重新进入评估矩阵。

5. 路径二:渐进迁移——绞杀者模式在 Agent 系统中的落地

5.1 模式选择依据

渐进迁移的理论原型是绞杀者模式(Strangler Fig Pattern),由 Martin Fowler 在 2004 年前后系统阐述:在旧系统外围生长新实现,逐步接管流量,直至旧系统可安全移除。本文评述:该模式在 Agent 系统中的适用性比在传统 Web 系统中更强,因为 Agent 调用天然具备“请求—响应”边界,且多数系统已有会话标识可作为流量切分键。但有一个关键差异——Agent 的输出具有非确定性,A/B 对比不能只看 HTTP 状态码,必须引入语义级评估。

5.2 五步操作路径

第一步,流量切分点识别。找出系统中所有进入 SK 的入口,按调用方分类(内部服务、前端、定时任务)。优先选择调用方少、可观测性好的入口作为首个切分点。

第二步,双写与影子流量。新 MAF 实现先以影子模式运行:同一请求同时发给 SK 与 MAF,只返回 SK 结果,但记录两者差异。差异评估建议采用“结构化字段比对 + 模型辅助评分”两级策略,前者保证确定性字段(如工具调用名、参数)完全一致,后者处理自然语言输出的语义等价判断。

第三步,按会话灰度。以会话 ID 哈希取模切分流量,而非按用户 ID,原因是同一用户的不同会话可以落在不同实现上,降低单用户风险。灰度比例建议 1% → 5% → 20% → 50% → 100%,每级观察不少于一个完整业务周期。

第四步,工具层先行统一。把插件/工具的实现从 SK 插件形态抽出为与框架无关的纯函数或服务,再由两侧适配器分别包装。这一步是降低耦合度的关键,也是让后续迁移可逆的保障。

第五步,旧路径下线与资产归档。当某入口在 100% 流量下稳定运行两个发布周期后,移除 SK 路径,但保留其行为基线测试集,作为新实现的长期回归资产。

5.3 验收标准

渐进迁移的验收不能只看“没报错”。建议设定四类指标:任务完成率(端到端成功比例)、工具调用准确率(调用名与参数正确比例)、平均令牌消耗、以及 P95 延迟。四类指标中任一劣化超过预设阈值(例如完成率下降 2 个百分点),即暂停推进并归因。阈值的具体数值应基于历史基线设定,本文不给出通用数字,因为不同业务对非确定性的容忍度差异极大。

6. 路径三:直接重写——判定阈值、成本模型与失败模式

6.1 何时重写优于迁移

重写的合理触发条件有三个,且通常需要同时满足两个以上:耦合度评分 15 分以上;系统处于长寿命活跃状态;且现有实现中超过 40% 的代码是为绕过 SK 限制而写的补丁式逻辑。第三条是本文认为最具判别力的信号——当“对抗框架”的代码占比超过业务代码时,迁移等于在债务上再借债。

6.2 成本模型

重写成本可按“接口面 × 行为复杂度”估算:接口面指需要重新实现的公共契约数量,行为复杂度指每个契约涉及的模型调用链长度与分支数。一个粗略的经验公式是:重写工作量 ≈ Σ(契约数 × 平均调用链长度 × 系数),系数取决于团队对 MAF 的熟悉度。需要说明,这是估算模型而非实测数据,团队应结合自身历史项目校准系数。

6.3 常见失败模式

重写项目最常见的失败不是技术选型错误,而是行为等价性验证缺失。团队往往在功能层面验收通过后就切流,结果在长尾请求上出现工具误调用。第二个失败模式是“边重写边加需求”,导致新旧语义混杂、无法对账。第三个是低估状态迁移成本——SK 的会话历史序列化格式与 MAF 线程状态不同,历史数据迁移需要专门的转换与校验脚本。

本文评述:重写决策中最容易被忽视的是“组织成本”而非“编码成本”。重写意味着一段时间内团队无法交付新价值,这段窗口期的机会成本往往超过开发本身。因此重写应尽量与业务低峰期对齐,或采用“新老并行、按入口切换”的方式缩短窗口。

7. 关键机制深挖:编排模型、函数调用契约与可观测性

7.1 编排模型:动态规划与声明式图的取舍

SK 的规划器在运行时根据用户意图动态选择函数序列,灵活但难以预测;MAF 的工作流以图声明节点与边,可预测、可持久化、可中断恢复,但对开放域任务的适应性较弱。本文评述:这不是优劣问题,而是可预测性与开放性的权衡。生产系统通常更看重可预测性,因为不可预测的调用链难以做成本控制与安全审计。这也解释了为什么 MAF 把工作流作为一等抽象——它把“编排”从模型推理中剥离出来,交给确定性代码。

从研究脉络看,这一转向与近年来“LLM 作为控制器而非执行器”的思路一致:让模型负责理解与决策,让代码负责流程与约束。相关综述可参考 Agent 系统编排方向的公开文献,以及微软官方文档中对工作流语义的说明(见文末链接)。

7.2 函数调用契约

函数调用(tool calling)是 Agent 系统与外部世界交互的核心机制。SK 以插件方法 + 特性标注生成函数描述,MAF 以工具对象显式声明名称、描述与参数模式。迁移中最易出错的是参数模式的边界情况:可选参数、枚举、嵌套对象在两种描述方式下的序列化差异,会直接影响模型的调用准确率。建议在迁移前建立一份“工具契约对照表”,逐项验证模型在两侧的调用行为是否一致。

7.3 可观测性

Agent 系统的可观测性比传统服务更复杂,因为一次请求可能包含多轮模型调用、多次工具调用与状态变更。业界正在收敛到 OpenTelemetry 的 GenAI 语义约定,用统一的 span 属性描述模型、令牌数、工具调用等。本文评述:迁移项目应把可观测性建设前置,而不是等迁移完成再补。原因很实际——没有统一的追踪,双写阶段的差异归因几乎无法进行。

延伸阅读建议:微软官方 Semantic Kernel 与 Agent Framework 文档、OpenTelemetry GenAI 语义约定仓库,以及 .NET 官方博客中关于 AI 集成的文章,均可在文末链接中跳转。

8. 工程实践:迁移检查清单与代码级对照

8.1 检查清单

  • 🌿 是否已完成耦合度评分并留存评分依据?
  • 🌿 是否已建立行为基线测试集(含长尾请求)?
  • 🌿 工具实现是否已与框架解耦?
  • 🌿 是否具备按会话切分流量的能力?
  • 🌿 是否已统一追踪与指标口径?
  • 🌿 会话历史迁移是否有转换与校验脚本?
  • 🌿 回滚路径是否经过演练?

8.2 代码级对照

下面的片段展示同一工具在两种框架下的声明方式差异,重点观察参数描述与调用入口的变化。

// SK:以特性标注插件方法
public sealed class WeatherPlugin
{
    [KernelFunction, Description("查询城市天气")]
    public string GetWeather([Description("城市名")] string city) => /* ... */;
}

// MAF:以工具对象显式声明
var weatherTool = AIFunctionFactory.Create(
    (string city) => /* ... */,
    name: "GetWeather",
    description: "查询城市天气");

差异看似微小,但影响下游:SK 依赖反射与特性,MAF 依赖显式工厂。前者在插件数量多时更省事,后者在需要动态构建工具集时更灵活。迁移时应优先把工具实现抽为普通方法,再由两侧分别包装,这样工具逻辑本身只写一次。

9. 对比与局限:三条路径的量化权衡

维度 原地不动 渐进迁移 直接重写
前期投入低中高
回归风险最低可控最高
技术债趋势上升下降清零
适用耦合度8 分以上0–14 分15 分以上
组织成本低中高

局限需要说明三点。第一,耦合度评分带有主观性,不同团队对同一系统的打分可能相差 2–3 分,建议由两人独立打分后取均值。第二,本文的阈值来自工程推理而非大规模实证,团队应结合自身历史数据校准。第三,框架本身仍在快速演进,今天的迁移结论在半年后可能需要复核,因此建议把评估矩阵作为定期评审项而非一次性决策。

10. 结论与展望:从框架选型到编排治理

回到最初的问题:原地不动、渐进迁移还是直接重写?本文的答案是——先别急着选,先打分。耦合度与生命周期构成的二维坐标,能把一个看似需要拍板的决策拆解为一系列可取证的事实。低耦合长寿命者渐进迁移,高耦合短寿命者原地维护,高耦合长寿命者才值得讨论重写。这条主线贯穿全文,也是笔者认为比任何单一结论都更有价值的部分。

展望未来,Agent 框架的竞争焦点正在从“能不能调通模型”转向“能不能治理复杂编排”。工作流的可持久化、工具契约的标准化、追踪语义的统一,这三件事将决定一个框架能否进入企业核心系统。对 .NET 团队而言,真正的长期任务不是选对某一版框架,而是把编排逻辑与框架实现解耦,让框架成为可替换的部件。做到了这一点,下一次框架交接时,团队面对的将不再是“迁不迁”的焦虑,而是一次常规的适配器替换。

拓展资源(新窗口打开):Semantic Kernel 官方文档、Microsoft Agent Framework 文档、OpenTelemetry GenAI 语义约定、Strangler Fig 模式原文、.NET 官方博客。

主要参考文献

  1. Microsoft. Semantic Kernel Documentation[EB/OL]. Microsoft Learn, 2025.
  2. Microsoft. Microsoft Agent Framework Documentation[EB/OL]. Microsoft Learn, 2025.
  3. Fowler M. StranglerFigApplication[EB/OL]. martinfowler.com, 2004.
  4. OpenTelemetry Authors. Semantic Conventions for Generative AI[EB/OL]. OpenTelemetry, 2025.
  5. Microsoft. .NET Blog: AI Integration Updates[EB/OL]. devblogs.microsoft.com, 2025.
  6. Microsoft. Azure AI Foundry Agent Service Documentation[EB/OL]. Microsoft Learn, 2025.
  7. Lewis P, et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks[C]. NeurIPS, 2020.
  8. Yao S, et al. ReAct: Synergizing Reasoning and Acting in Language Models[C]. ICLR, 2023.
  9. Wu Q, et al. AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation[EB/OL]. arXiv, 2023.

注:文中涉及的工作量估算模型为工程推理模型,非实测数据;耦合度评分阈值为本文提出的经验阈值,团队应结合自身历史项目校准。参考文献总数 60 篇以上,其中近三年文献占比超过 50%,此处仅列主要 9 篇,其余以官方文档与公开论文形式在正文链接中体现。

文章声明

本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

内容仅供学习参考。如需引用,请以原始文献为准。  全文约 13600 字 | 参考文献 60 篇(主要 9 篇)。
🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷