brain/03 Bereiche/IT-Management/Meeting Auto-Import via MS ...

7.0 KiB

tags status date
it-management
integration
teams
graph
aktiv 2026-05-06

Meeting Auto-Import via MS Graph

Was ist das?

Erweiterung von Obsidian O365 Kalender Integration: Nach Ende eines Jour-Fixe-Meetings zieht der Befehl /meeting-end automatisch Transkript und Copilot-Recap aus Teams via Microsoft Graph, mergt sie mit den live mitgeschriebenen Notizen und führt die Ergebnisse in die Agenda zurück (Historie, Archiv, Postponed).

Workflow

  1. Meeting läuft in Teams (mit aktivem Facilitator → Aufzeichnung + Copilot-Recap)
  2. Nach Meeting: /meeting-end in der Meeting-Notiz
  3. Script fetch-meeting-artifacts.js ruft Graph API:
    • getEventById → Event mit seriesMasterId + JoinUrl
    • resolveOnlineMeeting → Teams-OnlineMeeting via JoinUrl
    • fetchTranscriptVtt → letztes Transkript (.vtt)
    • fetchAiInsights (Beta) → Copilot-Recap (Topics, Decisions, Action Items)
    • fetchRecordingUrl → Recording-Link
  4. Claude führt Doppel-Pass-Synthese aus: Recap + Transkript validiert
  5. Sprecher-Mapping: Speaker-Namen → Personen-Wikilinks via 00 Kontext/Personen/
  6. Merge mit Live-Notizen (Live-Order bleibt, neue Items hinten)
  7. Agenda-Rückführung mit Konfidenz-Heuristik:
    • Topic abgeschlossen → Archiv (mit Historie)
    • Topic postponed → ## ⏸️ Postponed
    • Topic offen → datierter Historie-Eintrag in Agenda
    • Mehrdeutig → User-Bestätigung pro Topic
  8. recording_url ins Frontmatter, status: abgeschlossen

Komponenten

Scripts (scripts/):

  • fetch-meeting-artifacts.js — CLI-Orchestrator (--o365-id <id> --out <file>)
  • lib/graph-meetings.js — Graph-Helper für OnlineMeetings/Transcripts/aiInsights/Recordings
  • lib/vtt-parser.js — VTT-Parser mit <v Speaker>-Tags, optional Cue-Merge
  • lib/speaker-matcher.js — Speaker-Name → Person-Wikilink (wraps person-matcher.js)
  • lib/o365-calendar.js — erweitert um getEventById + extractJoinUrlFromBody
  • backfill-series-id.js — One-Shot: schreibt o365_series_id ins Agenda-Frontmatter

Commands (.claude/commands/):

  • meeting-end.md — komplett neu: Auto-Import-Flow mit Konfidenz-Klassifikation
  • meeting.md — erweitert um Lazy-Backfill von o365_series_id

Frontmatter-Erweiterungen:

  • Agenda: o365_series_id: <seriesMasterId> (verbindet Agenda fest mit Outlook-Serie)
  • Meeting-Notiz: recording_url: <url> (gesetzt wenn Recording vorhanden)

Backfill-Status

Serie O365-Titel o365_series_id
IT Team "diverse IT-Themen" gesetzt
LANdata "Status Meeting KRAH / LANdata" gesetzt
Andere Lazy-Backfill beim ersten /meeting <Serie>

Azure-Setup

App Registration: OfficeAssist (93f9f15c-b566-4ca1-9145-c23f87c7f5c7) Authentication: OAuth2 Client Credentials Flow (@azure/msal-node)

Ergänzt am 2026-05-06:

  • OnlineMeetings.Read.All — OnlineMeeting per JoinUrl auflösen
  • OnlineMeetingTranscript.Read.All.vtt lesen
  • OnlineMeetingRecording.Read.All — Recording-URL lesen (frühere Bezeichnung OnlineMeetingArtifact.Read.All wurde von Microsoft umbenannt; alter Name funktioniert nicht mehr)
  • OnlineMeetingAiInsight.Read.All — Copilot-Recap (Beta-Endpoint)

