Eigene Flow-Operations in Directus mit dem Extension SDK bauen

Directus Flows decken viele Automatisierungsfälle bereits mit Standard-Operations ab. Daten lesen, Daten schreiben, Bedingungen prüfen, Webhooks aufrufen oder JavaScript ausführen – für viele Workflows reicht das vollkommen aus.

Irgendwann entsteht jedoch häufig ein wiederkehrender Spezialfall:

  • eine interne API soll immer gleich angesprochen werden
  • eine Datentransformation taucht in mehreren Flows auf
  • ein komplexer Prüfprozess soll nicht ständig per Run Script kopiert werden
  • eine eigene Operation soll im Flow Editor sauber konfigurierbar sein

Dann lohnt sich eine eigene Flow-Operation.

Mit dem Directus Extension SDK können Sie solche Operations als wiederverwendbare Erweiterung bauen, im Data Studio konfigurieren und bei Bedarf intern oder über den Marketplace verteilen.

Wenn Sie zunächst das Grundprinzip von Triggern, Operations und Data Chains verstehen möchten, empfehlen wir die Directus Flows Anleitung.

Wann eine eigene Operation nötig ist

Nicht jede individuelle Logik benötigt sofort eine eigene Extension.

Oft reicht eine bestehende Operation oder ein kleines Run Script.

Eine Custom Operation lohnt sich dann, wenn Logik wiederverwendbar, wartbar und klar konfigurierbar sein soll.

Wiederverwendung statt Run-Script-Copy-Paste

Die Run-Script-Operation ist praktisch.

Sie eignet sich für:

  • kleine Berechnungen
  • einfache Transformationen
  • schnelle Prototypen

Sie wird problematisch, wenn derselbe Code in vielen Flows auftaucht.

Dann entstehen typische Wartungsprobleme:

  • Änderungen müssen an mehreren Stellen erfolgen
  • Fehler werden mehrfach kopiert
  • Tests sind schwierig
  • Verantwortlichkeiten verschwimmen

Eine eigene Operation kapselt diese Logik zentral.

Aufruf eigener Microservices ohne Generic Webhook

Natürlich kann Directus externe Systeme per Webhook Request URL aufrufen.

Für wiederkehrende interne APIs ist das aber oft zu generisch.

Eine eigene Operation kann:

  • Authentifizierung kapseln
  • Header automatisch setzen
  • Fehler standardisieren
  • Payloads validieren
  • Response-Daten normalisieren

Dadurch wird der Flow Editor deutlich sauberer.

Spezielle Datentransformationen

Typische Beispiele:

  • ERP-Artikelnummern normalisieren
  • Preislisten transformieren
  • Adressdaten validieren
  • Kundensegmente berechnen
  • KI-Antworten strukturieren

Wenn diese Logik fachlich relevant ist, sollte sie nicht als versteckter JavaScript-Block im Flow liegen.

 

Extension-SDK Grundlagen

Directus Extensions folgen einer klaren Struktur.

Für Flow-Operations sind vor allem zwei Dateien wichtig:

  • app.ts
  • api.ts

Diese Trennung ist eine der häufigsten Stolperfallen.

app.ts: Die Oberfläche im Data Studio

Die Datei app.ts beschreibt, wie die Operation im Directus Data Studio aussieht.

Dazu gehören:

  • ID
  • Name
  • Icon
  • Beschreibung
  • Eingabefelder
  • Validierungen
  • Vorschau

Kurz gesagt:

app.ts ist die UI-Konfiguration.

api.ts: Die Server-Logik

Die Datei api.ts enthält die eigentliche Ausführung.

Hier passiert die Logik:

  • Daten entgegennehmen
  • Optionen auswerten
  • externe API aufrufen
  • Directus Services nutzen
  • Ergebnis zurückgeben

Kurz gesagt:

api.ts ist die Runtime-Logik.

Lokale Entwicklung mit create-directus-extension

Der schnellste Einstieg erfolgt über das Directus-CLI-Tool.

Beispiel:

npx create-directus-extension

Danach wählen Sie:

Operation

und idealerweise:

TypeScript

Für produktive Projekte empfehlen wir TypeScript, weil Directus-Typen und Optionsstrukturen deutlich besser wartbar werden.

 

Projektstruktur

Eine einfache Operation sieht typischerweise so aus:

directus-extension-send-internal-api/
├── src/
│ ├── app.ts
│ └── api.ts
├── package.json
├── tsconfig.json
└── README.md

Wichtig:

  • app.ts definiert die Darstellung im Flow Builder
  • api.ts definiert die Ausführung auf Serverseite
  • package.json enthält Extension-Metadaten
  • Build-Ergebnis wird in Directus installiert

 

Sandboxing

Directus unterstützt sandboxed Extensions. Das ist besonders wichtig, wenn Erweiterungen veröffentlicht oder in sicherheitskritischen Umgebungen eingesetzt werden.

Sandboxing begrenzt, was eine Operation darf.

Beispielsweise:

  • Netzwerkzugriffe
  • Zugriff auf Umgebungsvariablen
  • Zugriff auf Directus Services

