AutomationFlowsAI & RAG › Battery AI – Daily Optimizer

Battery AI – Daily Optimizer

Battery AI – Daily Optimizer. Uses executeWorkflowTrigger, httpRequest, agent, mcpClientTool. Scheduled trigger; 19 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered19 nodesExecute Workflow TriggerHTTP RequestAgentMcp Client ToolAnthropic Chat
AI & RAG Trigger: Cron / scheduled Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Execute Workflow Trigger recipe pattern — see all workflows that pair these two integrations.

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 →

Download .json
{
  "name": "Battery AI \u2013 Daily Optimizer",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 14 * * *"
            }
          ]
        }
      },
      "id": "d4e31765-e259-405e-ae16-16a7073864c7",
      "name": "Trigger: t\u00e4glich 14:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "typeVersion": 1.3
    },
    {
      "parameters": {},
      "id": "execute-workflow-trigger-id",
      "name": "Wenn manuell aufgerufen",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        0,
        -160
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "url": "http://homeassistant:8123/api/states/input_boolean.ki_batteriesteuerung_aktiv",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "id": "c2bf8cfe-8e8f-491a-b04b-668601762f61",
      "name": "HA: KI-Schalter pr\u00fcfen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        224,
        0
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.state }}",
              "value2": "on"
            }
          ]
        },
        "options": {}
      },
      "id": "9371ce00-bdad-43e2-9b32-bd189445a6df",
      "name": "KI aktiv?",
      "type": "n8n-nodes-base.if",
      "position": [
        448,
        0
      ],
      "typeVersion": 2.3
    },
    {
      "parameters": {
        "url": "http://a0d7b954-influxdb:8086/query",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "db",
              "value": "evcc"
            },
            {
              "name": "q",
              "value": "SELECT integral(\"value\") / 3600000 as energy_kwh FROM \"homePower\" WHERE time > now() - 28d GROUP BY time(1d) fill(none)"
            }
          ]
        },
        "options": {}
      },
      "id": "cc558740-3d4a-4b46-93e7-3e570bf5b5e7",
      "name": "InfluxDB: Verbrauch abfragen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        672,
        0
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "notes": "Liest t\u00e4glichen Hausverbrauch der letzten 28 Tage aus InfluxDB. Credential: InfluxDB evcc (HTTP Basic Auth)."
    },
    {
      "parameters": {
        "url": "http://a0d7b954-influxdb:8086/query",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "db",
              "value": "evcc"
            },
            {
              "name": "q",
              "value": "SELECT integral(\"value\") / 3600000 FROM \"homePower\" WHERE time > now() - 28d GROUP BY time(1h) fill(0)"
            }
          ]
        },
        "options": {}
      },
      "id": "influxdb-lastprofil-daily",
      "name": "InfluxDB: Lastprofil abfragen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        784,
        80
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const data = $('InfluxDB: Verbrauch abfragen').first()?.json ?? {};\nconst profileRaw = $input.first()?.json ?? {};\nconst series = data?.results?.[0]?.series?.[0]?.values ?? [];\n\n// Morgen's Wochentag (0=So, 1=Mo, ..., 6=Sa)\nconst tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1);\nconst targetWeekday = tomorrow.getDay();\n\n// Gleicher Wochentag, Werte > 1 kWh (vollst\u00e4ndige Tage)\nconst sameWeekday = series\n  .filter(([time, kwh]) => new Date(time).getDay() === targetWeekday && kwh > 1)\n  .map(([, kwh]) => kwh);\n\n// Fallback: alle Tage mit Daten\nconst allDays = series\n  .filter(([, kwh]) => kwh > 1)\n  .map(([, kwh]) => kwh);\n\nconst values = sameWeekday.length >= 2 ? sameWeekday : allDays;\nconst avg = values.length > 0\n  ? values.reduce((a, b) => a + b, 0) / values.length\n  : 10;\n\nconst source = sameWeekday.length >= 2\n  ? 'gleicher Wochentag'\n  : allDays.length > 0\n    ? 'Gesamtdurchschnitt'\n    : 'Fallback';\n\nconst avgRounded = Math.round(avg * 10) / 10;\nconst dataDays = sameWeekday.length || allDays.length;\n\n// Lastprofil berechnen (gleicher Wochentag wie morgen, 28d)\nconst profileSeries = profileRaw?.results?.[0]?.series?.[0]?.values ?? [];\nconst offsetHours = -new Date().getTimezoneOffset() / 60;\nconst byHour = {};\nfor (let h = 0; h < 24; h++) byHour[h] = [];\n\nprofileSeries\n  .filter(([time]) => {\n    const local = new Date(new Date(time).getTime() + offsetHours * 3600000);\n    return local.getDay() === targetWeekday;\n  })\n  .forEach(([time, kwh]) => {\n    const local = new Date(new Date(time).getTime() + offsetHours * 3600000);\n    const hour = local.getHours();\n    if (kwh !== null && kwh > 0) byHour[hour].push(kwh);\n  });\n\nconst profile = [];\nfor (let h = 0; h < 24; h++) {\n  const vals = byHour[h];\n  profile.push({\n    hour: h,\n    avg_kwh: vals.length > 0 ? Math.round(vals.reduce((a, b) => a + b, 0) / vals.length * 100) / 100 : 0,\n    samples: vals.length\n  });\n}\n\nconst profileDays = Math.max(...profile.map(p => p.samples), 0);\nconst hasProfile = profileDays >= 4;\n\nconst profileSection = hasProfile\n  ? '\\n\\nSt\u00fcndliches Verbrauchsprofil (gleicher Wochentag, ' + profileDays + ' Messtage, 28d-Durchschnitt):\\n' +\n    profile.map(p => p.hour.toString().padStart(2, '0') + ':00: ' + p.avg_kwh + ' kWh').join(' | ') +\n    '\\n\\nBerechne pro Stunde den Netto-Bedarf (Verbrauch minus PV-Prognose). Stunden mit Netto-Bedarf > 0 brauchen Batterie-Reserve. Plane die Ladestrategie so dass der SoC zu Lastspitzen ausreicht.'\n  : '';\n\nconst prompt = 'Analysiere den aktuellen Zustand der Hausbatterie und optimiere die Ladekosten fuer morgen.\\n\\nVorgehen:\\n1. Rufe getState auf um SoC, Solar-Prognose und aktuelle Situation zu sehen\\n2. Rufe getTariffInfo mit type=grid auf um die Tibber-Preise fuer morgen zu sehen\\n3. Berechne den optimalen Preisschwellwert:\\n   - Verfuegbare Kapazitaet = (1 - SoC/100) * 7.6 kWh\\n   - Energiebedarf = ' + avgRounded + ' kWh (Verbrauchsdaten: ' + source + ', ' + dataDays + ' Messtage) - Solar-Prognose morgen - verfuegbare Kapazitaet\\n   - Wenn Bedarf <= 0: Schwellwert = 0 (kein Netzladen noetig, Solar reicht)\\n   - Wenn Bedarf > 0: Guenstigste Preis-Slots fuer morgen waehlen bis Bedarf gedeckt, Schwellwert = hoechster gewaehlter Preis * 1.05\\n4. Setze den Schwellwert mit setBatteryGridChargeLimit (Wert in EUR/kWh, also ct/100)\\n   - Beispiel: 8.5 ct/kWh = 0.085 EUR/kWh\\n   - Wenn Schwellwert = 0: removeBatteryGridChargeLimit aufrufen\\n5. Antworte mit einer kurzen deutschen Zusammenfassung:\\n   { \"threshold_ct\": <Zahl>, \"reasoning\": \"<Begruendung>\" }' + profileSection;\n\nreturn [{ json: {\n  avg_consumption_kwh: avgRounded,\n  data_days: dataDays,\n  source,\n  prompt\n}}];"
      },
      "id": "33f8f8af-40ea-43c2-aaf0-d5b5affae010",
      "name": "Verbrauch berechnen",
      "type": "n8n-nodes-base.code",
      "position": [
        896,
        0
      ],
      "typeVersion": 2,
      "notes": "Berechnet Durchschnittsverbrauch: bevorzugt gleicher Wochentag (\u22652 Werte), sonst Gesamtdurchschnitt, sonst 10 kWh Fallback."
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.prompt }}",
        "options": {
          "systemMessage": "Du bist ein Energieoptimierungs-Agent f\u00fcr eine Hausbatterie.\nSpecs: 7,6 kWh Kapazit\u00e4t, max. 7 kW Ladeleistung, Einspeiseverg\u00fctung 6,7 ct/kWh.\nDu hast Zugriff auf evcc via MCP-Tools. Nutze sie um Daten zu lesen und Einstellungen zu setzen.\nWichtig: setBatteryGridChargeLimit erwartet den Wert in EUR/kWh (nicht ct). Beispiel: 10 ct = 0.10 EUR.\nGib am Ende IMMER valides JSON zur\u00fcck: { \"threshold_ct\": <Zahl>, \"reasoning\": \"<Text>\" }\nDas Haus hat eine Wallbox mit 2 E-Fahrzeugen. Pr\u00fcfe in getState die loadpoints[]:\n- Ist ein Fahrzeug angeschlossen (vehiclePresent=true)? Addiere dessen verbleibenden Ladeenergiebedarf zum Energiebedarf des Hauses.\n- Ist ein Ladeplan gesetzt (planTime, planEnergy)? Stelle sicher dass der Schwellwert so gew\u00e4hlt wird, dass bis zur planTime genug g\u00fcnstiger Strom f\u00fcr Batterie UND Fahrzeug verf\u00fcgbar ist.\n- Fahrzeugladen hat Priorit\u00e4t gegen\u00fcber Batterie-Netzentladung."
        }
      },
      "id": "dc15163c-265c-4a33-ae4e-2270dcb691d5",
      "name": "Claude Sonnet + evcc MCP",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1120,
        0
      ],
      "typeVersion": 3.1,
      "notes": "Claude hat direkten evcc-Zugriff via MCP. Liest State, analysiert Preise, setzt Schwellwert selbst."
    },
    {
      "parameters": {
        "endpointUrl": "http://192.168.1.8:7070/mcp",
        "options": {}
      },
      "id": "c3b85d64-ef42-4b9f-abde-ea6316f87da7",
      "name": "evcc MCP Tools",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        1328,
        224
      ],
      "typeVersion": 1.2,
      "notes": "Stellt evcc MCP-Tools f\u00fcr Claude bereit. Nur lesende + Batterie-Tools aktiviert."
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "claude-sonnet-4-6",
          "mode": "list",
          "cachedResultName": "Claude Sonnet 4.6"
        },
        "options": {
          "temperature": 0
        }
      },
      "id": "21c09059-223e-4e49-9f29-d64c291a99c3",
      "name": "Claude Sonnet 4.6",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        1120,
        288
      ],
      "typeVersion": 1.3,
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      },
      "notes": "Anthropic Credential muss gesetzt sein."
    },
    {
      "parameters": {
        "jsCode": "// Alle m\u00f6glichen Pfade f\u00fcr die Claude-Antwort probieren\n  const item = $input.first() ?? $input.item;\n  const data = item?.json ?? {};\n\n  const response = data.output\n    ?? data.text\n    ?? data.message\n    ?? data.content\n    ?? JSON.stringify(data);\n\n  let threshold = null;\n  let reasoning = 'Keine Begr\u00fcndung';\n\n  // Versuche JSON-Block zu extrahieren (letzten Block bevorzugen, keine verschachtelten Klammern)\n  const allMatches = [...String(response).matchAll(/\\{[^{}]*\"threshold_ct\"[^{}]*\\}/g)];\n  const jsonMatch = allMatches.length > 0 ? allMatches[allMatches.length - 1][0] : null;\n  if (jsonMatch) {\n    try {\n      const parsed = JSON.parse(jsonMatch);\n      threshold = parseFloat(parsed.threshold_ct);\n      reasoning = parsed.reasoning ?? reasoning;\n    } catch(e) {}\n  }\n\n  // Fallback: Zahl nach threshold_ct suchen\n  if (threshold === null) {\n    const numMatch = String(response).match(/threshold_ct[\"' ]*[:=][\"' ]*(\\d+\\.?\\d*)/);\n    if (numMatch) threshold = parseFloat(numMatch[1]);\n  }\n\n  // Wenn nichts gefunden: Debug-Info ausgeben statt crash\n  if (threshold === null || isNaN(threshold)) {\n    return [{ json: {\n      error: true,\n      debug_response: String(response).slice(0, 1000),\n      debug_keys: Object.keys(data).join(', ')\n    }}];\n  }\n\n  threshold = Math.min(50, Math.max(0, threshold));\n\n  return [{ json: {\n    threshold_ct: threshold,\n    reasoning,\n    timestamp: new Date().toISOString()\n  }}];"
      },
      "id": "59deca75-b384-4ad5-8430-5eeb133a1951",
      "name": "Ergebnis extrahieren",
      "type": "n8n-nodes-base.code",
      "position": [
        1424,
        0
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://homeassistant:8123/api/states/sensor.battery_charge_threshold",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"state\": String($json.threshold_ct), \"attributes\": { \"unit_of_measurement\": \"ct/kWh\", \"friendly_name\": \"Batterie Preisschwellwert (KI)\",\n  \"reasoning\": $json.reasoning, \"last_updated\": $json.timestamp } } }}",
        "options": {}
      },
      "id": "962a7a52-5d81-48ec-b8a2-916128d28950",
      "name": "HA: Status aktualisieren",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1536,
        208
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const usage = $('Claude Sonnet + evcc MCP').first()?.json?.tokenUsage ?? {};\nconst inputTokens = usage.inputTokens ?? usage.prompt_tokens ?? 4500;\nconst outputTokens = usage.outputTokens ?? usage.completion_tokens ?? 500;\nconst cost_usd = (inputTokens / 1000000 * 3) + (outputTokens / 1000000 * 15);\nconst costRounded = Math.round(cost_usd * 100000) / 100000;\nreturn [{ json: {\n  workflow: 'daily',\n  input_tokens: inputTokens,\n  output_tokens: outputTokens,\n  cost_usd: costRounded,\n  timestamp: new Date().toISOString(),\n  line_protocol: 'ai_costs,workflow=daily input_tokens=' + inputTokens + 'i,output_tokens=' + outputTokens + 'i,cost_usd=' + costRounded\n}}];"
      },
      "id": "token-kosten-daily",
      "name": "Token: Kosten berechnen",
      "type": "n8n-nodes-base.code",
      "position": [
        1760,
        208
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://a0d7b954-influxdb:8086/write?db=evcc",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "text/plain",
        "body": "={{ $json.line_protocol }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "id": "influxdb-token-write-daily",
      "name": "InfluxDB: Token-Kosten schreiben",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        1984,
        80
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const now = new Date();\nconst todayUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())).toISOString();\nconst monthUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)).toISOString();\nreturn [{ json: {\n  today_utc: todayUTC,\n  month_utc: monthUTC,\n  query_today: 'SELECT sum(\"cost_usd\") FROM \"ai_costs\" WHERE time >= \\'' + todayUTC + '\\'',\n  query_month: 'SELECT sum(\"cost_usd\") FROM \"ai_costs\" WHERE time >= \\'' + monthUTC + '\\''\n}}];"
      },
      "id": "aggregat-timestamps",
      "name": "Aggregat-Timestamps",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        208
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "url": "http://a0d7b954-influxdb:8086/query",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "db",
              "value": "evcc"
            },
            {
              "name": "q",
              "value": "={{ $json.query_today }}"
            }
          ]
        },
        "options": {}
      },
      "id": "influxdb-kosten-heute",
      "name": "InfluxDB: Kosten heute",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2208,
        208
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "http://a0d7b954-influxdb:8086/query",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "db",
              "value": "evcc"
            },
            {
              "name": "q",
              "value": "={{ $('Aggregat-Timestamps').first().json.query_month }}"
            }
          ]
        },
        "options": {}
      },
      "id": "influxdb-kosten-monat",
      "name": "InfluxDB: Kosten Monat",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2432,
        208
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://homeassistant:8123/api/states/sensor.battery_ai_cost_today",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"state\": String(Math.round(($('InfluxDB: Kosten heute').first()?.json?.results?.[0]?.series?.[0]?.values?.[0]?.[1] ?? 0) * 10000) / 10000), \"attributes\": { \"unit_of_measurement\": \"USD\", \"friendly_name\": \"KI API-Kosten heute\" } } }}",
        "options": {}
      },
      "id": "ha-kosten-heute",
      "name": "HA: Kosten heute aktualisieren",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2656,
        208
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://homeassistant:8123/api/states/sensor.battery_ai_cost_month",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"state\": String(Math.round(($('InfluxDB: Kosten Monat').first()?.json?.results?.[0]?.series?.[0]?.values?.[0]?.[1] ?? 0) * 10000) / 10000), \"attributes\": { \"unit_of_measurement\": \"USD\", \"friendly_name\": \"KI API-Kosten Monat\" } } }}",
        "options": {}
      },
      "id": "ha-kosten-monat",
      "name": "HA: Kosten Monat aktualisieren",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2880,
        208
      ],
      "typeVersion": 4.4,
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Wenn manuell aufgerufen": {
      "main": [
        [
          {
            "node": "HA: KI-Schalter pr\u00fcfen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger: t\u00e4glich 14:00": {
      "main": [
        [
          {
            "node": "HA: KI-Schalter pr\u00fcfen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HA: KI-Schalter pr\u00fcfen": {
      "main": [
        [
          {
            "node": "KI aktiv?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "KI aktiv?": {
      "main": [
        [
          {
            "node": "InfluxDB: Verbrauch abfragen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "InfluxDB: Verbrauch abfragen": {
      "main": [
        [
          {
            "node": "InfluxDB: Lastprofil abfragen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verbrauch berechnen": {
      "main": [
        [
          {
            "node": "Claude Sonnet + evcc MCP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "evcc MCP Tools": {
      "ai_tool": [
        [
          {
            "node": "Claude Sonnet + evcc MCP",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Claude Sonnet 4.6": {
      "ai_languageModel": [
        [
          {
            "node": "Claude Sonnet + evcc MCP",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Claude Sonnet + evcc MCP": {
      "main": [
        [
          {
            "node": "Ergebnis extrahieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ergebnis extrahieren": {
      "main": [
        [
          {
            "node": "HA: Status aktualisieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HA: Status aktualisieren": {
      "main": [
        [
          {
            "node": "Token: Kosten berechnen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Token: Kosten berechnen": {
      "main": [
        [
          {
            "node": "InfluxDB: Token-Kosten schreiben",
            "type": "main",
            "index": 0
          },
          {
            "node": "Aggregat-Timestamps",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregat-Timestamps": {
      "main": [
        [
          {
            "node": "InfluxDB: Kosten heute",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "InfluxDB: Kosten heute": {
      "main": [
        [
          {
            "node": "InfluxDB: Kosten Monat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "InfluxDB: Kosten Monat": {
      "main": [
        [
          {
            "node": "HA: Kosten heute aktualisieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HA: Kosten heute aktualisieren": {
      "main": [
        [
          {
            "node": "HA: Kosten Monat aktualisieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "InfluxDB: Lastprofil abfragen": {
      "main": [
        [
          {
            "node": "Verbrauch berechnen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "3781b882-636b-4e74-ada0-1d194822bccb",
  "id": "qyuXhAXnYTHh80eL",
  "tags": []
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Battery AI – Daily Optimizer. Uses executeWorkflowTrigger, httpRequest, agent, mcpClientTool. Scheduled trigger; 19 nodes.

Source: https://github.com/OZON08/EVCC-KI-Automation/blob/a5798fc4ac05b813c8b6be99a9f993745aad8dff/n8n-workflows/daily-optimizer.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

generate_full_word_documents_with_ai. Uses formTrigger, httpRequest, agent, outputParserStructured. Event-driven trigger; 32 nodes.

Form Trigger, HTTP Request, Agent +7
AI & RAG

This workflow automates tax compliance monitoring and revenue analysis for accounting teams and finance managers handling multi-source income data. It solves the critical problem of manually tracking

n8n, Agent, HTTP Request +5
AI & RAG

This automation workflow transforms Meta advertising data into executive ready presentation decks, eliminating manual report creation while ensuring stakeholders receive consistent performance insight

Agent, Mcp Client Tool, Google Drive +3
AI & RAG

The AI-Powered Shopify SEO Content Automation is an enterprise-grade workflow that transforms product content creation for e-commerce stores. This sophisticated multi-agent system integrates GPT-4o, C

Perplexity Tool, Memory Buffer Window, Agent +15
AI & RAG

This workflow is for beauty salons who want consistent, high‑quality social media content without writing every post manually. It also suits agencies and automation builders who manage multiple beauty

Telegram, Google Sheets Trigger, Agent +26