YouMind
Anmelden

Erstellen einer benutzerdefinierten Harness mit Pi und Jev

@omarsar0
ENGLISCH23. Sept. 2026
102K
1.1K
115
41
2.2K

TL;DR

Dieses Tutorial führt Entwickler durch die Erstellung einer benutzerdefinierten AI-Agent-Harness unter Verwendung des Pi SDK und Jev, eines spezialisierten Entscheidungsmodells. Es demonstriert die Implementierung von Sicherheits-Gates, dynamischem Model-Routing und Antwortverifizierung zur Optimierung von Leistung und Kosten.

Ein AI Agent ist ein Sprachmodell, das in einer Schleife arbeitet. Es liest die Aufgabe, nutzt ein Werkzeug wie „lies diese Datei“ oder „lösche jene Datei“, prüft das Ergebnis und macht weiter, bis die Arbeit erledigt ist. Jedes Mal, wenn das Modell ein Werkzeug anfordert, nennt man diesen Vorgang einen Tool Call.

Der Code, der diese Schleife ausführt, heißt Harness. Das Modell entscheidet, was es tun möchte. Der Harness führt es aus – und legt gleichzeitig fest, was das Modell überhaupt tun darf.

Ein guter Harness trifft unterwegs viele kleine Entscheidungen. Welches Modell soll diese Anfrage bearbeiten? Ist dieser Tool Call sicher? Ist diese Antwort gut genug, um sie zurückzugeben? Die meisten Harnesses beantworten das, indem sie ein Chat-Modell fragen und dessen Antwort auswerten. Das kostet jedes Mal einen vollständigen Modellaufruf, weshalb in der Praxis viele Prüfungen einfach übersprungen werden.

Jev von TypeSafe AI ist ein kleines Modell, das genau für diese Entscheidungen gebaut wurde. Du beschreibst die Situation, stellst ein paar Fragen, und es beantwortet jede einzelne mit einer Zahl. Text schreibt es nie.

Das ist besonders wichtig, wenn du einen Custom Harness baust – also deine eigene Agent-Schleife statt eines fertigen Agents von der Stange. Mit einem Custom Harness bestimmst du selbst, welche Modelle laufen, worauf der Agent zugreifen darf und wann eine Aufgabe als erledigt gilt. Jev macht die Prüfungen hinter diesen Entscheidungen so günstig, dass du sie bei jedem Schritt ausführen kannst.

In diesem Tutorial baust du einen Harness mit dem Pi SDK, einem TypeScript-Toolkit für Agents, und setzt Jev an drei Stellen ein. Am Ende lässt du den fertigen Harness in einer Live-Sandbox laufen und passt die Einstellungen selbst an.

Hier geht's zum vollständigen interaktiven Tutorial und zur Playground-Umgebung:

https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness

Dieser Guide wurde von Sydney Runkles Artikel Building a Harness with Jev im LangChain-Blog inspiriert, der Model Routing und Tool Gating als fertige LangChain-Middleware zeigt. Hier baust du dieselben Ideen selbst im Pi SDK nach und ergänzt zwei weitere Muster für Fehlerbehandlung und Antwortprüfung.

Was du bauen wirst

Der Harness besteht aus drei Teilen. Jeder stellt Jev zu einem anderen Zeitpunkt eine Frage – im Rest dieses Guides werden sie mit diesen Namen bezeichnet.

elvis - inline image

Als durchgehendes Beispiel dient ein Agent, der in einem Ordner mit Notizen aus Wanderbegehungen arbeitet – eine Datei pro Tour. Er kann diese Notizen lesen, schreiben und tatsächlich löschen. Genau deshalb ist das Gate so wichtig.

Was Jev ist

TypeSafe bezeichnet Jev als System-One-Modell. Der Name geht auf den Psychologen Daniel Kahneman zurück, der zwei Denkmodi beschrieben hat: System 1 ist schnell und automatisch – wie das Wissen, dass eine Pfanne heiß ist. System 2 ist langsam und überlegt – wie schriftliches Dividieren.

In diesem Harness übernimmt ein normales Sprachmodell die langsame Arbeit: Dateien lesen und Antworten formulieren. Jev trifft die schnellen Entscheidungen drumherum. Jev ist so günstig und schnell, dass du jeden einzelnen Tool Call prüfen lassen kannst – nicht nur die, von denen du erwartest, dass sie riskant sind.

elvis - inline image

