Integrieren · E3 · 7 Stufen

Funktionen & HTTP-Services mit ScriptEngine

Track E dockt AuxData an die Außenwelt an. In E4 baust du die ScriptEngine-Mechanik selbst: das Modell, die Sprache ES5.1, die Module mit ihren Signaturen, Umgebungsvariablen, den HTTP-Service-Editor und eine vollständige, robuste Funktion.

Was du in diesem Tutorial baust

Wir bauen die Preisabfrage-/E-Mail-Funktion aus C5 als eigenständiges, robustes Modul nach — eine ScriptEngine-Funktion, die einen Parameter validiert, per HTTP einen externen Dienst abfragt, das Ergebnis protokolliert und über einen sauberen Fehlerpfad immer einen definierten String zurückliefert. Dazu kommt der passende HTTP-Service im Editor.

Voraussetzung: Track B, gut ergänzt durch C5 (HTTP/Funktion/MCP im Workflow), und ein Grundverständnis von JavaScript. Keine echten Secrets, Tokens oder Endpunkte — alle Zugangsdaten liegen in Umgebungsvariablen (api_token, db_password) bzw. als ${env.NAME}-Platzhalter.

Abgrenzung zu C5: C5 zeigt die Nutzung von HTTP-Service und Funktion als Vor-/Nachverarbeitung im Workflow. E4 vertieft die Mechanismen selbst. Das Programmierhandbuch (ScriptEngine) ist Primärquelle für Syntax, Module und Signaturen; AH 7.1/7.2 ergänzt Editor und Sicherheit.

Quellen und Stand