Für Marketplace-Extensions sind deklarierte Sandbox-Permissions besonders wichtig.

Ohne korrekt deklarierte Permissions kann die Operation im Marketplace nicht sauber geprüft und angezeigt werden.

 

app.ts: UI-Konfiguration der Operation

Die UI-Datei beschreibt, wie Ihre Operation im Flow Editor erscheint.

Ein einfaches Beispiel:

export default {
id: 'send-internal-api',
name: 'Send to Internal API',
icon: 'send',
description: 'Sendet Daten an eine interne API.',
overview: ({ url, method }) => [
{
label: 'URL',
text: url,
},
{
label: 'Methode',
text: method,
},
],
options: [
{
field: 'url',
name: 'API URL',
type: 'string',
meta: {
width: 'full',
interface: 'input',
required: true,
},
},
{
field: 'method',
name: 'HTTP Method',
type: 'string',
schema: {
default_value: 'POST',
},
meta: {
width: 'half',
interface: 'select-dropdown',
options: {
choices: [
{ text: 'POST', value: 'POST' },
{ text: 'PUT', value: 'PUT' },
{ text: 'PATCH', value: 'PATCH' },
],
},
},
},
],
};

ID, Name und Icon

Die id sollte stabil bleiben. Sie ist die technische Referenz der Operation. Der name ist die sichtbare Bezeichnung im Flow Editor. Das icon hilft, die Operation visuell zu unterscheiden.

Options-Schema

Über options definieren Sie die Felder, die später im Data Studio konfigurierbar sind.

Typische Felder:

  • URL
  • API-Key
  • Methode
  • Mapping
  • Timeout
  • Retry-Verhalten

Dadurch wird die Operation für Nicht-Entwickler nutzbar.

Vorschau-Template

Mit overview können Sie die wichtigsten Einstellungen direkt im Flow Builder anzeigen.

Das ist besonders hilfreich bei komplexen Flows.

 

api.ts: Server-Logik der Operation

Die Runtime-Datei führt die Operation aus.

Ein einfaches Beispiel:

type Options = {
url: string;
method: 'POST' | 'PUT' | 'PATCH';
};

export default {
id: 'send-internal-api',
handler: async (options: Options, context: any) => {
const { url, method } = options;
const { data } = context;

const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});

if (!response.ok) {
throw new Error(`Internal API failed with status ${response.status}`);
}

return await response.json();
},
};

Handler-Signatur

Der Handler erhält typischerweise:

  • Optionen aus dem Data Studio
  • Flow-Kontext
  • Data Chain
  • Directus Services

Die Operation sollte immer ein Ergebnis zurückgeben.

Dieses Ergebnis wird Teil der Data Chain und steht nachfolgenden Operations zur Verfügung.

Zugriff auf Directus Services

In Custom Operations können Directus Services genutzt werden, etwa um:

  • Items zu lesen
  • Items zu schreiben
  • Rollen zu prüfen
  • Benutzerinformationen zu laden

Das ist besonders nützlich, wenn die Operation nicht nur externe APIs anspricht, sondern direkt mit Directus-Daten arbeiten soll.

Fehlerbehandlung

Fehler sollten explizit geworfen werden.

Beispiel:

if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}

Dadurch wird der Flow sauber als fehlgeschlagen markiert.

Für produktive Setups empfiehlt sich zusätzlich:

  • Logging
  • Retry-Strategie
  • Fehler-Collection
  • Monitoring

 

Beispiel: Operation “Send to Internal API”

Nehmen wir an, Sie möchten Kundendaten an einen internen Pricing-Service senden.

Der Flow soll:

  1. durch eine Kundenerstellung starten
  2. Kundendaten an die Custom Operation übergeben
  3. Pricing-Service aufrufen
  4. Ergebnis in der Data Chain zurückgeben

app.ts

export default {
id: 'send-pricing-service',
name: 'Send to Pricing Service',
icon: 'price_check',
description: 'Sendet Kundendaten an den internen Pricing-Service.',
options: [
{
field: 'endpoint',
name: 'Endpoint',
type: 'string',
meta: {
interface: 'input',
width: 'full',
required: true,
},
},
{
field: 'apiKey',
name: 'API Key',
type: 'string',
meta: {
interface: 'input',
width: 'full',
required: true,
},
},
],
};

api.ts

type Options = {
endpoint: string;
apiKey: string;
};

export default {
id: 'send-pricing-service',
handler: async (options: Options, context: any) => {
const { endpoint, apiKey } = options;
const payload = context.data;

const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
body: JSON.stringify(payload),
});

if (!response.ok) {
return {
success: false,
status: response.status,
message: await response.text(),
};
}

const result = await response.json();

return {
success: true,
pricing: result,
};
},
};

Test mit lokalem Flow

Zum Testen:

  1. Extension lokal bauen
  2. Directus neu starten
  3. Flow anlegen
  4. Custom Operation auswählen
  5. Testdaten übergeben
  6. Ausführung im Flow Log prüfen

