Skip to content

feat(teams): add pipeline outbound delivery via existing adapter (salvage of #21411)#22024

Merged
teknium1 merged 4 commits into
mainfrom
hermes/hermes-f0bc99f0
May 8, 2026
Merged

feat(teams): add pipeline outbound delivery via existing adapter (salvage of #21411)#22024
teknium1 merged 4 commits into
mainfrom
hermes/hermes-f0bc99f0

Conversation

@teknium1

@teknium1 teknium1 commented May 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Salvage of #21411 onto current main. Extends the existing plugins/platforms/teams/adapter.py with a TeamsSummaryWriter class that the meeting pipeline uses for outbound summary delivery — one Teams integration surface, not two.

Fourth slice of the MS Teams meeting pipeline stack. With #21410 merged, hermes teams-pipeline produces meeting summary payloads. This PR is how those summaries actually land in Teams.

Credit to @dlkakbs — two of the three commits are hers (feat + refactor), preserved via rebase-merge.

Changes

  • plugins/platforms/teams/adapter.py: TeamsSummaryWriter class with write_summary() entrypoint, incoming_webhook mode (simple POST, markdown body), graph mode (POST to /chats/{id}/messages or /teams/{id}/channels/{id}/messages, HTML body with h3 headings + bullets), force_resend override on existing sink records, _StaticAccessTokenProvider shim so the caller can inject a pre-acquired delegated token instead of triggering a fresh client_credentials flow per summary.
  • plugins/teams_pipeline/pipeline.py: 5-line change to invoke the writer when teams_delivery.enabled is true.
  • tests/gateway/test_teams.py: full TeamsSummaryWriter coverage — mode selection, URL construction, HTML/markdown rendering, force_resend, missing-config errors.
  • tests/plugins/test_teams_pipeline_plugin.py: architectural test that build_pipeline_runtime uses the writer from plugins/platforms/teams/adapter.py rather than introducing a new surface.

Refactor commit drops a dead delivery-mode branch in _resolve_delivery_config that was unreachable after the config merge logic was settled.

Follow-ups added on top during salvage:

  • Test input fix: test_build_pipeline_runtime_reuses_existing_teams_adapter_surface set delivery_mode="incoming_webhook" but omitted incoming_webhook_url. The guarded build_pipeline_runtime gate (which checks _teams_delivery_is_configured) correctly left teams_sender=None in that case, so the assertion failed. Test intent was architectural (prove we reuse the existing adapter surface) — filled in the URL so the gate passes and the assertion holds.
  • Docs (shipped with the code):
    • /docs/user-guide/messaging/teams gains a "Meeting Summary Delivery (Teams Meeting Pipeline)" section with config-snippet example, mode-choice trade-off table, and an explicit note that settings are inert when the pipeline plugin is disabled.
    • /docs/reference/environment-variables gains a Teams Meeting Summary Delivery subsection documenting TEAMS_DELIVERY_MODE, TEAMS_INCOMING_WEBHOOK_URL, TEAMS_GRAPH_ACCESS_TOKEN, TEAMS_TEAM_ID, TEAMS_CHANNEL_ID, TEAMS_CHAT_ID.

Validation

  • scripts/run_tests.sh tests/gateway/test_teams.py tests/plugins/test_teams_pipeline_plugin.py tests/gateway/test_teams_pipeline_runtime_wiring.py tests/hermes_cli/test_teams_pipeline_plugin_cli.py tests/gateway/test_msgraph_webhook.py tests/tools/test_microsoft_graph_auth.py tests/tools/test_microsoft_graph_client.py — 104/104 passed.
  • Broader tests/gateway/ + tests/plugins/ slice: 599/599 passed.
  • npm run build in website/ — pages route correctly, no new warnings or errors.

Closes #21411.

Next (and last) in the stack: #21412 — full setup docs + operator runbook + SKILL.md, where I'll add the maintain-subscriptions cron recipe for the 72h Graph subscription expiry that the operator runbook references but doesn't actually set up.

dlkakbs and others added 4 commits May 8, 2026 11:19
test_build_pipeline_runtime_reuses_existing_teams_adapter_surface set
delivery_mode='incoming_webhook' but omitted incoming_webhook_url.
_teams_delivery_is_configured() requires the URL to mark delivery as
enabled, so the guarded build_pipeline_runtime gate in runtime.py
correctly left teams_sender=None and the assertion failed.

The intent of the test — prove we reuse the existing TeamsSummaryWriter
from plugins/platforms/teams/adapter.py rather than introducing a new
adapter surface elsewhere — is unchanged. Added the URL so the gate
passes and the architectural assertion holds.
Third docs slice shipped alongside the TeamsSummaryWriter code so
operators can configure outbound summary delivery the moment this
PR lands.

- website/docs/user-guide/messaging/teams.md: new 'Meeting Summary
  Delivery (Teams Meeting Pipeline)' section under Features,
  explaining that the existing teams adapter handles pipeline
  outbound (not a separate adapter surface), with a config-snippet
  example for graph and incoming_webhook modes, a mode-choice
  trade-off table, and a note that settings are inert when the
  teams_pipeline plugin is disabled.

- website/docs/reference/environment-variables.md: new Teams Meeting
  Summary Delivery subsection documenting TEAMS_DELIVERY_MODE,
  TEAMS_INCOMING_WEBHOOK_URL, TEAMS_GRAPH_ACCESS_TOKEN, TEAMS_TEAM_ID,
  TEAMS_CHANNEL_ID, TEAMS_CHAT_ID with cross-link to the Teams setup
  page section.

Verified via npm run build: pages route correctly, no new warnings
or errors.
@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-f0bc99f0 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 7797 on HEAD, 7794 on base (🆕 +3)

🆕 New issues (4):

Rule Count
invalid-argument-type 2
unresolved-import 2
First entries
plugins/teams_pipeline/runtime.py:94: [invalid-argument-type] invalid-argument-type: Argument to `TeamsMeetingPipeline.__init__` is incorrect: Expected `((TeamsMeetingSummaryPayload, dict[str, Any], dict[str, Any] | None, /) -> Awaitable[dict[str, Any]]) | None`, found `None | TeamsSummaryWriter`
plugins/platforms/teams/adapter.py:270: [invalid-argument-type] invalid-argument-type: Argument to `MicrosoftGraphClient.__init__` is incorrect: Expected `MicrosoftGraphTokenProvider`, found `_StaticAccessTokenProvider`
tests/gateway/test_teams.py:12: [unresolved-import] unresolved-import: Cannot resolve imported module `httpx`
plugins/platforms/teams/adapter.py:33: [unresolved-import] unresolved-import: Cannot resolve imported module `httpx`

✅ Fixed issues (1):

Rule Count
unresolved-import 1
First entries
plugins/teams_pipeline/runtime.py:82: [unresolved-import] unresolved-import: Module `plugins.platforms.teams.adapter` has no member `TeamsSummaryWriter`

Unchanged: 4091 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@teknium1 teknium1 merged commit 9680827 into main May 8, 2026
12 of 13 checks passed
@teknium1 teknium1 deleted the hermes/hermes-f0bc99f0 branch May 8, 2026 19:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants