【2026年版・コード全文】Claude Code × Microsoft Teams で会議トランスクリプトから議事録 + アクションを自動生成する完全手順(Microsoft Graph + Planner連携)

この記事をシェア:
目次 クリックで開く

「会議は終わった。でも議事録を書く30分が始まる」——会議疲れの上にもう一仕事、というのが現場の実態です。本記事では Claude Code × Microsoft Teams(transcript) × Microsoft Planner を組み合わせ、会議終了直後にAIが議事録 + アクションアイテム + 担当者割当を一気に生成する仕組みをコード付きで解説します。

この記事のゴール:Teams会議のtranscript.vttを入力に、python build_teams_minutes.py 一発で「概要 / 決定事項 / アクション(担当・期日付き) / リスク」のmarkdown議事録を生成 → Plannerにタスクが自動登録される、再現可能なパイプラインを理解する。
目次

  1. 議事録に時間を取られる本当の理由
  2. 完成イメージ(会議トランスクリプト → 議事録)
  3. 処理フロー:Teams transcript → Claude → Planner
  4. 議事録プロンプトの組み立て方
  5. 完成スクリプト全文
  6. 運用パターン:会議直後配信・Planner自動登録・週次サマリ
  7. セキュリティと監査
  8. FAQ

1. 議事録に時間を取られる本当の理由

  • 「誰が何をやるか」を聞き分けて構造化するのは、人間の認知負荷が高い
  • 会議が連続していると、議事録は翌日以降にずれ、記憶が薄れて精度が落ちる
  • 担当者割当が口頭ベースだと、後日「言った/言わない」問題が発生する

これらは全てLLMが圧倒的に得意な領域。会議終了直後の3分以内に「決定事項 + 担当 + 期日 + リスク」が文字で残ると、組織の意思決定品質が一段上がります。

2. 完成イメージ

Microsoft Teams会議の発言ログから、Claude Codeが議事録・決定事項・アクションアイテムを自動生成しているプレビュー
左:Teams会議のtranscript(発言者・時刻・本文)/右:自動生成された議事録(概要 / 決定事項 / アクションアイテム / リスク)。アクションは Microsoft Planner に自動登録される。

3. 処理フロー

ステップ 処理 API/ツール
1 Teams会議終了をWebhookで検知 Microsoft Graph (subscriptions)
2 transcript.vttをダウンロード Microsoft Graph onlineMeetings/transcripts
3 発言者ごとの構造化(speaker, time, text) webvtt-py
4 Claude API で要約・決定・アクション・リスクに構造化 Anthropic SDK
5 Planner にタスク自動登録(owner / due / title) Microsoft Graph planner/tasks
6 関係者にmarkdown議事録メール送信 Microsoft Graph sendMail

4. 議事録プロンプトの組み立て方

NG:「議事録を書いて」だけだと、要約と決定事項が混ざった散文になりがち。
OK: JSON Schema(concept・decisions・action_items[owner/task/due]・risks)で出力フォーマットを縛る。Claude は構造化出力指示への追従性が高く、後段のPlanner登録ロジックが安定します。

本記事のサンプル claude_structure は決定論スタブですが、出力JSON形状は実運用と一致しています。

5. 完成スクリプト全文

"""Teams × Claude Code: 会議トランスクリプト → 議事録 + アクションアイテム自動生成。

In production:
  - Microsoft Graph API で Teams 会議の transcript.vtt を取得
  - Claude API に投げて構造化(要約・決定事項・アクション)
  - Outlook で関係者に議事録メール送信 + Plannerにタスク登録

Demo:
  - サンプルtranscript.json を入力に
  - 決定論スタブで Claude の出力を再現
  - minutes.json + minutes.md を出力
"""
from pathlib import Path
import json

ROOT = Path(__file__).parent
TRANSCRIPT = ROOT / "transcript.json"
MINUTES_JSON = ROOT / "minutes.json"
MINUTES_MD = ROOT / "minutes.md"

