
用 Semantic Kernel 為 Microsoft Copilot Studio 構建自定義 Skill從低代碼擴展到 Pro-Code 的完整實戰【免費下載鏈接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps項目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel本篇技術指南以當前倉庫中python/samples/demos/copilot_studio_skill示例為核心系統講解如何將 Semantic Kernel 以Copilot Studio Skill的形式接入 Microsoft Copilot Studio通過 Azure Bot Service 與部署在 Azure Container Apps 上的自定義 API 擴展 Agent 能力。讀完本文你將掌握 Copilot Studio Skill 的完整架構、Entra IDAzure AD應用注冊、azd up一鍵部署、Bot Framework 技能清單Manifest編寫以及基于 Semantic KernelChatCompletionAgent的對話后端實現細節并能直接照搬源碼改造出你自己的生產級 Skill。為什么需要 Pro-Code 方式擴展 Copilot StudioMicrosoft Copilot Studio 是一個圖形化的低代碼工具既可以用于創建 Agent包括通過 Power Automate 構建自動化流程也可以將企業自有數據和場景擴展進 Microsoft 365 Copilot。然而在某些場景下默認 Agent 能力無法滿足需求例如需要調用企業內部的私有 API、復雜計算或領域算法需要細粒度的權限控制與多租戶安全校驗需要把 LLM 編排多輪對話、函數調用、插件體系交給自己完全可控的代碼。此時Pro-Code 優先的方式——把 Semantic Kernel 封裝成一個可被 Copilot Studio 調用的 Skill——就成為一種自然選擇。本示例正是這一思路的最小可運行實現Copilot Studio 中的 Topic 通過一個 Action 節點調用遠程 SkillSkill 后端由 Semantic Kernel 驅動的聊天 Agent 處理并返回響應。注意示例演示了一個講笑話的 Agentsk_conversation_agent.py中的指令為 You invent jokes to have a fun conversation with the user.但整個框架可以替換為任何業務邏輯如 RAG 問答、訂單查詢、內容生成等。架構總覽一條從 Copilot Studio 到 SK Agent 的請求鏈路示例采用Azure Bot Service作為請求入口負責將請求路由到后端服務——一個運行在Azure Container Apps中、由 Semantic Kernel 驅動的自定義 API。整體時序如下摘自原文檔架構圖此處以 Mermaid 還原鏈路中有兩條關鍵路徑注冊路徑一次性Copilot Studio 直接向 SK App 的/manifest端點拉取技能清單Skill Manifest完成 Skill 注冊運行時路徑每次對話用戶消息經 Copilot Studio → Azure Bot Service → SK App 的/api/messages端點SK Agent 處理后沿原路返回響應。從倉庫源碼看這個SK App實際是一個基于aiohttp的輕量 Web 服務app.py路由定義非常清晰APP web.Application() APP.router.add_post(/api/messages, messages) APP.router.add_get(/manifest, copilot_manifest)POST /api/messagesBot Framework 協議的消息處理入口處理來自 Copilot Studio 的 ActivityGET /manifest動態生成并返回 Copilot Studio Skill Manifest帶身份與端點信息。提示原文檔特別指出截至目前 Bot Framework SDK for Python 僅提供aiohttp支持不支持 FastAPI/Flask 等框架這也是示例選擇 aiohttp 的原因。見 requirements.txt 中的botbuilder-integration-aiohttp4.15.0。前置條件與環境要求開始部署前請確認具備以下環境與原文檔一致前置項說明Azure 訂閱用于部署 Bot Service、Container Apps、Azure OpenAI 等資源Azure CLI用于創建 Entra ID 應用注冊與憑據Azure Developer CLIazd用于一鍵部署基礎設施與代碼Python 3.12 或更高后端 API 的運行時Dockerfile 基于python:3.12-slim啟用 Copilot Studio 的 Microsoft 365 租戶用于注冊 Skill 與測試對話關于租戶有兩個值得注意的細節Azure 訂閱與 Microsoft 365 租戶不必是同一租戶但必須在啟用 Copilot Studio 的租戶的 Entra IDAzure AD中擁有注冊應用的權限因為 Bot 身份App Registration決定了 Copilot Studio 能否安全調用你的 Skill。端到端部署步驟第一步克隆倉庫并定位示例git clone https://gitcode.com/GitHub_Trending/se/semantic-kernel cd semantic-kernel/python/samples/demos/copilot_studio_skill示例目錄結構如下倉庫內實際文件copilot_studio_skill/ ├── azure.yaml # azd 服務定義Container Apps Docker ├── image.png # 運行效果截圖 ├── infra/ # Bicep 基礎設施模板main.bicep、bot.bicep、aca.bicep 等 └── src/api/ # SK Skill 后端 API ├── adapter.py # 帶錯誤處理的 CloudAdapter ├── app.py # aiohttp 入口與路由 ├── auth.py # 調用方 Claims 校驗器 ├── bot.py # Teams Application 消息處理 ├── config.py # 環境變量配置類 ├── copilot-studio.manifest.json # Skill Manifest 模板 ├── dockerfile ├── requirements.txt └── sk_conversation_agent.py # Semantic Kernel ChatCompletionAgent第二步在 Entra ID 中創建應用注冊Skill 需要以 Bot 身份運行因此先在 Microsoft 365 租戶Copilot Studio 所在租戶中創建 App Registration并生成 client secret。原文檔給出的 PowerShell 命令如下az login --tenant COPILOT-tenant-id $appId az ad app create --display-name SKCopilotSkill --query appId -o tsv $secret az ad app credential reset --id $appId --append --query password -o tsv記下三個值它們將用于后續部署與配置$appId→ 對應環境變量BOT_APPID$secret→ 對應環境變量BOT_PASSWORDCOPILOT-tenant-id→ 對應環境變量BOT_TENANT_ID對應關系可從 infra/main.parameters.json 中確認botAppId、botPassword、botTenantId分別綁定到BOT_APPID、BOT_PASSWORD、BOT_TENANT_ID環境變量。第三步使用 azd 一鍵部署 Azure 資源登錄 Azure 訂閱后執行azd auth login --tenant AZURE-tenant-id azd up交互過程中需要提供以下輸入原文檔明確列出提示項來源botAppId上一步的應用注冊 App IDbotPassword上一步的 client secretbotTenantIdCopilot Studio 所在租戶 ID現有的 Azure OpenAI 資源名及其資源組需提前在 Azure 訂閱中創建好此外 main.parameters.json 還暴露了模型相關參數均有默認值openAIModel默認gpt-4oopenAIApiVersion默認2024-08-01-previewapiAppExists默認false是否復用已存在的容器應用部署由 azure.yaml 驅動——它將src/api作為containerapp類型的服務使用倉庫內 dockerfile 構建鏡像python:3.12-slim基礎鏡像暴露端口 80運行時環境變量HOST0.0.0.0、PORT80。提示部署完成后API 的 URL 會顯示在 Azure Developer CLI 的output部分請復制保存后續注冊 Skill 與配置homeUrl都會用到。第四步配置 App Registration 的 homeUrl將第二步創建的 App Registration 的homeUrl設置為已部署 API 的 URL。這是 Bot 能夠響應 Copilot Studio 請求的必要條件——原文檔強調required for the bot to be able to respond to requests from Copilot Studio。第五步在 Copilot Studio 中把 Bot 注冊為 Skill在 Microsoft 365 租戶中打開 Copilot Studio新建一個 Agent 或復用已有 Agent在 Agent 頁面右上角進入 Settings進入 Skills 標簽頁點擊 Add a skill輸入API_URL/manifestAPI_URL即部署輸出的 API 地址作為 Skill URL點擊 Next 完成注冊注冊完成后編輯或新建一個 Topic在主題流中添加該 Skill 節點即可開始使用。上圖image.png展示的正是這一步的產物左側是 Copilot Studio 的主題工作流編輯器——Trigger 節點描述為 Jokes通過藍色箭頭連接到 Invoke Semantic Kernel skill 的 Action 節點右側測試面板中用戶提問 Tell me a joke about developersAgent 返回 Why do developers prefer dark mode? Because light attracts bugs!驗證了端到端鏈路已打通。源碼級實現解析Skill 后端是如何工作的1. 配置層環境變量即契約config.pyconfig.py 定義了全部運行時配置是理解 Skill 行為的關鍵入口HOST os.getenv(HOST, localhost) PORT int(os.getenv(PORT, 8080)) APP_ID os.getenv(BOT_APP_ID) # Bot 應用注冊 ID APP_PASSWORD os.getenv(BOT_PASSWORD) # Bot 應用注冊 client secret APP_TENANTID os.getenv(BOT_TENANT_ID) # 租戶 ID APP_TYPE os.getenv(APP_TYPE, singletenant) # 默認單租戶 # Required for Copilot Skill ALLOWED_CALLERS os.getenv(ALLOWED_CALLERS, [*]) # 允許調用本 Skill 的父 Bot ID 列表或 * 放行全部 AZURE_OPENAI_CHAT_DEPLOYMENT_NAME os.getenv(AZURE_OPENAI_CHAT_DEPLOYMENT_NAME) AZURE_OPENAI_ENDPOINT os.getenv(AZURE_OPENAI_ENDPOINT) AZURE_OPENAI_API_VERSION os.getenv(AZURE_OPENAI_API_VERSION)validate()方法在模塊加載時強制執行配置校驗HOST/PORT、APP_ID/APP_PASSWORD/APP_TENANTID、ALLOWED_CALLERS任一缺失都會直接拋異常避免帶著錯誤配置上線。三個值得深挖的配置語義APP_TYPE默認singletenant聲明 Bot 的身份驗證模式單租戶模式下令牌校驗范圍被限定在APP_TENANTID指定的租戶內是多租戶安全的第一道閘門ALLOWED_CALLERS聲明允許調用本 Skill 的父 Bot即 Copilot Studio 一側的 AgentApp ID 白名單默認[*]表示放行所有 Agent。生產環境務必改為具體的 App ID 列表見下方 auth.py 的校驗邏輯Azure OpenAI 三件套AZURE_OPENAI_CHAT_DEPLOYMENT_NAME、AZURE_OPENAI_ENDPOINT、AZURE_OPENAI_API_VERSION會被AzureChatCompletion消費由 azd 部署時注入。2. 入口層aiohttp 應用與 Manifest 動態生成app.pyapp.py 實現兩個端點/api/messages讀取請求 JSON 后直接交給bot.process(req)。原文檔與代碼注釋都強調了一個 Skill 特有約束在 Skill 上下文中必須把響應作為請求的返回值返回給 Copilot Studio而在 Teams 等其他渠道中Activity 是由 Bot Framework 主動推送的/manifest讀取copilot-studio.manifest.json模板用容器應用的實際 FQDN 與 Bot App ID 做字符串替換后返回fqdn fhttps://{os.getenv(CONTAINER_APP_NAME)}.{os.getenv(CONTAINER_APP_ENV_DNS_SUFFIX)}/api/messages manifest manifest.replace(__botEndpoint, fqdn).replace(__botAppId, config.APP_ID)即 Manifest 中endpointUrl最終指向https://容器應用FQDN/api/messagesmsAppId指向 Bot 的 App ID。3. 清單層Copilot Studio Skill Manifestcopilot-studio.manifest.jsoncopilot-studio.manifest.json 是 Copilot Studio 識別 Skill 的名片核心字段包括$schemaBot Framework Skill Manifest v2.2 的 JSON Schema$id/name/version/description/publisherNameSkill 的標識與描述信息endpoints聲明BotFrameworkV3協議的默認端點endpointUrl與msAppId為__botEndpoint/__botAppId占位符由/manifest端點動態替換activities聲明本 Skill 支持message類型的 ActivityInvoke Semantic Kernel skill這是 Copilot Studio 與 Skill 交互的唯一活動類型。4. 對話層Teams Application Semantic Kernel Agentbot.py 與 sk_conversation_agent.pybot.py 使用teams-ai的Application[TurnState]構建 Bot 應用bot ApplicationTurnState, adapterAdapterWithErrorHandler(ConfigurationBotFrameworkAuthentication(config, auth_configurationauth)), ) )注意代碼注釋中的關鍵提醒adapter參數不能傳 dict必須傳一個帶APP_ID、APP_PASSWORD、APP_TENANTID屬性的類實例——這里的config對象恰好滿足這一契約。對話邏輯通過兩個事件裝飾器掛載bot.before_turn async def setup_chathistory(context, state): chat_history state.conversation.get(chat_history) or ChatHistory() state.conversation[chat_history] chat_history return state bot.activity(message) async def on_message(context, state): user_message context.activity.text chat_history.add_user_message(user_message) sk_response await agent.get_response(historychat_history, user_inputuser_message) state.conversation[chat_history] chat_history await context.send_activity(MessageFactory.text(sk_response, input_hintInputHints.ignoring_input)) end Activity.create_end_of_conversation_activity() end.code EndOfConversationCodes.completed_successfully await context.send_activity(end) return True幾個要點多輪記憶利用TurnState的 conversation 級存儲把 Semantic Kernel 的ChatHistory持久化在會話狀態中實現跨輪次的上下文連續SK 對話后端調用agent.get_response(historychat_history, user_inputuser_message)。代碼注釋標明該 API 需要semantic-kernel1.22.0見 requirements.txtSkill 協議收尾響應后必須發送EndOfConversation活動completed_successfully告知 Copilot Studio 本輪對話結束。注釋也提醒真實 Skill 中應在用戶完成目標任務后再發送而非像示例這樣每輪都立即結束。sk_conversation_agent.py 則是最簡的 Semantic Kernel Agent 構造from azure.identity import AzureCliCredential from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion agent ChatCompletionAgent( serviceAzureChatCompletion(credentialAzureCliCredential()), nameChatAgent, instructionsYou invent jokes to have a fun conversation with the user., )使用ChatCompletionAgentSemantic Kernel 的對話補全 Agent 抽象連接器為AzureChatCompletion憑證采用AzureCliCredential在 Azure 環境內亦可替換為工作負載身份等托管身份憑證instructions即系統提示詞是 SK Agent 的行為底座可自由替換為你的業務指令。5. 安全層調用方校驗與錯誤處理auth.py 與 adapter.py調用方白名單校驗auth.pyauth.py 實現AllowedCallersClaimsValidator其核心邏輯將ALLOWED_CALLERS配置轉為frozenset在claims_validator中當白名單不含*且請求帶有 Skill 聲明SkillValidation.is_skill_claim(claims)時從令牌中提取appId若不在白名單則拋出PermissionError該 validator 通過AuthenticationConfiguration注入 Bot 認證流程見 bot.py 中auth AuthenticationConfiguration(tenant_id..., claims_validator...)。代碼注釋明確指出不添加 claims validator 會導致 Skill 運行報錯——這是 Skill 模式與普通 Bot 的關鍵差異之一。錯誤處理適配器adapter.pyadapter.py 的AdapterWithErrorHandler繼承CloudAdapter在 turn 異常時向用戶發送友好錯誤消息The skill encountered an error or bug.發送 trace activity 供 Bot Framework Emulator 排查向 Skill 調用方父 Bot發送EndOfConversation活動code 為SkillErrortext 攜帶異常信息讓調用方決定后續處理。這保證了 Skill 異常不會導致父 Agent 掛起是生產化部署的必要加固。關鍵注意事項與生產化建議綜合原文檔與源碼以下坑點與建議值得重點記錄框架選擇受限Python 的 Bot Framework SDK 目前僅支持 aiohttp不要嘗試用 FastAPI/Flask 直接替換Skill 必須同步返回響應/api/messages的 HTTP 響應就是給 Copilot Studio 的回復這與 Teams 等主動推送渠道的編程模型不同必須實現 claims validatorALLOWED_CALLERS白名單校驗是 Skill 安全的基礎生產環境不要保留*通配記得發送 EndOfConversation一輪對話結束要顯式發送該活動成功用completed_successfully異常用SkillError否則調用方可能一直等待homeUrl必須指向已部署 API否則 Copilot Studio 無法回調你的 Skill配置即契約BOT_APP_ID、BOT_PASSWORD、BOT_TENANT_ID等環境變量名是 Bot Framework 與 azd 參數映射的固定約定config.py 中特意注釋 DO NOT CHANGE THIS KEYS!!模型參數可調通過 azd 參數可指定 Azure OpenAI 模型默認gpt-4o與 API 版本默認2024-08-01-preview需與你的 Azure OpenAI 資源實際部署保持一致。總結本示例展示了一條完整且可復用的低代碼 Pro-Code混合擴展路徑Copilot Studio 負責用戶體驗與流程編排Semantic Kernel 負責 LLM 驅動的對話智能。你可以在此基礎上將sk_conversation_agent.py中的簡單笑話 Agent 替換為接入插件Plugin、函數調用Function Calling、向量檢索RAG等能力的完整業務 Agent并通過ALLOWED_CALLERS白名單、錯誤處理適配器與托管身份認證將 Skill 推向生產環境。示例全部源碼位于 python/samples/demos/copilot_studio_skill基礎設施模板集中在 infra 目錄可作為你落地同類集成的起點。【免費下載鏈接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps項目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考