TellFlow Interactive Messages
To use interactive UI components like selection boxes, forms, cards, article lists, video selection, and Q&A within the chat, a Chatwoot-like format is used in the webhook response.
Format reference: Chatwoot – Interactive messages.
Webhook request and session_id: The mobile app sends a session_id with every message. On the n8n side, you should use this as the conversation memory key. Details: Webhook Session Memory.
Webhook / API Response Format
The TellFlow mobile app uses the following structure. In the response body, you can directly send content, content_type, and content_attributes, or use the interactive_message object or interactive_message_json string (the mobile app prioritizes these).
Common Fields
| Field | Type | Required | Description |
|---|---|---|---|
content | string | No | The header text of the message (description). |
content_type | string | Yes | text | input_select | form | cards | article | video_select | question_answer |
content_attributes | object | Yes* | Contains items based on output type. Can be {} for text. |
interactive_message | object | No | Object containing the above fields; if present, the mobile app uses this. |
interactive_message_json | string | No | JSON string of the interactive_message; used after parsing. |
* content_attributes and items are required for all types except text.
How the Mobile App Extracts the Payload
The mobile app tries to find the interactive data in this order:
response.interactive_message(if it's an object)response.interactive_message_json(if it's a string → parse)- Root-level
content+content_type+content_attributes
JSON Schema (for Mobile Rendering)
The following structures are compatible with n8n node outputs and the format the backend should return. Mobile widgets render based on these field names.
General Structure
{
"content": "Header text (optional)",
"content_type": "input_select | form | cards | article | video_select | question_answer | text",
"content_attributes": { ... }
}
1. content_type: "text"
Plain text only; no interactive component.
{
"content": "Hello, how can I help you?",
"content_type": "text",
"content_attributes": {}
}
2. content_type: "input_select"
Selection buttons. When clicked, the selected value is sent as a user message.
content_attributes:
| Field | Type | Description |
|---|---|---|
items | array | Each item: title (display text), value (value to be sent) |
{
"content": "Select an option",
"content_type": "input_select",
"content_attributes": {
"items": [
{ "title": "Option 1", "value": "opt1" },
{ "title": "Option 2", "value": "opt2" }
]
}
}
3. content_type: "form"
Form fields (text, email, textarea, select). On submit, a map of field name → value is sent.
content_attributes.items for each item:
| Field | Type | Description |
|---|---|---|
name | string | Field name (key) |
type | string | text | email | text_area | select |
label | string | Label |
placeholder | string | Placeholder |
default | string | Default value |
options | array | Only for select: [{ "label": "...", "value": "..." }] |
{
"content": "Enter your details",
"content_type": "form",
"content_attributes": {
"items": [
{ "name": "email", "type": "email", "label": "Email", "placeholder": "email@example.com", "default": "" },
{ "name": "choice", "type": "select", "label": "Choice", "options": [{ "label": "A", "value": "a" }, { "label": "B", "value": "b" }] }
]
}
}
4. content_type: "cards"
Card list: image, title, description, and action buttons (link or postback).
content_attributes.items for each item:
| Field | Type | Description |
|---|---|---|
media_url | string | URL for the card image |
title | string | Title |
description | string | Description |
actions | array | Buttons: type, text, uri (link) or payload (postback) |
actions item:
| Field | Type | Description |
|---|---|---|
type | string | link | postback |
text | string | Button text |
uri | string | URL (for type: "link") |
payload | string | Value to be sent as a message (for type: "postback") |
{
"content": "Product cards",
"content_type": "cards",
"content_attributes": {
"items": [
{
"media_url": "https://example.com/image.jpg",
"title": "Product Name",
"description": "Short description",
"actions": [
{ "type": "link", "text": "Details", "uri": "https://example.com/detail" },
{ "type": "postback", "text": "Select", "payload": "SELECT_1" }
]
}
]
}
}
5. content_type: "article"
Title + description + link list items (opens link on click).
content_attributes.items for each item:
| Field | Type | Description |
|---|---|---|
title | string | Title |
description | string | Description |
link | string | URL |
{
"content": "Related articles",
"content_type": "article",
"content_attributes": {
"items": [
{ "title": "Article 1", "description": "Summary", "link": "https://example.com/1" },
{ "title": "Article 2", "description": "Summary", "link": "https://example.com/2" }
]
}
}
6. content_type: "video_select"
Video list (thumbnail, duration, play URL). Selection is passed back to the app via callback.
content_attributes.items for each item:
| Field | Type | Description |
|---|---|---|
id | string | Unique ID |
title | string | Title |
thumbnail_url | string | Preview image URL |
duration | string | Duration (e.g., "2:30") |
url | string | Video URL |
{
"content": "Select a video",
"content_type": "video_select",
"content_attributes": {
"items": [
{ "id": "v1", "title": "Video 1", "thumbnail_url": "https://...", "duration": "2:30", "url": "https://..." }
]
}
}
7. content_type: "question_answer"
Question-answer pairs (usually displayed as accordion or flat text).
content_attributes.items for each item:
| Field | Type | Description |
|---|---|---|
question | string | Question |
answer | string | Answer |
{
"content": "Frequently Asked Questions",
"content_type": "question_answer",
"content_attributes": {
"items": [
{ "question": "How do I cancel?", "answer": "Settings > Subscription > Cancel." },
{ "question": "Payment methods?", "answer": "Credit card and bank transfer." }
]
}
}
n8n Integration
- TellFlow Interactive Message: Used as an AI agent tool; generates selection, form, cards, article, video, Q&A, or text.
- TellFlow Interactive Message (From Input): Not an AI tool; generates the same interactive message format from JSON input (from webhook or previous node). Output structure is identical.
Both nodes produce content, content_type, content_attributes, interactive_message, and interactive_message_json in the output. You can add this output to the response body using "Respond to Webhook" or "Set"; the mobile app is compatible with both root fields and interactive_message / interactive_message_json.
Mobile Components
| content_type | File | Description |
|---|---|---|
| input_select | interactive_options_widget.dart | Selection buttons (title / value) |
| form | interactive_form_widget.dart | Text, email, textarea, select |
| cards | interactive_cards_widget.dart | media_url, title, description, actions (type, text, uri, payload) |
| article | interactive_article_widget.dart | Title, description, link |
| video_select | interactive_video_select_widget.dart | Thumbnail, duration, url |
| question_answer | interactive_question_answer_widget.dart | Question-answer pairs |
All components are selected and rendered via interactive_message_widget.dart based on the payload.