transcript = [
    {"t": "10:01", "spk": "佐藤(PM)", "text": "今日はQ2のSalesforce導入プロジェクトのキックオフです。スコープと期日を整理しましょう。"},
    {"t": "10:02", "spk": "田中(IT)", "text": "対象モジュールはSales Cloud + Service Cloud。Marketing Cloudは今期はスコープ外でいいですか?"},
    {"t": "10:03", "spk": "佐藤(PM)", "text": "はい、それでOKです。Marketing CloudはQ3以降に切り出します。"},
    {"t": "10:05", "spk": "鈴木(営業)", "text": "本番リリースは6月末の希望です。半期決算前に営業現場での運用を始めたい。"},
    {"t": "10:06", "spk": "田中(IT)", "text": "6月末は厳しいです。データ移行に最低3週間、UAT2週間、合計5週間は必要。逆算すると要件凍結を5/15までに完了させたい。"},
    {"t": "10:08", "spk": "佐藤(PM)", "text": "では5/15要件凍結、6/30本番、7/1から運用開始としましょう。データ移行の対象は田中さん側で精緻化お願いします。来週月曜までに第一版。"},
    {"t": "10:10", "spk": "山田(財務)", "text": "ライセンス費用は確定していますか?年間¥4,800,000の前提で予算組みしています。"},
    {"t": "10:11", "spk": "田中(IT)", "text": "Sales Cloud Enterprise 30名 + Service Cloud Enterprise 10名で年間¥5,200,000。¥400k超過。"},
    {"t": "10:12", "spk": "山田(財務)", "text": "予算超過は稟議が必要。鈴木さん、どの程度の追加価値があるか整理して稟議書ドラフトを来週中に。"},
    {"t": "10:14", "spk": "鈴木(営業)", "text": "了解。営業マネージャー10名分はサービスクラウド必須。¥400k超過は受注見込みベースで余裕で回収できる試算を添付します。"},
    {"t": "10:16", "spk": "佐藤(PM)", "text": "セキュリティレビューは情シス主導で5月中旬。中島さんに連携します。"},
    {"t": "10:18", "spk": "佐藤(PM)", "text": "次回ミーティングは5/9(金)10時、要件凍結ドラフトレビュー。以上で終了します。"},
]

TRANSCRIPT.write_text(json.dumps(transcript, ensure_ascii=False, indent=2), encoding="utf-8")


def claude_structure(transcript):
    """Stand-in for Claude API. Production: prompt → structured minutes."""
    return {
        "title": "Q2 Salesforce導入プロジェクト キックオフ",
        "date": "2026-05-02 10:00-10:20",
        "attendees": ["佐藤(PM)", "田中(IT)", "鈴木(営業)", "山田(財務)"],
        "summary": "Q2のSalesforce導入プロジェクトのスコープ・期日・予算について合意。Sales Cloud + Service Cloudを対象に、5/15要件凍結 / 6/30本番 / 7/1運用開始のスケジュールを決定。ライセンス費用が予算超過¥400kとなるため稟議手配が必要。",
        "decisions": [
            "対象モジュールはSales Cloud + Service Cloudのみ。Marketing CloudはQ3以降に切り出し",
            "5/15要件凍結 / 6/30本番リリース / 7/1運用開始",
            "ライセンス費用 年間¥5,200,000(予算¥4,800,000から¥400k超過、稟議要)",
            "セキュリティレビューは情シス主導で5月中旬",
            "次回 5/9(金) 10:00 要件凍結ドラフトレビュー",
        ],
        "action_items": [
            {"owner": "田中(IT)", "task": "データ移行対象の精緻化(第一版)", "due": "2026-05-05"},
            {"owner": "鈴木(営業)", "task": "ライセンス予算超過の稟議書ドラフト + ROI試算", "due": "2026-05-09"},
            {"owner": "佐藤(PM)", "task": "情シス中島氏へセキュリティレビュー依頼連携", "due": "2026-05-06"},
            {"owner": "佐藤(PM)", "task": "次回ミーティング 5/9 10:00 設定 + 要件凍結ドラフト共有", "due": "2026-05-08"},
        ],
        "risks": [
            "予算超過¥400kの稟議承認遅延 → プロジェクト全体のスケジュール後退リスク",
            "データ移行3週間の見積もりは保守的、実データ次第で延伸の可能性",
        ],
    }


