> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mibyanai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Operate the Teams Meeting Pipeline

> Runbook, go-live checklist, and operator worksheet for the Microsoft Teams meeting pipeline

Use this guide after you have already enabled the feature from [Teams Meetings](/desktop/user-guide/messaging/teams-meetings).

This page covers:

* operator CLI flows
* routine subscription maintenance
* failure triage
* go-live checks
* rollout worksheet

## Core Operator Commands

### Validate the config snapshot

```bash theme={null}
mibyan teams-pipeline validate
```

Use this first after any config change.

### Inspect token health

```bash theme={null}
mibyan teams-pipeline token-health
mibyan teams-pipeline token-health --force-refresh
```

Use `--force-refresh` when you suspect stale auth state.

### Inspect subscriptions

```bash theme={null}
mibyan teams-pipeline subscriptions
```

### Renew near-expiry subscriptions

```bash theme={null}
mibyan teams-pipeline maintain-subscriptions
mibyan teams-pipeline maintain-subscriptions --dry-run
```

### Automating subscription renewal (REQUIRED for production)

**Microsoft Graph subscriptions expire in at most 72 hours.** If nothing renews them, meeting notifications silently stop after 3 days and the pipeline looks "broken." This is the #1 operational failure mode for any Graph-backed integration.

You MUST run `maintain-subscriptions` on a schedule. Pick one of these three options:

#### Option 1: Mibyan cron (recommended if you already run the Mibyan gateway)

Mibyan ships a built-in cron scheduler. The `--no-agent` mode runs a script as the job (rather than using an LLM), and `--script` must point at a file under `~/.mibyan/scripts/`. First create the script:

```bash theme={null}
mkdir -p ~/.mibyan/scripts
cat > ~/.mibyan/scripts/maintain-teams-subscriptions.sh <<'EOF'
#!/usr/bin/env bash
exec mibyan teams-pipeline maintain-subscriptions
EOF
chmod +x ~/.mibyan/scripts/maintain-teams-subscriptions.sh
```

Then register a script-only cron job that runs every 12 hours (gives 6x headroom against the 72h expiry window):

```bash theme={null}
mibyan cron create "0 */12 * * *" \
  --name "teams-pipeline-maintain-subscriptions" \
  --no-agent \
  --script maintain-teams-subscriptions.sh \
  --deliver local
```

Verify it was registered and inspect the next run time:

```bash theme={null}
mibyan cron list
mibyan cron status        # scheduler status
```

#### Option 2: systemd timer (recommended for Linux production deployments)

Create `/etc/systemd/system/mibyan-teams-pipeline-maintain.service`:

```ini theme={null}
[Unit]
Description=Mibyan Teams pipeline subscription maintenance
After=network-online.target

[Service]
Type=oneshot
User=mibyan
EnvironmentFile=/etc/mibyan/env
ExecStart=/usr/local/bin/mibyan teams-pipeline maintain-subscriptions
```

And `/etc/systemd/system/mibyan-teams-pipeline-maintain.timer`:

```ini theme={null}
[Unit]
Description=Run Mibyan Teams pipeline subscription maintenance every 12 hours

[Timer]
OnBootSec=5min
OnUnitActiveSec=12h
Persistent=true

[Install]
WantedBy=timers.target
```