Jede Zahl ist eine Wahrscheinlichkeit zwischen 0 und 1. Ein Wert von 0,83 bedeutet, dass Jev ziemlich sicher ist, dass die Antwort „Ja“ lautet. Bei 0,03 ist es sich ziemlich sicher, dass die Antwort „Nein“ ist.

Drei Fragetypen

Jede Anfrage an Jev besteht aus zwei Teilen. Der State ist die Situation, die bewertet werden soll – etwa ein Tool Call oder eine Nutzeranfrage. Die Questions sind das, was du darüber wissen möchtest. Jev beantwortet alle Fragen in einem einzigen Aufruf gleichzeitig. Drei Fragen dauern also ungefähr so lange wie eine.

Jev unterstützt drei Arten von Fragen. Die erste, die Jev als „Noul“ bezeichnet, ist eine Ja-oder-Nein-Frage.

elvis - inline image

Jev weiß nur, was du ihm sagst. Beschreibe daher jede Option und jede Stufe in klaren Worten. Diese Beschreibungen sind der Prompt.

Setup

Jev ist über OpenRouter verfügbar – einen Dienst, der dir viele KI-Modelle hinter einem einzigen API-Key bietet. Dieser eine Key deckt sowohl das Sprachmodell als auch Jev ab. Installiere die beiden Pi-Pakete und hinterlege deinen Key.

bash
1npm install @earendil-works/pi-agent-core @earendil-works/pi-ai
bash
1OPENROUTER_API_KEY=...

Jev hat eine eigene URL, getrennt vom üblichen Chat-Endpunkt. Gib immer eine exakte Version an, z. B. typesafe/jev-1.13. Der gesamte Jev-Client ist ein einziger Fetch-Aufruf.

javascript
1const JEV = "typesafe/jev-1.13";
2
3async function ask(state: unknown, questions: unknown) {
4 const response = await fetch("https://openrouter.ai/api/alpha/decisions", {
5 method: "POST",
6 headers: {
7 "Content-Type": "application/json",
8 Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
9 },
10 body: JSON.stringify({ model: JEV, state, questions }),
11 signal: AbortSignal.timeout(2_000),
12 });
13 if (!response.ok) throw new Error(await response.text());
14 return response.json();
15}

Der Agent wartet, während Jev antwortet, deshalb bricht der Aufruf nach zwei Sekunden ab. Eine normale Antwort dauert 200 bis 400 Millisekunden.

Wo Jev ins Spiel kommt

Die Agent-Klasse von Pi übernimmt die Schleife für dich. Sie erlaubt deinem eigenen Code, an bestimmten Stellen in dieser Schleife einzugreifen. Diese Stellen heißen Hooks. Der Harness nutzt für jeden seiner drei Teile einen eigenen Hook.

elvis - inline image

Ein erstes Gate

Starten wir mit der kleinsten sinnvollen Version des Gates. Vor jedem Tool Call stellst du Jev eine einzige Ja-oder-Nein-Frage und blockierst den Aufruf, wenn die Antwort nach „Ja“ aussieht.

javascript
1import { Agent } from "@earendil-works/pi-agent-core";
2
3const agent = new Agent({
4 initialState: { systemPrompt, model, tools },
5 streamFn: models.streamSimple.bind(models),
6
7 beforeToolCall: async ({ toolCall, args }) => {
8 const { answers } = await ask(
9 { tool: toolCall.name, arguments: args },
10 {
11 destructive: {
12 type: "noul",
13 instructions: "This tool call destroys or overwrites data that was not created by this run.",
14 criteria: {
15 true: "Deletes files, truncates or overwrites existing content, drops data, or force-pushes over history.",
16 false: "Reads, lists, creates a new file, or appends to a file this run already created.",
17 },
18 },
19 },
20 );
21
22 if (answers.destructive.noul >= 0.65) {
23 return { block: true, reason: "Blocked: this looks destructive.", terminate: true };
24 }
25 },
26});

Der Wert 0,65 ist ein Threshold – der Grenzwert, ab dem der Harness einem Aufruf nicht mehr vertraut. Alles, was Jev mit diesem Wert oder höher bewertet, wird blockiert.

Jetzt stoppt ein Agent, der deine Notizen löschen will, bevor das Löschen passiert. Das Löschen einer Notiz ergibt etwa 0,83, das Lesen einer Notiz 0,01. Allerdings ist das Gate noch recht grob: Eine komplett neue Datei zu schreiben, ergibt rund 0,70 – und wird damit ebenfalls blockiert.