minutes = claude_structure(transcript)
MINUTES_JSON.write_text(json.dumps(minutes, ensure_ascii=False, indent=2), encoding="utf-8")

# Markdown report
md = []
md.append(f"# {minutes['title']}\n")
md.append(f"**開催**: {minutes['date']}  ")
md.append(f"**出席**: {', '.join(minutes['attendees'])}\n")
md.append("## 概要\n" + minutes["summary"] + "\n")
md.append("## 決定事項")
for d in minutes["decisions"]: md.append(f"- {d}")
md.append("\n## アクションアイテム\n")
md.append("| 担当 | タスク | 期日 |")
md.append("|---|---|---|")
for a in minutes["action_items"]:
    md.append(f"| {a['owner']} | {a['task']} | {a['due']} |")
md.append("\n## リスク・注意点")
for r in minutes["risks"]: md.append(f"- {r}")

MINUTES_MD.write_text("\n".join(md), encoding="utf-8")
print(f"[save] {MINUTES_JSON.name} ({MINUTES_JSON.stat().st_size:,} bytes)")
print(f"[save] {MINUTES_MD.name} ({MINUTES_MD.stat().st_size:,} bytes)")
print(f"[stats] decisions={len(minutes['decisions'])}, actions={len(minutes['action_items'])}, risks={len(minutes['risks'])}")

6. 運用パターン

6-1. 会議終了直後の自動配信

Teams Webhook で「meeting.ended」イベントを受け取ったら、5分待ってからtranscript取得(処理時間考慮)→ Claude → Planner → 関係者メール。出席者が席に戻る前に議事録が届きます。

6-2. Planner 自動タスク登録

各 action_item の owner(社内ID解決済み)に対し Planner タスクを作成。due は ISO日付で渡せばカレンダー連携も自動で揃います。

6-3. 週次サマリ(重要決定の横断ビュー)

同じパイプラインで生成された議事録JSONを週次で集約し、「今週の主要決定10件」「期日超過アクション」「リスクトピック」のダッシュボードを Slack / Teams に投稿。経営層が一目で把握できます。

7. セキュリティと監査

  • transcript はテナント内に保管。Claude API送信時は 会議メタデータ(タイトル、出席者)と発言テキストのみを送り、社員ID等は送らない
  • Microsoft Graph のスコープは OnlineMeetings.Read.All + Tasks.ReadWrite のみ
  • 議事録 JSON は会議ID + 生成日時で監査ログ化(GDPR/個人情報保護法対応)
  • 機密会議(マイク前にラベル)は処理をスキップする条件分岐を入れる

8. FAQ

Q1. Microsoft Copilot for Teams で議事録は出せるのでは?

A. Copilotは「会議要約」が標準で出ます。本記事のような「決定事項とアクションを構造化して、Plannerに自動登録する」ところまで踏み込むと、Copilot単体では難しく、本記事のClaude Code連携が現実的です。Copilotとの併用も可能です。

Q2. transcript精度が低い場合は?

A. Teams transcript は固有名詞や数字に弱い場合があります。「人名・金額・日付」を Claude プロンプトで「不確実な箇所には【要確認】を付ける」と明示することで、誤った議事録の確定を防げます。

Q3. オンプレ環境でTeamsを使っている場合は?

A. transcript取得が難しいケースもあります。代替策として「会議録音 → faster-whisper でローカル文字起こし → Claudeへ投入」のパイプラインで対応可能です。