Enable:

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl enable --now mibyan-teams-pipeline-maintain.timer
systemctl list-timers mibyan-teams-pipeline-maintain.timer
```

#### Option 3: Plain crontab

```cron theme={null}
0 */12 * * * /usr/local/bin/mibyan teams-pipeline maintain-subscriptions >> /var/log/mibyan/teams-pipeline-maintain.log 2>&1
```

Make sure the cron environment has the `MSGRAPH_*` credentials. Simplest fix: source `~/.mibyan/.env` at the top of a wrapper script that crontab calls.

#### Verifying renewal is working

After you've set up the schedule, check renewal activity after the first scheduled run:

```bash theme={null}
mibyan teams-pipeline subscriptions   # should show expirationDateTime advanced
mibyan teams-pipeline maintain-subscriptions --dry-run   # should show "0 expiring soon" most of the time
```

If you ever see your Graph webhook mysteriously "stop working" after exactly \~72 hours, this is the first thing to check: did the renewal job actually run?

### Inspect recent jobs

```bash theme={null}
mibyan teams-pipeline list
mibyan teams-pipeline list --status failed
mibyan teams-pipeline show <job-id>
```

### Replay a stored job

```bash theme={null}
mibyan teams-pipeline run <job-id>
```

### Dry-run meeting artifact fetches

```bash theme={null}
mibyan teams-pipeline fetch --meeting-id <meeting-id>
mibyan teams-pipeline fetch --join-web-url "<join-url>"
mibyan teams-pipeline fetch --join-web-url "<join-url>" --organizer-user-id <entra-user-id>
```

Pass `--organizer-user-id` (the organizer's Microsoft Entra user ID) to resolve
through the organizer-scoped `/users/{id}/onlineMeetings` Graph path. This is
required for Teams `/meet/` short URLs, which Graph rejects on the
`/communications/onlineMeetings` endpoint. Webhook-driven jobs derive the
organizer automatically from the notification's `@odata.id`.

## Routine Runbook

### After first setup

Run these in order:

```bash theme={null}
mibyan teams-pipeline validate
mibyan teams-pipeline token-health --force-refresh
mibyan teams-pipeline subscriptions
```

Then trigger or wait for a real meeting event and confirm:

```bash theme={null}
mibyan teams-pipeline list
mibyan teams-pipeline show <job-id>
```

### Daily or periodic checks

* run `mibyan teams-pipeline maintain-subscriptions --dry-run`
* inspect `mibyan teams-pipeline list --status failed`
* verify the Teams delivery target is still the correct chat or channel

### Before changing webhook URLs or delivery targets

* update the public notification URL or Teams target config
* run `mibyan teams-pipeline validate`
* renew or recreate affected subscriptions
* confirm new events land in the expected sink

## Failure Triage

### No jobs are being created

Check:

* `msgraph_webhook` is enabled
* the public notification URL points to `/msgraph/webhook`
* the client state in the subscription matches `MSGRAPH_WEBHOOK_CLIENT_STATE`
* subscriptions still exist remotely and are not expired

### Jobs stay in retry or fail before summarization

Check:

* transcript permissions and availability
* recording permissions and artifact availability
* `ffmpeg` availability if recording fallback is enabled
* Graph token health

### Summaries are produced but not delivered to Teams

Check:

* `platforms.teams.enabled: true`
* `delivery_mode`
* `incoming_webhook_url` for webhook mode
* `chat_id` or `team_id` plus `channel_id` for Graph mode
* Teams auth config if Graph posting is used

### Duplicate or unexpected replays

Check:

* whether you manually replayed a job with `mibyan teams-pipeline run`
* whether the sink record already exists for that meeting
* whether you intentionally enabled a resend path in your local config

## Go-Live Checklist

* [ ] Graph credentials are present and correct
* [ ] `msgraph_webhook` is enabled and reachable from the public internet
* [ ] `MSGRAPH_WEBHOOK_CLIENT_STATE` is set and matches subscriptions
* [ ] transcript subscription is created
* [ ] recording subscription is created if STT fallback is required
* [ ] `ffmpeg` is installed if recording fallback is enabled
* [ ] Teams outbound delivery target is configured and verified
* [ ] Notion and Linear sinks are configured only if actually needed
* [ ] `mibyan teams-pipeline validate` returns an OK snapshot
* [ ] `mibyan teams-pipeline token-health --force-refresh` succeeds
* [ ] **`maintain-subscriptions` is scheduled** (Mibyan cron, systemd timer, or crontab — see [Automating subscription renewal](#automating-subscription-renewal-required-for-production)). Without this, Graph subscriptions silently expire within 72 hours.
* [ ] a real end-to-end meeting event has produced a stored job
* [ ] at least one summary has reached the intended delivery sink

## Delivery-Mode Decision Guide

| Mode | Use when | Tradeoff |
| - | - | - |
| `incoming_webhook` | you only need simple posting into Teams | simplest setup, less control |
| `graph` | you need channel or chat posting through Graph | more control, more auth and target config |

## Operator Worksheet

Fill this out before rollout:

| Item | Value |
| - | - |
| Public notification URL | |
| Graph tenant ID | |
| Graph client ID | |
| Webhook client state | |
| Transcript resource subscription | |
| Recording resource subscription | |
| Teams delivery mode | |
| Teams chat ID or team/channel | |
| Notion database ID | |
| Linear team ID | |
| Store path override, if any | |
| Owner for daily checks | |

## Change Review Worksheet

Use this before changing the deployment:

| Question | Answer |
| - | - |
| Are we changing the public webhook URL? | |
| Are we rotating Graph credentials? | |
| Are we changing Teams delivery mode? | |
| Are we moving to a new Teams chat or channel? | |
| Do subscriptions need to be recreated or renewed? | |
| Do we need a fresh end-to-end verification run? | |

## Related Docs

* [Teams Meetings setup](/desktop/user-guide/messaging/teams-meetings)
* [Microsoft Teams bot setup](/desktop/user-guide/messaging/teams)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.