m365-agents-py

作成者: microsoft

Microsoft Agents SDKを使用し、aiohttpホスティング、AgentApplicationルーティング、ストリーミング応答、MSALベースの認証を活用して、Microsoft 365、Teams、Copilot Studio向けのエンタープライズエージェントを構築します。

npx skills add https://github.com/microsoft/agent-skills --skill m365-agents-py

Microsoft 365 Agents SDK (Python)

Build 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.

Before implementation

  • Use the microsoft-docs MCP to verify the latest API signatures for AgentApplication, start_agent_process, and authentication options.
  • Confirm package versions on PyPI for the microsoft-agents-* packages you plan to use.

Important Notice - Import Changes

⚠️ Breaking Change: Recent updates have changed the Python import structure from microsoft.agents to microsoft_agents (using underscores instead of dots).

Installation

pip install microsoft-agents-hosting-core
pip install microsoft-agents-hosting-aiohttp
pip install microsoft-agents-activity
pip install microsoft-agents-authentication-msal
pip install microsoft-agents-copilotstudio-client
pip install python-dotenv aiohttp

Environment Variables (.env)

CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=<client-id>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=<client-secret>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=<tenant-id>

# Optional: OAuth handlers for auto sign-in
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=<connection-name>

# Optional: Azure OpenAI for streaming (AAD auth via DefaultAzureCredential)
AZURE_OPENAI_ENDPOINT=<endpoint>
AZURE_OPENAI_API_VERSION=<version>

# Optional: Copilot Studio client
COPILOTSTUDIOAGENT__ENVIRONMENTID=<environment-id>
COPILOTSTUDIOAGENT__SCHEMANAME=<schema-name>
COPILOTSTUDIOAGENT__TENANTID=<tenant-id>
COPILOTSTUDIOAGENT__AGENTAPPID=<app-id>

Core Workflow: aiohttp-hosted AgentApplication

import logging
from os import environ

from dotenv import load_dotenv
from aiohttp.web import Request, Response, Application, run_app

from microsoft_agents.activity import load_configuration_from_env
from microsoft_agents.hosting.core import (
    Authorization,
    AgentApplication,
    TurnState,
    TurnContext,
    MemoryStorage,
)
from microsoft_agents.hosting.aiohttp import (
    CloudAdapter,
    start_agent_process,
    jwt_authorization_middleware,
)
from microsoft_agents.authentication.msal import MsalConnectionManager

# Enable logging
ms_agents_logger = logging.getLogger("microsoft_agents")
ms_agents_logger.addHandler(logging.StreamHandler())
ms_agents_logger.setLevel(logging.INFO)

# Load configuration
load_dotenv()
agents_sdk_config = load_configuration_from_env(environ)

# Create storage and connection manager
STORAGE = MemoryStorage()
CONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config)
ADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER)
AUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config)

# Create AgentApplication
AGENT_APP = AgentApplication[TurnState](
    storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config
)


@AGENT_APP.conversation_update("membersAdded")
async def on_members_added(context: TurnContext, _state: TurnState):
    await context.send_activity("Welcome to the agent!")


@AGENT_APP.activity("message")
async def on_message(context: TurnContext, _state: TurnState):
    await context.send_activity(f"You said: {context.activity.text}")


@AGENT_APP.error
async def on_error(context: TurnContext, error: Exception):
    await context.send_activity("The agent encountered an error.")


# Server setup
async def entry_point(req: Request) -> Response:
    agent: AgentApplication = req.app["agent_app"]
    adapter: CloudAdapter = req.app["adapter"]
    return await start_agent_process(req, agent, adapter)


APP = Application(middlewares=[jwt_authorization_middleware])
APP.router.add_post("/api/messages", entry_point)
APP["agent_configuration"] = CONNECTION_MANAGER.get_default_connection_configuration()
APP["agent_app"] = AGENT_APP
APP["adapter"] = AGENT_APP.adapter

if __name__ == "__main__":
    run_app(APP, host="localhost", port=environ.get("PORT", 3978))

AgentApplication Routing