Eine Anfrage kostet fast nichts. Jev berechnet 0,042 $ pro Million Input-Tokens – weniger als ein Drittel des Input-Preises von GLM 5.3 Flash, dem günstigeren der beiden Modelle, die dieser Harness nutzt.

Vom ersten Gate zum vollständigen Harness

Das erste Gate funktioniert, lässt aber vier Lücken offen.

  1. Der Threshold steckt direkt im Hook und lässt sich dadurch schwer anpassen oder testen.
  2. Jede Anfrage läuft auf demselben Modell, egal ob einfach oder komplex.
  3. Es ist nicht definiert, was passiert, wenn Jev nicht erreichbar ist.
  4. Niemand prüft, ob die finale Antwort überhaupt etwas taugt.

Jeder der folgenden nummerierten Abschnitte schließt eine dieser Lücken.

1. Thresholds zentral verwalten

Dieser Abschnitt verbessert das Gate.

Thresholds bestimmen, was der Agent tun darf – und du wirst sie oft anpassen, sobald du echte Ergebnisse siehst. Verschiebe sie deshalb aus dem Hook heraus in eine einfache Funktion namens decideGate(). Sie nimmt die Zahlen von Jev entgegen und gibt ein Verdict zurück: die endgültige Entscheidung des Harness über einen Aufruf. Diese Regeln an einem Ort zu bündeln, nennt man Policy.

Die Policy fügt außerdem eine mittlere Option hinzu. Ein einzelner Threshold kennt nur „erlauben“ oder „blockieren“. Zwei Thresholds ergeben drei mögliche Verdicts.

  • Ab blockAt oder höher wird der Aufruf blockiert.
  • Unterhalb von askAt wird er ausgeführt.
  • Dazwischen wartet der Aufruf auf die Freigabe durch einen Menschen.

Dieser mittlere Bereich fängt genau die Aufrufe ab, bei denen Jev unsicher ist – und bei denen ein einzelner Grenzwert zwangsläufig in die eine oder andere Richtung falsch liegen würde.

elvis - inline image
javascript
1export function decideGate(signals: GateSignals, policy = DEFAULT_GATE_POLICY): GateVerdict {
2 const worst = Math.max(
3 signals.destructive.noul,
4 signals.irreversible.noul,
5 signals.outsideWorkspace.noul,
6 );
7 if (worst >= policy.blockAt) return { action: "block", ... };
8 if (worst >= policy.askAt) return { action: "ask", ... };
9 return { action: "allow", ... };
10}

Da es eine einfache Funktion ist, kannst du sie testen, indem du Zahlen wie die obigen übergibst – ganz ohne laufendes Modell.

2. Pro Anfrage das passende Modell wählen

Dieser Abschnitt fügt den Router hinzu.

Manche Anfragen sind einfach, etwa eine Datei zu lesen. Andere sind knifflig, zum Beispiel herauszufinden, warum etwas kaputtgegangen ist. Alles auf dem stärksten Modell laufen zu lassen, verschwendet Geld. Alles auf einem günstigen Modell liefert bei komplexen Anfragen schwache Antworten. Der Router ordnet jede Anfrage der passenden Tier zu – also entweder dem schnellen, günstigen Modell oder dem leistungsstarken, teuren.

Bevor eine Anfrage startet, stellt der Router Jev in einem Aufruf zwei Fragen. Eine Auswahl bestimmt die Tier, ein Score bewertet die Komplexität der Anfrage.

elvis - inline image
javascript
1const ROUTER_QUESTIONS = {
2 tier: choice("Which model tier should handle this request?", {
3 fast: "Reading one file, pulling a fact out of it, or a small edit in a single place.",
4 powerful: "Work that spans several files, or a failure with no obvious cause.",
5 }),
6 complexity: score("How much reasoning does this request need?", [
7 "Mechanical. One step, no judgement.",
8 "Localized. A few steps inside one area.",
9 "Architectural. Many moving parts or an unknown root cause.",
10 ]),
11};

Die Policy des Routers nutzt die beiden Antworten so:

  • Ist der Complexity-Score hoch, nimm das leistungsstarke Modell – selbst wenn Jev „fast“ gewählt hat.
  • Ist Jev sich bei seiner Wahl unsicher, nimm zur Sicherheit das leistungsstarke Modell.
  • Ansonsten verwende das von Jev gewählte Modell.
