Human-in-the-loop für das OpenAI Agents SDK

Tool pausieren. Kundenfreigabe auf dem Handy einholen.

Dein OpenAI-Agent stoppt vor einer Erstattung. Dein Nutzer gibt sie auf dem Handy frei, dann läuft der Agent weiter.

Was OpenAI Agents SDK mitbringt

needsApproval und Laufunterbrechungen

Markiere ein Function-Tool mit needsApproval. Das SDK stoppt dann vor dessen Ausführung. Der Lauf liefert result.interruptions und einen speicherbaren RunState zurück. Dein Code genehmigt oder verwirft jede Unterbrechung und startet den Agenten aus diesem Zustand erneut.

Wo es nicht weitergeht

  • needsApproval legt fest, dass ein Mensch nötig ist. Es fragt aber niemanden; die Unterbrechung aufzulösen ist deine Aufgabe.
  • Für längere Wartezeiten musst du RunState speichern und mit demselben Agenten und derselben SDK-Version wiederherstellen.
  • Es weiß nicht, welcher deiner Nutzer antworten soll oder wie es ihn erreicht.

Die Lösung

Pushary holt die Antwort deines Nutzers ein.

Das Agents SDK kann einen Tool-Aufruf pausieren, benachrichtigt aber niemanden. Pushary schickt jeden pausierten Aufruf auf das Handy deines Nutzers und übergibt die Antwort an den Lauf.

issue_refund braucht eine Freigabe. Der Lauf stoppt deshalb vor der Ausführung. resolvePusharyInterruptions fragt deinen Nutzer zu jedem pausierten Aufruf, einzeln nacheinander. Eine Freigabe führt die Erstattung aus. Ablehnung, Ablauf oder fehlende Antwort lehnen sie ab; das Modell erhält den Grund. Deckt eine deiner Pushary-Regeln issue_refund ab, antwortet die Regel zuerst.

bash
npm i @pushary/openai-agents @openai/agents zod
Freigabe am riskanten Tool
import { Agent, run, tool } from "@openai/agents"
import { z } from "zod"
import { pusharyNeedsApproval, resolvePusharyInterruptions } from "@pushary/openai-agents"

const issueRefund = tool({
  name: "issue_refund",
  description: "Refund an order",
  parameters: z.object({ amount: z.number() }),
  needsApproval: pusharyNeedsApproval(),
  execute: async ({ amount }) => chargeBack(amount),
})

const agent = new Agent({ name: "Refunds", instructions: "Refund orders when asked.", tools: [issueRefund] })

let result = await run(agent, "Refund order 1234")
while (result.interruptions?.length) {
  const outcome = await resolvePusharyInterruptions(
    { externalId: user.id },
    { interruptions: result.interruptions, state: result.state },
  )
  result = await run(agent, result.state)
  if (!outcome.allApproved) break
}

Streaming und Responses API speichern unterschiedliche Dinge

Lies bei einem gestreamten Lauf die Ereignisse und warte mit await result.completed auf den Abschluss, bevor du Unterbrechungen prüfst und den Zustand speicherst. Das separate Responses API-Beispiel speichert die Response-ID und die genaue MCP-Freigabeanfrage. Danach sendet es mcp_approval_response mit previous_response_id. Das Tutorial behandelt beide Wege mit echten Diensten.

Stream abschließen, dann speichern
const result = await runner.run(agent, input, { stream: true });
for await (const event of result) {
  // Display appropriate events; output is not permission to act.
}
await result.completed;
// Now inspect result.interruptions and persist result.state.
// The complete recipe binds this state to customer + action.

So funktioniert es

Von der Installation zur ersten Antwort

Verbinde deinen Nutzer einmal. Sichere den riskanten Schritt mit einer Freigabe ab. Pushary schickt die Frage, wartet auf die Antwort und speichert sie.

  1. 01

    Adapter installieren

    Führe npm i @pushary/openai-agents @openai/agents zod aus und speichere deinen API-Schlüssel in PUSHARY_API_KEY. Für Python: pip install pushary-openai-agents.

  2. 02

    Nutzer einmal verbinden

    connect() liefert einen Link. Dein Nutzer öffnet ihn mit der kostenlosen Pushary-App auf seinem Handy. Dein API-Schlüssel und seine Nutzer-ID bleiben auf deinem Server.

  3. 03

    Das riskante Tool mit einer Freigabe absichern

    Setze needsApproval: pusharyNeedsApproval() am Tool. Der Lauf stoppt vor der Ausführung, und resolvePusharyInterruptions schickt jeden pausierten Aufruf an deinen Nutzer.

  4. 04

    Auf die Antwort reagieren

    Bei einer Freigabe startest du den Agenten aus result.state erneut. Bei Ablehnung oder fehlender Antwort wird der Aufruf verworfen. Für lange Wartezeiten speicherst du den Zustand und setzt den Lauf fort, wenn die Antwort kommt.

Eine Frage kann ein Ja oder Nein verlangen, eine Auswahl aus einer Liste oder eine Texteingabe. Jede Antwort wird gespeichert.

Vor der Veröffentlichung

Stolperfallen bei OpenAI Agents SDK