Geprüft gegen das Programmierhandbuch der ScriptEngine (Einführung, ECMAScript-5.1-Referenz, Umgebungsvariablen, Module, Code-Beispiele, Best Practices, Tutorial „Erste Funktion erstellen") sowie das Administrator-Handbuch Kapitel 7.1 (HTTP-Services) und 7.2 (Funktionen).

Stufe 1 von 7

ScriptEngine-Modell

Wie eine Funktion läuft — und warum jeder Parameter ein String ist.

1Otto-Engine und ES5.1-Sandbox

Die ScriptEngine basiert auf der Otto-JavaScript-Engine und unterstützt ECMAScript 5.1. Sie läuft als Sandbox ohne Dateisystem- oder Netz-IO außerhalb der eingebauten Module. (PH Einführung; AH 7.2)

Du schreibst keine vollständige Datei, sondern nur den Rumpf einer Funktion. Die Plattform legt einen künstlichen Funktionskopf um deinen Code und ruft ihn mit den übergebenen Parametern auf.

In Klartext: Dein Code läuft in einer abgeschotteten Mini-JavaScript-Umgebung — kein Internet- oder Dateizugriff außer über die freigegebenen Module. Du schreibst nur den Inhalt der Funktion; den Rahmen drumherum setzt AuxData automatisch.

2Funktionssignatur & String-Konvertierung

Die Plattform umschließt deinen Code etwa so — du lieferst nur den markierten Rumpf:

// Künstlicher Kopf der Plattform (nur zur Veranschaulichung):
function executorFunctionWrapper(parameter1, parameter2) {

  // ── ab hier schreibst du den Rumpf ──
  // Wichtig: ALLE Parameter kommen als String an!
  var summe = parseInt(parameter1) + parseInt(parameter2); // numerisch
  return String(summe); // Rückgabe wird als String erwartet

}
Achtung, String-Falle: Bei den Eingaben 5 und 8 liefert return parameter1 + parameter2 die Zeichenkette "58" statt 13 — weil Strings verkettet werden. Erst parseInt(...) bzw. parseFloat(...) rechnet numerisch.

Der Rückgabewert wird als String erwartet. Ohne return oder bei einem Abbruch im Fehlerfall ist der Rückgabewert undefined.

✎ Übung: Warum liefert return zahl1 + zahl2 bei den Eingaben 5 und 8 das Ergebnis „58" — und wie behebst du es?

✓ Das hast du jetzt verstanden

Stufe 2 von 7

Sprache & Muster (ECMAScript 5.1)

Was Otto kann — und welche ES6-Annahmen scheitern.

1Was ES5.1 unterstützt

Unterstützt sind var (kein let/const), die Typen String/Number/Boolean/Array/Object/null/undefined, die üblichen Operatoren, if/else, for, while, JSON.stringify/JSON.parse sowie eingebaute String-/Array-/Math-/Date-Funktionen. (PH ECMAScript-5.1-Referenz)

var namen = ["Anna", "Ben"];   // Array mit []
namen.push("Carla");           // mit push füllen

var antwort = "";
for (var i = 0; i < namen.length; i++) {
  if (namen[i] === "Ben") {    // strenge Gleichheit
    antwort = "gefunden";
  }
}

var daten = JSON.parse('{"ok": true}'); // String -> Objekt
var text  = JSON.stringify(daten);      // Objekt -> String

2Nicht unterstützt (ES6+)

Diese Konstrukte laufen in Otto nicht: let/const, Arrow-Funktionen, Template-Strings, Destructuring, Spread, class, Promise, async/await.

Keine ES6-Annahmen: Template-Strings (`Hallo ${name}`) und Arrow-Funktionen (var f = () => x) scheitern. Nutze "Hallo " + name und klassische function-Ausdrücke.

Häufige Fehler: var nicht vergessen (sonst entsteht eine globale Variable); konsequent strenge Gleichheit (===) verwenden; Arrays als [] anlegen und mit push füllen.

✎ Übung: Welche zwei der folgenden sind in ES5.1 verboten: let x = 1, var x = 1, var f = () => x, function f() {}?

✓ Das hast du jetzt verstanden

Stufe 3 von 7

Module & Signaturen

Erst getModule, dann die Funktionen — mit exakten Signaturen.

1Module initialisieren

Jedes Modul wird zuerst mit getModule("modulname") initialisiert; danach stehen seine Funktionen als globale Namen bereit. (PH Module; AH 7.2)

getModule("log");
getModule("http");

log_info("Modul http bereit");
var antwort = http_get("https://api.example.com/v1/data", {});
🧠 Für Profis: Schrittergebnisse ohne getModuleaiserviceresults
Läuft die Funktion als Schritt eines AI-Workflows, stellt die Plattform die Ergebnisse aller vorherigen Schritte als globale Variable aiserviceresults bereit — anders als Module braucht sie kein getModule(). Die Reihenfolge ist chronologisch: aiserviceresults[0] ist der älteste, aiserviceresults[aiserviceresults.length - 1] der unmittelbar vorhergehende Schritt. Außerhalb eines Workflows (Einzelaufruf) ist sie null — vor dem Zugriff prüfen: if (aiserviceresults === null) { … }. (Programmierhandbuch)

2Wichtige Module & exakte Signaturen

http
http_get(url, header), http_post(url, contentType, header, body), http_put(url, contentType, header, body), http_delete(url, header), http_queryEscape(value), http_search(search, exactMatch).
graphapi
graphapi_getResource(graphApiConfig, url), graphapi_postResource(graphApiConfig, url, body), graphapi_putResource(graphApiConfig, url, body), graphapi_deleteResource(graphApiConfig, url), graphapi_send(graphApiConfig, mail), graphapi_getNewFromInbox(graphApiConfig, maxCount).
aiservice
aiservice_run(agentId, serviceId, params), aiservice_runAsync(agentId, serviceId, params), aiservice_runWithToken(token, agentId, serviceId, params); Ergebnis über resultObj.MultiResults.Results[0].Result.
knowledgedb
saveText(agentId, containerId, name, content, documentId), saveBinary(agentId, containerId, name, content, documentId), find(searchText, agentId, containerId, qualityGate, resultLimit), findByKeyword(searchText, agentId, containerId, resultLimit).
personalknowledgedb
Lese-/Schreibzugriff auf die persönliche Wissens-DB des ausführenden Users — ohne Agent-/Container-Parameter.
sql
sql_execute(connectionConfig, sqlCommand), sql_query(connectionConfig, sqlCommand).
email
send(mail, smtpConfig), getNewFromInbox(imapConfig), getByCriteria(imapConfig, criteria), move(mailId, originFolder, destinationFolder, imapConfig).
document
document_readText(agentId, filename, filecontent, readImages).
user
user_getUser().
organisation
organisation_getOrganisation() — liefert u. a. ADConfig (MsGraphTenantId/ClientId/ClientSecret) und TeamsBotConfig; ideal, um graphApiConfig direkt aus der Org zu bauen statt aus Umgebungsvariablen.
log
log_info(message), log_warn(message), log_error(message), log_fatal(message), log_logs().
weitere
webcrawler_crawlWeb(url), webcrawler_crawlWebEnhanced(url, depth, pageCount) (max. Tiefe 3, 10 Seiten), webcrawler_liveSearch(prompt, maxPages, searchMode); docdb_load(documentId), docdb_save(documentId, document), docdb_delete(documentId).
Sicherheit & Voraussetzungen: SQL-Zugriff nur für Admins (AH 7.2). Die Module sql, graphapi und email brauchen ein Connection- bzw. Config-Objekt als ersten Parameter.
Mehrere Teilergebnisse: Liefert ein AI-Service mehrere Schritte, iterierst du über MultiResults.Results und filterst versteckte mit results[i].ServiceStepCommand.Displaytype != "Hidden"; aiservice_runWithToken(token, …) erlaubt Aufrufe ohne User-Auth (API-/Integrationskontext). (Programmierhandbuch)
Versionen: Jedes Speichern einer Funktion legt automatisch eine Version an — bis zu 50 unbenannte, benannte unbegrenzt; anschauen (Read-only), wiederherstellen (sichert vorher den aktuellen Stand) und löschen sind möglich (die aktive Version nicht). (AH 7.6)
✎ Übung: Welches Modul und welche Funktion liest ein hochgeladenes PDF als Text aus?

✓ Das hast du jetzt verstanden

Stufe 4 von 7

Umgebungsvariablen & Secrets

Werte aus dem Code heraushalten — und api_token sauber von ${env.NAME} trennen.

1Org- vs. Funktions-Variablen

Umgebungsvariablen halten Werte aus dem Code heraus, die keine Funktionsparameter sind (typisch: API-Tokens). Du setzt sie an der Organisation (gelten für jeden Funktionsaufruf) oder an der Funktion. (PH Umgebungsvariablen; AH 7.1/7.2)

Bei Namensgleichheit überschreibt die Organisation die Funktion. Beim Export einer Funktion wandern die Variablen-Deklarationen, aber nicht die Werte mit — so geraten keine Secrets in eine fremde Organisation. Vordefiniert ist timeout (Sekunden; nur an der Funktion wirksam, an der Organisation ignoriert; Default 600 s).

2Zugriff in der Funktion vs. im HTTP-Service

In der Funktion steht eine Umgebungsvariable als globaler Name bereit:

// Umgebungsvariable "api_token" steht als globaler Name bereit:
var apiKey = api_token;

// niemals hart codieren, niemals ins Log schreiben!
log_info("API-Aufruf vorbereitet"); // ok
// log_info("Token: " + api_token);  // FALSCH: Secret im Log
Kern-Abgrenzung: Die ScriptEngine-Funktion sieht die Variable direkt als globalen Namen (api_token, db_password). Der HTTP-Service-Editor referenziert dieselbe Idee dagegen in der Anfrage über die Template-Syntax ${env.NAME} (AH 7.1).
Secrets gehören in Umgebungsvariablen — nicht hart codiert in den Funktions-Body, nicht in Prompts und nicht ins Log.
HTTP-Service-Editor (offizielle Abbildung aus dem Admin-Handbuch)
Offizielle Abbildung aus dem Admin-Handbuch (Kap. 7) — der HTTP-Service-Editor.
✎ Übung: Eine Variable heißt an Organisation und Funktion gleich — welcher Wert greift?

✓ Das hast du jetzt verstanden

Stufe 5 von 7

HTTP-Service-Editor

Ein vordefinierter REST-Aufruf — gepflegt auf Organisationsebene.

1Der Editor und seine Reiter

Der HTTP-Service ist ein vordefinierter REST-Aufruf, gepflegt auf Organisationsebene (Org-Admin+). Editor httpserviceeditor.html mit den Reitern Stammdaten, Anfrage, Parameter und Umgebungsvariablen. (AH 7.1)

StammdatenAnfrageParameterUmgebungsvariablen
Anfrage
URL
https://api.example.com/v1/data
Methode
GETPOSTPUTDELETE
Content-Type
application/json
HeaderKey-Value-Paare
Authorization: Bearer ${env.AUX_TOKEN}
Request-BodyTemplate im ACE-Editor
{ "name": "${parameter}" }
Echter HTTP-Service-Editor (Demo-Instanz), Reiter Anfrage: Endpunkt mit URL, Methode GET, Content-Type und Body-Editor
Echter HTTP-Service-Editor an der Demo-Instanz (Reiter „Anfrage"): URL, Methode, Content-Type, Body — Demo-Platzhalter
Testdurchführung eines HTTP-Services (offizielle Abbildung aus dem Admin-Handbuch)
Offizielle Abbildung aus dem Admin-Handbuch (Kap. 7) — die Testdurchführung eines HTTP-Services.

Parameter (Name, Beschreibung, Default, Pflichtfeld) werden vom Aufrufer bzw. Workflow-Schritt gefüllt und im Body als ${parameter} referenziert. Umgebungsvariablen sind ein separater Schlüssel-Wert-Speicher für Secrets und produktionsabhängige URLs; sie lassen sich über ${env.NAME} in der Anfrage referenzieren und werden verschlüsselt in http_request.env gespeichert. Die eigene Testseite führt einen Probe-Aufruf aus und zeigt Request, Response, Status und Parsing-Ergebnis.

Sicherheit: Lege Tokens als Umgebungsvariablen ab und übergib sie bevorzugt im Header. Packe Secrets nicht als fachliches Body-Feld mit; Body-Auth wäre eine bewusst zu prüfende Ausnahme. HTTP-Calls werden gegen die URL-Whitelist geprüft (AH 7.2).
✎ Übung: Wo trägst du den API-Key ein — bei „Header" direkt oder bei „Umgebungsvariablen"?

✓ Das hast du jetzt verstanden

Stufe 6 von 7

Code-Beispiele — eine vollständige Funktion

Validierung → Logging → HTTP-Aufruf → Fehlerpfad.

1Die Demo-Funktion zusammengesetzt

Wir setzen die Demo-Funktion vollständig zusammen, nach dem Muster aus dem PH-Tutorial „Erste Funktion erstellen". (PH Code-Beispiele; AH 7.2)

// Module einmal am Anfang initialisieren
getModule("log");
getModule("http");

// Aufruf protokollieren (keine Rohdaten, keine Secrets)
log_info("Funktion aufgerufen; Parameter name erhalten");

// 1) Parameter validieren
if (!name || typeof name !== "string" || name.trim() === "") {
  log_warn("Ungültiger Parameter: name fehlt oder ist leer");
  return "FEHLER: Parameter 'name' fehlt oder ist leer.";
}

var cleanName = name.trim();

// 2) Pflicht-Secret prüfen, ohne den Wert zu loggen
if (!api_token || typeof api_token !== "string" || api_token.trim() === "") {
  log_error("Umgebungsvariable api_token fehlt");
  return "FEHLER: API-Konfiguration fehlt.";
}

var cleanApiToken = api_token.trim();

// 3) HTTP-Aufruf im try-Block
try {
  var header = {};
  header["Authorization"] = "Bearer " + cleanApiToken; // aus Umgebungsvariable
  header["Content-Type"]  = "application/json";

  // URL-Bestandteile mit dem HTTP-Modul absichern
  var sicher = http_queryEscape(cleanName);
  var url = "https://api.example.com/v1/greeting?name=" + sicher;

  var response = http_get(url, header);
  log_info("HTTP-Antwort erhalten");
  return "Hallo " + cleanName + "! Antwort: " + response;

} catch (error) {
  // 4) Fehlerpfad: immer ein definierter String
  log_error("HTTP-Anfrage fehlgeschlagen: " + error);
  return "Hallo " + cleanName + "! Willkommen in der ScriptEngine.";
}
Caveat: URL, Token-Name, Header und Endpunkt sind Demo-Platzhalter und gegen die konkrete Instanz bzw. das PH zu prüfen. Das ist ein Muster, kein blindes Copy-Paste-Skript.

Die Funktion gibt über jeden Pfad — Eingabevalidierung, Secret-Prüfung, Erfolg, Fehler — immer einen definierten String zurück. Sie loggt keinen Token-Wert, nutzt den getrimmten Namen nur einmal und escaped URL-Bestandteile mit der vom HTTP-Modul bereitgestellten Funktion.

✎ Übung: Welche Fehlermeldung würdest du bei fehlendem api_token zurückgeben, damit Nutzende genug Kontext bekommen, aber keinen internen Token-Namen oder Endpunkt sehen?

✓ Das hast du jetzt gebaut

Stufe 7 von 7

Best Practices & Sicherheit

Robust, validiert und sicher — die Regeln aus dem Handbuch.

1Best Practices

Sieben Regeln aus dem Programmierhandbuch, die jede Funktion produktionsreif machen. (PH Best Practices)

Fehlerbehandlung
immer try/catch + log_error.
Logging
großzügig log_info, aber keine Passwörter/Tokens loggen.
Module
nur einmal am Anfang initialisieren.
Validierung
Parameter prüfen mit typeof, isNaN, trim.
Struktur
Funktionen klein halten und in Teilfunktionen zerlegen.
Secrets
sensible Daten in Umgebungsvariablen statt Hartkodierung.
AI-Ergebnisse
vor dem Zugriff prüfen: if (result && result.MultiResults && result.MultiResults.Results.length > 0).

2Sicherheit (AH 7.2)

HTTP-Calls werden gegen die URL-Whitelist geprüft; SQL nur für Admins; die Otto-Sandbox erlaubt kein Dateisystem-/Netz-IO außerhalb der Module. SQL- und HTML-Injection entschärfst du durch Escapen:

// einfache SQL-Escape-Hilfe (Demo): einfache Quotes verdoppeln
var sicher = eingabe.replace(/'/g, "''");

// Logging-Disziplin: Benutzer ja, Passwort niemals
log_info("Login-Versuch für Benutzer: " + benutzername); // erlaubt
// log_info("Passwort: " + passwort);                      // VERBOTEN
Niemals Secrets ins Log: log_info("Login-Versuch für Benutzer: " + benutzername) ist erlaubt — das Passwort darf nicht geloggt werden.

Deine Funktion ist robust, validiert und sicher.

Die Preisabfrage-/E-Mail-Funktion steht als eigenständiges Modul: ES5.1-konform, mit den korrekten Modul-Signaturen, sauberer Trennung von Umgebungsvariablen und ${env.NAME}, einem getesteten HTTP-Service und einem Fehlerpfad, der immer einen definierten String liefert. Weiter mit E5 — Teams-Bot einrichten.

✎ Übung: Nenne zwei Regeln, die verhindern, dass ein API-Token nach außen sichtbar wird.

✓ Das hast du jetzt verinnerlicht

Kurz-Quiz

Sitzt die ScriptEngine?

7 Fragen aus den Stufen 1–7. Kein Zertifikat — zur Selbstkontrolle. Beliebig oft wiederholbar.

Frage 1 von 7
Lade Frage…