Important
Microsoft Agent 365 の早期アクセスを利用するには、フロンティア プレビュープログラムに参加する必要があります。 Frontierはマイクロソフトの最新のAIイノベーションと直接つながります。 Frontier のプレビューは、お客様の契約書に記載されている既存のプレビュー利用規約に従います。 これらの機能は現在開発中であるため、提供状況や機能は今後変更される可能性があります。
エージェント 365 SDK を使用すると、エージェントはインストールやアンインストールなどのプラットフォーム アクティビティ イベントを処理し、1 ターン内に複数の個別のメッセージを送信できます。 この記事では、エージェントが要求を処理している間にユーザーに応答し、それらを常に通知するための主要なパターンについて説明します。
エージェントのインストールイベントとアンインストールイベントを処理する
ユーザーが Teams またはその他のエージェント 365 ホストチャネルでエージェントをインストールまたはアンインストールすると、プラットフォームは InstallationUpdate アクティビティ ( agentInstanceCreated イベントとも呼ばれます) を送信します。 エージェントは、これらのイベントを処理して、インストール時にウェルカム メッセージを送信し、アンインストール時に別れのメッセージを送信できます。
| アクション | 説明 |
|---|---|
add |
ユーザーがエージェントをインストールする |
remove |
ユーザーがエージェントをアンインストールする |
通知ハンドラーとは異なり、ユーザーがアクティブなセッションを持つ前または後にインストールまたはアンインストール イベントが発生するため、 InstallationUpdate ハンドラーは認証を必要としません。
インストールおよびアンインストール ハンドラーを登録する
エージェントの初期化で、 InstallationUpdate アクティビティの種類のアクティビティ ハンドラーを登録します。
@agent_app.activity("installationUpdate")
async def on_installation_update(context: TurnContext, state: TurnState):
action = context.activity.action
from_prop = context.activity.from_property
logger.info(
"InstallationUpdate received — Action: '%s', DisplayName: '%s', UserId: '%s'",
action or "(none)",
getattr(from_prop, "name", "(unknown)") if from_prop else "(unknown)",
getattr(from_prop, "id", "(unknown)") if from_prop else "(unknown)",
)
if action == "add":
await context.send_activity("Thank you for hiring me! Looking forward to assisting you in your professional journey!")
elif action == "remove":
await context.send_activity("Thank you for your time, I enjoyed working with you.")
Activity.action は、エージェントのインストール時に "add" するか、アンインストール時に "remove" するように設定された文字列です。
Activity.from_property は、ユーザーの ID を含む ChannelAccount インスタンスです。
複数のメッセージを送信する
エージェント 365 エージェントは、1 つのユーザー プロンプトに応答して複数の個別メッセージを送信できます。 これを行うには、 SendActivityAsync (.NET)、 send_activity (Python)、または sendActivity (JavaScript) を 1 ターン内で複数回呼び出します。
Important
Teams では、エージェント ID のストリーミング応答はサポートされていません。 SDK はエージェント ID を検出し、ストリームを 1 つのメッセージにバッファーします。
SendActivityAsync、send_activity、またはsendActivityを直接使用して、ユーザーに直接個別のメッセージを送信します。
次の例は、LLM 応答の前に即時受信確認を送信することでパターンを示しています。
@agent_app.activity("message")
async def on_message(context: TurnContext, state: TurnState):
# Message 1: immediate ack — reaches the user right away
await context.send_activity("Got it — working on it…")
# ... LLM processing ...
# Message 2: the LLM response
await context.send_activity(response)
このサンプルでは、LLM 応答の前に即時受信確認を送信することで、on_message (host_agent_server.py) でこのパターンを示します。
sendActivity、send_activity、またはSendActivityAsyncを呼び出すたびに、個別のメッセージが作成されます。 進行状況の更新、部分的な結果、または最終的な回答を送信するために必要な回数呼び出すことができます。
入力インジケーター
Teams では、入力インジケーターが ... の進行状況アニメーションとして表示されます。
- 組み込みのビジュアル タイムアウトは約 5 秒で、4 秒ごとにループで更新する必要があります。
- チャネルではなく、1 対 1 のチャットと小さなグループ チャットにのみ表示されます。
エージェントは、LLM が要求を処理している間、 ... アニメーションを維持するために、4 秒ごとにループで入力インジケーターを送信します。
# Message 1: immediate ack — reaches the user right away
await context.send_activity("Got it — working on it…")
# Send typing indicator immediately (awaited so it arrives before the LLM call starts).
await context.send_activity(Activity(type="typing"))
# Background loop refreshes the "..." animation every ~4s (it times out after ~5s).
async def _typing_loop():
try:
while True:
await asyncio.sleep(4)
await context.send_activity(Activity(type="typing"))
except asyncio.CancelledError:
pass # Expected on cancel.
typing_task = asyncio.create_task(_typing_loop())
try:
response = await agent.process_user_message(...)
await context.send_activity(response)
finally:
typing_task.cancel()
try:
await typing_task
except asyncio.CancelledError:
pass