Microsoft Teams
コミュニケーションツール
Microsoft Teams
概要
Microsoft Teamsは、Microsoft 365統合のコラボレーションプラットフォームです。チャット、ビデオ会議、ファイル共有を統合し、最大250名まで対応の大規模ビデオ会議機能を提供します。Enterprise向け機能が充実し、Power Platform統合による豊富な自動化機能を利用できます。
詳細
Microsoft Teams(マイクロソフト チームズ)は、2017年にリリースされたMicrosoft 365統合のビジネスコラボレーションプラットフォームです。現在、2億5千万人のアクティブユーザーを抱え、Microsoft環境の企業ではSlackを上回る成長率を示しています。企業向けセキュリティ機能とOffice 365統合で差別化を図り、エンタープライズ市場でのシェアを拡大しています。
2024-2025年には、Teams AI library、新しいMeeting AI Insights API、Microsoft 365 Agents Toolkitなど、AI機能の大幅な強化が行われました。アプリマニフェストv1.22の導入、カスタムアクティビティアイコンのサポート、会議インサイトAPI、そしてPower Platform(Power Automate、Power Virtual Agents、Copilot Studio)との深い統合により、ノーコード・ローコードでの開発が大幅に効率化されています。
Teams Bot Frameworkを使用することで、JavaScript、C#、Pythonでの高度なBot開発が可能で、Graph APIを活用したMicrosoft 365全体との統合、Adaptive Cards UIによるリッチなユーザーインターフェースの構築ができます。
メリット・デメリット
メリット
- Microsoft 365完全統合: Office、SharePoint、OneDriveとのシームレス連携
- エンタープライズセキュリティ: 高度な認証・認可、コンプライアンス機能
- 大規模会議対応: 最大250名のビデオ会議、ウェビナー機能
- Power Platform統合: ノーコード・ローコードでの自動化・Bot開発
- 豊富なAPI: Graph API、Bot Framework、Teams API
- AI機能強化: Teams AI library、Meeting AI Insights API
- Azure AD統合: シングルサインオン、条件付きアクセス
- 開発ツール充実: Teams Toolkit(Microsoft 365 Agents Toolkit)
デメリット
- Microsoft依存: Microsoft エコシステムへの強い依存
- 学習コスト: 豊富な機能による複雑性
- ライセンス体系: 複雑な料金・ライセンス構造
- カスタマイズ制限: UI・UXのカスタマイズ制限
- パフォーマンス: 大規模組織での動作重さ
- 競合他社連携: 他社サービスとの統合に制限
主要リンク
- Microsoft Teams公式サイト
- Teams Developer Platform
- Bot Framework Documentation
- Teams AI Library
- Power Platform
- Teams Toolkit
- Microsoft Graph API
書き方の例
Teams AI Libraryを使用したBot開発(JavaScript)
import { Application, TurnState } from '@microsoft/teams-ai';
import { MemoryStorage } from 'botbuilder';
// ストレージとアプリの初期化
const storage = new MemoryStorage();
const app = new Application({
storage,
ai: {
planner: {
model: 'gpt-3.5-turbo',
apiKey: process.env.OPENAI_API_KEY,
}
}
});
// メッセージハンドラー
app.activity('message', async (context, state) => {
const replyText = `Echo: ${context.activity.text}`;
await context.sendActivity(replyText);
});
// AI アクション登録
app.ai.action('createTask', async (context, state, data) => {
const { title, description } = data;
// タスク作成ロジック
state.conversation.tasks = state.conversation.tasks || [];
state.conversation.tasks.push({ title, description, completed: false });
await context.sendActivity(`Task "${title}" created successfully!`);
return true;
});
// アプリの起動
app.start();
Bot Framework(C#)
using Microsoft.Bot.Builder;
using Microsoft.Bot.Framework;
using Microsoft.Teams.AI;
public class TeamsBot : ActivityHandler
{
private readonly ILogger<TeamsBot> _logger;
private readonly IConfiguration _config;
public TeamsBot(ILogger<TeamsBot> logger, IConfiguration config)
{
_logger = logger;
_config = config;
}
protected override async Task OnMessageActivityAsync(
ITurnContext<IMessageActivity> turnContext,
CancellationToken cancellationToken)
{
var replyText = $"Echo: {turnContext.Activity.Text}";
await turnContext.SendActivityAsync(
MessageFactory.Text(replyText),
cancellationToken);
}
protected override async Task OnMembersAddedAsync(
IList<ChannelAccount> membersAdded,
ITurnContext<IConversationUpdateActivity> turnContext,
CancellationToken cancellationToken)
{
var welcomeText = "Welcome to the Teams Bot!";
foreach (var member in membersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
await turnContext.SendActivityAsync(
MessageFactory.Text(welcomeText),
cancellationToken);
}
}
}
}
// Startup.cs での設定
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient().AddControllers().AddNewtonsoftJson();
// Bot Frameworkの設定
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
services.AddTransient<IBot, TeamsBot>();
// Teams AI の設定
services.AddSingleton<IStorage, MemoryStorage>();
}
Adaptive Cards を使用したリッチUI
// Adaptive Card の作成
const adaptiveCard = {
type: 'AdaptiveCard',
version: '1.4',
body: [
{
type: 'TextBlock',
text: 'Task Management',
weight: 'Bolder',
size: 'Medium'
},
{
type: 'Input.Text',
id: 'taskTitle',
placeholder: 'Enter task title'
},
{
type: 'Input.Text',
id: 'taskDescription',
placeholder: 'Enter task description',
isMultiline: true
}
],
actions: [
{
type: 'Action.Submit',
title: 'Create Task',
data: {
action: 'createTask'
}
}
]
};
// Adaptive Card の送信
app.message('create task', async (context, state) => {
const cardAttachment = {
contentType: 'application/vnd.microsoft.card.adaptive',
content: adaptiveCard
};
await context.sendActivity({
attachments: [cardAttachment]
});
});
// Adaptive Card の送信データ処理
app.adaptiveCards.actionSubmit('createTask', async (context, state, data) => {
const { taskTitle, taskDescription } = data;
// タスク作成処理
await context.sendActivity(`Task "${taskTitle}" created: ${taskDescription}`);
});
Microsoft Graph API統合
import { Client } from '@microsoft/microsoft-graph-client';
// Graph クライアントの初期化
const getGraphClient = (accessToken) => {
return Client.init({
authProvider: (done) => {
done(null, accessToken);
}
});
};
// チャンネル一覧取得
app.message('list channels', async (context, state) => {
try {
const token = await getAccessToken(context);
const graphClient = getGraphClient(token);
const teamId = context.activity.channelData.team.id;
const channels = await graphClient
.api(`/teams/${teamId}/channels`)
.get();
const channelList = channels.value
.map(channel => `- ${channel.displayName}`)
.join('\n');
await context.sendActivity(`Channels:\n${channelList}`);
} catch (error) {
await context.sendActivity('Error accessing Graph API');
}
});
// ファイル一覧取得(SharePoint統合)
app.message('list files', async (context, state) => {
try {
const token = await getAccessToken(context);
const graphClient = getGraphClient(token);
const teamId = context.activity.channelData.team.id;
const files = await graphClient
.api(`/groups/${teamId}/drive/root/children`)
.get();
const fileList = files.value
.map(file => `- [${file.name}](${file.webUrl})`)
.join('\n');
await context.sendActivity(`Files:\n${fileList}`);
} catch (error) {
await context.sendActivity('Error accessing files');
}
});
Power Automate 統合
// Power Automate フローのトリガー
app.message('trigger flow', async (context, state) => {
const flowUrl = process.env.POWER_AUTOMATE_FLOW_URL;
const payload = {
userMessage: context.activity.text,
userId: context.activity.from.id,
teamId: context.activity.channelData.team.id,
channelId: context.activity.channelData.channel.id
};
try {
const response = await fetch(flowUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (response.ok) {
const result = await response.json();
await context.sendActivity(`Flow executed: ${result.message}`);
} else {
await context.sendActivity('Failed to trigger flow');
}
} catch (error) {
await context.sendActivity('Error triggering Power Automate flow');
}
});
Meeting AI Insights API の活用(2024新機能)
import { Client } from '@microsoft/microsoft-graph-client';
// 会議インサイトの取得
app.message('meeting insights', async (context, state) => {
try {
const token = await getAccessToken(context);
const graphClient = getGraphClient(token);
// 最新の会議を取得
const meetings = await graphClient
.api('/me/onlineMeetings')
.orderby('creationDateTime desc')
.top(1)
.get();
if (meetings.value.length > 0) {
const meetingId = meetings.value[0].id;
// 会議インサイトを取得
const insights = await graphClient
.api(`/me/onlineMeetings/${meetingId}/insights`)
.get();
const summary = insights.summary || 'No summary available';
const actionItems = insights.actionItems || [];
let message = `**Meeting Summary:**\n${summary}\n\n`;
if (actionItems.length > 0) {
message += '**Action Items:**\n';
actionItems.forEach((item, index) => {
message += `${index + 1}. ${item.description}\n`;
});
}
await context.sendActivity(message);
} else {
await context.sendActivity('No recent meetings found');
}
} catch (error) {
await context.sendActivity('Error retrieving meeting insights');
}
});
Teams Toolkit マニフェスト設定
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.22/MicrosoftTeams.schema.json",
"manifestVersion": "1.22",
"version": "1.0.0",
"id": "${{TEAMS_APP_ID}}",
"developer": {
"name": "Your Company",
"websiteUrl": "https://www.yourcompany.com",
"privacyUrl": "https://www.yourcompany.com/privacy",
"termsOfUseUrl": "https://www.yourcompany.com/terms"
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"name": {
"short": "Teams AI Bot",
"full": "Teams AI Powered Bot"
},
"description": {
"short": "AI-powered Teams bot",
"full": "Advanced Teams bot with AI capabilities"
},
"accentColor": "#FFFFFF",
"bots": [
{
"botId": "${{BOT_ID}}",
"scopes": [
"personal",
"team",
"groupchat"
],
"supportsFiles": false,
"isNotificationOnly": false,
"commandLists": [
{
"scopes": [
"personal",
"team",
"groupchat"
],
"commands": [
{
"title": "Help",
"description": "Show help information"
},
{
"title": "Create Task",
"description": "Create a new task"
}
]
}
]
}
],
"permissions": [
"identity",
"messageTeamMembers"
],
"validDomains": [
"${{BOT_DOMAIN}}"
]
}
環境変数設定
# .env ファイル
# Bot Framework
BOT_ID=your-bot-id
BOT_PASSWORD=your-bot-password
MicrosoftAppId=your-app-id
MicrosoftAppPassword=your-app-password
# Azure OpenAI / OpenAI
AZURE_OPENAI_API_KEY=your-azure-openai-key
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
OPENAI_API_KEY=your-openai-key
# Microsoft Graph
MICROSOFT_APP_ID=your-graph-app-id
MICROSOFT_APP_SECRET=your-graph-app-secret
# Power Automate
POWER_AUTOMATE_FLOW_URL=https://prod-xx.eastus.logic.azure.com/workflows/xxx
# Teams Toolkit
TEAMS_APP_ID=your-teams-app-id
BOT_DOMAIN=your-bot-domain.com
Docker 設定例
FROM node:18-alpine
WORKDIR /app
# 依存関係のインストール
COPY package*.json ./
RUN npm ci --only=production
# アプリケーションのコピー
COPY . .
# 環境変数
ENV NODE_ENV=production
ENV PORT=3978
EXPOSE 3978
# アプリケーション実行
CMD ["npm", "start"]