> ## Documentation Index
> Fetch the complete documentation index at: https://docs.langdock.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Code

> Schreibe JavaScript- oder Python-Code direkt aus deinem Workflow heraus.

## Überblick

Mit dem Code-Node verarbeitest du Workflow-Daten direkt mit eigenem JavaScript- oder Python-Code. Nutze ihn, wenn Standard-Nodes nicht ausreichen, zum Beispiel für Berechnungen, Formatierungen, Validierungen, Dateiverarbeitung oder individuelle Geschäftslogik.

<img src="https://mintcdn.com/langdock-34/cWyoB3RsITQmAUnM/images/workflows/nodes/code.jpg?fit=max&auto=format&n=cWyoB3RsITQmAUnM&q=85&s=34341587cc99e314a2275f9db1f888b9" alt="Code" width="1920" height="903" data-path="images/workflows/nodes/code.jpg" />

## Wann du den Code-Node verwenden solltest

**Die Code-Node ist perfekt für:**

* Datentransformationen und Formatierung
* Mathematische Berechnungen
* Benutzerdefinierte Geschäftslogik
* JSON-Parsing und Manipulation
* Datenvalidierung und -bereinigung
* Datums-/Zeitoperationen
* Dateiverarbeitung mit JavaScript und Python

**Die Code-Node ist nicht ideal für:**

* KI-Analyse (verwende Agent-Node)
* Externe API-Aufrufe (verwende HTTP-Request-Node)
* Einfache Bedingungen (verwende Condition-Node)
* Lange oder interaktive Analysen (verwende Datenanalyse)

## Konfiguration

**Sprache**: Wähle aus, ob du deinen Code in JavaScript oder Python schreiben möchtest.

**Code-Editor**: Schreibe deine Transformationslogik in der ausgewählten Sprache im Code-Editor, der sich öffnet, wenn du den Code-Node auswählst

