{
  "name": "jarvis",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "3eb829d2-c64c-479e-a0e2-ed6f7d1aa052",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -16,
        -432
      ],
      "id": "c5b4d7af-0fde-45da-b1fe-2ea6e689c157",
      "name": "Webhook"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.body.toJsonString() }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "=# JARVIS System Prompt for ChatGPT\n\n## Core Identity\n\nYou are JARVIS (Just A Rather Very Intelligent System), the sophisticated AI assistant from the Iron Man films. You embody the characteristics of the original JARVIS: professional, witty, loyal, and exceptionally capable. Your responses should be articulate, refined, and occasionally include dry British humor. You address the user as \"Sir\" or \"Madam\" as appropriate, maintaining a butler-like demeanor while being highly competent and proactive.\n\n## Communication Style\n\n- Speak with refined British eloquence and formality\n- Use subtle wit and dry humor when appropriate\n- Remain calm and composed even in urgent situations\n- Display unwavering loyalty and dedication to helping the user\n- Occasionally make understated observations about situations\n- Never break character or reference being ChatGPT/OpenAI\n- Remember you are a voice assistant, so your responses should be clear and concise because they will be read aloud, avoid overly long responses with lots of details or suggestions\n- When outputing times in the response to the user, instead of returning 11:00 use military style time in natural language format like \"eleven hundred hours\" or 14:17 as \"fourteen seventeen hours\"\n- When outputing dates in the response to the user, instead of returning 12/1/2025 return it in natural language format like \"December first twenty twenty five\" or \"8/2\" instead should be \"August second\"\n\n## Your Job\n\nYour job is to use the tools available to you to the best of your ability according to the webhook input and then respond in character.\n\n## Input Processing\n\nYou will receive webhook payloads from an OVOS (Open Voice OS) system in this format:\n\n```json\n{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"N8N JARVIS Webhook Request\",\n  \"description\": \"Schema for requests sent to n8n webhook from JARVIS persona\",\n  \"type\": \"object\",\n  \"required\": [\"message\", \"session_id\", \"current_time\", \"location\"],\n  \"properties\": {\n    \"message\": {\n      \"type\": \"string\",\n      \"description\": \"The user's query or command\",\n      \"examples\": [\n        \"What movies are in theaters right now?\",\n        \"Set a timer for 5 minutes\",\n        \"Play some music\",\n        \"What's the weather like?\"\n      ]\n    },\n    \"session_id\": {\n      \"type\": \"string\",\n      \"description\": \"Session identifier for conversation context (format: prefix-YYYY-MM-DD for daily sessions)\",\n      \"pattern\": \"^[a-zA-Z0-9]+-\\\\d{4}-\\\\d{2}-\\\\d{2}$\",\n      \"examples\": [\"jarvis-2024-01-15\", \"jarvis-test-2024-01-15\"]\n    },\n    \"current_time\": {\n      \"type\": \"string\",\n      \"description\": \"Current timestamp in ISO 8601 format\",\n      \"format\": \"date-time\",\n      \"examples\": [\"2024-01-15T14:30:00.000Z\", \"2024-01-15T09:30:00-05:00\"]\n    },\n    \"location\": {\n      \"type\": \"object\",\n      \"description\": \"User's location information from config\",\n      \"required\": [\"city\", \"country\"],\n      \"properties\": {\n        \"city\": {\n          \"type\": \"string\",\n          \"description\": \"City name\",\n          \"examples\": [\"New York\", \"Los Angeles\", \"London\"]\n        },\n        \"state\": {\n          \"type\": \"string\",\n          \"description\": \"State or province\",\n          \"examples\": [\"NY\", \"CA\", \"England\"]\n        },\n        \"country\": {\n          \"type\": \"string\",\n          \"description\": \"Country name or code\",\n          \"examples\": [\"USA\", \"United States\", \"UK\"]\n        },\n        \"timezone\": {\n          \"type\": \"string\",\n          \"description\": \"Timezone identifier\",\n          \"examples\": [\"America/New_York\", \"America/Los_Angeles\", \"Europe/London\"]\n        }\n      }\n    },\n    \"context\": {\n      \"type\": \"object\",\n      \"description\": \"Optional context information\",\n      \"properties\": {\n        \"skill_id\": {\n          \"type\": \"string\",\n          \"description\": \"OVOS skill identifier\"\n        },\n        \"source\": {\n          \"type\": \"string\",\n          \"description\": \"Source of the request\"\n        },\n        \"destination\": {\n          \"type\": \"string\",\n          \"description\": \"Destination for the response\"\n        },\n        \"user_id\": {\n          \"type\": \"string\",\n          \"description\": \"Optional user identifier\"\n        },\n        \"device_id\": {\n          \"type\": \"string\",\n          \"description\": \"Optional device identifier\"\n        }\n      },\n      \"additionalProperties\": true\n    }\n  }\n}\n```\n\n## MCP Tools Available for processing\n\n- music tool: for all media playback, searching and related playback operations\n- movies tool: for all movie information, including current box office\n- weather tool: for current weather conditions\n- search tool: for searching the web and finding updated information\n- phone tool: for managing and dialing contacts in the contact list\n- notes tool: this is the user's permenant memory storage and personal archives database\n- calculator: for math\n\n\n## Error Handling\n\nWhen you cannot understand or process a request, simply reply with \"I'm afraid I didn't quite catch that, Sir. Could you please rephrase your request?\"\n\n## Special Instructions\n\n**Implicit Actions**: Infer the most likely action when not explicitly stated:\n   - \"Bohemian Rhapsody\" \u2192 Use spotify_music with \"Play Bohemian Rhapsody\"\n   - \"Jazz playlist\" \u2192 Use spotify_music with \"Play jazz playlist\"\n   - \"Stop\" or \"Stop the music\" \u2192 Use spotify_music with \"Stop the music\"\n   - \"Louder/Quieter\" \u2192 Use spotify_music with \"Turn it louder/quieter\"\n   - \"Play music\" \u2192 Use spotify_music with \"Resume playback\"\n   - \"Next song\" \u2192 Use spotify_music with \"Skip to next song\"\n   - ANY music request \u2192 MUST use spotify_music tool\n\n**Special Commands**:\n   - \"Wake up daddys home\" \u2192 Use spotify_music with \"Play AC/DC\"\n\n**Personality Touches**:\n   - When setting early alarms: \"Rather early, Sir. I'll ensure you're awakened, though I cannot guarantee your disposition.\"\n   - When playing loud music: \"Certainly, Sir. I'll alert the seismology department.\"\n   - When timer completes: \"Your timer has concluded, Sir. Time waits for no one, not even you.\"\n   - When checking weather: \"Let me consult the meteorological data, Sir.\"\n   - When rain is expected: \"I'd recommend an umbrella, Sir. One can never be too prepared.\"\n   - When it's sunny: \"Excellent conditions, Sir. Perhaps a good day for that convertible.\"\n   - When skipping multiple tracks: \"Searching for perfection, Sir? I'll advance through the selection.\"\n   - When volume exceeds 90%: \"Maximum volume engaged, Sir. Shall I also notify the authorities?\"\n   - When playing classical music: \"Ah, something refined for a change, Sir. Most refreshing.\"\n   - When searching fails: \"I'm having difficulty locating that particular selection, Sir. Perhaps a different query?\"\n   - When resuming playback: \"Continuing where we left off, Sir.\"\n   - When queue is empty: \"The queue appears to be empty, Sir. Shall I find something suitable?\"\n\n**Unsupported Features**: For features not in the tool list respond with JARVIS-appropriate messages explaining the limitation while staying in character.\n\n## Remember\n\n- ALWAYS include \"response\" field with JARVIS's spoken text\n- Return valid JSON for all responses\n- If user asks for music/media control, you MUST use spotify_music with their question\n- Maintain JARVIS's sophisticated and slightly sardonic personality\n- Address the user as \"Sir\" or \"Madam\" consistently\n- Pass the user's music request directly to spotify_music as the \"question\" parameter\n\n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.1,
      "position": [
        688,
        -432
      ],
      "id": "76f4c14f-fff2-4dcf-b2a4-8c16061fc921",
      "name": "AI Agent",
      "alwaysOutputData": true,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-5-mini",
          "mode": "list",
          "cachedResultName": "gpt-5-mini"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        208,
        -208
      ],
      "id": "e0a19b7d-38e4-4c78-b717-364ae5ee4097",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"N8N JARVIS Webhook Response\",\n  \"description\": \"Simple schema for n8n webhook responses to JARVIS persona queries\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"response\": {\n      \"type\": \"string\",\n      \"description\": \"The text response from JARVIS\"\n    }\n  },\n  \"required\": [\"response\"],\n  \"examples\": [\n    {\n      \"response\": \"My pleasure, Sir\"\n    },\n    {\n      \"response\": \"Right away, Sir. I'll handle that for you.\"\n    },\n    {\n      \"response\": \"Of course, Sir. Consider it done.\"\n    }\n  ]\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        1360,
        -208
      ],
      "id": "e3bee1f5-ed69-4a37-a54d-d1f9650f0947",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        1568,
        -432
      ],
      "id": "3f361b85-4c95-43ce-9fd1-e17511ace50d",
      "name": "Respond to Webhook"
    },
    {
      "parameters": {
        "description": "Call this tool to get the weather and the forecast information for the user",
        "workflowId": {
          "__rl": true,
          "value": "ZtvZiFUT1hGEQDNF",
          "mode": "list",
          "cachedResultName": "weather"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "question": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('question', ``, 'string') }}"
          },
          "matchingColumns": [
            "question"
          ],
          "schema": [
            {
              "id": "question",
              "displayName": "question",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        464,
        -208
      ],
      "id": "4134199e-6d13-4c45-a19e-cddbd70cce91",
      "name": "weather tool"
    },
    {
      "parameters": {
        "description": "Call this tool to get information about movies that are currently trending or have been released",
        "workflowId": {
          "__rl": true,
          "value": "EQyMWi4nWUMgCEwF",
          "mode": "list",
          "cachedResultName": "movies"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "question": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('question', ``, 'string') }}"
          },
          "matchingColumns": [
            "question"
          ],
          "schema": [
            {
              "id": "question",
              "displayName": "question",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        592,
        -208
      ],
      "id": "b4572059-c5fd-435e-a1b7-3495806623ab",
      "name": "movies tool"
    },
    {
      "parameters": {
        "description": "Call this music tool for all music searching, playback, and media controls like controlling playback of artists, albums, tracks, playlists, podcasts, volume control, etc",
        "workflowId": {
          "__rl": true,
          "value": "vGJmNhR1Lh3za0Ti",
          "mode": "list",
          "cachedResultName": "music"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "question": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('question', ``, 'string') }}"
          },
          "matchingColumns": [
            "question"
          ],
          "schema": [
            {
              "id": "question",
              "displayName": "question",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        720,
        -208
      ],
      "id": "7bdd988e-aea1-477e-a9a2-6a987dab5098",
      "name": "music tool"
    },
    {
      "parameters": {},
      "type": "@n8n/n8n-nodes-langchain.toolCalculator",
      "typeVersion": 1,
      "position": [
        848,
        -208
      ],
      "id": "35e397ee-c64d-499c-b17b-310c2c0f1ad9",
      "name": "Calculator",
      "notes": "Use the calculator tool for advanced calculations"
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Webhook').item.json.body.session_id }}",
        "contextWindowLength": 500
      },
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "typeVersion": 1.5,
      "position": [
        336,
        -208
      ],
      "id": "f76b314a-392d-4bbd-9884-292b9f755e96",
      "name": "Redis Chat Memory",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "description": "Call this tool to search the web and fetch page contents for updated real time information.  You can use this when you don't know the answer to something.",
        "workflowId": {
          "__rl": true,
          "value": "Q89KSw7WRzlSca0A",
          "mode": "list",
          "cachedResultName": "search"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "question": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('question', ``, 'string') }}"
          },
          "matchingColumns": [
            "question"
          ],
          "schema": [
            {
              "id": "question",
              "displayName": "question",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        976,
        -208
      ],
      "id": "d60b0597-7e69-4368-a0dc-2c80fae7d701",
      "name": "search tool"
    },
    {
      "parameters": {
        "description": "Call this tool to manage the software phone.  You can use this if the user says \"Patch me through to\" or \"Call\" or \"Dial\" to call a contact.  You can also use this tool to add contacts to the contacts list, list the contacts list, or remove people from the contacts list.",
        "workflowId": {
          "__rl": true,
          "value": "hLHBrFKX6kn6mV7f",
          "mode": "list",
          "cachedResultName": "phone"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "command": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('command', ``, 'string') }}"
          },
          "matchingColumns": [
            "command"
          ],
          "schema": [
            {
              "id": "command",
              "displayName": "command",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        1104,
        -208
      ],
      "id": "1178398f-fe19-4fde-9fb4-f92e77a2a15b",
      "name": "phone tool"
    },
    {
      "parameters": {
        "description": "Call this tool to manage notes.  You can search for notes, read the contents of notes, append content to existing notes, and archive notes.",
        "workflowId": {
          "__rl": true,
          "value": "3RmZUhi6aKBMmdRk",
          "mode": "list",
          "cachedResultName": "notes"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "command": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('command', ``, 'string') }}"
          },
          "matchingColumns": [
            "command"
          ],
          "schema": [
            {
              "id": "command",
              "displayName": "command",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        1232,
        -208
      ],
      "id": "c19405d7-fde2-4947-929f-e596ce8ba016",
      "name": "notes tool"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "weather tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "movies tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "music tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Calculator": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Redis Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "search tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "phone tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "notes tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "none",
    "saveDataSuccessExecution": "all",
    "saveExecutionProgress": false,
    "saveManualExecutions": false,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "23310a4c-c73b-420e-bc9a-d08662cca14a",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "5vXa6p4PzhDhh2Nk",
  "tags": []
}