Microsoft Semantic Kernel

一句话定位

Semantic Kernel(SK)是一个 DI 风格的中间件 SDK——Kernel 是服务容器(AI 连接器 + 插件 + 过滤器),“agent”是搭在 kernel 函数调用原语之上的一层,而不是相反。曾经的招牌功能 Planner 子系统在 Python SDK 里已被完全移除docs/PLANNERS.md 只剩一个跳转 stub,grep -ril planner python/semantic_kernel 零命中),规划能力要么隐式发生在模型自己挑工具的 auto-invoke 循环里,要么显式外包给 Magentic 编排器(对 AutoGen Magentic-One 的近乎逐字移植)。

核心架构总览

Polyglot monorepo:dotnet/python/java/ 三套 SDK 共享 docs/decisions/(MADR 格式 ADR)。本次调研聚焦 Python SDKpython/semantic_kernel/),因为它是可读性/完整度最高的参考实现,并交叉核对了语言无关的 ADR。commit f6391ad8b6b47b6de44e80d54ce9f3ffe4f3ed42(2026-07-07 git clone --depth 1git rev-parse HEAD 取得)。

关键目录/文件(均相对 python/semantic_kernel/):

  • kernel.py —— Kernel 类本体:invoke/invoke_stream/invoke_prompt/invoke_function_call(工具调用派发与参数校验)/_inner_auto_function_invoke_handler/clone()/as_mcp_server()
  • connectors/ai/chat_completion_client_base.py —— 真正的 agent 主循环所在地(不在 Kernel 里)。
  • connectors/ai/function_choice_behavior.py —— FunctionChoiceBehavior,循环轮数上限的来源。
  • agents/ —— Agent 抽象基类、ChatCompletionAgentorchestration/(Magentic/Handoff/GroupChat/Concurrent/Sequential)、azure_ai/open_ai/(OpenAI Assistants 变体)、runtime/(actor-model 运行时)。
  • contents/history_reducer/ —— 会话历史压缩(截断 / LLM 摘要)。
  • filters/ —— 洋葱式中间件链,SK 的通用拦截点(日志/缓存/审批门都要靠它自建)。
  • connectors/mcp.py —— MCP 客户端(4 种传输)+ MCP 服务端(把 Kernel 自身暴露为 MCP server)。
  • processes/ —— 独立的确定性图/状态机工作流引擎(Process Framework),可选 Dapr 后端。
  • docs/decisions/*.md —— ADR,含 OTel 采纳决策、Agent Framework 起源、hooks→filters 演化。

Agent Loop(主循环 / 何时继续何时停)

主循环不在 Kernel 里,而在 connectors/ai/chat_completion_client_base.py:136-174get_chat_message_contents,非流式)与 :255-318get_streaming_chat_message_contents,流式):

  • 循环体:for request_index in range(settings.function_choice_behavior.maximum_auto_invoke_attempts): —— 调 LLM;若返回内容里没有 FunctionCallContent,直接 return(停止条件①:模型没要工具);否则通过 asyncio.gather(kernel.invoke_function_call(...)) 并行执行所有请求的工具调用;若任一调用的 AutoFunctionInvocationContext.terminate == True,提前 break/return(停止条件②:某个 auto-function-invocation filter 显式终止);否则带着更新后的 chat history 再循环一轮。
  • 轮数上限:maximum_auto_invoke_attempts 默认 5connectors/ai/function_choice_behavior.py:18,58)。for 循环耗尽轮数时触发 else 分支:重置工具调用配置(_reset_function_choice_settings),再发起一次不带工具调用的 LLM 调用强制拿到纯文本答案(chat_completion_client_base.py:171-174)。
  • 这是”单轮”(per-turn)循环;跨整个对话的”要不要继续”由更上层的 Magentic/GroupChat/Handoff 编排器负责(见”Router / 编排”节),基础循环本身不管这层。

记忆与上下文管理(压缩、长期记忆、会话持久化)

  • 基础 ChatHistory 没有自动的、token-budget 感知的压缩;压缩是通过挂在 ChatHistoryAgentThread 上的 ChatHistoryReducer 子类opt-in实现的:
    • ChatHistoryTruncationReducercontents/history_reducer/chat_history_truncation_reducer.py,105 行)—— 硬截断到 target_count(留 threshold_count 缓冲),不调 LLM,保留第一条 system/developer 消息。
    • ChatHistorySummarizationReducercontents/history_reducer/chat_history_summarization_reducer.py,216 行)—— 历史超过 target_count+threshold_count 时用 LLM 生成滚动摘要(内置默认 prompt 要求 ≤5 句),摘要消息打上 SUMMARY_METADATA_KEY 避免被重复摘要,可选是否把函数调用/结果内容也纳入摘要(include_function_content_in_summary)。
  • .reduce() 暴露在 ChatHistoryAgentThreadagents/chat_completion/chat_completion_agent.py:107-113)——需要调用方/框架主动调用,不是每轮自动触发(文档提到的 auto_reduce 标志仍要靠线程/agent 侧接线才生效)。
  • 长期记忆:遗留的 memory/semantic_text_memory.pySemanticTextMemory 已标注 deprecated(“将在未来版本移除”);connectors/memory_stores/ 下有 13 个向量库后端(Qdrant/Redis/Pinecone/Chroma/Milvus/Weaviate/Azure Cognitive Search/CosmosDB/Postgres/MongoDB Atlas/AstraDB/usearch);官方推荐路径是 semantic_kernel/data 的 Vector Store 抽象(本轮未深读,仅记录路径)。
  • 会话持久化:ChatHistoryAgentThread 包一个带 thread_idChatHistory,持久化后端由调用方自行提供——core 里没有内置的数据库级线程存储;Azure AI Agent / OpenAI Assistants 变体则借用各自托管服务自身的线程持久化。

工具体系(定义/调用协议/注册/权限)

  • 定义@kernel_function 装饰器(functions/kernel_function_decorator.py)用 inspect.signature 内省普通 Python 函数(支持 Annotated[type, "description"]),元数据存成 __kernel_function_parameters__ 等 dunder 属性;此外还支持 prompt 驱动的函数(KernelFunctionFromPrompt,“技能”本质就是一个 prompt 模板)、OpenAPI spec 派生函数(connectors/openapi_plugin/openapi_manager.py)、MCP server 派生函数(connectors/mcp.py)。
  • 注册:函数打包进 KernelPluginfunctions/kernel_plugin.py),插件注册到 Kernel.plugins 字典;调用时 kernel.get_function(plugin_name, function_name) 解析。
  • 调用协议:模型发出 OpenAI 风格 tool_calls(或已废弃的 legacy function_call);provider 连接器把它解析成 FunctionCallContentopen_ai_chat_completion_base.py:240-268_get_tool_calls_from_chat_choice/_get_function_call_from_chat_choice);Kernel.invoke_function_callkernel.py:326-463)依次:(a) 校验函数在模型可见的 allowlist 内(function_behavior.filters);(b) 校验必填/多余参数是否匹配 function_to_call.parameters;(c) 构建 AutoFunctionInvocationContext;(d) 过一遍 auto_function_invocation_filters 中间件链;(e) 深拷贝结果防止后续变更泄漏;(f) 把 FunctionResultContent 追加进 chat history。
  • 权限FunctionChoiceBehavior.filters 支持 excluded_plugins/included_plugins/excluded_functions/included_functions——是最接近工具 ACL 的机制,在 kernel.py:342-349 强制执行(模型调用允许列表外的函数时,返回错误消息给模型而非直接崩溃)。这是静态允许列表,不是逐次交互式审批(审批相关见”安全与权限”节)。

Prompt 设计(系统提示结构、动态组装)

  • 三套可互换的模板引擎:SK 自有的 {{$var}}/{{plugin.function arg=val}} mini-DSL、Handlebars、Jinja2(prompt_template/{kernel,handlebars,jinja2}_prompt_template.py),由 template_format 字段选择。
  • Agent 指令每次调用都重新渲染Agent.format_instructions()agents/agent.py:443-459)惰性地基于 self.instructions 构建 KernelPromptTemplate 并调 .render(kernel, arguments)——即系统提示本身是一个模板,可在请求时插入 kernel 参数/函数输出,而不是静态字符串。
  • 声明式 agent:agents/agent.py 里的 AgentSpec/ModelSpec/ToolSpec 类配合 DeclarativeSpecMixin,允许整个 agent(指令、模型连接、工具)用 YAML 定义加载——是手写 Python 之外的配置驱动替代路径。
  • 编排器级 prompt(Magentic)是纯 Python 字符串模板,同样用 {{$var}} 语法,单独存在 agents/orchestration/prompts/_magentic_prompts.py(facts 调查、plan、progress-ledger 严格 JSON、final answer)——值得一提:progress-ledger prompt 明确要求”DO NOT OUTPUT ANYTHING OTHER THAN JSON”并内联 schema,即靠 prompt 工程实现结构化输出,而非依赖 function-calling/JSON-mode API 特性。

Router / 编排(任务分解、多 agent、子 agent)

  • Planner 子系统已从 Python SDK 完全移除docs/PLANNERS.md 是跳转 stub;代码零命中)。被以下几者取代:(a) 单 agent 场景下原生 auto-function-invocation 循环本身承担了工具编排;(b) agents/orchestration/* 承担多 agent 编排;(c) processes/* Process Framework 承担确定性工作流。
  • Magentic 编排agents/orchestration/magentic.py,911 行)—— 移植自 AutoGen 的 Magentic-One:MagenticManagerBase 这个 LLM 驱动的中央编排器维护 MagenticContext(任务台账:facts + plan),每轮要求编排器 LLM 输出结构化 JSON 的 ProgressLedgeris_request_satisfied/is_in_loop/is_progress_being_made/next_speaker/instruction)。停滞检测:无进展时 stall_count 递增,超过 max_stall_count(默认 3,第 137 行)触发 plan 重置(reset_count,受 max_reset_count 上限约束);max_round_count 是硬性轮数天花板(第 617-690 行附近检查 round_count >= max_round_count)。
  • Handoff 编排agents/orchestration/handoffs.py,530 行)—— 去中心化路由:每个 agent 被注入额外的 kernel 函数(_add_handoff_functions,代表”交接给 agent X”);由当前发言 agent 自己的 LLM决定是否调用这个交接函数(普通工具调用),编排层拦截(_handoff_function_filter)切换当前发言人——路由决策外包给模型的常规 function-calling,而非中央 planner。
  • GroupChatagents/orchestration/group_chat.py)、Concurrent(同一输入 fan-out 给 N 个 agent)、Sequential(agent i 输出接 agent i+1 输入)补齐编排模式库;更早一代的 agents/group_chat/agent_group_chat.py + 可插拔 SelectionStrategy/TerminationStrategyagents/strategies/)仍然存在,是基于轮次的老式多 agent 聊天 API。
  • Process Frameworkprocesses/)—— 独立的确定性图/状态机引擎:ProcessBuilder.add_step() 注册步骤类,ProcessStepEdgeBuilder 连接事件驱动的边;运行时支持 local_runtime(进程内)或 dapr_runtime(Dapr 虚拟 actor,用于持久化/分布式执行)——这是 SK 针对”业务流程式”(而非 LLM 即兴决定)编排给出的结构化答案。
  • agents/runtime/core_runtime.pyin_process/in_process_runtime.py)—— 一套 actor-model 运行时(agent_id/topic/subscription/message_handler 模式),Magentic/Handoff/GroupChat/Concurrent/Sequential 全都作为 actor 跑在这套运行时上——架构上借鉴/对齐了 AutoGen 的 core runtime 设计。

Skill / 插件体系

“插件”= KernelPlugin,一袋命名好的 KernelFunction。四种填充方式:(a) 原生 Python 类/函数打 @kernel_function;(b) prompt 驱动函数(KernelFunctionFromPrompt,即”技能”字面上就是一个 prompt 模板);(c) OpenAPI spec 导入(connectors/openapi_plugin/openapi_manager.py 把 OpenAPI 文档解析成可调用函数);(d) MCP 客户端(connectors/mcp.py,stdio/SSE/streamable-HTTP/websocket 四种传输)。core_plugins/ 目录(未逐行深读,仅列目录)提供少量第一方内置插件(文本/时间/数学类工具样例)。双向 MCP 支持是一个特色点:Kernel 不仅能作为 MCP 客户端消费外部工具服务器,还能反过来通过 Kernel.as_mcp_server()kernel.py:578-625connectors/mcp.py:create_mcp_server_from_kernel)把自身注册的全部函数暴露成 MCP 工具/prompt 供其他客户端使用。

自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)

未实现。python/semantic_kernel 做穷举式 grep(self-improv|learn from|training data|fine-tun|eval-driven|reflexion,不区分大小写)零相关命中。没有任何机制把运行轨迹自动反馈进模型权重、prompt 或持久化的学习型记忆。最接近的邻近功能是:(a) 历史摘要 reducer(属于记忆压缩,不是学习);(b) Magentic 编排器在停滞时更新 facts/plan(仅限单次运行内的自我纠正,运行结束后通过 MagenticContext.reset() 丢弃,不持久化)。

可观测性(日志 / trace 格式)

  • 采纳 OpenTelemetry GenAI 语义约定,而非自造一套 SK 专属 trace 格式——这是文档化的明确设计决策(docs/decisions/0044-OTel-semantic-convention.md)。
  • 属性词表在 utils/telemetry/model_diagnostics/gen_ai_attributes.pygen_ai.systemgen_ai.request.modelgen_ai.request.{max_tokens,temperature,top_p,seed,...}gen_ai.response.{id,finish_reason}gen_ai.usage.{input_tokens,output_tokens}gen_ai.tool.{call.id,call.arguments,call.result,name,description},外加 SK 自定义的 sk.available_functions
  • Span 通过 @trace_chat_completion/@trace_streaming_chat_completion 装饰器创建(包裹 _inner_get_chat_message_contents,见 open_ai_chat_completion_base.py:74,94),另有一个专门的 AUTO_FUNCTION_INVOCATION_SPAN_NAME span 包住整个 auto-invoke 循环(chat_completion_client_base.py:137,256,410-426,经由 _start_auto_function_invocation_activity)。
  • 独立的 agent_diagnostics 遥测模块(utils/telemetry/agent_diagnostics/)把 agent 级调用/流式与原始模型调用分开打点(trace_agent_get_response/trace_agent_invocation/trace_agent_streaming_invocation,在 chat_completion_agent.py:34-38 引入)。
  • ADR 明确要求 prompt/completion 内容类遥测事件必须可 opt-out(PII 考虑)。

安全与权限(审批门、密钥管理)

  • 没有内置的人工审批(HITL)原语用于工具调用。AutoFunctionInvocationContext.terminate 标志(可在 auto_function_invocation_filter 内设置)是应用开发者用来自建审批门的机制(例如在调用 next(context) 之前暂停并询问人类),但这是一个 DIY 扩展点,不是开箱即用的行为。TRANSPARENCY_FAQS.md 明确把”Filtering”点名为开发者应该”落地 Responsible AI”的地方。
  • 工具调用允许列表(FunctionChoiceBehavior.filters:excluded/included plugins/functions)是最接近权限边界的东西,但只是静态允许列表,不是逐次交互式审批。
  • MCP 专属的安全阀门:sampling_consent_callbackconnectors/mcp.py:62,248-260,377-410)—— 调用方提供的 Callable[[str, CreateMessageRequestParams], Awaitable[bool]],在 MCP server 触发”sampling”请求(即要求客户端的 LLM 代其生成内容)之前调用。若未配置回调,此类请求默认自动通过,仅打一条警告日志(“MCP sampling request … was auto-approved because no sampling consent callback was configured”)——这是一个真实存在、代码可核实的权限门模式,但默认开放而非默认拒绝,值得在安全对比里点名。
  • 密钥/凭据:仓库内无密钥保险库;API key/连接串通过连接器构造函数或基于环境变量的 Pydantic Settings 类传入(标准 SDK 做法,非特色安全功能)。

沙箱与执行隔离

本地未实现。 SK 自身没有原生代码执行沙箱。Code-interpreter 能力完全外包给托管后端:agents/azure_ai/azure_ai_agent.pycode_interpreter 注册为工具 spec(@_register_tool("code_interpreter") → CodeInterpreterTool),转发给 Azure AI Agent Service;OpenAI Assistants agent 变体(agents/open_ai/openai_assistant_agent.py)同理委托给 OpenAI 的托管 code interpreter。python/semantic_kernel 内没有任何本地 subprocess/容器/沙箱执行层——一个原生 @kernel_function 工具就是普通的进程内 Python 调用,权限等同宿主进程本身,框架不施加任何隔离。

与模型的协同设计

  • 深度依赖模型原生的 function-calling / tool-use API(OpenAI tool_calls、legacy function_call,以及 Azure OpenAI、Bedrock(agents/bedrock/action_group_utils.py)、Google、Mistral、ONNX、Ollama 等连接器下的等价物)—— auto-invoke 循环假定底层模型 API 能吐出结构化 tool-call 对象;每个连接器上的 SUPPORTS_FUNCTION_CALLING: ClassVar[bool] 标志决定循环是否启用。
  • FunctionChoiceType(AUTO/NONE/REQUIRED)直接映射到各 provider 原生的 tool_choice 参数(各连接器的 _update_function_choice_settings_callback 把 SK 的抽象选择翻译成 provider 特定的请求字段)——即 SK 不重新实现工具选择启发式,只是对模型 API 已有能力做一层薄的、provider 感知的透传。
  • MCP sampling 支持(connectors/mcp.py 的 sampling_callback)是一个双向协同设计点:MCP 工具服务器可以请求客户端配置的 chat completion 模型做一次子生成,遵循客户端自己的 model/temperature/max-token 设置——即工具服务器借用宿主的 LLM,而不是自带一个。
  • 未发现模型特定的 prompt hack 或训练期协同设计痕迹(符合中间件 SDK 而非模型提供方的定位预期)。

轨迹利用(session/trajectory 是否反哺训练/评测)

未实现 / 不适用。 没有代码路径把完整会话轨迹持久化用于后续训练或离线评测反馈。ChatHistory/ChatHistoryAgentThread 只是运行时会话状态(按”记忆与上下文管理”节所述被 reduce/truncate/summarize,不导出到本仓库内任何 eval 或训练管线)。OpenTelemetry trace(见”可观测性”节)是”轨迹”唯一的持久化记录,但它是给运维方用的可观测性产物,不是 SK 自身拥有的训练反馈闭环。

与同类 harness 的关键差异(1-3 条)

  1. Planner 的消失与再分布:SK 曾经的招牌”Planner”子系统在 Python SDK 里被彻底移除(非弃用,是删除),规划能力拆解到两处——单 agent 场景下隐式发生在模型自己的工具选择里,多 agent 场景下显式外包给 Magentic 编排器的任务台账/进度台账 prompt。这与仍保留显式 planner 抽象的框架(如某些仍有 Planner 类的框架)形成直接对比。
  2. 与 AutoGen 的架构收敛:Magentic 编排器是对 AutoGen Magentic-One 近乎逐字的移植(prompt 可辨识度很高),且共享 actor-model 运行时层(agents/runtime/core)——SK 的多 agent 编排并非独立发明,值得与 AutoGen 的 dossier(如有)交叉对比。
  3. 安全默认值偏宽松:与”默认拒绝、需显式授权”的安全模型不同,SK 目前唯一内置的、代码可验证的许可回调(MCP sampling consent)在未配置时默认自动批准,只打警告日志;框架整体把审批门的实现责任完全留给应用开发者通过 filter 自建,这是一个值得在跨 harness 安全对比中点名的设计取舍。

原始源码定位

  • repo: https://github.com/microsoft/semantic-kernel
  • commit/version analyzed: f6391ad8b6b47b6de44e80d54ce9f3ffe4f3ed42git clone --depth 1,2026-07-07)
  • 关键文件列表(相对 python/semantic_kernel/,除非另注明):
    • kernel.py
    • connectors/ai/chat_completion_client_base.py
    • connectors/ai/function_choice_behavior.py
    • connectors/ai/open_ai/services/open_ai_chat_completion_base.py
    • connectors/mcp.py
    • agents/agent.py
    • agents/chat_completion/chat_completion_agent.py
    • agents/orchestration/magentic.py
    • agents/orchestration/prompts/_magentic_prompts.py
    • agents/orchestration/handoffs.py
    • agents/orchestration/group_chat.pyorchestration_base.pyconcurrent.pysequential.py
    • agents/strategies/selection/*agents/strategies/termination/*
    • agents/runtime/core_runtime.pyagents/runtime/in_process/in_process_runtime.py
    • contents/history_reducer/chat_history_summarization_reducer.py
    • contents/history_reducer/chat_history_truncation_reducer.py
    • filters/kernel_filters_extension.py
    • filters/auto_function_invocation/auto_function_invocation_context.py
    • functions/kernel_function_decorator.py
    • reliability/kernel_reliability_extension.py
    • utils/telemetry/model_diagnostics/gen_ai_attributes.py
    • utils/telemetry/agent_diagnostics/*
    • docs/decisions/0044-OTel-semantic-convention.md
    • docs/decisions/0032-agents.md
    • docs/decisions/0005-kernel-hooks-phase1.mddocs/decisions/0033-kernel-filters.md
    • docs/PLANNERS.md
    • processes/process_builder.pyprocesses/kernel_process/kernel_process_step.pyprocesses/local_runtime/local_kernel_process.py
    • connectors/openapi_plugin/*
    • memory/semantic_text_memory.py
    • agents/azure_ai/azure_ai_agent.py
    • agents/open_ai/openai_assistant_agent.py
    • agents/bedrock/action_group_utils.py
    • TRANSPARENCY_FAQS.md(repo 根目录)

一手源存档(sources/)

/Users/zhao/projects/self-wiki/ai-research/sources/harness/microsoft-semantic-kernel/ 下:

  • NOTES.md —— 完整调研笔记(含逐维度发现、文件:行号引用)
  • key-files/PLANNERS.md
  • key-files/TRANSPARENCY_FAQS.md
  • key-files/kernel.py
  • key-files/connectors_mcp.py
  • key-files/agents/agent.pychat_completion_agent.pymagentic.pyhandoffs.py 等,具体见目录)
  • key-files/connectors/(chat_completion_client_base.py、function_choice_behavior.py、open_ai_chat_completion_base.py 等)
  • key-files/contents/(history_reducer 相关)
  • key-files/docs/(ADR 节选)
  • key-files/filters/(filter 扩展点相关)