import re
from microsoft_agents.hosting.core import (
    AgentApplication, TurnState, TurnContext, MessageFactory
)
from microsoft_agents.activity import ActivityTypes

AGENT_APP = AgentApplication[TurnState](
    storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config
)

# Welcome handler
@AGENT_APP.conversation_update("membersAdded")
async def on_members_added(context: TurnContext, _state: TurnState):
    await context.send_activity("Welcome!")

# Regex-based message handler
@AGENT_APP.message(re.compile(r"^hello$", re.IGNORECASE))
async def on_hello(context: TurnContext, _state: TurnState):
    await context.send_activity("Hello!")

# Simple string message handler
@AGENT_APP.message("/status")
async def on_status(context: TurnContext, _state: TurnState):
    await context.send_activity("Status: OK")

# Auth-protected message handler
@AGENT_APP.message("/me", auth_handlers=["GRAPH"])
async def on_profile(context: TurnContext, state: TurnState):
    token_response = await AGENT_APP.auth.get_token(context, "GRAPH")
    if token_response and token_response.token:
        # Use token to call Graph API
        await context.send_activity("Profile retrieved")

# Invoke activity handler
@AGENT_APP.activity(ActivityTypes.invoke)
async def on_invoke(context: TurnContext, _state: TurnState):
    invoke_response = Activity(
        type=ActivityTypes.invoke_response, value={"status": 200}
    )
    await context.send_activity(invoke_response)

# Fallback message handler
@AGENT_APP.activity("message")
async def on_message(context: TurnContext, _state: TurnState):
    await context.send_activity(f"Echo: {context.activity.text}")

# Error handler
@AGENT_APP.error
async def on_error(context: TurnContext, error: Exception):
    await context.send_activity("An error occurred.")

Streaming Responses with Azure OpenAI

from openai import AsyncAzureOpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from microsoft_agents.activity import SensitivityUsageInfo

# AAD token provider (preferred over AZURE_OPENAI_API_KEY)
token_provider = get_bearer_token_provider(
    DefaultAzureCredential(),
    "https://cognitiveservices.azure.com/.default",
)

# Module-level singleton: client lives for the agent app lifetime.
CLIENT = AsyncAzureOpenAI(
    api_version=environ["AZURE_OPENAI_API_VERSION"],
    azure_endpoint=environ["AZURE_OPENAI_ENDPOINT"],
    azure_ad_token_provider=token_provider,
)

@AGENT_APP.message("poem")
async def on_poem_message(context: TurnContext, _state: TurnState):
    # Configure streaming response
    context.streaming_response.set_feedback_loop(True)
    context.streaming_response.set_generated_by_ai_label(True)
    context.streaming_response.set_sensitivity_label(
        SensitivityUsageInfo(
            type="https://schema.org/Message",
            schema_type="CreativeWork",
            name="Internal",
        )
    )
    context.streaming_response.queue_informative_update("Starting a poem...\n")

    # Stream from Azure OpenAI
    streamed_response = await CLIENT.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "You are a creative assistant."},
            {"role": "user", "content": "Write a poem about Python."}
        ],
        stream=True,
    )

    try:
        async for chunk in streamed_response:
            if chunk.choices and chunk.choices[0].delta.content:
                context.streaming_response.queue_text_chunk(
                    chunk.choices[0].delta.content
                )
    finally:
        await context.streaming_response.end_stream()

OAuth / Auto Sign-In

@AGENT_APP.message("/logout")
async def logout(context: TurnContext, state: TurnState):
    await AGENT_APP.auth.sign_out(context, "GRAPH")
    await context.send_activity(MessageFactory.text("You have been logged out."))


@AGENT_APP.message("/me", auth_handlers=["GRAPH"])
async def profile_request(context: TurnContext, state: TurnState):
    user_token_response = await AGENT_APP.auth.get_token(context, "GRAPH")
    if user_token_response and user_token_response.token:
        # Use token to call Microsoft Graph
        async with aiohttp.ClientSession() as session:
            headers = {
                "Authorization": f"Bearer {user_token_response.token}",
                "Content-Type": "application/json",
            }
            async with session.get(
                "https://graph.microsoft.com/v1.0/me", headers=headers
            ) as response:
                if response.status == 200:
                    user_info = await response.json()
                    await context.send_activity(f"Hello, {user_info['displayName']}!")