Ein optionales Frage-Tool erzwingt keine Freigabe
pusharyTool ist ein Tool, dessen Aufruf das Modell selbst wählt. Das passt zu „frag dazu nach“. Für „das darf ohne Ja nicht passieren“ setzt du needsApproval direkt am riskanten Tool. Ein Prompt mit „erst fragen“ hält nichts auf.
Eine gespeicherte Antwort ist kein gespeicherter Agent
Speichere vor der Frage den Laufzustand, den genauen Aufruf, den Nutzer und die Aktionsversion. Pushary speichert die Antwort, stellt aber weder deinen Prozess wieder her noch plant es die Fortsetzung. Dafür ist dein eigenes Jobsystem zuständig.
Die Freigabe gilt für den Aufruf, den dein Nutzer gesehen hat
Lies die Antwort erneut aus Pushary und prüfe, ob sie zum gespeicherten Aufruf passt. Nur ein Ja auf eine Ja/Nein-Frage erlaubt die Ausführung. Ändert sich der Entwurf, frage erneut. Wartende, abgelaufene, abgebrochene und abgelehnte Anfragen zählen nie als Freigabe.
Eine Wiederholung kann die Aktion trotzdem zweimal ausführen
Das Beispiel führt jede Fortsetzung nur einmal aus. Deine Erstattungs-API braucht trotzdem einen eigenen Vorgangsschlüssel, damit eine Wiederholung nichts bewirkt. Ist das Netzwerkergebnis unklar, prüfe vor dem Wiederholen, was passiert ist. Das Beispiel verarbeitet einen pausierten Aufruf pro gespeichertem Vorgang.

Der Partner-Tarif

Dein Agent fragt deine Nutzer, nicht nur dich

Stelle deinen Nutzern deinen Agenten bereit. Jeder gibt dessen riskante Aktionen vom eigenen Handy aus frei, unter deiner Marke.

$99/ Monat, alle Frameworks enthalten
Start free

Deine Nutzer brauchen kein Pushary-Konto und zahlen nichts an uns.

Deine Nutzer antworten auf ihren eigenen Handys

Verbinde jeden Nutzer einmal über einen Link. Er installiert die kostenlose Pushary-App und antwortet vom Sperrbildschirm aus, ohne eigenes Konto.

Keine Antwort heißt Nein

Führe die Aktion nur nach einer ausdrücklichen Freigabe aus. Eine wartende, abgelaufene oder abgebrochene Anfrage zählt nie als Ja. Pushary behält jede Anfrage, damit dein Code sie nach einem Neustart wieder aufnehmen kann.

Erreicht sie auf dem Handy

Die App kommt zuerst, denn nur sie zeigt „Genehmigen“ und „Ablehnen“ auf dem Sperrbildschirm. Browser-Benachrichtigungen folgen danach. Du musst kein Zustellsystem bauen.

Jede Antwort gespeichert

Zu jeder Antwort wird gespeichert, wer wann geantwortet hat. Du kannst sie durchsuchen und exportieren. Mit einer Callback-URL geht jede Antwort außerdem als signierter Webhook an deinen Server.

FAQ

Fragen und Antworten

Welche OpenAI-Pakete gibt es?
@pushary/openai-agents für TypeScript und pushary-openai-agents für Python. Beide bieten connect(), ein Frage-Tool und eine Freigabesperre für needsApproval: pusharyNeedsApproval und resolvePusharyInterruptions beziehungsweise die snake_case-Namen in Python. Die Beispiele für gespeicherte Zustände, Streaming und Responses API sind in TypeScript.
Ruft das Streaming-Beispiel ein echtes Modell oder Handy auf?
Nein. Es nutzt das echte Agents SDK mit simulierten Modellereignissen, HTTP-Antworten und Erstattungen sowie SQLite und frisch gestarteten Workern. Du brauchst weder Konto noch API-Schlüssel. Das Tutorial zeigt die Anbindung echter Dienste. Diese Prüfungen belegen nicht, dass eine Benachrichtigung auf einem Handy angekommen ist.
Wie setzt das MCP-Beispiel für die Responses API den Lauf fort?
Es speichert eine abgeschlossene Response-ID und die genaue mcp_approval_request, prüft die Antwort deines Nutzers und sendet dann mcp_approval_response mit previous_response_id. require_approval bleibt auf always gesetzt. Das ist unabhängig vom RunState des Agents SDK und erfordert gespeicherte Responses.
Was passiert, wenn der Kunde nie antwortet?
Der Aufruf läuft nicht. Eine noch wartende Anfrage ist kein Ja. Der Worker verwirft abgelaufene, abgebrochene oder abgelehnte Anfragen. Deine App fragt den Status ab oder wartet auf einen signierten Webhook und speichert den Laufzustand des SDK selbst. Pushary speichert die Anfrage, nicht deinen Prozess.
Ersetzt Pushary die Autorisierung oder Codex Auto-review?
Nein. Die Antwort deines Nutzers ergänzt deine eigene Autorisierung, Eingabeprüfungen und Grenzen für die Fähigkeiten jedes Tools. Apps auf Basis der Responses API oder des Agents SDK erhalten Codex Auto-review nicht automatisch.

Lass deinen OpenAI Agents SDK-Agenten fragen, bevor er handelt.

Verbinde einen Nutzer einmal, frage mit einem Aufruf und führe die Aktion nur bei einem Ja aus. Jede Antwort wird gespeichert.

Start free

Partner-Tarif, $99 im Monat. Deine Nutzer brauchen kein Pushary-Konto und zahlen nichts an uns.