[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M78DMS7B0PBNK63CPPASXSC1":3,"skill-same:01M78DMS7B0PBNK63CPPASXSC1":48},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":27,"commitSha":28,"skillDirectory":29,"forksCount":14,"repositoryHtmlUrl":30,"repositoryHomepageUrl":31,"ownerHtmlUrl":32,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":33,"install":34,"resources":47},"01M78DMS7B0PBNK63CPPASXSC1","m365-agents-py",null,"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.","princepatel04477-web\u002Ftrivoxa-group","princepatel04477-web","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F227740714?v=4","01M788ZAJ2KECD5KXVP55PZXKS","Prince Patel","01M788ZAJTCN8YSD737MRSKC5Q",0,"MIT","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fm365-agents-py\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\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","# 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",{"name":5,"risk":24,"source":25,"date_added":26,"description":7},"unknown","community","2026-02-27","master","877653a671c51fae6476bd9f0d34ee6c408d68b9",".github\u002Fskills\u002Fm365-agents-py","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group","https:\u002F\u002Ftrivoxa-group.vercel.app","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web","2026-08-01 17:29:31",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add princepatel04477-web\u002Ftrivoxa-group --skill m365-agents-py",{"tool":40,"command":41},"bunx","bunx skills add princepatel04477-web\u002Ftrivoxa-group --skill m365-agents-py",{"tool":43,"command":44},"pnpm","pnpm dlx skills add princepatel04477-web\u002Ftrivoxa-group --skill m365-agents-py","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fm365-agents-py\u002FSKILL.md",true,[],[49,56,63,70,77,84],{"skillNo":50,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":55,"publishedAt":19},"01M78G4Z5RFJ72G536XYPC77PG","zustand-store-ts","Create Zustand stores following established patterns with proper TypeScript types and middleware.","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fzustand-store-ts\u002FSKILL.md",[],[],{"skillNo":57,"name":58,"nameZh":6,"description":59,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":60,"categories":61,"keywords":62,"publishedAt":19},"01M78G4WQMHRST36KDP7AV3NR3","zoom-automation","Automate Zoom meeting creation, management, recordings, webinars, and participant tracking via Rube MCP (Composio). Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fzoom-automation\u002FSKILL.md",[],[],{"skillNo":64,"name":65,"nameZh":6,"description":66,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":69,"publishedAt":19},"01M78G4T37F4SPS7M4KT0A8JJB","zoho-crm-automation","Automate Zoho CRM tasks via Rube MCP (Composio): create\u002Fupdate records, search contacts, manage leads, and convert leads. Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fzoho-crm-automation\u002FSKILL.md",[],[],{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":19},"01M78G4QAJMF71KD1G38MNDQYK","zod-validation-expert","Expert in Zod — TypeScript-first schema validation. Covers parsing, custom errors, refinements, type inference, and integration with React Hook Form, Next.js, and tRPC.","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fzod-validation-expert\u002FSKILL.md",[],[],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":19},"01M78G4MS3WE96MH5P561KFY95","zipai-optimizer","Adaptive token optimizer: intelligent filtering, surgical output, ambiguity-first, context-window-aware, VCS-aware, MCP-aware.","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fzipai-optimizer\u002FSKILL.md",[],[],{"skillNo":85,"name":86,"nameZh":6,"description":87,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":19},"01M78G4GZ0T47C6929V9CVH1AK","zeroize-audit","Detects missing zeroization of sensitive data in source code and identifies zeroization removed by compiler optimizations, with assembly-level analysis, and control-flow verification. Use for auditing C\u002FC++\u002FRust code handling secrets, keys, passwords, or other sensitive data.","https:\u002F\u002Fgithub.com\u002Fprincepatel04477-web\u002Ftrivoxa-group\u002Fblob\u002Fmaster\u002F.github\u002Fskills\u002Fzeroize-audit\u002FSKILL.md",[],[]]