Wichtig:

Testen Sie nicht nur den Erfolgsfall.

Prüfen Sie auch:

  • Timeout
  • falscher API-Key
  • leere Payload
  • ungültige Response
  • Service nicht erreichbar

 

Build und Installation

Typischer Build:

npm run build

Danach wird das Build-Ergebnis in den Directus-Extensions-Ordner kopiert.

Beispiel:

/extensions/operations/send-pricing-service/

Nach einem Neustart steht die Operation im Flow Builder zur Verfügung.

 

Distribution

Eigene Operations können intern oder öffentlich verteilt werden.

NPM Publishing

Für interne Teams empfiehlt sich ein privates NPM-Paket.

Vorteile:

  • Versionierung
  • CI/CD-fähig
  • einfache Installation
  • Rollback möglich

Marketplace-Eintrag

Für öffentliche Extensions kann ein Marketplace-Eintrag erstellt werden.

Dafür wichtig:

  • klare Beschreibung
  • README
  • Screenshots
  • Lizenz
  • Versionierung
  • Sandbox-Permissions

Sandbox-Permissions deklarieren

Marketplace-Extensions benötigen saubere Permission-Angaben.

Beispiele:

{
"permissions": {
"network": ["https://api.example.com"],
"env": ["INTERNAL_API_KEY"]
}
}

Fehlende Permissions führen dazu, dass die Operation nicht korrekt ausgeführt oder nicht akzeptiert wird.

 

Best Practices

TypeScript verwenden

TypeScript reduziert Fehler und verbessert Wartbarkeit.

Gerade bei Optionen und Response-Strukturen lohnt sich der Mehraufwand.

Keine Secrets hart codieren

API-Keys gehören nicht in den Code.

Besser:

  • Environment Variables
  • Directus Settings
  • Secret Manager

Kleine Operations bauen

Eine Operation sollte genau eine Aufgabe erfüllen.

Nicht: Validieren, transformieren, API aufrufen, E-Mail senden

Besser: Eine Operation je Verantwortlichkeit

Flow-Logs ernst nehmen

Custom Operations sollten gut nachvollziehbare Ergebnisse zurückgeben.

So bleibt Debugging möglich.

 

Custom Operation oder Custom Endpoint?

Eine häufige Frage lautet:

Wann baue ich eine Operation und wann einen Endpoint?

Custom Operation

Geeignet für:

  • Flow-Schritte
  • interne Automatisierung
  • wiederverwendbare Prozesslogik

Custom Endpoint

Geeignet für:

  • externe APIs
  • eigene REST-Routen
  • Frontend-spezifische Endpunkte

Faustregel:

Wenn die Logik innerhalb eines Flows genutzt wird, bauen Sie eine Operation.

Wenn externe Systeme die Logik direkt aufrufen sollen, bauen Sie einen Endpoint.

 

Fazit

Eigene Flow-Operations sind der richtige Weg, wenn Directus-Flows über Standardbausteine hinausgehen und wiederverwendbare Logik benötigen.

Sie verhindern Copy-Paste in Run-Script-Operations, kapseln API-Aufrufe und machen komplexe Prozesse für Fachanwender konfigurierbar.

Das wichtigste Architekturprinzip lautet:

  • app.ts definiert die Oberfläche
  • api.ts enthält die Logik
  • Sandbox-Permissions definieren, was erlaubt ist

Wer diese Trennung sauber einhält, kann Directus Flows gezielt erweitern und daraus eine robuste Automatisierungsplattform machen.

Der nächste sinnvolle Schritt: Prüfen Sie, wie KI-Agenten-Workflows eigene Operations nutzen können, um Daten kontrolliert zu lesen, zu transformieren und Aktionen auszulösen.

FAQ

Was unterscheidet eine Custom Operation von einer Custom Endpoint Extension?

Eine Custom Operation wird innerhalb von Directus Flows genutzt. Ein Custom Endpoint stellt eine eigene API-Route bereit, die von externen Systemen oder Frontends aufgerufen werden kann.

Kann ich Node-Module in einer sandboxed Operation nutzen?

Nur eingeschränkt. Sandboxed Extensions sind bewusst limitiert. Externe Abhängigkeiten und Berechtigungen müssen explizit erlaubt und sauber deklariert werden.

Wie deklariere ich Sandbox-Permissions?

Sandbox-Permissions werden in den Extension-Metadaten definiert. Dort legen Sie fest, auf welche Netzwerkziele, Umgebungsvariablen oder Ressourcen die Extension zugreifen darf.

Wie veröffentliche ich meine Operation im Marketplace?

Sie benötigen ein sauberes NPM-Paket, Dokumentation, Versionierung, Lizenzinformationen und deklarierte Sandbox-Permissions. Anschließend kann die Extension für den Marketplace eingereicht werden.

Sollte ich Custom Operations in TypeScript oder JavaScript schreiben?

Für produktive Projekte ist TypeScript empfehlenswert, weil Optionen, Responses und Directus-Kontexte besser typisiert werden können.