Copilot Studio Client (Direct to Engine)

import asyncio
from msal import PublicClientApplication
from microsoft_agents.activity import ActivityTypes, load_configuration_from_env
from microsoft_agents.copilotstudio.client import (
    ConnectionSettings,
    CopilotClient,
)

# Token cache (local file for interactive flows)
class LocalTokenCache:
    # See samples for full implementation
    pass

def acquire_token(settings, app_client_id, tenant_id):
    pca = PublicClientApplication(
        client_id=app_client_id,
        authority=f"https://login.microsoftonline.com/{tenant_id}",
    )

    token_request = {"scopes": ["https://api.powerplatform.com/.default"]}
    accounts = pca.get_accounts()

    if accounts:
        response = pca.acquire_token_silent(token_request["scopes"], account=accounts[0])
        return response.get("access_token")
    else:
        response = pca.acquire_token_interactive(**token_request)
        return response.get("access_token")


async def main():
    settings = ConnectionSettings(
        environment_id=environ.get("COPILOTSTUDIOAGENT__ENVIRONMENTID"),
        agent_identifier=environ.get("COPILOTSTUDIOAGENT__SCHEMANAME"),
    )

    token = acquire_token(
        settings,
        app_client_id=environ.get("COPILOTSTUDIOAGENT__AGENTAPPID"),
        tenant_id=environ.get("COPILOTSTUDIOAGENT__TENANTID"),
    )

    # CopilotClient does not implement the context manager protocol.
    copilot_client = CopilotClient(settings, token)

    # Start conversation
    act = copilot_client.start_conversation(True)
    async for action in act:
        if action.text:
            print(action.text)

    # Ask question
    replies = copilot_client.ask_question("Hello!", action.conversation.id)
    async for reply in replies:
        if reply.type == ActivityTypes.message:
            print(reply.text)


asyncio.run(main())

Best Practices

  1. This skill is async-first (aiohttp-based). Use async handlers and async with for aiohttp sessions.
  2. Always use context managers for clients and async credentials. Wrap every client in with Client(...) as client: (sync) or async with Client(...) as client: (async). For async DefaultAzureCredential from azure.identity.aio, also use async with credential: so tokens and transports are cleaned up.
  3. Use microsoft_agents import prefix (underscores, not dots).
  4. Use MemoryStorage only for development; use BlobStorage or CosmosDB in production.
  5. Always use load_configuration_from_env(environ) to load SDK configuration.
  6. Include jwt_authorization_middleware in aiohttp Application middlewares.
  7. Use MsalConnectionManager for MSAL-based authentication.
  8. Call end_stream() in finally blocks when using streaming responses.
  9. Use auth_handlers parameter on message decorators for OAuth-protected routes.
  10. Keep secrets in environment variables, not in source code.

Reference Links

ResourceURL
Microsoft 365 Agents SDKhttps://learn.microsoft.com/en-us/microsoft-365/agents-sdk/
GitHub samples (Python)https://github.com/microsoft/Agents-for-python
PyPI packageshttps://pypi.org/search/?q=microsoft-agents
Integrate with Copilot Studiohttps://learn.microsoft.com/en-us/microsoft-365/agents-sdk/integrate-with-mcs

microsoftのその他のスキル

