[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-f10955b6-2812-4fcb-a2c7-e3255273c478":3,"$fOxltUDxPF41PuZ46RUfcemBG1Oct8ZFzKXmt2ylZGJY":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"f10955b6-2812-4fcb-a2c7-e3255273c478","m365-agents-py","Microsoft 365 代理 SDK for Python。使用 aiohttp 主机、AgentApplication 路由、流式响应和基于 MSAL 的身份验证构建 Teams\u002FM365\u002FCopilot Studio 的多渠道代理。","cat_writing_copywriting","mod_writing","sickn33,writing","---\nname: m365-agents-py\ndescription: Microsoft 365 Agents SDK for Python. Build multichannel agents for Teams\u002FM365\u002FCopilot Studio with aiohttp hosting, AgentApplication routing, streaming responses, and MSAL-based auth.\nrisk: unknown\nsource: community\ndate_added: '2026-02-27'\n---\n\n# Microsoft 365 Agents SDK (Python)\n\nBuild enterprise agents for Microsoft 365, Teams, and Copilot Studio using the Microsoft Agents SDK with aiohttp hosting, AgentApplication routing, streaming responses, and MSAL-based authentication.\n\n## Before implementation\n- Use the microsoft-docs MCP to verify the latest API signatures for AgentApplication, start_agent_process, and authentication options.\n- Confirm package versions on PyPI for the microsoft-agents-* packages you plan to use.\n\n## Important Notice - Import Changes\n\n> **⚠️ Breaking Change**: Recent updates have changed the Python import structure from `microsoft.agents` to `microsoft_agents` (using underscores instead of dots).\n\n## Installation\n\n```bash\npip install microsoft-agents-hosting-core\npip install microsoft-agents-hosting-aiohttp\npip install microsoft-agents-activity\npip install microsoft-agents-authentication-msal\npip install microsoft-agents-copilotstudio-client\npip install python-dotenv aiohttp\n```\n\n## Environment Variables (.env)\n\n```bash\nCONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=\u003Cclient-id>\nCONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=\u003Cclient-secret>\nCONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=\u003Ctenant-id>\n\n# Optional: OAuth handlers for auto sign-in\nAGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=\u003Cconnection-name>\n\n# Optional: Azure OpenAI for streaming\nAZURE_OPENAI_ENDPOINT=\u003Cendpoint>\nAZURE_OPENAI_API_VERSION=\u003Cversion>\nAZURE_OPENAI_API_KEY=\u003Ckey>\n\n# Optional: Copilot Studio client\nCOPILOTSTUDIOAGENT__ENVIRONMENTID=\u003Cenvironment-id>\nCOPILOTSTUDIOAGENT__SCHEMANAME=\u003Cschema-name>\nCOPILOTSTUDIOAGENT__TENANTID=\u003Ctenant-id>\nCOPILOTSTUDIOAGENT__AGENTAPPID=\u003Capp-id>\n```\n\n## Core Workflow: aiohttp-hosted AgentApplication\n\n```python\nimport logging\nfrom os import environ\n\nfrom dotenv import load_dotenv\nfrom aiohttp.web import Request, Response, Application, run_app\n\nfrom microsoft_agents.activity import load_configuration_from_env\nfrom microsoft_agents.hosting.core import (\n    Authorization,\n    AgentApplication,\n    TurnState,\n    TurnContext,\n    MemoryStorage,\n)\nfrom microsoft_agents.hosting.aiohttp import (\n    CloudAdapter,\n    start_agent_process,\n    jwt_authorization_middleware,\n)\nfrom microsoft_agents.authentication.msal import MsalConnectionManager\n\n# Enable logging\nms_agents_logger = logging.getLogger(\"microsoft_agents\")\nms_agents_logger.addHandler(logging.StreamHandler())\nms_agents_logger.setLevel(logging.INFO)\n\n# Load configuration\nload_dotenv()\nagents_sdk_config = load_configuration_from_env(environ)\n\n# Create storage and connection manager\nSTORAGE = MemoryStorage()\nCONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config)\nADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER)\nAUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config)\n\n# Create AgentApplication\nAGENT_APP = AgentApplicationTurnState\n\n\n@AGENT_APP.conversation_update(\"membersAdded\")\nasync def on_members_added(context: TurnContext, _state: TurnState):\n    await context.send_activity(\"Welcome to the agent!\")\n\n\n@AGENT_APP.activity(\"message\")\nasync def on_message(context: TurnContext, _state: TurnState):\n    await context.send_activity(f\"You said: {context.activity.text}\")\n\n\n@AGENT_APP.error\nasync def on_error(context: TurnContext, error: Exception):\n    await context.send_activity(\"The agent encountered an error.\")\n\n\n# Server setup\nasync def entry_point(req: Request) -> Response:\n    agent: AgentApplication = req.app[\"agent_app\"]\n    adapter: CloudAdapter = req.app[\"adapter\"]\n    return await start_agent_process(req, agent, adapter)\n\n\nAPP = Application(middlewares=[jwt_authorization_middleware])\nAPP.router.add_post(\"\u002Fapi\u002Fmessages\", entry_point)\nAPP[\"agent_configuration\"] = CONNECTION_MANAGER.get_default_connection_configuration()\nAPP[\"agent_app\"] = AGENT_APP\nAPP[\"adapter\"] = AGENT_APP.adapter\n\nif __name__ == \"__main__\":\n    run_app(APP, host=\"localhost\", port=environ.get(\"PORT\", 3978))\n```\n\n## AgentApplication Routing\n\n```python\nimport re\nfrom microsoft_agents.hosting.core import (\n    AgentApplication, TurnState, TurnContext, MessageFactory\n)\nfrom microsoft_agents.activity import ActivityTypes\n\nAGENT_APP = AgentApplicationTurnState\n\n# Welcome handler\n@AGENT_APP.conversation_update(\"membersAdded\")\nasync def on_members_added(context: TurnContext, _state: TurnState):\n    await context.send_activity(\"Welcome!\")\n\n# Regex-based message handler\n@AGENT_APP.message(re.compile(r\"^hello$\", re.IGNORECASE))\nasync def on_hello(context: TurnContext, _state: TurnState):\n    await context.send_activity(\"Hello!\")\n\n# Simple string message handler\n@AGENT_APP.message(\"\u002Fstatus\")\nasync def on_status(context: TurnContext, _state: TurnState):\n    await context.send_activity(\"Status: OK\")\n\n# Auth-protected message handler\n@AGENT_APP.message(\"\u002Fme\", auth_handlers=[\"GRAPH\"])\nasync def on_profile(context: TurnContext, state: TurnState):\n    token_response = await AGENT_APP.auth.get_token(context, \"GRAPH\")\n    if token_response and token_response.token:\n        # Use token to call Graph API\n        await context.send_activity(\"Profile retrieved\")\n\n# Invoke activity handler\n@AGENT_APP.activity(ActivityTypes.invoke)\nasync def on_invoke(context: TurnContext, _state: TurnState):\n    invoke_response = Activity(\n        type=ActivityTypes.invoke_response, value={\"status\": 200}\n    )\n    await context.send_activity(invoke_response)\n\n# Fallback message handler\n@AGENT_APP.activity(\"message\")\nasync def on_message(context: TurnContext, _state: TurnState):\n    await context.send_activity(f\"Echo: {context.activity.text}\")\n\n# Error handler\n@AGENT_APP.error\nasync def on_error(context: TurnContext, error: Exception):\n    await context.send_activity(\"An error occurred.\")\n```\n\n## Streaming Responses with Azure OpenAI\n\n```python\nfrom openai import AsyncAzureOpenAI\nfrom microsoft_agents.activity import SensitivityUsageInfo\n\nCLIENT = AsyncAzureOpenAI(\n    api_version=environ[\"AZURE_OPENAI_API_VERSION\"],\n    azure_endpoint=environ[\"AZURE_OPENAI_ENDPOINT\"],\n    api_key=environ[\"AZURE_OPENAI_API_KEY\"]\n)\n\n@AGENT_APP.message(\"poem\")\nasync def on_poem_message(context: TurnContext, _state: TurnState):\n    # Configure streaming response\n    context.streaming_response.set_feedback_loop(True)\n    context.streaming_response.set_generated_by_ai_label(True)\n    context.streaming_response.set_sensitivity_label(\n        SensitivityUsageInfo(\n            type=\"https:\u002F\u002Fschema.org\u002FMessage\",\n            schema_type=\"CreativeWork\",\n            name=\"Internal\",\n        )\n    )\n    context.streaming_response.queue_informative_update(\"Starting a poem...\\n\")\n\n    # Stream from Azure OpenAI\n    streamed_response = await CLIENT.chat.completions.create(\n        model=\"gpt-4o\",\n        messages=[\n            {\"role\": \"system\", \"content\": \"You are a creative assistant.\"},\n            {\"role\": \"user\", \"content\": \"Write a poem about Python.\"}\n        ],\n        stream=True,\n    )\n    \n    try:\n        async for chunk in streamed_response:\n            if chunk.choices and chunk.choices[0].delta.content:\n                context.streaming_response.queue_text_chunk(\n                    chunk.choices[0].delta.content\n                )\n    finally:\n        await context.streaming_response.end_stream()\n```\n\n## OAuth \u002F Auto Sign-In\n\n```python\n@AGENT_APP.message(\"\u002Flogout\")\nasync def logout(context: TurnContext, state: TurnState):\n    await AGENT_APP.auth.sign_out(context, \"GRAPH\")\n    await context.send_activity(MessageFactory.text(\"You have been logged out.\"))\n\n\n@AGENT_APP.message(\"\u002Fme\", auth_handlers=[\"GRAPH\"])\nasync def profile_request(context: TurnContext, state: TurnState):\n    user_token_response = await AGENT_APP.auth.get_token(context, \"GRAPH\")\n    if user_token_response and user_token_response.token:\n        # Use token to call Microsoft Graph\n        async with aiohttp.ClientSession() as session:\n            headers = {\n                \"Authorization\": f\"Bearer {user_token_response.token}\",\n                \"Content-Type\": \"application\u002Fjson\",\n            }\n            async with session.get(\n                \"https:\u002F\u002Fgraph.microsoft.com\u002Fv1.0\u002Fme\", headers=headers\n            ) as response:\n                if response.status == 200:\n                    user_info = await response.json()\n                    await context.send_activity(f\"Hello, {user_info['displayName']}!\")\n```\n\n## Copilot Studio Client (Direct to Engine)\n\n```python\nimport asyncio\nfrom msal import PublicClientApplication\nfrom microsoft_agents.activity import ActivityTypes, load_configuration_from_env\nfrom microsoft_agents.copilotstudio.client import (\n    ConnectionSettings,\n    CopilotClient,\n)\n\n# Token cache (local file for interactive flows)\nclass LocalTokenCache:\n    # See samples for full implementation\n    pass\n\ndef acquire_token(settings, app_client_id, tenant_id):\n    pca = PublicClientApplication(\n        client_id=app_client_id,\n        authority=f\"https:\u002F\u002Flogin.microsoftonline.com\u002F{tenant_id}\",\n    )\n    \n    token_request = {\"scopes\": [\"https:\u002F\u002Fapi.powerplatform.com\u002F.default\"]}\n    accounts = pca.get_accounts()\n    \n    if accounts:\n        response = pca.acquire_token_silent(token_request[\"scopes\"], account=accounts[0])\n        return response.get(\"access_token\")\n    else:\n        response = pca.acquire_token_interactive(**token_request)\n        return response.get(\"access_token\")\n\n\nasync def main():\n    settings = ConnectionSettings(\n        environment_id=environ.get(\"COPILOTSTUDIOAGENT__ENVIRONMENTID\"),\n        agent_identifier=environ.get(\"COPILOTSTUDIOAGENT__SCHEMANAME\"),\n    )\n    \n    token = acquire_token(\n        settings,\n        app_client_id=environ.get(\"COPILOTSTUDIOAGENT__AGENTAPPID\"),\n        tenant_id=environ.get(\"COPILOTSTUDIOAGENT__TENANTID\"),\n    )\n    \n    copilot_client = CopilotClient(settings, token)\n    \n    # Start conversation\n    act = copilot_client.start_conversation(True)\n    async for action in act:\n        if action.text:\n            print(action.text)\n    \n    # Ask question\n    replies = copilot_client.ask_question(\"Hello!\", action.conversation.id)\n    async for reply in replies:\n        if reply.type == ActivityTypes.message:\n            print(reply.text)\n\n\nasyncio.run(main())\n```\n\n## Best Practices\n\n1. Use `microsoft_agents` import prefix (underscores, not dots).\n2. Use `MemoryStorage` only for development; use BlobStorage or CosmosDB in production.\n3. Always use `load_configuration_from_env(environ)` to load SDK configuration.\n4. Include `jwt_authorization_middleware` in aiohttp Application middlewares.\n5. Use `MsalConnectionManager` for MSAL-based authentication.\n6. Call `end_stream()` in finally blocks when using streaming responses.\n7. Use `auth_handlers` parameter on message decorators for OAuth-protected routes.\n8. Keep secrets in environment variables, not in source code.\n\n## Reference Files\n\n| File | Contents |\n| --- | --- |\n| references\u002Facceptance-criteria.md | Import paths, hosting pipeline, streaming, OAuth, and Copilot Studio patterns |\n\n## Reference Links\n\n| Resource | URL |\n| --- | --- |\n| Microsoft 365 Agents SDK | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoft-365\u002Fagents-sdk\u002F |\n| GitHub samples (Python) | https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FAgents-for-python |\n| PyPI packages | https:\u002F\u002Fpypi.org\u002Fsearch\u002F?q=microsoft-agents |\n| Integrate with Copilot Studio | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoft-365\u002Fagents-sdk\u002Fintegrate-with-mcs |\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,213,1626,"2026-05-16 13:27:19",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"写作研究","writing","mdi-pencil-outline","从学术写作到创意文案，让 AI 成为你的专属写作助手",1,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"文案策划","copywriting","mdi-comment-text-outline","广告文案、品牌故事、Slogan",4,72,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"280a3885-5a46-432b-980d-bce5c20e2fb9","1.0.0","m365-agents-py.zip",4136,"uploads\u002Fskills\u002Ff10955b6-2812-4fcb-a2c7-e3255273c478\u002Fm365-agents-py.zip","20c9e24887cde5e519b04e78814f5a77412d85a1d3f27cd85e53d35e36261ff8","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":12131}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]