Zum Inhalt springen

Output Gate

Das Output Gate ist ToolMeshs Inhaltskontrollschicht. JavaScript-Policies laufen vor (pre) und nach (post) jeder Tool-Ausführung und ermöglichen Eingabevalidierung, Ausgabefilterung und PII-Schwärzung.

Gate-Policies sind Top-Level-JavaScript-Dateien im policies/-Verzeichnis. Sie werden von goja ausgeführt, einer Go-nativen JavaScript-Engine, mit einem Timeout von 5 Sekunden pro Policy.

Jede Policy erhält eine einzige globale Variable ctx und läuft in einer von zwei Phasen:

  • pre — vor der Tool-Ausführung. ctx.params modifizieren, um den Aufruf umzuschreiben, oder throw, um ihn abzulehnen.
  • post — nach der Tool-Ausführung. ctx.response.content modifizieren, um die Antwort zu filtern.

Wirft das Skript einen String oder Error, wird der Aufruf abgelehnt. Läuft es ohne Throw durch, wird der Aufruf zugelassen.

FeldBeschreibung
ctx.phase"pre" oder "post"
ctx.toolTool-Name mit Backend-Präfix (z. B. github_merge_pull)
ctx.toolAccessDADL-Access-Tag: "read", "write", "admin", "dangerous" oder leer
ctx.paramsTool-Parameter (in pre mutierbar)
ctx.response.contentTool-Antwort (in post mutierbar; nur in post befüllt)
ctx.user.userIDAuthentifizierte Nutzerkennung
ctx.user.callerIdCaller-Identität (z. B. cli, claude-desktop)
ctx.user.callerClass"trusted", "standard" oder "untrusted"
ctx.user.rolesArray mit Nutzerrollen
ctx.rateLimitExceeded(n)Funktion — liefert true, wenn der Nutzer n Aufrufe/Stunde überschritten hat
policies/block-force-delete.js
if (ctx.phase === "pre" && ctx.params.force_delete === true) {
throw "force_delete ist per Policy gesperrt";
}
policies/redact-email.js
if (ctx.phase === "post" && ctx.response && ctx.response.content) {
for (var i = 0; i < ctx.response.content.length; i++) {
var block = ctx.response.content[i];
if (block && block.type === "text" && block.text) {
block.text = block.text.replace(
/[\w.-]+@[\w.-]+\.\w+/g,
"[REDACTED]"
);
}
}
}

Mutationen an ctx.response.content werden in die Live-Antwort zurückpropagiert — nachgelagerte Evaluatoren und der Executor sehen den geschwärzten Inhalt.

Viele AI-Coding-Agents hängen Co-Authored-By-Trailer an Commit-Nachrichten und PR-Beschreibungen. Eine Pre-Gate-Policy entfernt diese vor dem GitHub-API-Aufruf:

policies/strip-co-authored-by.js
if (ctx.phase === "pre") {
var coAuthorPattern = /^[Cc]o-[Aa]uthored-[Bb]y:.*$/gm;
function stripTrailer(text) {
if (!text) return text;
return text
.replace(coAuthorPattern, "")
.replace(/\n{3,}/g, "\n\n")
.replace(/\n+$/, "\n");
}
if (ctx.tool === "github_create_pull" || ctx.tool === "github_update_pull") {
if (ctx.params.body) {
ctx.params.body = stripTrailer(ctx.params.body);
}
}
if (ctx.tool === "github_merge_pull" && ctx.params.commit_message) {
ctx.params.commit_message = stripTrailer(ctx.params.commit_message);
}
if (ctx.tool === "github_create_git_commit" && ctx.params.message) {
ctx.params.message = stripTrailer(ctx.params.message);
}
}

Der AI-Agent merkt nichts davon, und keine Co-Authored-By-Zeile erreicht das Repository.

Read-only-Durchsetzung für untrusted Caller (pre)

Abschnitt betitelt „Read-only-Durchsetzung für untrusted Caller (pre)“
policies/untrusted-readonly.js
if (ctx.phase === "pre" &&
ctx.user.callerClass === "untrusted" &&
ctx.toolAccess !== "read") {
throw "CallerClass 'untrusted' darf nur Tools mit Access-Tag 'read' aufrufen";
}

Das setzt auf den DADL-access-Tag (read, write, admin, dangerous), der pro Tool deklariert wird — siehe DADL-Spezifikation.

Das Gate erhält die CallerClass und ermöglicht abgestufte Policies:

CallerClassTypische Filterung
trustedNur Credentials
standardHochrisiko-PII + Credentials
untrustedAlle PII-Muster, nur Read-Tools

Policies können ein Sliding-Window-Rate-Limit pro Nutzer durchsetzen:

if (ctx.phase === "pre" && ctx.rateLimitExceeded(100)) {
throw "Rate Limit überschritten (100/Stunde)";
}
Terminal-Fenster
GATE_EVALUATORS=goja # goja-Evaluator aktivieren (Standard)

Policy-Dateien im policies/-Verzeichnis ablegen. ToolMesh lädt sie beim Start.

Die Enterprise-Erweiterung fügt einen LLM-basierten Gate-Evaluator hinzu, der Inhalte gegen Compliance-Regeln klassifiziert. Das ermöglicht Policies wie „Antworten mit Finanzberatung blockieren”, ohne Regex-Muster schreiben zu müssen.