oss-growth
microsoft
OSS成長ハッカーのペルソナ
official
microsoft-foundry
microsoft
Foundryエージェントのエンドツーエンドでのデプロイ、評価、管理:Dockerビルド、ACRプッシュ、ホスト型/プロンプトエージェント作成、コンテナ起動、バッチ評価、継続的評価、プロンプト最適化ワークフロー、agent.yaml、トレースからのデータセットキュレーション。用途:エージェントをFoundryにデプロイ、ホスト型エージェント、エージェント作成、エージェント呼び出し、エージェント評価、バッチ評価実行、継続的評価、継続的モニタリング、継続的評価ステータス、プロンプト最適化、プロンプト改善、プロンプトオプティマイザー、エージェント指示最適化、エージェント改善...
officialdevelopmentdevops
azure-ai
microsoft
Azure AI向けに使用:Search、Speech、OpenAI、Document Intelligence。検索、ベクター/ハイブリッド検索、音声認識、音声合成、文字起こし、OCRを支援。使用時:AI Search、クエリ検索、ベクター検索、ハイブリッド検索、セマンティック検索、音声認識、音声合成、文字起こし、OCR、テキスト読み上げ。
officialdevelopmentapi
azure-deploy
microsoft
既存の.azure/deployment-plan.mdとインフラストラクチャファイルを持つ、すでに準備済みのアプリケーションに対してAzureデプロイを実行します。ユーザーが新しいアプリケーションの作成を依頼した場合はこのスキルを使用せず、代わりにazure-prepareを使用してください。このスキルは、azd up、azd deploy、terraform apply、az deploymentコマンドを組み込みのエラーリカバリ機能付きで実行します。azure-prepareからの.azure/deployment-plan.mdと、azure-validateからの検証済みステータスが必要です。使用タイミング:「azd upを実行」、「azd deployを実行」、「デプロイを実行」...
officialdevopsaws
azure-storage
microsoft
Azure Storage Servicesには、Blob Storage、File Shares、Queue Storage、Table Storage、Data Lakeが含まれます。ストレージアクセス層(ホット、クール、コールド、アーカイブ)について、各層の使用タイミングや比較に関する質問に回答します。オブジェクトストレージ、SMBファイル共有、非同期メッセージング、NoSQLキーバリュー、ビッグデータ分析を提供します。ライフサイクル管理を含みます。使用用途:ブロブストレージ、ファイル共有、キューストレージ、テーブルストレージ、データレイク、ファイルアップロード、ブロブダウンロード、ストレージアカウント、アクセス層、...
officialdevelopmentdatabase
azure-diagnostics
microsoft
Azure上でAppLens、Azure Monitor、リソースヘルス、安全なトリアージを使用して、Azureの本番環境の問題をデバッグします。使用時:本番環境の問題のデバッグ、App Serviceのトラブルシューティング、App Serviceの高CPU、App Serviceのデプロイ障害、コンテナアプリのトラブルシューティング、Functionsのトラブルシューティング、AKSのトラブルシューティング、kubectlが接続できない、kube-system/CoreDNSの障害、PodがPending状態、CrashLoop、ノードがReadyにならない、アップグレード障害、ログの分析、KQL、インサイト、イメージプル障害、コールドスタート問題、ヘルスプローブ障害、...
officialdevopsdevelopment
azure-prepare
microsoft
Azureアプリのデプロイ準備(インフラBicep/Terraform、azure.yaml、Dockerfiles)。新規作成/モダナイズ、または作成+デプロイに使用。クロスクラウド移行には非対応(azure-cloud-migrateを使用)。使用禁止:copilot-sdkアプリ(azure-hosted-copilot-sdkを使用)。対象:「アプリ作成」「Webアプリ構築」「API作成」「サーバーレスHTTP API作成」「フロントエンド作成」「バックエンド作成」「サービス構築」「アプリケーションのモダナイズ」「アプリケーション更新」「認証追加」「キャッシュ追加」「Azureへのホスティング」「作成および...」
officialdevelopmentdevops
azure-validate
microsoft
Azureへの準備が整っているかを確認するためのデプロイ前検証。構成、インフラストラクチャ(BicepまたはTerraform)、RBACロールの割り当て、マネージドIDの権限、前提条件について詳細なチェックを実行します。使用場面:アプリの検証、デプロイ準備状況の確認、事前チェックの実行、構成の確認、デプロイ可能かの確認、azure.yamlの検証、Bicepの検証、デプロイ前のテスト、デプロイエラーのトラブルシューティング、Azure Functionsの検証、関数アプリの検証、サーバーレスの検証...
officialdevopstesting