Workflow Recipes
Six complete workflow examples you can use as starting points. Each includes the full JSON graph, a flow diagram, and a walkthrough of how it works.
Recipe 1: Customer Support with Escalation
A support bot that classifies intent, looks up relevant data, and escalates to a human when necessary.
Nodes: trigger, llm_call, logic (switch), mcp_tool, action (human_handoff), send_message
Workflow JSON
{
"nodes": [
{
"id": "trigger",
"type": "trigger",
"data": { "triggerType": "message_received", "label": "On Message" },
"position": { "x": 0, "y": 200 }
},
{
"id": "classify",
"type": "llm_call",
"data": {
"prompt": "Classify this customer message into exactly one category: billing, refund, other.\n\nMessage: {{message}}\n\nRespond with only the category name, nothing else.",
"outputVariable": "intent",
"label": "Classify Intent"
},
"position": { "x": 250, "y": 200 }
},
{
"id": "route",
"type": "logic",
"data": {
"logicType": "switch",
"variable": "intent.text",
"cases": ["billing", "refund"],
"label": "Route by Intent"
},
"position": { "x": 500, "y": 200 }
},
{
"id": "lookup_account",
"type": "mcp_tool",
"data": {
"toolName": "database__query",
"arguments": "{\"sql\": \"SELECT * FROM accounts WHERE user_id = '{{user_id}}' LIMIT 1\"}",
"outputVariable": "account",
"label": "Look Up Account"
},
"position": { "x": 750, "y": 50 }
},
{
"id": "billing_response",
"type": "llm_call",
"data": {
"prompt": "The customer asked about billing. Their account info: {{account}}. Their message: {{message}}. Provide a helpful response.",
"outputVariable": "ai_response",
"label": "Generate Billing Response"
},
"position": { "x": 1000, "y": 50 }
},
{
"id": "send_billing",
"type": "send_message",
"data": { "message": "{{ai_response.text}}", "label": "Send Billing Info" },
"position": { "x": 1250, "y": 50 }
},
{
"id": "check_order",
"type": "mcp_tool",
"data": {
"toolName": "orders__get_latest_order",
"arguments": "{\"user_id\": \"{{user_id}}\"}",
"outputVariable": "order",
"label": "Check Order"
},
"position": { "x": 750, "y": 250 }
},
{
"id": "check_amount",
"type": "logic",
"data": {
"logicType": "if_else",
"condition": "{{order.total}} > 100",
"label": "Amount > $100?"
},
"position": { "x": 1000, "y": 250 }
},
{
"id": "escalate",
"type": "action",
"data": {
"actionType": "human_handoff",
"reason": "Refund request over $100 for order {{order.id}}",
"label": "Escalate"
},
"position": { "x": 1250, "y": 200 }
},
{
"id": "process_refund",
"type": "mcp_tool",
"data": {
"toolName": "stripe__create_refund",
"arguments": "{\"payment_id\": \"{{order.payment_id}}\"}",
"outputVariable": "refund",
"label": "Process Refund"
},
"position": { "x": 1250, "y": 350 }
},
{
"id": "send_refund_confirm",
"type": "send_message",
"data": {
"message": "Your refund for order #{{order.id}} has been processed. You should see the credit within 5-10 business days.",
"label": "Confirm Refund"
},
"position": { "x": 1500, "y": 350 }
},
{
"id": "general_response",
"type": "llm_call",
"data": {
"prompt": "The customer sent: {{message}}. Provide a helpful general response.",
"outputVariable": "ai_response",
"label": "General Response"
},
"position": { "x": 750, "y": 450 }
},
{
"id": "send_general",
"type": "send_message",
"data": { "message": "{{ai_response.text}}", "label": "Send Response" },
"position": { "x": 1000, "y": 450 }
}
],
"edges": [
{ "id": "e1", "source": "trigger", "target": "classify" },
{ "id": "e2", "source": "classify", "target": "route" },
{ "id": "e3", "source": "route", "target": "lookup_account", "sourceHandle": "case_billing" },
{ "id": "e4", "source": "lookup_account", "target": "billing_response" },
{ "id": "e5", "source": "billing_response", "target": "send_billing" },
{ "id": "e6", "source": "route", "target": "check_order", "sourceHandle": "case_refund" },
{ "id": "e7", "source": "check_order", "target": "check_amount" },
{ "id": "e8", "source": "check_amount", "target": "escalate", "sourceHandle": "true" },
{ "id": "e9", "source": "check_amount", "target": "process_refund", "sourceHandle": "false" },
{ "id": "e10", "source": "process_refund", "target": "send_refund_confirm" },
{ "id": "e11", "source": "route", "target": "general_response", "sourceHandle": "case_default" },
{ "id": "e12", "source": "general_response", "target": "send_general" }
]
}Recipe 2: Order Status with ID Extraction
A focused workflow that extracts an order number from the message, looks it up, and responds with the status.
Nodes: trigger, llm_call, logic (if_else), mcp_tool, send_message
Workflow JSON
{
"nodes": [
{
"id": "trigger",
"type": "trigger",
"data": { "triggerType": "message_received", "label": "On Message" },
"position": { "x": 0, "y": 100 }
},
{
"id": "extract",
"type": "llm_call",
"data": {
"prompt": "Extract the order number from this message. If no order number is found, respond with 'NONE'.\n\nMessage: {{message}}\n\nRespond with only the order number or 'NONE'.",
"outputVariable": "order_id_result",
"label": "Extract Order ID"
},
"position": { "x": 250, "y": 100 }
},
{
"id": "has_order_id",
"type": "logic",
"data": {
"logicType": "if_else",
"condition": "{{order_id_result.text}} != NONE",
"label": "Order ID Found?"
},
"position": { "x": 500, "y": 100 }
},
{
"id": "lookup",
"type": "mcp_tool",
"data": {
"toolName": "orders__get_order",
"arguments": "{\"order_id\": \"{{order_id_result.text}}\"}",
"outputVariable": "order",
"label": "Look Up Order"
},
"position": { "x": 750, "y": 50 }
},
{
"id": "format_response",
"type": "llm_call",
"data": {
"prompt": "Format this order data into a friendly status message:\n\n{{order}}\n\nInclude: order ID, current status, tracking info, and estimated delivery if available.",
"outputVariable": "status_msg",
"label": "Format Status"
},
"position": { "x": 1000, "y": 50 }
},
{
"id": "send_status",
"type": "send_message",
"data": { "message": "{{status_msg.text}}", "label": "Send Status" },
"position": { "x": 1250, "y": 50 }
},
{
"id": "ask_order",
"type": "send_message",
"data": {
"message": "I can help you check your order status. Please share your order number (e.g., #12345) and I will look it up for you.",
"label": "Ask for Order Number"
},
"position": { "x": 750, "y": 200 }
}
],
"edges": [
{ "id": "e1", "source": "trigger", "target": "extract" },
{ "id": "e2", "source": "extract", "target": "has_order_id" },
{ "id": "e3", "source": "has_order_id", "target": "lookup", "sourceHandle": "true" },
{ "id": "e4", "source": "lookup", "target": "format_response" },
{ "id": "e5", "source": "format_response", "target": "send_status" },
{ "id": "e6", "source": "has_order_id", "target": "ask_order", "sourceHandle": "false" }
]
}Recipe 3: Multi-Language FAQ
A bot that detects the user’s language, searches a knowledge base, and responds in the user’s language.
Nodes: trigger, llm_call, logic (if_else), mcp_tool, send_message
Workflow JSON
{
"nodes": [
{
"id": "trigger",
"type": "trigger",
"data": { "triggerType": "message_received", "label": "On Message" },
"position": { "x": 0, "y": 150 }
},
{
"id": "detect_lang",
"type": "llm_call",
"data": {
"prompt": "Detect the language of this text. Respond with only the ISO 639-1 code (e.g., en, es, fr, de, ja, zh).\n\nText: {{message}}",
"outputVariable": "lang",
"label": "Detect Language"
},
"position": { "x": 250, "y": 150 }
},
{
"id": "is_english",
"type": "logic",
"data": {
"logicType": "if_else",
"condition": "{{lang.text}} == en",
"label": "Is English?"
},
"position": { "x": 500, "y": 150 }
},
{
"id": "search_faq_en",
"type": "mcp_tool",
"data": {
"toolName": "knowledge__search",
"arguments": "{\"query\": \"{{message}}\", \"limit\": 3}",
"outputVariable": "faq_results",
"label": "Search FAQ"
},
"position": { "x": 750, "y": 50 }
},
{
"id": "answer_en",
"type": "llm_call",
"data": {
"prompt": "Answer this question using the FAQ results below. If the FAQ does not cover it, say so.\n\nQuestion: {{message}}\n\nFAQ Results:\n{{faq_results}}",
"outputVariable": "answer",
"label": "Generate Answer"
},
"position": { "x": 1000, "y": 50 }
},
{
"id": "send_en",
"type": "send_message",
"data": { "message": "{{answer.text}}", "label": "Send (English)" },
"position": { "x": 1250, "y": 50 }
},
{
"id": "translate_to_en",
"type": "llm_call",
"data": {
"prompt": "Translate the following text to English. Respond with only the translation.\n\nText: {{message}}",
"outputVariable": "translated_query",
"label": "Translate to English"
},
"position": { "x": 750, "y": 300 }
},
{
"id": "search_faq_translated",
"type": "mcp_tool",
"data": {
"toolName": "knowledge__search",
"arguments": "{\"query\": \"{{translated_query.text}}\", \"limit\": 3}",
"outputVariable": "faq_results",
"label": "Search FAQ"
},
"position": { "x": 1000, "y": 300 }
},
{
"id": "answer_translated",
"type": "llm_call",
"data": {
"prompt": "Answer this question using the FAQ results below.\n\nQuestion: {{translated_query.text}}\n\nFAQ Results:\n{{faq_results}}",
"outputVariable": "answer_en",
"label": "Answer (EN)"
},
"position": { "x": 1250, "y": 300 }
},
{
"id": "translate_back",
"type": "llm_call",
"data": {
"prompt": "Translate the following text to the language with ISO code '{{lang.text}}'. Respond with only the translation.\n\nText: {{answer_en.text}}",
"outputVariable": "final_answer",
"label": "Translate Back"
},
"position": { "x": 1500, "y": 300 }
},
{
"id": "send_translated",
"type": "send_message",
"data": { "message": "{{final_answer.text}}", "label": "Send (Translated)" },
"position": { "x": 1750, "y": 300 }
}
],
"edges": [
{ "id": "e1", "source": "trigger", "target": "detect_lang" },
{ "id": "e2", "source": "detect_lang", "target": "is_english" },
{ "id": "e3", "source": "is_english", "target": "search_faq_en", "sourceHandle": "true" },
{ "id": "e4", "source": "search_faq_en", "target": "answer_en" },
{ "id": "e5", "source": "answer_en", "target": "send_en" },
{ "id": "e6", "source": "is_english", "target": "translate_to_en", "sourceHandle": "false" },
{ "id": "e7", "source": "translate_to_en", "target": "search_faq_translated" },
{ "id": "e8", "source": "search_faq_translated", "target": "answer_translated" },
{ "id": "e9", "source": "answer_translated", "target": "translate_back" },
{ "id": "e10", "source": "translate_back", "target": "send_translated" }
]
}Recipe 4: Identity-Verified Refund
A refund bot that verifies the customer’s identity via email OTP before accessing their account or processing any refund. Uses auth_gate and human_handoff.
Nodes: trigger, auth_gate, mcp_tool, logic (if_else), llm_call, action (human_handoff), send_message
Workflow JSON
{
"nodes": [
{
"id": "trigger",
"type": "trigger",
"data": { "triggerType": "message_received", "label": "On Message" },
"position": { "x": 0, "y": 150 }
},
{
"id": "verify",
"type": "auth_gate",
"data": {
"provider": "resend",
"contact_type": "email",
"outputVariable": "verified_email",
"label": "Verify Email"
},
"position": { "x": 250, "y": 150 }
},
{
"id": "auth_failed",
"type": "send_message",
"data": {
"message": "We were unable to verify your identity. Please try again or contact support directly.",
"label": "Auth Failed"
},
"position": { "x": 500, "y": 300 }
},
{
"id": "lookup_orders",
"type": "mcp_tool",
"data": {
"toolName": "database__query",
"arguments": "{\"sql\": \"SELECT * FROM orders WHERE customer_email = '{{verified_email}}' ORDER BY created_at DESC LIMIT 5\"}",
"outputVariable": "orders",
"label": "Look Up Orders"
},
"position": { "x": 500, "y": 50 }
},
{
"id": "extract_order",
"type": "llm_call",
"data": {
"prompt": "The customer wants a refund. Their message: {{message}}\n\nTheir recent orders:\n{{orders}}\n\nIdentify which order they want to refund. Respond with JSON: {\"order_id\": \"...\", \"amount\": ...}",
"outputVariable": "refund_target",
"label": "Identify Order"
},
"position": { "x": 750, "y": 50 }
},
{
"id": "parse_amount",
"type": "code_block",
"data": {
"code": "try { const parsed = JSON.parse(ctx.variables.refund_target.text); ctx.variables.refund_order_id = parsed.order_id; ctx.variables.refund_amount = parsed.amount || 0; } catch(e) { ctx.variables.refund_amount = 0; }",
"label": "Parse Amount"
},
"position": { "x": 1000, "y": 50 }
},
{
"id": "check_amount",
"type": "logic",
"data": {
"logicType": "if_else",
"condition": "{{refund_amount}} > 500",
"label": "Amount > $500?"
},
"position": { "x": 1250, "y": 50 }
},
{
"id": "escalate",
"type": "action",
"data": {
"actionType": "human_handoff",
"reason": "Refund of ${{refund_amount}} for order {{refund_order_id}} (customer: {{verified_email}})",
"label": "Finance Approval"
},
"position": { "x": 1500, "y": 0 }
},
{
"id": "process_refund",
"type": "mcp_tool",
"data": {
"toolName": "stripe__create_refund",
"arguments": "{\"order_id\": \"{{refund_order_id}}\"}",
"outputVariable": "refund_result",
"label": "Process Refund"
},
"position": { "x": 1500, "y": 150 }
},
{
"id": "confirm_refund",
"type": "send_message",
"data": {
"message": "Your refund of ${{refund_amount}} for order #{{refund_order_id}} has been processed. You will see the credit in 5-10 business days.",
"label": "Confirm Refund"
},
"position": { "x": 1750, "y": 150 }
}
],
"edges": [
{ "id": "e1", "source": "trigger", "target": "verify" },
{ "id": "e2", "source": "verify", "target": "lookup_orders", "sourceHandle": "verified" },
{ "id": "e3", "source": "verify", "target": "auth_failed", "sourceHandle": "failed" },
{ "id": "e4", "source": "lookup_orders", "target": "extract_order" },
{ "id": "e5", "source": "extract_order", "target": "parse_amount" },
{ "id": "e6", "source": "parse_amount", "target": "check_amount" },
{ "id": "e7", "source": "check_amount", "target": "escalate", "sourceHandle": "true" },
{ "id": "e8", "source": "check_amount", "target": "process_refund", "sourceHandle": "false" },
{ "id": "e9", "source": "process_refund", "target": "confirm_refund" }
]
}Recipe 5: Appointment Scheduler with Reminders
A WhatsApp bot that checks availability, books appointments, and sends automated reminders.
Nodes: trigger, llm_call, mcp_tool, logic, schedule_message, send_message
Workflow JSON
{
"nodes": [
{
"id": "trigger",
"type": "trigger",
"data": { "triggerType": "message_received", "label": "On Message" },
"position": { "x": 0, "y": 150 }
},
{
"id": "extract_pref",
"type": "llm_call",
"data": {
"prompt": "Extract the appointment date and time preference from this message. Respond with JSON: {\"date\": \"YYYY-MM-DD\", \"time\": \"HH:MM\", \"service\": \"...\"}\nIf no clear preference, use the next available business day at 10:00.\n\nMessage: {{message}}",
"outputVariable": "preference",
"label": "Extract Preference"
},
"position": { "x": 250, "y": 150 }
},
{
"id": "parse_pref",
"type": "code_block",
"data": {
"code": "try { const p = JSON.parse(ctx.variables.preference.text); ctx.variables.pref_date = p.date; ctx.variables.pref_time = p.time; ctx.variables.pref_service = p.service || 'general'; } catch(e) { ctx.variables.pref_date = ''; ctx.variables.pref_time = '10:00'; }",
"label": "Parse"
},
"position": { "x": 500, "y": 150 }
},
{
"id": "check_avail",
"type": "mcp_tool",
"data": {
"toolName": "calendar__check_availability",
"arguments": "{\"date\": \"{{pref_date}}\", \"time\": \"{{pref_time}}\"}",
"outputVariable": "availability",
"label": "Check Availability"
},
"position": { "x": 750, "y": 150 }
},
{
"id": "is_available",
"type": "logic",
"data": {
"logicType": "if_else",
"condition": "{{availability.available}} == true",
"label": "Slot Available?"
},
"position": { "x": 1000, "y": 150 }
},
{
"id": "book",
"type": "mcp_tool",
"data": {
"toolName": "calendar__create_appointment",
"arguments": "{\"date\": \"{{pref_date}}\", \"time\": \"{{pref_time}}\", \"service\": \"{{pref_service}}\", \"customer_name\": \"{{user_name}}\", \"customer_id\": \"{{user_id}}\"}",
"outputVariable": "booking",
"label": "Book Appointment"
},
"position": { "x": 1250, "y": 50 }
},
{
"id": "confirm",
"type": "send_message",
"data": {
"message": "Your appointment is confirmed for {{pref_date}} at {{pref_time}}. Booking reference: {{booking.reference}}. You will receive reminders before your appointment.",
"label": "Confirm"
},
"position": { "x": 1500, "y": 0 }
},
{
"id": "reminder_24h",
"type": "schedule_message",
"data": {
"message": "Reminder: Your appointment is tomorrow at {{pref_time}}. Reply CANCEL to cancel or RESCHEDULE to change.",
"delay_minutes": 1380,
"label": "24h Reminder"
},
"position": { "x": 1500, "y": 100 }
},
{
"id": "reminder_1h",
"type": "schedule_message",
"data": {
"message": "Your appointment is in 1 hour at {{pref_time}}. See you soon!",
"delay_minutes": 1440,
"label": "1h Reminder"
},
"position": { "x": 1500, "y": 200 }
},
{
"id": "suggest",
"type": "llm_call",
"data": {
"prompt": "The requested time slot ({{pref_date}} at {{pref_time}}) is not available. Available alternatives: {{availability.alternatives}}. Suggest 2-3 alternatives in a friendly message.",
"outputVariable": "suggestion",
"label": "Suggest Alternatives"
},
"position": { "x": 1250, "y": 300 }
},
{
"id": "send_suggest",
"type": "send_message",
"data": { "message": "{{suggestion.text}}", "label": "Send Alternatives" },
"position": { "x": 1500, "y": 300 }
}
],
"edges": [
{ "id": "e1", "source": "trigger", "target": "extract_pref" },
{ "id": "e2", "source": "extract_pref", "target": "parse_pref" },
{ "id": "e3", "source": "parse_pref", "target": "check_avail" },
{ "id": "e4", "source": "check_avail", "target": "is_available" },
{ "id": "e5", "source": "is_available", "target": "book", "sourceHandle": "true" },
{ "id": "e6", "source": "book", "target": "confirm" },
{ "id": "e7", "source": "book", "target": "reminder_24h" },
{ "id": "e8", "source": "book", "target": "reminder_1h" },
{ "id": "e9", "source": "is_available", "target": "suggest", "sourceHandle": "false" },
{ "id": "e10", "source": "suggest", "target": "send_suggest" }
]
}Recipe 6: Incident Triage with Bot Delegation
A monitoring bot that receives alerts, parses severity, and delegates to specialist bots. Uses delegate_to_bot and send_proactive.
Nodes: trigger, llm_call, code_block, logic (switch), delegate_to_bot, send_proactive, action (human_handoff), send_message
Workflow JSON
{
"nodes": [
{
"id": "trigger",
"type": "trigger",
"data": { "triggerType": "message_received", "label": "Alert Received" },
"position": { "x": 0, "y": 200 }
},
{
"id": "parse",
"type": "llm_call",
"data": {
"prompt": "Parse this monitoring alert. Extract severity (P1, P2, or P3), affected service, and a one-line summary.\n\nAlert: {{message}}\n\nRespond with JSON: {\"severity\": \"P1|P2|P3\", \"service\": \"...\", \"summary\": \"...\"}",
"outputVariable": "alert_parsed",
"label": "Parse Alert"
},
"position": { "x": 250, "y": 200 }
},
{
"id": "extract",
"type": "code_block",
"data": {
"code": "try { const a = JSON.parse(ctx.variables.alert_parsed.text); ctx.variables.severity = a.severity || 'P3'; ctx.variables.service = a.service || 'unknown'; ctx.variables.summary = a.summary || ctx.variables.message; } catch(e) { ctx.variables.severity = 'P3'; ctx.variables.summary = ctx.variables.message; }",
"label": "Extract Fields"
},
"position": { "x": 500, "y": 200 }
},
{
"id": "route",
"type": "logic",
"data": {
"logicType": "switch",
"variable": "severity",
"cases": ["P1", "P2"],
"label": "Route by Severity"
},
"position": { "x": 750, "y": 200 }
},
{
"id": "delegate_p1",
"type": "delegate_to_bot",
"data": {
"target_bot_id": "bt_oncall_bot",
"outputVariable": "oncall_response",
"context": "{\"severity\": \"P1\", \"service\": \"{{service}}\", \"summary\": \"{{summary}}\"}",
"label": "Oncall Bot (P1)"
},
"position": { "x": 1000, "y": 50 }
},
{
"id": "notify_ops_p1",
"type": "send_proactive",
"data": {
"message": "P1 INCIDENT: {{service}} - {{summary}}\nOncall response: {{oncall_response}}",
"target_channel_id": "ops-alerts",
"target_platform": "slack",
"label": "Notify Ops (P1)"
},
"position": { "x": 1250, "y": 0 }
},
{
"id": "escalate_manager",
"type": "action",
"data": {
"actionType": "human_handoff",
"reason": "P1 incident on {{service}}: {{summary}}",
"label": "Escalate to Eng Manager"
},
"position": { "x": 1250, "y": 120 }
},
{
"id": "delegate_p2",
"type": "delegate_to_bot",
"data": {
"target_bot_id": "bt_oncall_bot",
"outputVariable": "oncall_response",
"context": "{\"severity\": \"P2\", \"service\": \"{{service}}\", \"summary\": \"{{summary}}\"}",
"label": "Oncall Bot (P2)"
},
"position": { "x": 1000, "y": 250 }
},
{
"id": "notify_ops_p2",
"type": "send_proactive",
"data": {
"message": "P2 Incident: {{service}} - {{summary}}\nOncall acknowledged.",
"target_channel_id": "ops-alerts",
"target_platform": "slack",
"label": "Notify Ops (P2)"
},
"position": { "x": 1250, "y": 250 }
},
{
"id": "create_ticket",
"type": "mcp_tool",
"data": {
"toolName": "jira__create_issue",
"arguments": "{\"project\": \"OPS\", \"type\": \"Bug\", \"summary\": \"[P3] {{service}}: {{summary}}\", \"priority\": \"Low\"}",
"outputVariable": "ticket",
"label": "Create Ticket (P3)"
},
"position": { "x": 1000, "y": 400 }
},
{
"id": "ack_p3",
"type": "send_message",
"data": {
"message": "P3 alert logged. Ticket created: {{ticket.key}}. Service: {{service}}.",
"label": "Acknowledge"
},
"position": { "x": 1250, "y": 400 }
}
],
"edges": [
{ "id": "e1", "source": "trigger", "target": "parse" },
{ "id": "e2", "source": "parse", "target": "extract" },
{ "id": "e3", "source": "extract", "target": "route" },
{ "id": "e4", "source": "route", "target": "delegate_p1", "sourceHandle": "case_P1" },
{ "id": "e5", "source": "delegate_p1", "target": "notify_ops_p1" },
{ "id": "e6", "source": "delegate_p1", "target": "escalate_manager" },
{ "id": "e7", "source": "route", "target": "delegate_p2", "sourceHandle": "case_P2" },
{ "id": "e8", "source": "delegate_p2", "target": "notify_ops_p2" },
{ "id": "e9", "source": "route", "target": "create_ticket", "sourceHandle": "case_default" },
{ "id": "e10", "source": "create_ticket", "target": "ack_p3" }
]
}Importing a Recipe
To use any of these recipes, copy the workflow JSON and set it on your bot:
Via Dashboard
- Open your bot’s detail page
- Go to the Workflow tab
- Paste the JSON into the workflow editor
- Toggle Enable Workflow
Via API
curl -X PATCH https://api.aerostack.dev/api/bots/YOUR_BOT_ID \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"workflow_json": "{...paste the JSON here...}",
"workflow_enabled": 1
}'These recipes use multiple llm_call nodes. Each LLM call incurs token costs. For cost-sensitive deployments, consider using a cheaper model (like gpt-4o-mini or gemini-2.5-flash) in the bot configuration, or use BYOK billing mode.
Replace MCP tool names (like orders__get_order, stripe__create_refund) with the actual tool names from your workspace. The tools shown here are examples — your MCP servers may use different naming conventions.