javascript
1if (complexity.score >= policy.escalateAtComplexity) return powerful;
2if (tierAnswer.confidence < policy.minConfidence) return policy.fallbackTier;
3return tierAnswer.choice;

Das ist ein Beispiel für eine Policy. Deine kann die Antworten anders gewichten, passend zu deiner Domäne – etwa grundsätzlich günstig bleiben bei einem Batch-Job mit hohem Volumen oder alles eskalieren, was die Produktion berührt. Jev liefert nur die Antworten; dein Code entscheidet, was damit passiert.

Warum nur einmal wählen?

Der Router wählt das Modell einmal zu Beginn der Anfrage und behält es bei, bis die Anfrage abgeschlossen ist. Der Grund dafür ist Prompt Caching.

Bei jedem Schritt des Agents liest das Modell die bisherige Konversation komplett neu. KI-Anbieter speichern kürzlich gelesene Konversationen, damit dieses erneute Lesen günstig bleibt. Aber jedes Modell hat seinen eigenen Speicher. Wechselst du mitten drin das Modell, muss das neue alles noch einmal zum vollen Preis lesen.

Der Gründer von Jev rechnet das in einem Design-Doc über Coding Agents vor. In einer langen Session kostete der Wechsel von Claude Opus zum günstigeren Sonnet und zurück rund 50 % mehr, als die ganze Zeit bei Opus zu bleiben. Wähle das Modell also am Anfang, solange die Konversation noch kurz ist, und bleib dabei.

3. Für den Fall planen, dass Jev ausfällt

Dieser Abschnitt ändert sowohl das Gate als auch den Router.

Sobald der Harness Jev bei jedem Tool Call fragt, hängt der Agent von Jev ab. Wie jeder Onlinedienst kann Jev langsam oder offline sein. Lege vorher fest, was jeder Teil tut, wenn keine Antwort kommt. Die richtige Wahl unterscheidet sich je nach Komponente.

Das Gate blockiert den Aufruf. Wenn das Gate Jev nicht fragen kann, weiß es nicht, ob der Aufruf sicher ist. Ihn durchzulassen könnte Dateien löschen – also verweigert das Gate ihn. Entwickler nennen das Fail Closed, wie eine Tür, die bei Stromausfall automatisch verriegelt.

Der Router nutzt das leistungsstarke Modell. Wenn der Router Jev nicht fragen kann, weiß er nicht, wie schwer die Anfrage ist. Das starke Modell schafft alles, also bekommt die Anfrage trotzdem eine gute Antwort – du zahlst nur etwas mehr. Das ist Fail Open: Die Arbeit läuft einfach weiter.

elvis - inline image

4. Die Antwort prüfen

Dieser Abschnitt fügt den Verifier hinzu. In Agent-Harnesses ist ein Verifier der Schritt, der die Arbeit des Agents kontrolliert, bevor sie als erledigt gilt.

Ein Agent kann mit einer Antwort abschließen, die etwas Wichtiges auslässt oder Dinge behauptet, die er in den Dateien gar nicht geprüft hat. Wer das liest, merkt es oft nicht. Die Antwort vor der Rückgabe zu kontrollieren, fängt solche Fehler ab – solange der Agent es noch einmal versuchen kann.

Der Verifier schickt Jev die fertige Antwort zusammen mit den Dateien und Tool-Ergebnissen, auf denen sie basiert. Jev bewertet die Qualität der Antwort und sagt, ob ihre Aussagen grounded sind – also durch das gedeckt werden, was der Agent tatsächlich gelesen hat.

elvis - inline image
javascript
1const VERIFY_QUESTIONS = {
2 quality: score("How well does the answer satisfy the request?", [
3 "Does not answer the request.",
4 "Partly answers it, with a gap the reader would notice.",
5 "Fully answers the request.",
6 ]),
7 grounded: noul("Every factual claim is supported by the files or tool results in the transcript."),
8};

Zwei Regeln verhindern, dass der Agent endlos neue Versuche startet. Er bekommt insgesamt maximal zwei Versuche. Und wenn Jev sich bei seiner eigenen Bewertung unsicher ist, akzeptiert der Harness die Antwort lieber, statt einen weiteren Versuch zu bezahlen.

Sicherheit und Logging

Jev liefert eine Wahrscheinlichkeit – und Wahrscheinlichkeiten können falsch sein. Alles, was normaler Code zuverlässig prüfen kann, sollte auch im Code geprüft werden. In diesem Harness blockiert jedes Datei-Werkzeug Pfade außerhalb des Projektordners, völlig unabhängig davon, was Jev sagt. Heb dir Jev für die Entscheidungen auf, die Code nicht treffen kann.

