The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Upwork Inbox Watcher \u00b7 AI replies",
"nodes": [
{
"id": "bb000000-0000-4000-8000-000000000001",
"name": "\u25b6 Run now",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-360,
540
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000002",
"name": "\ud83d\udd52 Every 15 min",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-360,
760
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 15
}
]
}
},
"typeVersion": 1.2
},
{
"id": "bb000000-0000-4000-8000-000000000003",
"name": "\u2460 Fetch unread chats",
"type": "n8n-nodes-base.httpRequest",
"position": [
40,
620
],
"parameters": {
"url": "http://localhost:4178/api/messages",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "unread",
"value": "1"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "bb000000-0000-4000-8000-000000000004",
"name": "\u2461 Split + skip mine",
"type": "n8n-nodes-base.code",
"position": [
420,
620
],
"parameters": {
"jsCode": "// one item per unread room where the CLIENT (not you) sent last\nconst rooms = ($input.first().json.rooms) || [];\nreturn rooms.filter(r => r && !r.from_me).map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "bb000000-0000-4000-8000-000000000005",
"name": "\u2462 Draft reply (LLM)",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
800,
620
],
"parameters": {
"url": "http://localhost:4178/api/reply",
"method": "POST",
"options": {
"timeout": 240000
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "room_id",
"value": "={{ $json.id }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "bb000000-0000-4000-8000-000000000006",
"name": "\u2463 Assemble alerts",
"type": "n8n-nodes-base.code",
"position": [
1180,
620
],
"parameters": {
"jsCode": "// pair each room with its drafted reply\nconst rooms = $('\u2461 Split + skip mine').all().map(i=>i.json);\nconst replies = $input.all().map(i=>i.json);\nreturn rooms.map((r,idx)=>({ json: { room: r.name, unread: r.unread, client_message: r.last_message, suggested_reply: (replies[idx]||{}).reply || '(draft pending)', room_id: r.id } }));"
},
"typeVersion": 2
},
{
"id": "bb000000-0000-4000-8000-000000000007",
"name": "\ud83d\udce4 Notify (Slack/email)",
"type": "n8n-nodes-base.noOp",
"position": [
1560,
620
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000008",
"name": "note-in",
"type": "n8n-nodes-base.stickyNote",
"position": [
20,
420
],
"parameters": {
"color": 4,
"width": 720,
"height": 140,
"content": "## \u2460 WATCH INBOX\nEvery 15 min, pull **unread** rooms and keep only chats where the client messaged last."
},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000009",
"name": "note-llm",
"type": "n8n-nodes-base.stickyNote",
"position": [
780,
420
],
"parameters": {
"color": 2,
"width": 340,
"height": 140,
"content": "## \u2461 AI REPLY (Codex, free)\nDraft a suggested reply per chat. Nothing is sent \u2014 you approve first."
},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000010",
"name": "note-out",
"type": "n8n-nodes-base.stickyNote",
"position": [
1160,
420
],
"parameters": {
"color": 6,
"width": 760,
"height": 140,
"content": "## \u2462 ALERT\nBundle chat + suggested reply. Swap the last node for Slack / email / Telegram."
},
"typeVersion": 1
}
],
"connections": {
"\u25b6 Run now": {
"main": [
[
{
"node": "\u2460 Fetch unread chats",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd52 Every 15 min": {
"main": [
[
{
"node": "\u2460 Fetch unread chats",
"type": "main",
"index": 0
}
]
]
},
"\u2460 Fetch unread chats": {
"main": [
[
{
"node": "\u2461 Split + skip mine",
"type": "main",
"index": 0
}
]
]
},
"\u2461 Split + skip mine": {
"main": [
[
{
"node": "\u2462 Draft reply (LLM)",
"type": "main",
"index": 0
}
]
]
},
"\u2462 Draft reply (LLM)": {
"main": [
[
{
"node": "\u2463 Assemble alerts",
"type": "main",
"index": 0
}
]
]
},
"\u2463 Assemble alerts": {
"main": [
[
{
"node": "\ud83d\udce4 Notify (Slack/email)",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Upwork Inbox Watcher · AI replies. Uses httpRequest. Event-driven trigger; 10 nodes.
Source: https://github.com/Majboor/upwork-mcp-cli/blob/main/examples/n8n/upwork-inbox-watcher.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow is for anyone who is using N8N. It's especially helpful if you are a DevOps and your N8N instance is self hosted. If you carea lot about security and number of failed executions and at t
This n8n workflow monitors significant register, financial, and news-related events for German companies. It takes a list of companies (for example from a CRM or lead list), resolves them via the Impl
[](https://xqus.relezy.com/haveibeenpwnedcom-breaches) Security professionals Developers Individuals interested in data breach awareness Automated monitoring for new breaches Proactive identity protec
Stay ahead of credential expirations by automatically detecting Entra ID application client secrets and certificates that are about to expire, and sending a neatly formatted email report.
This n8n template shows how to upload a file in your Google Drive desired folder, compress it with the iLovePDF tool and move the compressed file to another folder.