# Microsoft Teams

接入 Microsoft Teams 机器人，让聊天和频道能够启动并继续 Beeuni 会话。

Canonical page: https://beeuni.ai/docs/ja/connect/teams

Microsoft Teams はチャネルです。Teams のチャットやチャネルで `@` にメンションすると
[セッション](/docs/ja/work/sessions)が始まり、エージェントはその場でリアルタイムの
進捗を返信します。[Slack](/docs/ja/connect/slack)と同じセッション、ID、認証情報のルールに従います。
このページでは Teams 固有の内容を説明します。

すべてのプロジェクトで Teams を接続できます。有効にするための機能フラグはありません。

<a id="connect"></a>

## 接続

プロジェクトの **Connectors → Channels** ページから、次のいずれかの方法で接続します。

- **ワンクリック（管理型）。** Teams の**テナント管理者**が **Add to Teams** をクリックし、
  サインインして同意します。Beeuni がアプリを組織の Teams カタログに自動で公開するため、
  ビルドや貼り付けは不要です。その後、行に **Add to Teams**（Teams クライアントへのディープリンク）
  が表示され、誰でもボットをチャットやチャネルに追加できます。Beeuni がアプリの新しいバージョンを
  リリースした場合は、[アプリを更新](#update-the-app)を参照してください。
- **独自のボットを使用。** **Use your own Microsoft Teams app** をクリックして、3 ステップの
  ウィザードを開始します。Azure Bot を登録し、アプリ ID、クライアント シークレット、テナント ID で
  Beeuni に接続してから、生成されたアプリ パッケージをダウンロードし、Teams にアップロードします。
  独自のボット登録を使用する場合はこちらを選んでください。

  手順の順序が重要です。Beeuni は**お客様の**アプリ ID からマニフェストを作成するため、
  パッケージを生成できるのはステップ 2 の後です。ウィザードでは、ほかの情報を求める前に、
  Azure に貼り付けるメッセージング エンドポイントが表示されます。

CLI でもダッシュボードと同じ操作ができます。

```bash
beeuni channels connect --platform teams      # prints the admin-consent URL
beeuni channels status --platform teams        # tenant, catalog, publish state, app version
beeuni channels disconnect --platform teams
```

<a id="update-the-app"></a>

## アプリを更新

Beeuni は Teams アプリに権限を随時追加します。アプリ バージョン 1.1.0 では、
エージェントがチャネルのスレッドを読み取るために必要な `ChannelMessage.Read.Group` が追加されました。
バージョン 1.3.0 では `ChatMessage.Read.Chat` が追加され、グループ チャットの返信で
メンションなしにセッションを継続できるようになりました。1.0.0 のままのチームでは、
すべてのスレッド読み取りが拒否され、エージェントが受け取る拒否メッセージに、誰が修正すべきかが示されます。

アプリを更新するには、次の順で 2 人が操作します。

1. **Teams 管理者が更新を公開します。** 組織のカタログに古いバージョンがある場合、Channels ページに
   **Update the Beeuni app in Teams** が表示され、Teams の行のボタンは **Publish app update** と表示されます。
   管理者がこれをクリックし、Microsoft にサインインします。`beeuni channels status --platform teams` には
   両方のバージョンが表示され、`beeuni channels connect --platform teams` にはサインイン リンクが表示されます。
2. **チーム所有者が、Teams で更新が提示される各チームのアプリを更新します。** Teams でチームを開き、
   **⋯ → Manage team → Apps** の順に進み、Beeuni アプリの **Update** を選択して承認します。
   権限またはメッセージ アクションが追加されない限り、Teams は自動で更新をインストールします。
   それらが追加される場合は、チーム所有者による操作が必要です。

Beeuni は公開のたびにアプリのバージョンを記録します。Beeuni がバージョンを記録する前に公開された
インストールでは、次に公開されるまで通知が表示されます。

<a id="chats-channels-and-mentions"></a>

## チャット、チャネル、メンション

- **個人チャット:** すべてのメッセージがボットに届きます。
- **チーム チャネル / グループ チャット:** 新しい投稿には `@` のメンションが必要です。その後、
  ボットがすでに担当している会話への返信は、Slack のスレッドと同様に、メンションなしで
  セッションを継続します。これにはアプリの `ChannelMessage.Read.Group`（チャネル）および
  `ChatMessage.Read.Chat`（グループ チャット）権限が必要で、アプリの追加時にテナント管理者が同意します。
  これらの権限が要求される前にアプリを追加した場合は、チーム所有者がアプリを更新します。
  [アプリを更新](#update-the-app)を参照してください。

チャットやチャネルの会話ごとに、個別のセッションが作成されます。最初のメッセージでセッションが作成され、
サンドボックスの停止後に再開した場合も、後続のメッセージでセッションが継続します。複数のプロジェクトに
接続されたテナントでは、ルーティングされていない最初のメッセージに**プロジェクト選択画面**が表示され、
選択内容が記憶されます。チャネルでは、ボットにメンションしたメッセージにのみ選択画面が表示されます。
また、`/models` のようにプロジェクトに関するコマンドを送ると、最初にプロジェクトを尋ねられます。

チャネルでは、新しい投稿ごとに独自のセッションが始まります。個人チャットまたはグループ チャットは、
その会話が続く限り 1 つの会話として扱われるため、`/new` を送信するまで
1 つのセッションが継続します。その後にメッセージ（`/new summarize today's deploys`）を送ると、そのメッセージで
新しいセッションが始まります。前のセッションは全履歴とともに Beeuni に残り、確認メッセージから開けます。

<a id="conversation-names"></a>

## 会話名

Teams は `19:…@thread.tacv2;messageid=…` のような ID を送信します。Channels ページと
`beeuni channels bindings` には、Teams でユーザーに表示される名前が表示されます。

| 会話 | 名前 | 名前の下に表示される内容 |
|---|---|---|
| チャネルの投稿 | `Team › Channel` | セッションのタイトル。同じチャネル内の 2 つの投稿を区別できます |
| グループ チャット | チャットのタイトル | グループ チャット |
| 個人チャット | 相手の名前 | 個人チャット |

チャネルのメッセージにはチーム ID が含まれますが、チーム名は含まれません。そのため Beeuni は Teams から
チーム名とチャネル名を取得して保存します。チームの General チャネルへの投稿は、次に Channels ページで
一覧表示されるときに名前が付けられます。ほかのチャネルへの投稿は、次のメッセージが届いたときに名前が付きます。
それまでは **チャネルのスレッド** と表示されます。

<a id="who-may-join-a-session"></a>

## セッションに参加できるユーザー

各会話には参加ポリシーがあり、Teams で `/policy` を使うか、Channels ページで設定します。
Channels ページの Teams 行にある **N channels** には、すべての会話が表示されます。

- **open**（既定）— リンクされたプロジェクト メンバーなら誰でも、この会話で開始したセッションに参加できます。
- **approval** — 新しい参加者ごとに、セッション所有者に承認 / 拒否カードが表示されます。
- **owner** — セッションを開始したユーザーだけが参加できます。

**approval** と **owner** の場合、Beeuni でもセッションはプロジェクト全体には表示されません。
表示されるのは、所有者、承認を受けて参加したユーザー、セッションを管理するアカウント管理者のみです。
レビューまたは承認カードでの決定により、どのポリシーでもエージェントが再開します。

<a id="identity-linking"></a>

## ID のリンク

送信者は `/login` を使って Beeuni アカウントを一度リンクします。その後、エージェントは
そのユーザーとして実行され、本人の認証情報、シークレット、接続済みアプリを使用します。リンクされていない送信者、
またはプロジェクトへのアクセス権がない送信者には、セッションの代わりに、接続またはアクセス申請のカードが表示されます。

サインイン リンクは、自分だけに表示される場所にのみ現れます。ボットとの 1 対 1 のチャット、またはチャネルや
グループ チャットで **自分にのみ表示されるメッセージ** とマークされた返信です。このリンクは発行対象のユーザーと、
リンクを開いたユーザーを結び付けるため、ほかの人に見える場所には表示されません。Teams がこの非公開の返信を拒否した場合、
ボットはリンクをボットとの個人チャットに送り、その旨を会話内で知らせます。この方法が使えるのは、自分用にアプリを
追加している場合のみです。そうでない場合、カードの案内に従ってボットとの個人チャットを開き、そこで `/login` を
送信してください。リンク前にチャネルで送信したメッセージは、10 分以内に接続すれば実行されます。ブラウザーで接続を
完了すると、ボットとの個人チャットで、どの Beeuni アカウントとしてリンクされたかが確認できます。

サインイン リンクは 1 回だけ使え、10 分後に有効期限が切れます。Teams アカウントは、1 つの Beeuni アカウントに
接続すると、別のアカウントには接続できません。まず `/logout` を送信してください。組織で 2 要素認証が
必須の場合、Beeuni は接続前に 2 つ目の要素を求めます。チャットは、その要素を使って接続したアカウントとして実行されます。
2 つ目の要素なしで作成されたリンクでは、再接続を求められます。

アクセス権のない人がアクセスを求めると、すべてのアカウント所有者と管理者にBeeuniでリクエストが届きます。Teamsをリンクしている人には、ボットとのプライベートチャットにも、**Beeuniで確認**ボタン付きで届きます。

<a id="private-replies"></a>

## プライベート返信

チャンネルまたはグループチャットで、ボットが1人に伝える内容は、その人だけに表示され、Slackのエフェメラルメッセージと同様に**このメッセージはあなただけに表示されています**と示されます。

- コマンドへの返信
- アカウントの接続またはアクセスのリクエスト用カード
- メッセージが実行されなかった理由：参加ポリシー、または使用できないエージェント
- **承認**中の、所有者による承認／拒否カードと、リクエストした人への決定通知

全員に表示される**処理中…**カードは、メッセージを実行できる可能性がある場合にのみ表示されます。Teamsでは、プライベート返信は24時間後に削除されます。Teamsがプライベート返信を拒否した場合、ボットは代わりに会話全体へカードを投稿します。サインインリンクだけは例外で、その場合は会話ではなく、ボットとのプライベートチャットに送られます。

<a id="roles-and-permissions"></a>

## 役割と権限

チャット自体にはBeeuniの認証情報がないため、すべての操作は、その操作を行った人のリンク済みBeeuniアカウントと、そのアカウントのプロジェクトロールで実行されます。アカウント所有者と管理者はプロジェクトマネージャーとして扱われます。

| 操作 | 実行できる人 |
| --- | --- |
| エージェントが回答するメッセージを送信する | プロジェクトへのアクセス権を持つリンク済みアカウントで、会話の参加ポリシーの範囲内にいる人 |
| 実行を停止する | 回答対象のメッセージを送信した人、またはそのセッションへの参加を承認され、引き続きプロジェクトを使用できる人 |
| グループチャットで`/new` | リンク済みのプロジェクトメンバー；`approval`または`owner`の下では、現在のセッションへの参加を承認された人 |
| プロジェクト、エージェント、モデル、またはポリシーを変更する | プロジェクトマネージャー；ボットとの個人チャットでは、任意のプロジェクトメンバー |
| レビューを承認または拒否する | プロジェクトマネージャー |
| コネクタ呼び出しを承認または拒否する | プロジェクトマネージャー、またはセッションを開始した人 |
| `approval`セッションへの参加を承認する | セッション所有者 |
| アクセスをリクエストする | リンク済みのすべての人；各アカウント所有者と管理者には1回通知されます |

エージェントの対象外に設定されている人は、Beeuniと同様に、Teamsからそのエージェントでセッションを開始できません。

<a id="commands"></a>

## コマンド

これらはボットとのチャットで入力します（チャンネルでは、最初に`@`-メンションします）。

| コマンド | 機能 |
| --- | --- |
| `/help` | コマンドを一覧表示する |
| `/login`、`/logout`、`/whoami` | Beeuniアカウントをリンク、リンク解除、または表示する |
| `/status` | ここで有効なプロジェクト、エージェント、モデル、および進行中の実行を表示する |
| `/stop` | ここで進行中の実行を停止する |
| `/new [message]` | このチャットで新しいセッションを開始する（個人チャットとグループチャット） |
| `/models`、`/model <ref>` | この会話のモデルを選択する — [モデルとキー](#models-and-keys) を参照 |
| `/agents`、`/agent <name>` | この会話のエージェントを選択する |
| `/projects`、`/use <name>` | 接続済みプロジェクトを一覧表示する、またはこのチャットを別のプロジェクトに接続する（プロジェクト自身のボットでは不可） |
| `/policy [open\|approval\|owner]` | ここで開始されたセッションに参加できる人を表示する |
| `/unbind` | この会話とプロジェクトの接続を解除する；次のメッセージで再びプロジェクトを選択する |
| `/home` | 組織のプロジェクトと試すべきことを表示する |

任意のメッセージで、**⋯ → Beeuniで開く**を選択すると、その会話が属するセッションが開きます。自分用にアプリを追加すると、ボットとのプライベートチャットは`/home`と同じ概要で始まります。

<a id="models-and-keys"></a>

## モデルとキー

`/models`には、ここで実行できるすべてのモデルが、Webの選択画面と同じように一覧表示されます。Beeuniのモデルと、プロバイダーAPIキーまたはChatGPTサブスクリプションを通じて利用するモデルです。それぞれの支払い方法も表示されます。長いリストは検索可能なドロップダウンになります。モデルをタップするか、`/model <id>`と入力します。`/model default`でプロジェクトのデフォルトに戻ります。

利用できるキーはチャットによって異なります。

- **ボットとの個人チャット** — 自分のキーとChatGPTサブスクリプションに加え、プロジェクトと共有されているキー。セッションは自分だけに公開されます。
- **グループチャットまたはチャンネル** — プロジェクト全体で共有されているキーのみ。チャットは共有されるため、個人キーを使うと、その中の全員が1人のサブスクリプションを使用できてしまいます。そのようなモデルは、代わりに個人チャットで選択してください。

キーで実行するモデルは、そのプロバイダーで自分が使用できるすべてのキーを使い、レート制限時にはキーを切り替えます。選択は次のメッセージに適用され、チャットのセッションは維持されます。実行中のセッションのモデルを変更するにはリンク済みアカウントが必要です。また、`owner`または`approval`ポリシーの下では、セッション所有者だけが変更できます。そこでセッションが非公開になる前に開始された個人チャットのセッションは、引き続きプロジェクトと共有されます。`/model`にその旨が記載されており、`/new`で非公開のセッションが開始されます。[プロバイダーキーとメンバーアクセス](/docs/ja/project/models#provider-keys-and-member-access) を参照してください。

<a id="while-the-agent-works"></a>

## エージェントの処理中

エージェントは1つのカードで回答します。処理中の手順が表示され、その後に返信が表示されます。長い返信は行の途中で切り取られ、切り取られたことが示され、Beeuniの完全なセッションへのリンクが表示されます。別のメッセージは現在の実行を待機し、その後、自分専用のカードを受け取ります。静かなステップでは実行は終了せず、ランタイムが完了した場合にのみ終了します。

<a id="stopping-a-run"></a>

## 実行の停止

エージェントの処理中は、ライブカードに**停止**ボタンが表示されます。カードが画面外にスクロールされた後も、`/stop`で同じ操作を行えます。どちらの場合も、カード上だけでなくランタイムで実行を終了します。開いたままの実行があると、会話内の次のメッセージを回答せずに取り込んでしまいます。

回答対象のメッセージを送信した人は実行を停止できます。また、そのセッションへの参加を承認され、引き続きプロジェクトを使用できる人も停止できます。チャンネル内の傍観者は停止できず、チャットの以前のセッションへの参加を承認された人も停止できません。

<a id="files"></a>

## ファイル

エージェントは`teams send --file`でファイルを送信します。画像は個人チャット、グループチャット、チャンネルチャットでインライン表示されます。サイズが大きすぎる画像は、個人チャットではOneDriveの同意カードに、チャンネルではチームファイルに切り替わります。グループチャットではサイズが大きすぎる転送を受信できません。その他のファイルは、個人チャットでは同意カードとして、チームに共有された場合はSharePointリンクとして届きます。受信ファイルと貼り付けられた画像（チャンネルメッセージ本文に埋め込まれた画像を含む）は、エージェントがダウンロードして処理できます。

- チャンネルまたはグループチャットに貼り付けられた画像は、[チャンネルの読み取り](#reading-a-channel)に記載されたルールに従い、エージェントがそのスレッドまたはチャットを読める場合にのみダウンロードされます。それ以外の場合、`teams download`が`403`に回答します。
- ダウンロードは50 MBで停止し、`413`に回答します。
- `teams history`と`teams thread`には、投稿のインライン画像（`images`。それぞれ`teams download`用のURL）と、SharePointから共有されたファイルの名前（`files`）が一覧表示されます。エージェントはSharePointファイルをダウンロードできません。

スクリーンショットを貼り付けて質問すると、会話自体のモデルがテキスト専用であっても、画像を読み取れるモデルでターンが実行されます。セッションのモデル選択はそのまま維持されます。セッションで実行できなくなったモデル（キーが取り消された場合や、チャットで使用できないChatGPTサブスクリプションなど）は、失敗させずに、同じ方法でそのメッセージだけ別のモデルに置き換えられます。

<a id="questions-and-forms"></a>

## 質問とフォーム

エージェントは文章ではなく、選択肢付きで質問します。質問が1つで、選択肢が6つ以下なら、選択肢ごとにボタンが1つ表示されます。質問が複数ある場合、複数選択の質問、または選択肢が多い場合は、自由回答欄付きのフォームが表示されます。日付、時刻、数値、オン／オフの選択には、それぞれに合った入力欄が使われます。回答は、どの質問への回答かを示すラベルとともに、次のメッセージとしてエージェントに届きます。いつでも回答を直接入力できます。

<a id="approvals"></a>

## 承認

リスクの高い手順や、承認が必要な変更など、エージェントが先に人の判断を必要とする場合、エージェントはレビュー項目を作成します。この会話からセッションを開始した場合、判断を求めるカードがここに表示されます。カードにはタイトル、概要、リスクレベル、**承認**、**変更をリクエスト**、**却下**の各ボタンと、Beeuniへのリンクが含まれます。

カードには任意のフィードバック欄があります。入力した内容は判断とともに保存され、エージェントにも渡されるため、「変更をリクエスト」した後に意図を確認するためのやり取りを追加する必要はありません。フィードバック欄は任意です。通常の承認に入力は必要ありません。

会話に参加している全員にカードが表示されますが、操作するにはプロジェクトへのアクセス権がある、リンク済みのBeeuniアカウントが必要です。

<a id="posting-on-its-own"></a>

## 単独での投稿

エージェントは、質問への返信に加え、このプロジェクトでボットがすでに参加しているチャットやチャネルに投稿できます。夜間の要約、アラート、引き継ぎなどを投稿できます。追加されたことのない会話にはアクセスできません。

<a id="when-a-session-will-not-start"></a>

## セッションを開始できない場合

再試行しても解決しない開始時の失敗がほとんどであるため、Beeuniは再試行を促すのではなく、原因を示します。たとえば、存在しなくなったサンドボックステンプレート、リンクされていないアカウント、アクセスできないプロジェクト、クレジット切れのワークスペースなどです。原因ごとに、解決方法と、それに適用するコマンドが示されます。

会話に設定されているエージェントが削除または名前変更されている場合は、エージェント選択画面が表示されます。利用可能なエージェントを選び、メッセージをもう一度送信してください。リストには、アクセス権のあるエージェントだけが表示されます。

<a id="reading-a-channel"></a>

## チャネルの読み取り

チャネルでは、ボットが受信するのは自分宛てのメンションがあるメッセージだけなので、質問された内容の会話はセッションに含まれていません。文脈が必要な場合、エージェントは、チームへのアプリ追加時にアプリが要求する`ChannelMessage.Read.Group`権限を使って、メンションされたスレッドまたはチャネルの最近の投稿を読み取ります。この権限が要求される前にアプリを追加したチームでは、アプリを更新する必要があります。[アプリを更新する](#update-the-app)を参照してください。個人チャットでは、すべてのメッセージがすでにセッションに届いているため、それ以前のメッセージを読み取る必要はありません。

同じMicrosoft 365テナントに接続された各プロジェクトでは、同じアプリが使われるため、Beeuniは各プロジェクト内の会話だけを読み取ります。チャネルでは、新しい投稿はそれぞれ個別の会話として扱われます。

| 読み取る内容 | 許可される条件 |
| --- | --- |
| スレッド（`teams thread`） | スレッドがこのプロジェクトの会話であるか、どのプロジェクトにも属さず、かつチャネルを読み取れる |
| チャネルの最近の投稿（`teams history`） | このプロジェクトがそのチャネルで会話をしている。他のプロジェクトの会話を開始する投稿は除外される |
| どのプロジェクトも会話していないチャネル | このテナントに他のプロジェクトが接続されていない |

読み取りが拒否されると、`403`は理由`conversation_not_in_project`と、チャネル名またはスレッド名を示すメッセージを返します。複数のプロジェクトがあるテナントで、最初の種類のチャネルを読み取るには、そのチャネルでボットにメンションし、このプロジェクトを選択してください。

`get_channel`と`list_channels`は標準チャネルを対象とします。プライベートチャネルまたは共有チャネルは、上記のルールに従ってエージェントが読み取れる場合にのみ表示されます。`get_team`、`list_members`、`get_user`、`list_teams`はテナントのディレクトリを読み取るため、制限はありません。

<a id="limits"></a>

## 制限

Teamsボットではメッセージへのリアクションの追加やメッセージ検索はできません。Slackにあるこれらの機能に相当するものは、Teamsにはありません。エージェントがチャネルを読み取れるのは、アプリが追加されているチーム内に限られます。また、[チャネルの読み取り](#reading-a-channel)に記載されたルールに従います。