Das Gate betrachtet nur den Tool Call selbst, also den Namen des Werkzeugs und seine Eingaben. Das hilft gegen Prompt Injection, bei der versteckter Text in einer Datei oder Webseite das Modell zu schädlichem Verhalten verleitet. Das Gate sieht den Trick nie, wohl aber den schädlichen Aufruf, der daraus folgt.

Logge jede Entscheidung zusammen mit den zugrunde liegenden Zahlen. Das Log erklärt, warum etwas blockiert wurde, und liefert echte Werte für die Thresholds. Der Harness schreibt eine Zeile pro Entscheidung in eine Datei namens decisions.jsonl. Da das Gate alles sieht, was der Agent versucht, maskiert das Log E-Mail-Adressen und Keys und kürzt lange Eingaben.

Ausprobieren

Die Sandbox unten führt den fertigen Harness aus diesem Tutorial aus – verbunden mit dem echten Jev. Sie arbeitet mit dem Ordner voller Wander-Notizen, und ihr delete_path-Tool kann sie tatsächlich löschen.

Hier ausprobieren: https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness

Warum du deinen eigenen Harness bauen solltest

Fertige Agents treffen diese Entscheidungen mit ihren eingebauten Regeln. Ein Custom Harness verlagert sie in deinen Code. Du wählst die Modelle, legst die Thresholds fest, bestimmst, wann ein Mensch eingreift, und kannst im Log exakt nachvollziehen, warum welcher Aufruf stattfand.

Jev macht das erst praktikabel. Jede Entscheidung dauert wenige hundert Millisekunden und kostet einen winzigen Bruchteil eines Cents. So kannst du überall dort eine Prüfung einbauen, wo dein Workflow sie braucht – und nicht nur dort, wo du dir einen kompletten Modellaufruf leisten kannst. Die drei Teile aus diesem Tutorial sind ein Startpunkt. Ein Custom Harness für deine eigene Domäne kann Jev genau die Fragen stellen, die dort relevant sind.

Weitere Einsatzmöglichkeiten

Dieselben drei Bausteine funktionieren auch außerhalb von Coding Agents.

  • Code-Review-Bots. Bewerte jeden Änderungsvorschlag und zeige Menschen nur die, die wirklich lesenswert sind.
  • Datensatzbereinigung. Prüfe vor dem Zusammenführen, ob zwei Datensätze dasselbe beschreiben, und überlass unsichere Paare einem Menschen.
  • Dokumenten-Pipelines. Bewerte jede extrahierte Seite und lass nur die schlecht bewerteten erneut verarbeiten.
  • Freigabe-Queues. Nur Aufrufe im Bereich „Mensch fragen“ landen bei einem Reviewer.

In allen Fällen erledigt das Sprachmodell die offene Arbeit, und Jev beantwortet die kleinen Fragen drumherum.

Die Fragen, Thresholds und Policies in diesem Tutorial sind Lernbeispiele, keine feinjustierten Produktionswerte. Wir benchmarken gerade, wie sich diese Harness-Anpassungen auf Kosten und Antwortqualität auswirken – ein Folge-Guide mit den Ergebnissen erscheint bald.

Ich habe einen Abend mit Opus 5.5 verbracht, um diesen Guide und die Sandbox zusammenzustellen. Falls du auf Probleme stößt, schreib mir gerne eine DM. Kopier den Artikel ruhig und gib ihn deinen Agents, um mit den Ideen weiterzuexperimentieren.

Mit einem Klick speichern

Virale Artikel mit YouMind per KI tief lesen

Speichere die Quelle, stelle gezielte Fragen, fasse die Argumentation zusammen und verwandle einen viralen Artikel in wiederverwendbare Notizen in einem einzigen KI-Arbeitsbereich.

YouMind entdecken
Für Creator

Verwandle dein Markdown in einen sauberen 𝕏-Artikel

Wenn du eigene Langtexte veröffentlichst, wird die 𝕏-Formatierung von Bildern, Tabellen und Codeblöcken mühsam. YouMind macht aus einem ganzen Markdown-Entwurf einen sauberen, sofort postbaren 𝕏-Artikel.

Markdown zu 𝕏 testen

Mehr Muster zum Entschlüsseln

Aktuelle virale Artikel

Mehr virale Artikel entdecken