{
  "name": "02 - AI Agent Chat",
  "nodes": [
    {
      "id": "n0",
      "name": "Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1,
      "position": [
        100,
        300
      ],
      "parameters": {}
    },
    {
      "id": "n1",
      "name": "Get Brain Context",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        320,
        300
      ],
      "parameters": {
        "method": "GET",
        "url": "=http://host.docker.internal:4242/brain/context",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $json.chatId }}"
            },
            {
              "name": "message",
              "value": "={{ encodeURIComponent($json.message) }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 10000
        }
      }
    },
    {
      "id": "n2",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        560,
        300
      ],
      "parameters": {
        "promptType": "define",
        "text": "={{ $('Trigger').item.json.message }}",
        "systemMessage": "={{ $('Get Brain Context').item.json.system_prompt }}\n\nCurrent time: {{ $now.toISO() }}\nOwner chat_id: {{ $('Trigger').item.json.chatId }}",
        "options": {
          "maxIterations": 8,
          "returnIntermediateSteps": false,
          "passthroughBinaryImages": false
        }
      }
    },
    {
      "id": "n2-memory",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        560,
        480
      ],
      "parameters": {
        "sessionKey": "={{ $('Trigger').item.json.chatId }}",
        "contextWindowLength": 20
      }
    },
    {
      "id": "n2-model",
      "name": "Gemini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        400,
        480
      ],
      "parameters": {
        "modelName": "gemini-2.0-flash-001",
        "options": {
          "maxOutputTokens": 2048,
          "temperature": 0.7
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "tool-execute",
      "name": "Mac Agent Execute",
      "type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
      "typeVersion": 1.1,
      "position": [
        730,
        480
      ],
      "parameters": {
        "method": "POST",
        "url": "http://host.docker.internal:4242/execute",
        "name": "execute",
        "description": "Execute actions on the owner's Mac. Tools: shell (run commands), file_read, file_write, notify (macOS notification), open_url, brain_note (remember a fact), brain_recall (search memory), brain_stats, brain_new_session.\nPass: {\"tool\": \"<tool_name>\", \"args\": {\"chat_id\": \"<chatId>\", ...tool_args}}",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "tool",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('tool', 'The tool name to execute', 'string') }}"
            },
            {
              "name": "args",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('args', 'Tool arguments as JSON object', 'json') }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 35000
        },
        "placeholderDefinitions": {
          "values": [
            {
              "name": "tool",
              "description": "Tool name: shell, file_read, file_write, notify, open_url, brain_note, brain_recall, brain_stats, brain_new_session",
              "type": "string"
            },
            {
              "name": "args",
              "description": "Tool arguments object. Always include chat_id for brain tools. For shell: {\"command\": \"...\"}. For brain_note: {\"fact\": \"...\", \"category\": \"...\", \"chat_id\": \"...\"}. For brain_recall: {\"query\": \"...\", \"chat_id\": \"...\"}.",
              "type": "json"
            }
          ]
        }
      }
    },
    {
      "id": "n3",
      "name": "Send Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        800,
        300
      ],
      "parameters": {
        "chatId": "={{ $('Trigger').item.json.chatId }}",
        "text": "={{ $json.output }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "continueOnFail": true
    },
    {
      "id": "n4",
      "name": "Save to Brain",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1020,
        300
      ],
      "parameters": {
        "method": "GET",
        "url": "http://host.docker.internal:4242/brain/save-get",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $('Trigger').item.json.chatId }}"
            },
            {
              "name": "role",
              "value": "user"
            },
            {
              "name": "content",
              "value": "={{ encodeURIComponent($('Trigger').item.json.message) }}"
            },
            {
              "name": "provider",
              "value": "gemini-agent"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 5000
        }
      },
      "continueOnFail": true
    },
    {
      "id": "n4b",
      "name": "Save AI Reply",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1020,
        420
      ],
      "parameters": {
        "method": "GET",
        "url": "http://host.docker.internal:4242/brain/save-get",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $('Trigger').item.json.chatId }}"
            },
            {
              "name": "role",
              "value": "assistant"
            },
            {
              "name": "content",
              "value": "={{ encodeURIComponent($('AI Agent').item.json.output) }}"
            },
            {
              "name": "provider",
              "value": "gemini-agent"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 5000
        }
      },
      "continueOnFail": true
    },
    {
      "id": "n5",
      "name": "Extract Facts",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1240,
        300
      ],
      "parameters": {
        "method": "GET",
        "url": "http://host.docker.internal:4242/brain/extract",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $('Trigger').item.json.chatId }}"
            },
            {
              "name": "user_text",
              "value": "={{ encodeURIComponent($('Trigger').item.json.message) }}"
            },
            {
              "name": "ai_text",
              "value": "={{ encodeURIComponent($('AI Agent').item.json.output) }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 20000
        }
      },
      "continueOnFail": true
    },
    {
      "id": "n-error",
      "name": "Error Handler",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        800,
        500
      ],
      "parameters": {
        "chatId": "={{ $('Trigger').item.json.chatId }}",
        "text": "Hmm, couldn't reach my brain right now. Try again in a moment? \ud83d\ude43",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Trigger": {
      "main": [
        [
          {
            "node": "Get Brain Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Brain Context": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Send Reply",
            "type": "main",
            "index": 0
          }
        ]
      ],
      "error": [
        [
          {
            "node": "Error Handler",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Reply": {
      "main": [
        [
          {
            "node": "Save to Brain",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save AI Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Brain": {
      "main": [
        [
          {
            "node": "Extract Facts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Windows Buffer Memory": {},
    "Gemini Model": {},
    "Mac Agent Execute": {}
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": ""
  },
  "meta": {
    "description": "Agentic AI chat via n8n AI Agent node (Gemini 2.0 Flash). Reply-first ordering: user gets response before save/extract. Fallback error handler sends friendly message if AI Agent fails."
  }
}