**Auf vorherige Nodes zugreifen**: Outputs von vorherigen Nodes sind als Variablen im Code-Node verfügbar. Die verfügbaren Variablennamen werden oben im Code-Editor angezeigt. Wie du den Output des Code-Nodes später verwendest, findest du unter [Auf Code-Output zugreifen](#auf-code-output-zugreifen).

## Beispiele

### Statistiken berechnen

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Zugriff auf Daten von vorherigen Nodes
  const scores = agent.output.structured.scores || [];

  // Statistiken berechnen
  const average = scores.reduce((a, b) => a + b, 0) / scores.length;
  const max = Math.max(...scores);
  const min = Math.min(...scores);

  // Ergebnis zurückgeben
  return {
    average_score: average.toFixed(2),
    highest_score: max,
    lowest_score: min,
    grade: average >= 90 ? "A" : average >= 80 ? "B" : "C"
  };
  ```

  ```python Python theme={null}
  # Zugriff auf Daten von vorherigen Nodes
  agent_output = agent.get("output", {})
  scores = agent_output.get("structured", {}).get("scores", [])

  if not scores:
      return {
          "average_score": 0,
          "highest_score": None,
          "lowest_score": None,
          "grade": "N/A"
      }

  # Statistiken berechnen
  average = sum(scores) / len(scores)
  print(f"{len(scores)} Scores verarbeitet")

  # Ergebnis zurückgeben
  return {
      "average_score": round(average, 2),
      "highest_score": max(scores),
      "lowest_score": min(scores),
      "grade": "A" if average >= 90 else "B" if average >= 80 else "C"
  }
  ```
</CodeGroup>

### Daten validieren und bereinigen

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Zugriff auf Formulardaten
  const email = trigger.output.email || "";
  const amount = trigger.output.amount || 0;

  // Validieren
  if (!email.includes("@")) {
    throw new Error("Ungültiges E-Mail-Format");
  }

  if (amount <= 0) {
    throw new Error("Betrag muss größer als null sein");
  }

  // Bereinigen und zurückgeben
  return {
    email: email.trim().toLowerCase(),
    amount: parseFloat(amount.toFixed(2)),
    validated: true
  };
  ```

  ```python Python theme={null}
  # Zugriff auf Formulardaten
  trigger_output = trigger.get("output", {})
  email = trigger_output.get("email", "")
  amount = trigger_output.get("amount", 0)

  # Validieren
  if "@" not in email:
      raise ValueError("Ungültiges E-Mail-Format")

  if amount <= 0:
      raise ValueError("Betrag muss größer als null sein")

  # Bereinigen und zurückgeben
  return {
      "email": email.strip().lower(),
      "amount": round(float(amount), 2),
      "validated": True
  }
  ```
</CodeGroup>

### Arrays transformieren und filtern

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Zugriff auf Daten von vorherigem Node
  const customers = trigger.output.customers || [];

  // Aktive Kunden filtern
  const activeCustomers = customers.filter(c => c.status === "active");

  // Daten transformieren
  const processed = activeCustomers.map(customer => ({
    id: customer.id,
    name: `${customer.firstName} ${customer.lastName}`.trim(),
    email: customer.email.toLowerCase(),
    tier: customer.totalSpent > 1000 ? "premium" : "standard"
  }));

  return {
    customers: processed,
    total: processed.length,
    premiumCount: processed.filter(c => c.tier === "premium").length
  };
  ```

  ```python Python theme={null}
  # Zugriff auf Daten von vorherigem Node
  customers = trigger.get("output", {}).get("customers", [])

  # Aktive Kunden filtern
  active_customers = [
      customer for customer in customers
      if customer.get("status") == "active"
  ]

  # Daten transformieren
  processed = [
      {
          "id": customer.get("id"),
          "name": f"{customer.get('firstName', '')} {customer.get('lastName', '')}".strip(),
          "email": customer.get("email", "").lower(),
          "tier": "premium" if customer.get("totalSpent", 0) > 1000 else "standard"
      }
      for customer in active_customers
  ]

  return {
      "customers": processed,
      "total": len(processed),
      "premiumCount": len([c for c in processed if c["tier"] == "premium"])
  }
  ```
</CodeGroup>

### Datumsoperationen

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Zugriff auf Event-Daten
  const events = trigger.output.events || [];
  const now = new Date();

  const processedEvents = events.map(event => {
    const eventDate = new Date(event.date);
    const daysUntil = Math.ceil((eventDate - now) / (1000 * 60 * 60 * 24));

    return {
      title: event.title,
      date: eventDate.toISOString(),
      formatted: eventDate.toLocaleDateString("de-DE", {
        weekday: "long",
        year: "numeric",
        month: "long",
        day: "numeric"
      }),
      daysUntil: daysUntil,
      isUpcoming: daysUntil >= 0,
      isThisWeek: daysUntil >= 0 && daysUntil <= 7
    };
  });

  return {
    events: processedEvents,
    upcomingCount: processedEvents.filter(e => e.isUpcoming).length,
    thisWeekCount: processedEvents.filter(e => e.isThisWeek).length
  };
  ```

  ```python Python theme={null}
  from datetime import datetime, timezone

  # Zugriff auf Event-Daten
  events = trigger.get("output", {}).get("events", [])
  now = datetime.now(timezone.utc)

  processed_events = []
  for event in events:
      event_date = datetime.fromisoformat(event["date"].replace("Z", "+00:00"))
      days_until = (event_date.date() - now.date()).days

      processed_events.append({
          "title": event.get("title"),
          "date": event_date.isoformat(),
          "formatted": event_date.strftime("%A, %B %d, %Y"),
          "daysUntil": days_until,
          "isUpcoming": days_until >= 0,
          "isThisWeek": 0 <= days_until <= 7
      })

  return {
      "events": processed_events,
      "upcomingCount": len([e for e in processed_events if e["isUpcoming"]]),
      "thisWeekCount": len([e for e in processed_events if e["isThisWeek"]])
  }
  ```
</CodeGroup>

### JSON-Verarbeitung

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Verschachteltes JSON von API-Response
  const apiResponse = http_request.output || {};

  // Verschachtelte Daten extrahieren und vereinfachen
  const users = apiResponse.data?.users || [];

  const flattened = users.map(user => ({
    id: user.id,
    name: `${user.first_name || ""} ${user.last_name || ""}`.trim(),
    email: user.contact?.email || "",
    city: user.address?.city || "Unbekannt",
    isActive: user.status === "active"
  }));

  return {
    users: flattened,
    total: flattened.length,
    activeCount: flattened.filter(u => u.isActive).length
  };
  ```

  ```python Python theme={null}
  # Verschachteltes JSON von API-Response
  api_response = http_request.get("output", {})

  # Verschachtelte Daten extrahieren und vereinfachen
  users = api_response.get("data", {}).get("users", [])

  flattened = [
      {
          "id": user.get("id"),
          "name": f"{user.get('first_name', '')} {user.get('last_name', '')}".strip(),
          "email": user.get("contact", {}).get("email", ""),
          "city": user.get("address", {}).get("city", "Unbekannt"),
          "isActive": user.get("status") == "active"
      }
      for user in users
  ]

  return {
      "users": flattened,
      "total": len(flattened),
      "activeCount": len([user for user in flattened if user["isActive"]])
  }
  ```
</CodeGroup>

### Aggregieren und Zusammenfassen

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Verkaufsdaten von vorherigem Node
  const sales = http_request.output.sales || [];

  // Nach Kategorie gruppieren
  const byCategory = {};
  sales.forEach(sale => {
    const cat = sale.category || "Sonstiges";
    if (!byCategory[cat]) {
      byCategory[cat] = { total: 0, count: 0, items: [] };
    }
    byCategory[cat].total += sale.amount || 0;
    byCategory[cat].count += 1;
    byCategory[cat].items.push(sale);
  });

  // Zusammenfassung berechnen
  const summary = Object.entries(byCategory).map(([category, data]) => ({
    category,
    totalRevenue: data.total.toFixed(2),
    orderCount: data.count,
    averageOrder: (data.total / data.count).toFixed(2)
  }));

  // Nach Umsatz sortieren
  summary.sort((a, b) => parseFloat(b.totalRevenue) - parseFloat(a.totalRevenue));

  return {
    summary: summary,
    topCategory: summary[0]?.category || "Keine",
    grandTotal: sales.reduce((sum, s) => sum + (s.amount || 0), 0).toFixed(2)
  };
  ```

  ```python Python theme={null}
  # Verkaufsdaten von vorherigem Node
  sales = http_request.get("output", {}).get("sales", [])

  # Nach Kategorie gruppieren
  by_category = {}
  for sale in sales:
      category = sale.get("category") or "Sonstiges"
      if category not in by_category:
          by_category[category] = {"total": 0, "count": 0, "items": []}

      by_category[category]["total"] += sale.get("amount", 0)
      by_category[category]["count"] += 1
      by_category[category]["items"].append(sale)

  # Zusammenfassung berechnen
  summary = [
      {
          "category": category,
          "totalRevenue": f"{data['total']:.2f}",
          "orderCount": data["count"],
          "averageOrder": f"{data['total'] / data['count']:.2f}"
      }
      for category, data in by_category.items()
  ]

  # Nach Umsatz sortieren
  summary.sort(key=lambda row: float(row["totalRevenue"]), reverse=True)

  return {
      "summary": summary,
      "topCategory": summary[0]["category"] if summary else "Keine",
      "grandTotal": f"{sum(sale.get('amount', 0) for sale in sales):.2f}"
  }
  ```
</CodeGroup>

### Datei mit JavaScript erstellen

JavaScript kann Workflow-Dateien erzeugen, indem es ein `files`-Array zurückgibt. Jeder Eintrag muss `fileName`, `mimeType` und entweder `text` (für Text-, CSV- oder JSON-Inhalte) oder `base64` (für binäre Inhalte) enthalten. Die Laufzeit lädt die Dateien hoch und hängt sie am Node-Output unter `_files` an.

```javascript JavaScript theme={null}
const customers = trigger.output.customers || [];
const activeCustomers = customers.filter((c) => c.status === "active");

const csv = [
  ["id", "email"],
  ...activeCustomers.map((c) => [c.id, (c.email || "").toLowerCase()]),
]
  .map((row) => row.map((cell) => `"${String(cell).replaceAll('"', '""')}"`).join(","))
  .join("\n");

return {
  active_count: activeCustomers.length,
  files: [
    {
      fileName: "active_customers.csv",
      mimeType: "text/csv",
      text: csv,
    },
  ],
};
```

### Dateien aus vorherigen Nodes lesen

Dateien aus vorherigen Nodes, zum Beispiel Formular-Uploads oder Action-Outputs, liegen im Python-Arbeitsverzeichnis bereit. Jedes Datei-Objekt enthält einen `path`, den du direkt an `open()` übergeben kannst, sowie den ursprünglichen Dateinamen unter `_metadata.name`.

```python Python theme={null}
# Datei-Upload-Felder enthalten eine Liste von Datei-Objekten
files = trigger.get("output", {}).get("resume", [])

processed = []
for file in files:
    with open(file["path"], "rb") as f:
        content = f.read()

    processed.append({
        "name": file["_metadata"]["name"],
        "size_bytes": len(content)
    })

return {"files_processed": processed}
```

### Datei mit Python erstellen

Dateien, die du mit Python im Arbeitsverzeichnis erstellst, werden dem Node-Output unter `_files` hinzugefügt.

```python Python theme={null}
import csv

customers = trigger.get("output", {}).get("customers", [])
active_customers = [c for c in customers if c.get("status") == "active"]

with open("active_customers.csv", "w", newline="") as file:
    writer = csv.DictWriter(file, fieldnames=["id", "email"])
    writer.writeheader()

    for customer in active_customers:
        writer.writerow({
            "id": customer.get("id"),
            "email": customer.get("email", "").lower()
        })

print(f"CSV mit {len(active_customers)} Kunden erstellt")

return {
    "active_count": len(active_customers),
    "file_name": "active_customers.csv"
}
```

## Auf Code-Output zugreifen

Verwende den Code-Node-Namen, um auf zurückgegebene Werte aus JavaScript oder Python in nachfolgenden Nodes zuzugreifen:

```handlebars theme={null}
{{code_node_name.output.customer}}
{{code_node_name.output.total}}
{{code_node_name.output.formatted_date}}
{{code_node_name.output.processed_items[0].name}}
```

Dateien, die JavaScript zurückgibt oder die du mit Python im Arbeitsverzeichnis erstellst, sind unter `_files` verfügbar:

```handlebars theme={null}
{{code_node_name.output._files[0]._metadata.name}}
```

## Sprachfunktionen

Die Funktionen des Code-Nodes hängen von der ausgewählten Sprache ab.

### JavaScript

JavaScript läuft in einer sicheren Sandbox-Umgebung mit integrierten Utility-Funktionen:

* **`ld.request()`**: HTTP-Anfragen ausführen
* **`ld.log()`**: Debugging-Informationen ausgeben
* **Datenkonvertierungen**: CSV-, Parquet-, Arrow-Format-Konvertierungen
* **Datei-Erstellung**: Gib ein `files`-Array zurück, um erzeugte Dateien unter `_files` bereitzustellen
* **Standard-JavaScript**: JSON-, Date-, Math-, Array-, Object-Methoden

<Card title="Vollständige Utilities-Referenz" icon="code" href="/de/using-langdock/guides/integrations/sandbox-utilities">
  Sieh dir alle verfügbaren Sandbox-Utilities an, einschließlich Datenkonvertierungen, SQL-Validierung, Kryptographie und mehr.
</Card>

### Python

Python läuft in einer isolierten Umgebung ohne Internetzugang.

* Verwende `return` auf oberster Ebene, um den Node-Output festzulegen
* Verwende `print()`, um Logs zu schreiben
* Verwende vorinstallierte Daten- und Dokumentbibliotheken wie pandas, numpy, openpyxl und pypdf
* Greife auf vorherige Node-Outputs als Variablen zu, wenn ihre Slugs gültige Python-Bezeichner sind
* Lies Dateien aus vorherigen Nodes, indem du `file["path"]` an `open()` übergibst
* Speichere Dateien im Arbeitsverzeichnis, um sie unter `_files` bereitzustellen
* Läuft ohne Internetzugang

Die JavaScript-Utilities `ld.*` sind in Python nicht verfügbar.

## Best Practices

<AccordionGroup>
  <Accordion title="Gib strukturierte Objekte zurück">
    Gib Daten als Objekte zurück für einfachen Zugriff in späteren Nodes. Das macht es einfach, spezifische Werte in nachfolgenden Nodes mit Punkt-Notation zu referenzieren.
  </Accordion>

  <Accordion title="Handle fehlende Daten">
    Verwende `||`, Optional Chaining oder Python `.get()`, um Standardwerte bereitzustellen und Fehler zu verhindern, wenn Daten undefined oder null sind.
  </Accordion>

  <Accordion title="Verwende Error Handling">
    Umschließe riskante Operationen mit `try/catch` in JavaScript oder `try/except` in Python. Das hilft dir, Workflow-Fehler zu verhindern und aussagekräftige Fehlermeldungen bereitzustellen.
  </Accordion>

  <Accordion title="Halte es einfach">
    Komplexe Logik könnte in einem Agent-Node besser aufgehoben sein. Verwende Code-Nodes für unkomplizierte Transformationen und Berechnungen, nicht für Aufgaben, die Intelligenz oder Kontextverständnis erfordern.
  </Accordion>

  <Accordion title="Füge Kommentare hinzu">
    Dokumentiere, was dein Code macht, für zukünftige Referenz. Klare Kommentare helfen dir und deinem Team, die Logik zu verstehen, wenn der Workflow später erneut besucht wird.
  </Accordion>
</AccordionGroup>

## Limits

Jeder Code-Node hat ein **Limit von 5 MiB** für die kombinierten Eingaben, die er von vorherigen Nodes erhält. Bevor dein Code ausgeführt wird, misst Langdock die Größe aller Outputs der vorgelagerten Nodes, auf die der Code-Node zugreifen kann. Überschreiten diese 5 MiB, schlägt der Node mit einer Fehlermeldung fehl und dein Code wird nicht ausgeführt.

Häufige Ursachen:

* Ein Loop-Node, der die Outputs vieler Iterationen in einem einzigen Array sammelt.
* Ein vorgelagerter Node, der eine sehr große API-Antwort, Dateiinhalte oder einen großen Datensatz zurückgibt.
* Tief verschachtelte Objekte, deren Größe nicht sicher gemessen werden kann.

Wenn du an dieses Limit stößt, kannst du Folgendes tun:

* Verkleinere den Output des vorgelagerten Nodes, indem du filterst, zusammenfasst oder nur die benötigten Felder auswählst.
* Verarbeite weniger Elemente pro Iteration in einem vorhergehenden Loop-Node.
* Deaktiviere die Output-Sammlung im vorhergehenden Loop-Node, wenn du dessen aggregierte Ergebnisse nicht benötigst.

## Nächste Schritte

<CardGroup cols={2}>
  <Card title="Agent" icon="brain" href="/de/using-langdock/workflows/nodes/agent-node">
    Verwende KI für intelligente Verarbeitung
  </Card>

  <Card title="HTTP Request" icon="globe" href="/de/using-langdock/workflows/nodes/http-request-node">
    Hole externe Daten ab
  </Card>

  <Card title="Datenanalyse" icon="chart-bar" href="/de/using-langdock/guides/data-analysis">
    Analysiere Daten mit einem Agent
  </Card>
</CardGroup>