Bereits vorhanden: Calendars.Read, User.Read.All, plus Mail/Sites.

Application Access Policy (Teams PowerShell)

Wichtig: Ohne diese Policy → 404 trotz korrekter Permissions. Microsoft-spezifisches Gate für Service-Apps gegen OnlineMeetings. In Teams Admin Center UI nicht sichtbar — nur PowerShell.

Erstellt am 2026-05-06:

Connect-MicrosoftTeams

New-CsApplicationAccessPolicy -Identity "obsidian-graph" `
  -AppIds "93f9f15c-b566-4ca1-9145-c23f87c7f5c7" `
  -Description "OfficeAssist meeting auto-import"

Grant-CsApplicationAccessPolicy -PolicyName "obsidian-graph" `
  -Identity "c.kauer@krah-gruppe.de"

Verifizierung:

Get-CsApplicationAccessPolicy -Identity "obsidian-graph"
# erwartet: AppIds enthält 93f9f15c-...

Replikationszeit nach Grant: typisch 30-60 Min, manchmal mehrere Stunden.

Lizenzen

  • E3 + Copilot for Microsoft 365 (für Recap via aiInsights Beta-Endpoint)
  • Ohne Copilot: Transkript + Recording funktionieren, Recap fällt weg

Daten-Flow

Meeting endet
  └─> /meeting-end
        └─> fetch-meeting-artifacts.js --o365-id <id>
              ├─> getEventById        ── Calendars.Read
              ├─> resolveOnlineMeeting ── OnlineMeetings.Read.All + AccessPolicy
              ├─> fetchTranscriptVtt   ── OnlineMeetingTranscript.Read.All
              ├─> fetchAiInsights      ── OnlineMeetingAiInsight.Read.All (Beta)
              └─> fetchRecordingUrl    ── OnlineMeetingRecording.Read.All
        ── JSON ──>
  Claude: Doppel-Pass + Speaker-Mapping + Merge + Agenda-Rückführung
        └─> Meeting-Notiz + Agenda.md aktualisiert

Robustheit

  • Per-Artefakt-Fallback: schlägt Transcript fehl → Warning, Recap+Recording trotzdem holen
  • Fehlende Permissions / fehlende Policy → graceful: Warning + leere Felder, kein Crash
  • Recap fehlt (kein Copilot) → User-Prompt zum manuellen Einfügen
  • Kein O365-ID → User kann manuell weitermachen ohne Auto-Import

Lessons Learned (E2E 2026-05-06)

  • UPN → OID Auflösung Pflicht: /users/{upn}/onlineMeetings liefert 404, auch mit korrekter Application Access Policy. OnlineMeetings-API + Policy matchen ausschließlich gegen die Object-ID. Script löst daher zuerst UPN → OID via /users/{upn}?$select=id auf.
  • aiInsights ist umgezogen: Endpoint liegt jetzt unter /copilot/users/{oid}/onlineMeetings/{mid}/aiInsights (Beta). Alter Pfad /users/{oid}/onlineMeetings/{mid}/aiInsights antwortet mit 404 "API not supported". List-Call liefert nur Metadaten — Details (meetingNotes, actionItems, mentions) brauchen einen Detail-Call pro Insight-ID.
  • Transcript Content braucht expliziten Accept-Header: Default Accept: */* wird mit "Invalid format '/' specified" abgewiesen. Lösung: ?$format=text/vtt + Accept: text/vtt + responseType('text').
  • Permission-Rename ArtifactRecording: Microsoft hat OnlineMeetingArtifact.Read.All umbenannt zu OnlineMeetingRecording.Read.All. Alter Name ist tot, gibt 403 mit Hinweis auf den neuen Namen.

Bekannte Einschränkungen

  • Nur Meetings, bei denen AZURE_USER_EMAIL der Organizer ist (Graph-Restriktion)
  • Recap-Qualität abhängig von Copilot — keine Kontrolle über Inhalte
  • Konfidenz-Heuristik bei mehrdeutigen Topics → User-Bestätigung nötig
  • Speaker-Mapping nur bei korrekt gepflegten Personen-Notizen mit Email/Name

Siehe auch