opsadvanced15 min setupby Mantle

Teams channel message to a Jira issue

A message in a watched Teams channel raises a Jira issue, so an ask in chat does not get lost.

Channel messageRaise the issue

Drag to pan, pinch to zoom. This is the real graph the template installs.

Purpose

A message in a watched Teams channel raises a Jira issue, so an ask in chat does not get lost.

How it works

What it does

  • Subscribes to new messages in one Microsoft Teams channel.
  • Creates a Jira task carrying the message id and the raw notification.

Validation

This template is contract-validated: the unit suite checks every node type, every config key and the whole graph against the same rules a saved workflow passes. It has not been run against the live provider — the ids, names and columns below are placeholders to replace with your own.

Nodes 2

  1. 01Channel messagetrigger.teams_eventTrigger
  2. 02Raise the issuejira.create_issueApp
View template JSON
{
  "format": "mantle-workflow/v1",
  "id": "teams-message-to-jira",
  "name": "Teams channel message to a Jira issue",
  "graph": {
    "nodes": [
      {
        "id": "message",
        "type": "trigger.teams_event",
        "label": "Channel message",
        "config": {
          "watch": "channel_message",
          "team_id": "00000000-0000-0000-0000-000000000000",
          "channel_id": "19:0000000000000000000000000000000@thread.tacv2",
          "change_types": [
            "created"
          ]
        },
        "worker_type": "generic-worker",
        "position": {
          "x": 60,
          "y": 220
        }
      },
      {
        "id": "issue",
        "type": "jira.create_issue",
        "label": "Raise the issue",
        "config": {
          "project_key": "OPS",
          "issue_type": "Task",
          "summary": "Teams request {{ $json.message_id }}",
          "description": "Raised from Microsoft Teams channel {{ $json.channel_id }}.\n\n{{ $json.payload }}"
        },
        "worker_type": "generic-worker",
        "position": {
          "x": 380,
          "y": 220
        }
      }
    ],
    "edges": [
      {
        "from": "message",
        "to": "issue"
      }
    ]
  }
}

Requirements

The connections and permissions each step needs, from the node contracts in the catalog.

  • Used by Channel message.

    Credential: {"client_id", "client_secret", "refresh_token"}

    • The refresh token needs ChannelMessage.Read.All to watch a channel, or Chat.Read to watch a chat — Graph refuses a subscription whose credential cannot read the resource. Connect-with-Microsoft does not mint Teams connections yet, so the refresh token has to be supplied on the connection directly. Publishing also needs MANTLE_APP_PUBLIC_BASE_URL set to an https URL Graph can reach: it probes that URL before it will create the subscription.
    • Publishing creates the Graph subscription; unpublishing, disabling or archiving deletes it. A workflow that is off is off at Microsoft too.
    • Graph subscriptions expire — three days is the ceiling for Teams messages — so Mantle renews this one automatically well before it lapses.
    • The notification carries the message's id and path, not its text. Rich notifications need an encryption certificate; read the message with a Teams node instead.
    • Deliveries are checked against the clientState Graph echoes back. That is a shared secret in the body, not a signature: it proves who sent the notification, not that the body is unmodified in transit.
    • One run per (subscription, change type, message id) — Graph retries an undelivered notification for up to four hours and a retry cannot start a second run.
    • Microsoft counts every Teams subscription in the tenant against one 10,000-subscription quota, and allows one per app-and-channel (or chat) combination; a second workflow watching the same channel is refused.
  • JiraUsername & password

    Used by Raise the issue.

    Credential: {"email", "api_token"}

Setup

  • Replace team_id and channel_id with your own.
  • The Teams refresh token needs ChannelMessage.Read.All, and MANTLE_APP_PUBLIC_BASE_URL must be an https URL Microsoft Graph can probe before the subscription is created.
  • Every message raises an issue. Put a Filter node before Raise the issue if you only want ones that mention a keyword.
  • Pick Teams and Jira connections and set project_key.

Sample input and output

Synthetic examples: node-contract samples or placeholders, never customer data.

Input

What the Channel message trigger receives, as its node contract samples it.

{
  "change_type": "created",
  "channel_id": "19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2",
  "chat_id": "",
  "message_id": "1612293113399",
  "payload": {
    "changeType": "created",
    "resourceData": {
      "id": "1612293113399"
    }
  },
  "resource": "teams('fbe2bf47-16c8-47cf-b4a5-4b9b187c508b')/channels('19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2')/messages('1612293113399')",
  "subscription_expires_at": "2026-09-13T11:26:41.0537895Z",
  "subscription_id": "9f9d1ed0-c9cc-42e7-8d80-a7fc4b0cda3c",
  "team_id": "fbe2bf47-16c8-47cf-b4a5-4b9b187c508b",
  "tenant_id": "84bd8158-6d4d-4958-8b9f-9d6445542f95"
}

Output

Raise the issue jira.create_issue

{
  "issue_key": "",
  "ok": false,
  "url": ""
}

Failure handling

What the graph does when a step fails, read from its retry settings, error branches and error policies.

  • A step that fails, after any retries, fails the run. The failed step is kept with its input and error.

See it run, then make it yours.

Templates install as drafts. Edit any step, and Workflow Health re-checks the graph on every save.