Q4. アクションアイテムの「担当者解決」はどう?

A. 社内ディレクトリ(Microsoft Graph users)からよく使う氏名→IDマップをキャッシュし、Claude出力の「鈴木(営業)」を該当社員IDに変換してPlannerに渡します。同姓同名がいる場合は「部署+氏名」で一意化します。

Q5. 機密会議の扱いは?

A. 会議タイトルに「【機密】」プレフィックス、または特定タグが付いた会議はパイプライン側で処理スキップ。Claude API への外部送信を避けたい場合は、ローカルLLM(llama.cpp + Mixtral等)に claude_structure() を差し替えればオンプレ完結も可能です。

9. 上位記事との差別化:Teams議事録自動化のディテール

9-1. transcript取得APIの権限スコープ

API 必要スコープ(Application) 用途
onlineMeetings/getAllTranscripts OnlineMeetingTranscript.Read.All 会議のtranscript一覧取得
transcripts/{id}/content 同上 VTT本体ダウンロード
planner/tasks Tasks.ReadWrite.All アクション登録
users/{id}/sendMail Mail.Send 議事録メール配信
OnlineMeetingTranscript.Read.All は管理者同意が必須。IT部門に「議事録自動化用 Entra ID アプリ登録」を依頼してください。

9-2. VTTパース + 話者分離の扱い

import webvtt
segments = []
for cue in webvtt.read("transcript.vtt"):
    # <v 田中 太郎> 発言内容 形式
    m = re.match(r"<v ([^>]+)>(.+)", cue.text)
    speaker, text = (m.group(1), m.group(2)) if m else ("不明", cue.text)
    segments.append({"start": cue.start, "speaker": speaker, "text": text.strip()})

連続する同一話者の発言は itertools.groupby で結合すると、Claude に渡すトークン量が30〜40%削減できます。

9-3. Microsoft Copilot for Teams との機能比較

Copilot for Teams 本記事の自作パイプライン
会議要約 ○ 標準機能
決定事項の構造化(JSON) △ 散文要約のみ ○ Schema固定
Plannerタスク自動登録 ×(手動コピペ)
Slack/外部システム連携 ×
カスタムプロンプト 限定的 ○ 自由
ライセンス費 $30/user/月 Claude API 従量課金(会議1本¥10〜30)

9-4. Plannerタスク作成の必須フィールド

POST /planner/tasks
{
  "planId": "...",          # 必須
  "bucketId": "...",        # 必須(議事録専用バケット推奨)
  "title": "ライセンス予算稟議書ドラフト",
  "assignments": {"<userId>": {"@odata.type": "...taskAssignment", "orderHint": " !"}},
  "dueDateTime": "2026-05-09T09:00:00Z",
  "priority": 5
}

9-5. 決定事項・課題・ToDo を分離するプロンプト設計

Claude には JSON Schema を強く指定して、decisions / action_items / open_questions / risks の4つに必ず分類させます。曖昧な発言は open_questions に振り分けることで、後日の論点漏れを防げます。

関連記事(クラスター)

本記事は「AI業務自動化完全ガイド」のクラスター記事です。Excel・PowerPoint・Outlook・Teams 各領域の Claude Code 実装サンプルを上記ガイドからまとめて参照できます。

AI・業務自動化

ChatGPT・Claude APIを活用したAIエージェント開発、n8n・Difyによるワークフロー自動化で繰り返し業務を削減します。まずはどの業務をAI化できるか診断します。

AT
aurant technologies 編集

上場企業からスタートアップまで、数多くのデータ分析基盤構築・AI導入プロジェクトを主導。単なる技術提供にとどまらず、MA/CRM(Salesforce, Hubspot, kintone, LINE)導入によるマーケティング最適化やバックオフィス業務の自動化など、常に「事業数値(売上・利益)」に直結する改善実績多数。

この記事が役に立ったらシェア: