Channel Delivery Templates
When an Agentic Flow agent sends a message through a channel, a delivery template controls what that message looks like. Templates are configured on the Channel Output node in the flow editor.
You have three options — leave the template empty, write a fixed message, or write a template with placeholders. The right choice depends on how much control you need over the output.
Quick Decision Guide
Do you know what the message should look like?
Yes, same every time → write a fixed template with no placeholders. The agent is not involved.
Yes, but the details change → write a template with placeholders. You define the layout; the agent fills in the values.
No, let the agent decide → leave the template empty. The agent writes the full message. For more control over when to deliver, set Invocation to
agentic.
Is this a HITL approval card or regular delivery?
HITL approval → template must include Approve and Reject buttons. Only the 7 tokens in the HITL placeholders table are substituted.
Regular delivery → no button requirement. Any placeholder token works; the agent fills it in.
Which channels support structured templates?
Adaptive Cards — Microsoft Teams (
adaptive_cardevent type), Universal Webhook.Email — Outlook Mail uses plain text or HTML (
email,email_replyevent types).Messaging channels — WhatsApp, Telegram, Slack, Facebook, Viber, Zalo deliver the agent’s response as plain text. The template is not rendered as a card on these channels.
The Delivery Targets Table
Open a flow in the Agentic Flow editor and add a Channel Output node. The Delivery Targets table has one row per destination.
Column |
Description |
|---|---|
Channel |
Where the message goes (Teams, Outlook, Slack, etc.). |
Channel Type |
Auto-filled from the channel you select. |
Route Type |
Auto-filled (conversation, notification, etc.). |
Event Type |
The kind of message: |
Recipient |
Who receives it. Pick a named contact, or use |
Template |
The message layout in JSON. Paste an Adaptive Card or email template here. |
Invocation |
|
The Template column only appears after you have selected a channel and event type for that row.
The Template Editor
Click the </> icon next to the Template column header to open the Template Editor. It validates your JSON as you type (save is blocked until valid or empty), shows a live preview of the rendered card with sample placeholder values, and includes built-in examples you can load or copy directly into the textarea.
Note
The live preview is a structural check, not a pixel-perfect render. Channels apply their own theme and button chrome at send time. Use the preview to verify structure and content, not exact styling.
Three Ways to Write a Template
Option A — Leave it empty
The agent sends its raw response as a plain message. No card structure, no placeholder processing. Best for short conversational replies or when you want the agent to fully control the output.
Option B — Fixed message (no placeholders)
Your JSON is sent exactly as written on every invocation. The agent is not involved. Use this for messages that always look the same — daily status cards, fixed notifications.
Option C — Template with placeholders
Define the layout using {{token}} placeholders. The agent (or the system, for HITL cards) fills in each token at run time. The structure and wording stay exactly as you wrote them; only the placeholder values change.
Allowed Placeholders
HITL Templates
Only the following 7 tokens are substituted in approval cards. Any other {{token}} appears as literal text in the delivered card.
Token |
What it shows |
Example |
|---|---|---|
|
Headline from the Approval Title field. |
|
|
Short explanation from the Approval Description field. |
|
|
The agent’s proposed response — the approver can edit this before approving. |
|
|
Internal ID used to resume the flow after a decision. |
|
|
The user message that triggered the flow. |
|
|
Display name of the user who sent the original message. |
|
|
The channel the original message came from. |
|
Output Templates
For regular delivery cards, placeholders are filled by the agent. You can use any token name and the agent will populate it with a contextually appropriate value.
Token |
What it shows |
|---|---|
|
A short headline derived from the agent’s response. |
|
The full agent response. |
|
Display name of the user who started the conversation. |
|
The channel the original message came from. |
Any custom token |
|
Tip
To prevent a token from being substituted, write it as plain text without {{ }}.
Template Examples
Example 1 — HITL Approval Card
An approval card for a Human-in-the-Loop flow. Includes the original message, a proposed response the approver can edit, and Approve/Reject buttons.
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "Container", "style": "accent", "bleed": true,
"items": [
{ "type": "TextBlock", "text": "⚠ {{title}}",
"size": "Large", "weight": "Bolder", "color": "Warning", "wrap": true },
{ "type": "TextBlock",
"text": "From {{sender_name}} via {{source_channel}}",
"size": "Small", "isSubtle": true, "spacing": "None" }
]
},
{ "type": "TextBlock", "text": "{{description}}", "wrap": true, "spacing": "Medium" },
{ "type": "TextBlock", "text": "💬 {{original_message}}", "wrap": true, "spacing": "Medium" },
{ "type": "Input.Text", "id": "edited_response",
"placeholder": "Edit the response before approving…",
"isMultiline": true, "value": "{{bot_response}}" },
{ "type": "TextBlock", "text": "Ref: {{execution_id}}",
"size": "Small", "isSubtle": true, "spacing": "Small" }
],
"actions": [
{ "type": "Action.Submit", "title": "✅ Approve & Send",
"style": "positive", "data": { "hitl_action": "approve" } },
{ "type": "Action.Submit", "title": "Reject",
"style": "destructive", "data": { "hitl_action": "reject" } }
]
}
Example 2 — Output Delivery Card
A delivery card for a Channel Output node. No approve/reject buttons — just a formatted message.
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "Container", "style": "emphasis", "bleed": true,
"items": [
{ "type": "TextBlock", "text": "{{title}}",
"size": "Large", "weight": "Bolder", "wrap": true }
]
},
{ "type": "TextBlock", "text": "{{bot_response}}", "wrap": true, "spacing": "Medium" },
{ "type": "TextBlock", "text": "Sent via {{source_channel}}",
"size": "Small", "isSubtle": true, "spacing": "Small" }
]
}
Example 3 — Empty template
Leave the template field blank. The agent’s raw response is sent as a plain text message. Best for short, conversational replies.
Example 4 — Fixed card (no placeholders)
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{ "type": "TextBlock", "text": "Daily summary ready.",
"weight": "Bolder", "size": "Medium", "wrap": true }
]
}
Sent exactly as written on every invocation. No placeholder substitution, no agent involvement.
Validation
The system validates your template when you save a delivery target row.
HITL templates — save is blocked unless all four checks pass:
Check |
What it means |
|---|---|
Valid JSON |
The template must be parseable JSON. |
|
The root object must be an Adaptive Card. |
Approve action present |
The template must include an Approve button. |
Reject action present |
The template must include a Reject button. |
Output templates — only valid JSON and "type": "AdaptiveCard" are required. An empty template is always valid.
If you use a token not in the HITL allowed list, the editor shows a warning but you can still save. The token appears as literal text in the delivered card.
HITL Configuration
HITL (Human-in-the-Loop) pauses a flow and sends an approval request to a reviewer before any message is delivered. Use it for high-impact actions — emails to customers, payments, anything that touches another system.
HITL is available on Agentic Flow agents and is configured from the Governance tab in agent settings.
Template rules:
The template must include at least one Approve button and one Reject button.
Tracking IDs (execution ID, approver identity) are added to each button automatically — you do not need to include them.
Only the 7 tokens in the HITL placeholders table are substituted. Anything else appears as literal text.
If the template is empty or invalid, the system uses a default card with Approve and Reject buttons only.
After approval: The flow resumes. If the approver edited the edited_response field, that text is used as the delivered message. If not, the original {{bot_response}} value is used.
After rejection: The flow resumes with a rejection signal. No message is delivered to the end user unless your flow explicitly sends one.
Note
The HITL template controls the approval card sent to the reviewer. The Channel Output node’s template controls the final delivered message to the end user. These are separate templates on separate nodes.