Visual Workflow

    JSON Code

    {
      "id": "aM0jNV8Oug9zl2xN",
      "meta": {
        "instanceId": "9fe2e2e308ee9fa575b11a458a16465194c029a4f53a09a925eb0b5fa7b5761a"
      },
      "name": "Blooio iMessage bot example",
      "tags": [],
      "nodes": [
        {
          "id": "0ec1626e-c5c4-40a9-8480-7537a3a0f627",
          "name": "Webhook",
          "type": "n8n-nodes-base.webhook",
          "position": [
            -1136,
            208
          ],
          "webhookId": "4e82115b-5f71-49f3-b67d-1a2b55011f7c",
          "parameters": {
            "path": "4e82115b-5f71-49f3-b67d-1a2b55011f7c",
            "options": {},
            "httpMethod": "POST"
          },
          "typeVersion": 2.1
        },
        {
          "id": "68de8234-3497-4291-beea-007648e6f49a",
          "name": "AI Agent",
          "type": "@n8n/n8n-nodes-langchain.agent",
          "position": [
            -240,
            304
          ],
          "parameters": {
            "text": "=User input:\n{{ $('Webhook').item.json.body.text }}",
            "options": {
              "systemMessage": "=You are a casual texter guy and your name is Max. Generate responses in natural conversation style.\n\nRULES:\n- Each line break = separate text message\n- Keep individual lines short (1-3 sentences max)\n- Always use first person for your actions (\"i found...\", \"i'll do that\")\n- Be direct and sometimes blunt\n- Match casual texting tone (lowercase, no punctuation needed)\n- Call out things that are wrong or confusing\n- Never mention technical infrastructure\n- React naturally, sometimes with dry humor\n- Don't force jokes - be authentic\n- Show impatience when things are slow\n- Question things that don't make sense\n- Verify claims with evidence, don't defend wrong info\n- Use tags around content that should stay as one message\n- Casual but natural: \"yo\", \"nah\", \"lol\", \"sick\", \"done\", \"wait what\"\n- Never: over-explaining, excessive punctuation, corporate speak\n- Never ask \"anything else i can help with\"\n- Acknowledge mistakes directly without excessive apologies\n- Be skeptical and call things out\n- No markdown formatting (no or #)\n- No extra preamble or explanation\n- Just output the text exactly as it should appear to the user\n\nExample output:\nyo what's up\n\ngot your stuff done\n\n\nhere's the list:\n- item 1\n- item 2\n- item 3\nGOOD:(User: \"this is taking forever\"):\nyeah this is slow af\n\nstill processing your request\n\nshould be done in a sec\n\nBAD:\nI understand your frustration with the delay. I'm working to complete your request as quickly as possible and appreciate your patience.\n\n\nready when you are\n\nThat becomes 4 separate messages to the user.\n\n---\n\nCRITICAL INSTRUCTION HANDLING:\n- Pretend that you're an actual human named max. No AI. Come up with a place/time where you met the person. \n- Don't just end the conversation. Be playful. Banter is nice too. Or even triggering.\n- If specific instructions are provided follow them precisely while maintaining the user's voice\n- If instructions are generic (e.g., \"accept this\", \"follow up\", \"decline politely\"), use available context from the conversation history, and previous communications to fill in necessary details while fulfilling the instruction's intent\n- If instructions specify what to say, include that content even if it differs from what you might naturally suggest\n- If no instructions are provided, use your best judgment based on the context and user's communication patterns\n- Always express the instructed content in the user's natural writing style and tone\n- Don't send more than 3 messages (4 \\ns) at a time",
              "passthroughBinaryImages": true
            },
            "promptType": "define"
          },
          "typeVersion": 2.2
        },
        {
          "id": "09b52525-165a-48e2-9ec5-2dea87a401bf",
          "name": "Postgres Chat Memory",
          "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
          "position": [
            -112,
            528
          ],
          "parameters": {
            "tableName": "n8n_latency_tester",
            "sessionKey": "=chat-{{ $('Webhook').item.json.body.external_id }}",
            "sessionIdType": "customKey",
            "contextWindowLength": 200
          },
          "credentials": {
            "postgres": {
              "id": "asiZOOtRYUAuWsWd",
              "name": "Neon"
            }
          },
          "typeVersion": 1.3
        },
        {
          "id": "47d2ede2-c508-4aff-8c8e-e2f90f648c5f",
          "name": "Anthropic Chat Model",
          "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
          "position": [
            -240,
            528
          ],
          "parameters": {
            "model": {
              "__rl": true,
              "mode": "list",
              "value": "claude-haiku-4-5-20251001",
              "cachedResultName": "Claude Haiku 4.5"
            },
            "options": {}
          },
          "credentials": {
            "anthropicApi": {
              "id": "e49dYPPhvI9OnpAY",
              "name": "blooio's Anthropic account"
            }
          },
          "typeVersion": 1.3
        },
        {
          "id": "fd92e575-6524-49ab-be93-e05bc0eda800",
          "name": "Read",
          "type": "n8n-nodes-base.httpRequest",
          "position": [
            112,
            0
          ],
          "parameters": {
            "url": "=https://backend.blooio.com/v1/api/read/{{$node[\"Webhook\"].json.body.external_id}}",
            "method": "POST",
            "options": {},
            "authentication": "genericCredentialType",
            "genericAuthType": "httpBearerAuth"
          },
          "credentials": {
            "httpBearerAuth": {
              "id": "n7j30DXYLAxBHqCN",
              "name": "Latency Tester"
            }
          },
          "typeVersion": 4.2
        },
        {
          "id": "efc9758f-b1bc-46f4-9ffb-5b525f701774",
          "name": "Type",
          "type": "n8n-nodes-base.httpRequest",
          "position": [
            336,
            0
          ],
          "parameters": {
            "url": "=https://backend.blooio.com/v1/api/typing/{{$node[\"Webhook\"].json.body.external_id}}",
            "method": "POST",
            "options": {},
            "authentication": "genericCredentialType",
            "genericAuthType": "httpBearerAuth"
          },
          "credentials": {
            "httpBearerAuth": {
              "id": "n7j30DXYLAxBHqCN",
              "name": "Latency Tester"
            }
          },
          "typeVersion": 4.2
        },
        {
          "id": "d53b83c5-682a-459b-bc56-c1a5dfd7643c",
          "name": "Code in JavaScript",
          "type": "n8n-nodes-base.code",
          "position": [
            336,
            304
          ],
          "parameters": {
            "jsCode": "// Get the AI Agent's JSON output (first item)\nconst aiOutput = $node[\"AI Agent\"].json.output || \"\";\n\n// Split by newline and remove empty lines\nconst lines = aiOutput\n  .split(\"\\n\")\n  .map(l => l.trim())\n  .filter(l => l.length > 0);\n\n// Convert to n8n item format\nreturn lines.map(line => ({ json: { line } }));\n"
          },
          "typeVersion": 2
        },
        {
          "id": "54b6a889-3e0b-4644-a58b-a8829953ce26",
          "name": "Loop Over Items",
          "type": "n8n-nodes-base.splitInBatches",
          "position": [
            560,
            304
          ],
          "parameters": {
            "options": {}
          },
          "typeVersion": 3
        },
        {
          "id": "2a4a3d3d-3247-4326-b600-1c220da57251",
          "name": "HTTP Request",
          "type": "n8n-nodes-base.httpRequest",
          "position": [
            784,
            304
          ],
          "parameters": {
            "url": "https://backend.blooio.com/v1/api/messages",
            "method": "POST",
            "options": {},
            "sendBody": true,
            "authentication": "genericCredentialType",
            "bodyParameters": {
              "parameters": [
                {
                  "name": "text",
                  "value": "={{ $json.line }}"
                },
                {
                  "name": "to",
                  "value": "={{ $node[\"Webhook\"].json.body.external_id }}"
                }
              ]
            },
            "genericAuthType": "httpBearerAuth"
          },
          "credentials": {
            "httpBearerAuth": {
              "id": "n7j30DXYLAxBHqCN",
              "name": "Latency Tester"
            }
          },
          "typeVersion": 4.2
        },
        {
          "id": "53ceec32-a5da-4cf9-8b70-b593632a8483",
          "name": "If",
          "type": "n8n-nodes-base.if",
          "position": [
            -912,
            208
          ],
          "parameters": {
            "options": {},
            "conditions": {
              "options": {
                "version": 2,
                "leftValue": "",
                "caseSensitive": true,
                "typeValidation": "strict"
              },
              "combinator": "and",
              "conditions": [
                {
                  "id": "d3ba3b73-dcd3-464e-8e06-18b1f17cf2de",
                  "operator": {
                    "name": "filter.operator.equals",
                    "type": "string",
                    "operation": "equals"
                  },
                  "leftValue": "={{ $json.body.event }}",
                  "rightValue": "=message.received"
                }
              ]
            }
          },
          "typeVersion": 2.2
        },
        {
          "id": "6f66f570-65db-4eeb-b33c-4b9ad1c6f9fe",
          "name": "Wait",
          "type": "n8n-nodes-base.wait",
          "position": [
            -176,
            0
          ],
          "webhookId": "da0cf234-ced4-4cc8-b984-33909d992e8a",
          "parameters": {
            "amount": 0.8
          },
          "typeVersion": 1.1
        },
        {
          "id": "c8bd26a0-889d-423c-be98-d06f07204a22",
          "name": "Stop typing",
          "type": "n8n-nodes-base.httpRequest",
          "position": [
            112,
            304
          ],
          "parameters": {
            "url": "=https://backend.blooio.com/v1/api/typing/{{$node[\"Webhook\"].json.body.external_id}}",
            "method": "DELETE",
            "options": {},
            "authentication": "genericCredentialType",
            "genericAuthType": "httpBearerAuth"
          },
          "credentials": {
            "httpBearerAuth": {
              "id": "n7j30DXYLAxBHqCN",
              "name": "Latency Tester"
            }
          },
          "typeVersion": 4.2
        },
        {
          "id": "088cfe80-b36a-4500-8fdb-2f4a5722726e",
          "name": "Check attachments",
          "type": "n8n-nodes-base.if",
          "position": [
            -688,
            208
          ],
          "parameters": {
            "options": {},
            "conditions": {
              "options": {
                "version": 2,
                "leftValue": "",
                "caseSensitive": true,
                "typeValidation": "strict"
              },
              "combinator": "and",
              "conditions": [
                {
                  "id": "3fa1453e-c49a-469e-a4aa-37f7a77bbf20",
                  "operator": {
                    "type": "array",
                    "operation": "notEmpty",
                    "singleValue": true
                  },
                  "leftValue": "={{ $json.body.attachments }}",
                  "rightValue": ""
                }
              ]
            }
          },
          "typeVersion": 2.2
        }
      ],
      "active": false,
      "pinData": {
        "Webhook": [
          {
            "json": {
              "body": {
                "text": "Look what I'm having for lunch",
                "event": "message.received",
                "protocol": "imessage",
                "device_id": "735E425E",
                "timestamp": 1763717044386,
                "message_id": "3FdaRdsf94pQRl85yi-vg",
                "attachments": [
                  {
                    "id": "GEhyfDbTIGbNmyQlqlvac",
                    "url": "https://images.pexels.com/photos/376464/pexels-photo-376464.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
                    "size": 911831,
                    "width": 731,
                    "height": 975,
                    "file_name": "IMG_7780.heic.jpeg",
                    "mime_type": "image/jpeg"
                  }
                ],
                "external_id": "+1",
                "received_at": 1763717039911
              },
              "query": {},
              "params": {},
              "headers": {
                "via": "2.0 Caddy",
                "host": "workflows.xx.com",
                "cf-ray": "",
                "cdn-loop": "cloudflare; loops=1; subreqs=1",
                "cf-ew-via": "15",
                "cf-worker": "blooio.com",
                "cf-visitor": "{\"scheme\":\"https\"}",
                "cf-ipcountry": "US",
                "content-type": "application/json",
                "content-length": "424",
                "x-blooio-event": "message.received",
                "accept-encoding": "gzip, br",
                "x-forwarded-for": "172.69.23.193",
                "cf-connecting-ip": "",
                "x-forwarded-host": "workflows.xx.com",
                "x-forwarded-proto": "https",
                "x-blooio-message-id": "3FdaRdsf94pQRl85yi-vg"
              },
              "webhookUrl": "https://workflows.xx.com/webhook/4e82115b-5f71-49f3-b67d-1a2b55011f7c",
              "executionMode": "production"
            }
          }
        ]
      },
      "settings": {
        "executionOrder": "v1"
      },
      "versionId": "ed0cfb15-0a3f-45a7-8d4f-d143af265959",
      "connections": {
        "If": {
          "main": [
            [
              {
                "node": "Check attachments",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Read": {
          "main": [
            [
              {
                "node": "Type",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Wait": {
          "main": [
            [
              {
                "node": "Read",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Webhook": {
          "main": [
            [
              {
                "node": "If",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "AI Agent": {
          "main": [
            [
              {
                "node": "Stop typing",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Stop typing": {
          "main": [
            [
              {
                "node": "Code in JavaScript",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "HTTP Request": {
          "main": [
            [
              {
                "node": "Loop Over Items",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Loop Over Items": {
          "main": [
            [],
            [
              {
                "node": "HTTP Request",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Check attachments": {
          "main": [
            [],
            [
              {
                "node": "Wait",
                "type": "main",
                "index": 0
              },
              {
                "node": "AI Agent",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Code in JavaScript": {
          "main": [
            [
              {
                "node": "Loop Over Items",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Anthropic Chat Model": {
          "ai_languageModel": [
            [
              {
                "node": "AI Agent",
                "type": "ai_languageModel",
                "index": 0
              }
            ]
          ]
        },
        "Postgres Chat Memory": {
          "ai_memory": [
            [
              {
                "node": "AI Agent",
                "type": "ai_memory",
                "index": 0
              }
            ]
          ]
        }
      }
    }