[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FVM319F7A07FK0R99XPPMF":3,"skill-same:01M6FVM319F7A07FK0R99XPPMF":47},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":23,"frontMatter":24,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":13,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":30,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M6FVM319F7A07FK0R99XPPMF","m365-agents-py",null,"reikiplanet\u002Fdaoskills","reikiplanet","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F96377599?v=4","01M6CVWCMD740YHQDK7E9QYBW4","Reiki Planet","01M6CVWCS4KXVA2CWFVJ43EAXK",0,"MIT","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fdevelopment\u002Fm365-agents-py\u002FSKILL.md",[],[18,19],"m365 agents py","m365","2026-11-10 10:12:30",false,"---\nname: m365-agents-py\ndescription: \"|\"\n  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. Triggers: \"Microsoft 365 Agents SDK\", \"microsoft_agents\", \"AgentApplication\", \"start_agent_process\", \"TurnContext\", \"Copilot Studio client\", \"CloudAdapter\".\npackage: microsoft-agents-hosting-core, microsoft-agents-hosting-aiohttp, microsoft-agents-activity, microsoft-agents-authentication-msal, microsoft-agents-copilotstudio-client\nrisk: unknown\nsource: community\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","# 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",{},"master","dff58085da947e81e8418c922055644bf0082b1b","development\u002Fm365-agents-py","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills","https:\u002F\u002Fgithub.com\u002Freikiplanet","https:\u002F\u002Fwww.reiki-planet.com","Reiki Planet Game","2026-03-29 06:02:29",{"source":7,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add reikiplanet\u002Fdaoskills --skill m365-agents-py",{"tool":39,"command":40},"bunx","bunx skills add reikiplanet\u002Fdaoskills --skill m365-agents-py",{"tool":42,"command":43},"pnpm","pnpm dlx skills add reikiplanet\u002Fdaoskills --skill m365-agents-py","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fdevelopment\u002Fm365-agents-py\u002FSKILL.md",true,[],[48,75,87,102,122,145],{"skillNo":49,"name":50,"nameZh":6,"description":51,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":52,"categories":53,"keywords":54,"publishedAt":20},"01M6G614JTEQJHPT8AKK3YQ18S","web-games","Web browser game development principles. Framework selection, WebGPU, optimization, PWA.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fweb-games\u002FSKILL.md",[],[55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],"games","web games","web","grep","principles","selection","community","framework selection","edit","write","read","pwa","game","web browser","game development","Optimization","framework","browser","development","webgpu",{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":20},"01M6G611H2YGV0GZFP90D38ZMJ","vr-ar","VR\u002FAR development principles. Comfort, interaction, performance requirements.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fvr-ar\u002FSKILL.md",[],[82,83,73,84,85,61,63,64,65,58,86,59],"ar","vr ar","interaction","requirements","performance",{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":20},"01M6G60XNMHAMV1SV0EJ1CX0AY","templates","Project scaffolding templates for new applications. Use when creating new projects from scratch. Contains 12 templates for various tech stacks.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Ftemplates\u002FSKILL.md",[],[89,94,95,96,97,98,61,99,65,100,101,58],"project scaffolding","From Scratch","tech","project","scaffolding","use","projects","applications",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":108,"publishedAt":20},"01M6G60T0GATMK3Q5H8GDC1Z8S","wcag-audit-patterns","Conduct WCAG 2.2 accessibility audits with automated testing, manual verification, and remediation guidance. Use when auditing websites for accessibility, fixing WCAG violations, or implementing ac...","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fskills\u002Fsecurity\u002Fwcag-audit-patterns\u002FSKILL.md",[],[109,110,111,112,113,61,114,115,116,117,99,118,119,120,121],"wcag audit patterns","wcag audit","patterns","WCAG","audit","manual","with","automated testing","guidance","remediation","verification","accessibility","testing",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":20},"01M6G60PMCHW1FRZ63F931QK3R","vulnerability-scanner","Advanced vulnerability analysis principles. OWASP 2025, Supply Chain Security, attack surface mapping, risk prioritization.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fskills\u002Fsecurity\u002Fvulnerability-scanner\u002FSKILL.md",[],[129,130,131,132,133,134,135,136,61,65,58,137,59,138,139,140,141,142,143,144],"scanner","vulnerability scanner","vulnerability","prioritization","2025","mapping","chain","supply chain","Bash","analysis","risk","owasp","supply chain security","security","supply","advanced",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":151,"publishedAt":20},"01M6G60JZBB8DK0W3DSG1WNMZK","threat-modeling-expert","Expert in threat modeling methodologies, security architecture review, and risk assessment. Masters STRIDE, PASTA, attack trees, and security requirement extraction. Use for security architecture r...","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fskills\u002Fsecurity\u002Fthreat-modeling-expert\u002FSKILL.md",[],[152,153,154,155,156,157,158,159,142,99,160,161,162,61,163,164,165,139,166,167],"modeling","threat modeling expert","threat modeling","expert","threat","risk assessment","architecture review","architecture","security architecture review","trees","security architecture","security requirement extraction","assessment","extraction","review","stride"]