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 :ref:`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_card`` event type), Universal Webhook. * **Email** — Outlook Mail uses plain text or HTML (``email``, ``email_reply`` event 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. .. list-table:: :widths: 20 80 :header-rows: 1 * - 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: ``adaptive_card``, ``message``, ``email``, etc. For HITL rows this is locked to ``hitl_approval``. * - **Recipient** - Who receives it. Pick a named contact, or use ``auto`` to let the system resolve the recipient. * - **Template** - The message layout in JSON. Paste an Adaptive Card or email template here. * - **Invocation** - ``automatic`` — fires on every invocation. ``agentic`` — the agent decides whether and to whom to deliver. Default: ``automatic``. 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-placeholders: HITL Templates ~~~~~~~~~~~~~~ Only the following 7 tokens are substituted in approval cards. Any other ``{{token}}`` appears as literal text in the delivered card. .. list-table:: :widths: 25 40 35 :header-rows: 1 * - Token - What it shows - Example * - ``{{title}}`` - Headline from the Approval Title field. - ``Action Required`` * - ``{{description}}`` - Short explanation from the Approval Description field. - ``Please review before sending.`` * - ``{{bot_response}}`` - The agent's proposed response — the approver can edit this before approving. - ``Hi! Your refund of $42 has been processed.`` * - ``{{execution_id}}`` - Internal ID used to resume the flow after a decision. - ``f87a3d0f-0c66-4c1b-8f30-e082297be365`` * - ``{{original_message}}`` - The user message that triggered the flow. - ``Can you refund my last order?`` * - ``{{sender_name}}`` - Display name of the user who sent the original message. - ``Shivesh Kumar`` * - ``{{source_channel}}`` - The channel the original message came from. - ``microsoft_teams`` 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. .. list-table:: :widths: 30 70 :header-rows: 1 * - Token - What it shows * - ``{{title}}`` - A short headline derived from the agent's response. * - ``{{bot_response}}`` - The full agent response. * - ``{{sender_name}}`` - Display name of the user who started the conversation. * - ``{{source_channel}}`` - The channel the original message came from. * - Any custom token - ``{{priority}}``, ``{{amount}}``, ``{{order_id}}``, etc. — the agent fills these in based on the conversation context. .. 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. .. code-block:: json { "$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. .. code-block:: json { "$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) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: json { "$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: .. list-table:: :widths: 30 70 :header-rows: 1 * - Check - What it means * - Valid JSON - The template must be parseable JSON. * - ``"type": "AdaptiveCard"`` - 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 :ref:`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.