Skip to content

Message

The message is the body a notification carries. You write it once on the action, formatting it with Markdown and enriching it with dynamic variables (tokens) that are replaced with real values when the Flow runs.

Formatting the Message

The Message field is a rich text editor that stores what you write as Markdown. You can format as you go:

To Do This
Apply styles such as bold and italic Select the text and pick the style on the formatting toolbar that appears.
Write the formatting yourself Type the Markdown and the editor converts it as you type, for example **bold**, *italic*, or - for a list item.
Insert a block, such as a heading or a list Type / to open the block menu.
Insert a variable Type {{, or press Ctrl+Space, to open the variable menu. It has two groups: Variables, the tokens the Flow's trigger provides, and Optional section, one entry per token that can arrive empty, reading Only if has a value, which inserts a ready-made conditional block.
Spot a variable the trigger does not provide A name outside the menu turns red, with a dotted underline, as soon as you type it. The editor does not stop you, since you may still be typing, but publishing the Flow or testing the action refuses it (see Validation).

How the formatting arrives depends on the channel:

Channel How the Message Renders
In App The Markdown is rendered in the notification panel, so bold, italic, lists, and links arrive formatted.
Email The Markdown is rendered into the Qualytics email layout, so the message arrives formatted rather than as characters. A plain-text copy travels with it for clients that do not render HTML.
Slack and Microsoft Teams The channel composes its own per-event layout (an interactive message or an Adaptive Card), shown in the panel's Preview.
PagerDuty The message becomes the incident's plain-text summary, which is also the alert title, so Markdown arrives as characters. PagerDuty caps it at 1024 characters and refuses a longer one.
Webhook, HTTP Action, and n8n The message travels as text inside the JSON payload for the receiving system to use.

Where You Write It

The message is written on the action's settings panel, and the field you get depends on the channel:

Channel Message Field
In App and Email A rich text editor with a formatting toolbar. Its placeholder reads Write the message recipients will see..., and the hint under it says Type {{ for variables and optional sections. Email adds an Email Subject field that takes the same tokens.
PagerDuty, Webhook, and HTTP Action A plain text field with the same {{ menu, and the same red mark on a name the trigger does not provide, but no formatting toolbar, since these channels carry the message as text.
Slack and Microsoft Teams No message field. The channel composes its own layout from the event, and the panel shows it in a Preview field.
n8n No message field. The workflow receives the event's data and composes its own text.

Default Message

A new notification does not start empty. Every trigger has a default message, so the field opens on text that already reads well, and an edit is a departure from that default rather than from a blank page. The full default has four parts:

  1. A heading naming the event, such as Record anomaly in orders.
  2. A body written with optional sections, so it adapts to what the event carries. The Operation Completed default, for example, reads This operation finished with the result Success. when the operation recorded no message, and This operation finished with the result Failure and left logs. followed by a Logs heading and the logs when it did.
  3. A link back to the resource, such as Review this anomaly.
  4. A footer naming the Flow, as a quote: Sent by the Quality Monitor flow.

What a channel starts on depends on what it can show. Email gets all four parts. In App gets the body and the footer, since the notifications panel draws the title and the row itself is the link. Webhook and HTTP Action get the same text with the Markdown marks removed. PagerDuty starts on its own one-line summary instead, written to fit an alert title (see Add a PagerDuty Notification). A Schedule or Manual trigger has no resource to point at, so its default is the heading and a one-line body, with no link and no footer.

The default is also what Reset to defaults returns you to, on every channel that has a message field. It restores the message, and on Email the subject. A field that itself has a default returns to it as well, such as the PagerDuty Severity or the HTTP Action Http Verb and Auth Type; recipients, URLs, keys, and any field without a default are left as you set them.

Message Variables

The available tokens depend on the Flow's trigger type, and the same set applies to every notification channel. Pick the tab below for your trigger type.

Info

The message editor's autocomplete only offers the tokens valid for the Flow's trigger type. A token that does not appear in the list is not provided by that trigger: the editor marks it in red, and publishing the Flow or testing the action refuses it (see Validation).

A scheduled run has no target object, so the Flow's name is the only token available.

Token Description
{{flow_name}} The Flow's name.
Token Description
{{flow_name}} The Flow's name.
{{datastore_name}} The datastore the operation ran on.
{{datastore_link}} A link to that datastore.
{{operation_type}} The type of the operation (Sync, Profile, Scan, Export, or Materialize).
{{operation_result}} The operation's result (Success, Failure, or Aborted).
{{operation_message}} The message the operation recorded, such as its failure details.
{{target_link}} A direct link to the operation's details.

{{operation_message}} can be empty when the operation recorded no message; see Optional Sections.

Token Description
{{flow_name}} The Flow's name.
{{datastore_name}} The datastore where the anomalies were detected.
{{datastore_link}} A link to that datastore.
{{container_name}} The table or file where the anomalies were detected.
{{container_link}} A link to that table or file.
{{scan_target_name}} The name of the scanned partition. On a partitioned table it differs from {{container_name}}, which carries the table or file.
{{anomaly_count}} The number of anomalies detected.
{{anomaly_message}} A message describing the failed checks.
{{check_description}} The description of the checks behind the anomalies.
{{target_link}} A direct link to the results.

{{anomaly_message}} and {{check_description}} can be empty, for example on a shape anomaly with no failed check details; see Optional Sections.

Token Description
{{flow_name}} The Flow's name.
{{datastore_name}} The datastore where the anomaly was detected.
{{datastore_link}} A link to that datastore.
{{container_name}} The table or file where the anomaly was detected.
{{container_link}} A link to that table or file.
{{anomaly_id}} The anomaly's identifier.
{{anomaly_type}} The type of the anomaly.
{{anomaly_message}} The message describing the anomaly.
{{check_description}} The description of the check that identified the anomaly.
{{old_status}} The anomaly's previous status.
{{new_status}} The anomaly's current status.
{{target_link}} A direct link to the anomaly's details.

{{anomaly_message}}, {{check_description}}, and {{old_status}} can be empty, for example on a newly detected anomaly with no earlier status; see Optional Sections.

Token Description
{{flow_name}} The Flow's name.
{{datastore_name}} The datastore of the anomaly.
{{datastore_link}} A link to that datastore.
{{container_name}} The table or file of the anomaly.
{{container_link}} A link to that table or file.
{{anomaly_id}} The anomaly's identifier.
{{anomaly_type}} The type of the anomaly.
{{anomaly_message}} The message describing the anomaly.
{{check_description}} The description of the check that identified the anomaly.
{{old_status}} The status the anomaly changed from.
{{new_status}} The status the anomaly changed to.
{{target_link}} A direct link to the anomaly's details.

{{anomaly_message}}, {{check_description}}, and {{old_status}} can be empty; see Optional Sections.

A manual run has no target object, so the Flow's name is the only token available.

Token Description
{{flow_name}} The Flow's name.

Tokens after an anomaly action

A notification chained after an Archive or Delete action offers {{flow_name}}, {{anomaly_count}} (how many anomalies the action touched), {{inactivity_timeframe}} (the inactivity period in days), and {{target_link}}. {{anomaly_count}} and {{inactivity_timeframe}} can arrive empty, so wrap them as Optional Sections when the message has to read well either way; {{flow_name}} and {{target_link}} are always filled.

Tokens after a ticketing action

A notification chained after a Create Ticket action also offers {{ticket_number}}, {{ticket_url}}, {{ticket_status}}, and {{anomaly_id}}. One chained after an Update Ticket Status action offers {{tickets_updated_count}}, {{ticket_status}}, and {{anomaly_id}}. Every token specific to these two actions can arrive empty, so each is offered as an optional section. Slack and Microsoft Teams render these messages with a dedicated ticket layout.

Optional Sections

A token that can arrive empty is worth wrapping in a conditional section, so the message stays clean when there is nothing to show. The editor's autocomplete offers these as Optional section entries:

{{#if anomaly_message}}
Details: {{anomaly_message}}
{{else}}
No details recorded.
{{/if}}

The text between {{#if token}} and {{/if}} is only included when the token has a value; the {{else}} part is optional and is used when it does not.

Only a token that can arrive empty is offered as an Optional section. A token the trigger always fills has no entry, because its condition could never be false. Presence is the only test a condition makes: {{#if token}} asks whether the token has a value, and nothing else. A comparison inside the condition, a condition opened inside another, an {{else}} with a condition after it or a second one in the same block, and any block tag other than the conditional are refused when you publish or test, with a message saying what is not supported. To act on a value, filter on it in the Flow's trigger instead.

Validation

Publishing the Flow and Test Notification run the same check on the message, and on the Email subject. Saving the action on its panel does not run it: the check happens when the Flow is published, so a refused message is caught before the Flow goes live rather than on every edit. A template is refused when it names a variable the trigger does not provide, or when a conditional is malformed. The refusal names the field and the variable:

  • The message uses {{old_status}}, which this notification does not provide. A variable that is not provided is not filled in and reaches the recipient exactly as written.
  • The subject has a condition on {{ticket_number}}, which this notification does not provide. A condition can only check a variable this notification provides; otherwise its section would never be shown.

A malformed conditional is refused with a message saying what is wrong: an opening marker without its closing one, a condition opened inside another, a comparison inside the condition, an {{else}} with a condition after it or a second one in the same block, or a block tag other than the conditional.

Where the refusal shows up depends on what you clicked. See Publish Validation for the publish dialog and the action card, and Testing Notifications for the test verdict.

See Also