hermes-agent/website/docs/user-guide/messaging/teams-meetings.md
Teknium 242da9db96 docs(teams-pipeline): cron renewal recipe, sidebar wiring, skill rewrite
Fifth and final slice polish on top of @dlkakbs's docs + skill. Three
things ship here:

1. Subscription renewal cron recipe (the #1 operational footgun).

   Microsoft Graph webhook subscriptions expire at 72 hours max and
   don't auto-renew. The shipped operator runbook mentioned
   `maintain-subscriptions --dry-run` as a "daily or periodic check"
   but never told operators how to actually automate it. Without a
   scheduled job, any production deployment silently stops ingesting
   meetings three days after go-live.

   Adds an "Automating subscription renewal (REQUIRED for production)"
   section to website/docs/guides/operate-teams-meeting-pipeline.md
   with three concrete options and copy-pasteable configs:

   - Option 1: Hermes cron (`hermes cron add --schedule "0 */12 * * *"
     --script-only --command "hermes teams-pipeline maintain-subscriptions"`)
   - Option 2: systemd service + timer (12h cadence, Persistent=true
     so missed runs catch up after reboots)
   - Option 3: plain crontab with a wrapper that sources .env for
     credentials

   Go-Live Checklist gains a bolded mandatory item for the schedule
   being in place, with a cross-link to the section.

   website/docs/user-guide/messaging/teams-meetings.md adds a
   `::⚠️::` admonition right after the manual `subscribe`
   examples so anyone who creates a subscription manually is told
   the same day that it will silently expire in 72 hours.

2. Sidebar wiring. Shela's new docs pages (teams-meetings.md and
   operate-teams-meeting-pipeline.md) weren't in website/sidebars.ts,
   so they were orphaned URLs — reachable only if someone knew the
   path. Wired teams-meetings into Messaging Platforms next to the
   existing teams entry, and operate-teams-meeting-pipeline into
   Guides & Tutorials next to microsoft-graph-app-registration from
   PR #21922. Adjacent placement keeps the related pages discoverable
   from each other.

3. SKILL.md rewrite (v1.0.0 → v1.1.0).

   The original skill had five Turkish-only trigger phrases, which
   works in a Turkish-speaking session but doesn't match English
   triggers. Rewrote the skill to:

   - Describe triggers by intent instead of exact phrases, with
     explicit "works in any language" framing and example phrases
     in both English and Turkish.
   - Add a Decision Tree section covering the three most common user
     asks (missing summary, setup verification, re-run request) and
     the specific CLI command sequence for each.
   - Add a dedicated "Critical pitfall: Graph subscriptions expire
     in 72 hours" section that tells the agent exactly what to do
     when a user reports "worked yesterday, nothing today" — the
     most common operational failure mode.
   - Expand the command reference into three labeled groups (Status
     and inspection / Re-running and debugging / Subscription
     management) so the agent can reach for the right command
     without scanning.
   - Add cross-links to all four related docs pages (Azure app
     registration, webhook listener setup, full pipeline setup,
     operator runbook).

Validation:
- npm run build: all new pages route, anchor to
  #automating-subscription-renewal-required-for-production resolves
  from both the runbook TOC and the teams-meetings.md admonition.
- scripts/run_tests.sh on the relevant test suites (607 tests): all
  pass.
2026-05-08 12:41:41 -07:00

7.2 KiB

sidebar_position title description
6 Teams Meetings Set up the Microsoft Teams meeting summary pipeline with Microsoft Graph webhooks

Microsoft Teams Meetings

Use the Teams meeting pipeline when you want Hermes to ingest Microsoft Graph meeting events, fetch transcripts first, fall back to recordings plus STT when needed, and deliver a structured summary to downstream sinks.

This page focuses on setup and enablement:

  • Graph credentials
  • webhook listener configuration
  • Teams delivery modes
  • pipeline config shape

For day-2 operations, go-live checks, and the operator worksheet, use the dedicated guide: Operate the Teams Meeting Pipeline.

What This Feature Does

The pipeline:

  1. receives Microsoft Graph webhook events
  2. resolves the meeting and prefers transcript artifacts first
  3. falls back to recording download plus STT when no usable transcript is available
  4. stores durable job state and sink records locally
  5. can write summaries to Notion, Linear, and Microsoft Teams

Operator actions stay in the CLI:

hermes teams-pipeline validate
hermes teams-pipeline list
hermes teams-pipeline maintain-subscriptions

Prerequisites

Before enabling the meetings pipeline, make sure you have:

  • a working Hermes install
  • the existing Microsoft Teams bot setup if you want Teams outbound delivery
  • Microsoft Graph application credentials with the permissions required for the meeting resources you plan to subscribe to
  • a public HTTPS URL that Microsoft Graph can call for webhook delivery
  • ffmpeg installed if you want recording-plus-STT fallback

Step 1: Add Microsoft Graph Credentials

Add Graph app-only credentials to ~/.hermes/.env:

MSGRAPH_TENANT_ID=<tenant-id>
MSGRAPH_CLIENT_ID=<client-id>
MSGRAPH_CLIENT_SECRET=<client-secret>

These credentials are used by:

  • the Graph client foundation
  • subscription maintenance commands
  • meeting resolution and artifact fetches
  • Graph-based Teams outbound delivery when you do not provide a dedicated Teams access token

Step 2: Enable the Graph Webhook Listener

The webhook listener is a gateway platform named msgraph_webhook. At minimum, enable it and set a client state value:

MSGRAPH_WEBHOOK_ENABLED=true
MSGRAPH_WEBHOOK_PORT=8646
MSGRAPH_WEBHOOK_CLIENT_STATE=<random-shared-secret>
MSGRAPH_WEBHOOK_ACCEPTED_RESOURCES=communications/onlineMeetings

The listener exposes:

  • /msgraph/webhook for Graph notifications
  • /health for a simple health check

You need to route your public HTTPS endpoint to that listener. For example, if your public domain is https://ops.example.com, your Graph notification URL would typically be:

https://ops.example.com/msgraph/webhook

Step 3: Configure Teams Delivery and Pipeline Behavior

The meeting pipeline reads its runtime config from the existing teams platform entry. Pipeline-specific knobs live under teams.extra.meeting_pipeline. Teams outbound delivery stays on the normal Teams platform config surface.

Example ~/.hermes/config.yaml:

platforms:
  msgraph_webhook:
    enabled: true
    extra:
      port: 8646
      client_state: "replace-me"
      accepted_resources:
        - "communications/onlineMeetings"

  teams:
    enabled: true
    extra:
      client_id: "your-teams-client-id"
      client_secret: "your-teams-client-secret"
      tenant_id: "your-teams-tenant-id"

      # outbound summary delivery
      delivery_mode: "graph" # or incoming_webhook
      team_id: "team-id"
      channel_id: "channel-id"
      # incoming_webhook_url: "https://..."

      meeting_pipeline:
        transcript_min_chars: 80
        transcript_required: false
        transcription_fallback: true
        ffmpeg_extract_audio: true
        notion:
          enabled: false
        linear:
          enabled: false

Teams Delivery Modes

The pipeline supports two Teams summary-delivery modes inside the existing Teams plugin.

incoming_webhook

Use this when you want a simple webhook post into Teams without channel-message creation through Graph.

Required config:

platforms:
  teams:
    enabled: true
    extra:
      delivery_mode: "incoming_webhook"
      incoming_webhook_url: "https://..."

graph

Use this when you want Hermes to post the summary through Microsoft Graph into a Teams chat or channel.

Supported targets:

  • chat_id
  • team_id + channel_id
  • team_id + home_channel fallback for the existing Teams platform

Example:

platforms:
  teams:
    enabled: true
    extra:
      delivery_mode: "graph"
      team_id: "team-id"
      channel_id: "channel-id"

Step 4: Start the Gateway

Start Hermes normally after updating config:

hermes gateway run

Or, if you run Hermes in Docker, start the gateway the same way you already do for your deployment.

Check the listener:

curl http://localhost:8646/health

Step 5: Create Graph Subscriptions

Use the plugin CLI to create and inspect subscriptions.

Examples:

hermes teams-pipeline subscribe \
  --resource communications/onlineMeetings/getAllTranscripts \
  --notification-url https://ops.example.com/msgraph/webhook \
  --client-state "$MSGRAPH_WEBHOOK_CLIENT_STATE"

hermes teams-pipeline subscribe \
  --resource communications/onlineMeetings/getAllRecordings \
  --notification-url https://ops.example.com/msgraph/webhook \
  --client-state "$MSGRAPH_WEBHOOK_CLIENT_STATE"

:::warning Graph subscriptions expire in 72 hours

Microsoft Graph caps webhook subscriptions at 72 hours and will not auto-renew them. You MUST schedule hermes teams-pipeline maintain-subscriptions before going live, or notifications will silently stop three days after any manual subscription creation. See Automating subscription renewal in the operator runbook — three options (Hermes cron, systemd timer, plain crontab).

:::

For subscription maintenance and day-2 operator flows, continue with the guide: Operate the Teams Meeting Pipeline.

Validation

Run the built-in validation snapshot:

hermes teams-pipeline validate

Useful companion checks:

hermes teams-pipeline token-health
hermes teams-pipeline subscriptions

Troubleshooting

Problem What to check
Graph webhook validation fails Confirm the public URL is correct and reachable, and that Graph is calling the exact /msgraph/webhook path
Jobs do not appear in hermes teams-pipeline list Confirm msgraph_webhook is enabled and that subscriptions point at the right notification URL
Transcript-first never succeeds Check Graph permissions for transcript resources and whether the transcript artifact exists for that meeting
Recording fallback fails Confirm ffmpeg is installed and the Graph app can access recording artifacts
Teams summary delivery fails Re-check delivery_mode, target IDs, and Teams auth config