OpenAIAPILLMAIJavaScriptResponses APIStructured Outputs

OpenAI API: Responses API und Structured Outputs – Spezifikation und Implementierungshandbuch

Sloth255
Sloth255
·9 min read·1,918 words

Einführung

Mit dem Eintritt in das Jahr 2025 hat die OpenAI API einen wichtigen Wendepunkt erreicht. Im März 2025 wurde die Responses API offiziell veröffentlicht (GA) und konsolidiert die Konversationsfähigkeiten der Chat Completions API und die Tool-Integrationsfunktionen der Assistants API zu einem einzigen Endpunkt. Die Legacy Assistants API ist für die Abschaltung am 26. August 2026 vorgesehen.

Darüber hinaus entfaltet Structured Outputs, das sicherstellt, dass Modellausgaben strikt einem JSON-Schema entsprechen, in Kombination mit der Responses API sein volles Potenzial. Seit seiner Veröffentlichung im August 2024 hat es die Zuverlässigkeit von Agentic Workflows und Datenextraktionspipelines erheblich verbessert.

Dieser Artikel gibt zunächst einen Überblick über die OpenAI API-Landschaft 2025 und taucht dann in die Spezifikationen und Implementierungsdetails dieser beiden Schlüsselthemen ein.

Quellinformationen
Spezifikationen und Performance-Daten in diesem Artikel beziehen sich auf die OpenAI Offizielle Dokumentation (developers.openai.com/api), den Offiziellen Migrationsguide (developers.openai.com/api/docs/guides/migrate-to-responses) und den Offiziellen Blog (openai.com/index/introducing-structured-outputs-in-the-api).


1. API-Übersicht

Die wichtigsten Kategorien der OpenAI API 2025 sind wie folgt organisiert:

Kategorie Endpunkt Positionierung
Responses API POST /v1/responses Empfohlen für neue Projekte. Einheitliches Interface für Agenten.
Chat Completions API POST /v1/chat/completions Weiterhin unterstützt (kein geplantes Deprecation).
Realtime API WebRTC / WebSocket / SIP Bidirektionale Echtzeit-Sprache und Text.
Embeddings POST /v1/embeddings Vektorsuche und RAG.
Images POST /v1/images/generations Bildgenerierung und -bearbeitung.
Audio POST /v1/audio/transcriptions Spracherkennung und TTS.

OpenAI hat die Responses API als primäres Ziel für neue Funktionen positioniert, und die Abschaltung der Assistants API am 26. August 2026 ist offiziell bestätigt (Quelle: Offizieller Migrationsguide). Während die Chat Completions API ohne Abschaltungsdatum weiter unterstützt wird, ist die Responses API die aktuelle Empfehlung für neue Projekte.

Structured Outputs ist kein unabhängiger Endpunkt wie jene in der obigen Tabelle, sondern eine Ausgabeformat-Steueroption, die sowohl für die Responses API als auch für die Chat Completions API verfügbar ist. Sie wird mit dem Parameter text.format bei ersterer und dem Parameter response_format bei letzterer angegeben. Dieser Artikel konzentriert sich besonders auf die Kombination mit der Responses API.


2. Responses API

2.1 Übersicht

Die Responses API ist ein neues Primitiv, das die Chat Completions API ablöst und die Funktionen der Assistants API integriert. Sie erreichte im März 2025 die General Availability (GA).

Die bedeutendste Änderung ist die Fähigkeit, Konversationsstatus serverseitig zu persistieren. Im Gegensatz zu herkömmlichen Chat Completions, bei denen die gesamte Konversationsgeschichte in jede Anfrage einbezogen werden musste, ermöglicht die Responses API das Fortsetzen einer Konversation durch einfaches Übergeben einer previous_response_id.

2.2 Grundlegende Anfrage

import OpenAI from "openai";

const client = new OpenAI();

const response = await client.responses.create({
  model: "gpt-4o",
  input: "Tell me the weather in Tokyo.",
});

console.log(response.output_text); // Text direkt mit dem output_text-Helfer abrufen

2.3 Der output_text-Helfer

output_text ist eine vom OpenAI SDK bereitgestellte Convenience-Eigenschaft, kein Teil der API-Spezifikation selbst.

In der rohen Antwort der Responses API ist der Text innerhalb folgender Struktur verschachtelt:

response.output[0].content[0].text

output_text fasst das Traversieren dieses Pfades zusammen. Intern gibt es den Text des ersten Elements im output-Array zurück, das type: "message" und einen content-Block mit type: "output_text" hat.

// Beides ergibt die gleiche Ausgabe
console.log(response.output_text);
console.log(response.output[0].content[0].text);

Es funktioniert jedoch möglicherweise nicht wie erwartet, wenn das erste Element im output-Array keine Textnachricht ist – zum Beispiel wenn ein Tool-Aufruf stattfindet. Für robusten Agentic-Code, der Tools verwendet, ist es besser, das output-Array zu durchlaufen und den type zu prüfen.

for (const item of response.output) {
  if (item.type === "message") {
    for (const block of item.content) {
      if (block.type === "output_text") {
        console.log(block.text);
      }
    }
  }
}

2.4 role in Input-Nachrichten

Beim Übergeben eines Arrays an input können Sie für jede Nachricht eine role angeben. Die role teilt dem Modell mit, „wer diese Aussage macht", und es gibt drei Typen.

role Bedeutung Typische Verwendung
system Anweisungen vom System (Entwickler) Definiert das Verhalten, den Ton und die Einschränkungen des Modells. Generell einmal am Anfang einer Konversation platziert.
user Eingabe vom Endbenutzer Repräsentiert die Aussagen oder Fragen des Benutzers.
assistant Eigene vergangene Aussagen des Modells In Multi-Turn-Konversationen verwendet, um frühere Antworten als Geschichte bereitzustellen.
const response = await client.responses.create({
  model: "gpt-4o",
  input: [
    {
      role: "system",
      content: "You are a helpful Japanese assistant. Please answer concisely.",
    },
    {
      role: "user",
      content: "Tell me about JavaScript array methods.",
    },
  ],
});

Wenn Sie einen String direkt an input übergeben (wie im Beispiel in 2.2), wird dieser String als Nachricht mit role: "user" behandelt. Verwenden Sie das Array-Format, wenn Sie eine feinkörnige Kontrolle über das Modellverhalten wünschen oder system-Anweisungen bereitstellen möchten.

2.5 Antwortstruktur

Im Gegensatz zu choices bei Chat Completions werden Ergebnisse in einem output-Array zurückgegeben.

{
  "id": "resp_68af4030...",
  "object": "response",
  "created_at": 1756315696,
  "model": "gpt-4o",
  "output": [
    {
      "id": "msg_68af4033...",
      "type": "message",
      "status": "completed",
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "The weather in Tokyo is sunny."
        }
      ]
    }
  ],
  "usage": {
    "input_tokens": 15,
    "output_tokens": 12,
    "total_tokens": 27
  }
}

2.6 Multi-Turn-Konversation

Es gibt zwei Möglichkeiten, Multi-Turn-Konversationen mit der Responses API zu realisieren.

1. Verlauf als Array in input übergeben

Dies ist die traditionelle Methode aus der Chat Completions API. Sie verwenden und verwalten die Konversationsgeschichte clientseitig und fügen alle Nachrichten in jede Anfrage ein.

const history = [
  { role: "system", content: "You are a helpful assistant." },
  { role: "user", content: "Tell me the weather in Tokyo." },
  { role: "assistant", content: "It is sunny in Tokyo today." },
];

const response = await client.responses.create({
  model: "gpt-4o",
  input: [...history, { role: "user", content: "How about tomorrow?" }],
});

Da kein State auf dem Server gespeichert wird, besteht der Vorteil darin, dass Sie den Verlauf frei bearbeiten können, z. B. bestimmte Nachrichten löschen oder zusammenfassen. Mit zunehmender Konversationslänge steigt jedoch die Anzahl der Input-Tokens, was Kosten und Latenz beeinflusst.

2. previous_response_id übergeben (exklusiv für die Responses API)

Dies ist die serverseitige State-Management-Methode, die neu mit der Responses API eingeführt wurde. Durch einfaches Übergeben der vorherigen Antwort-ID werden die OpenAI-Server die Konversationsgeschichte übertragen.

// Erster Turn
const response1 = await client.responses.create({
  model: "gpt-4o",
  input: "Tell me the weather in Tokyo.",
});

// Zweiter Turn: Kontext wird nur mit previous_response_id geerbt
const response2 = await client.responses.create({
  model: "gpt-4o",
  input: "How about tomorrow?",
  previous_response_id: response1.id,
});

Der Client muss den gesamten Verlauf nicht verwalten oder senden, was die Anfragegröße klein hält. Darüber hinaus werden bei Reasoning-Modellen wie o1 oder o3 die Thinking-Tokens zwischen Turns persistiert, was ein erheblicher Vorteil ist, da die Genauigkeit für Aufgaben, die kontinuierliches Reasoning erfordern, verbessert wird.

Um diese Methode zu verwenden, muss die Antwort auf dem Server gespeichert werden. Beachten Sie, dass das Setzen von store: false eine Referenzierung per ID unmöglich macht, obwohl der Parameter store standardmäßig auf true steht.

Auswahlkriterien

Situation Empfohlene Methode
Verlauf auf halbem Weg ändern/bearbeiten müssen (RAG-Injektion, alte Nachrichten löschen usw.) ① Array-basiert
Komplexe Multi-Turn-Probleme mit Reasoning-Modellen lösen (o1, o3 usw.) previous_response_id
Einfacher Chat, bei dem manuelle Verlaufsverwaltung vermieden werden soll previous_response_id
Chat Completions API verwenden ① Array-basiert (previous_response_id ist nur für Responses API)

2.7 Eingebaute Tools

Einer der größten Vorteile der Responses API ist der Satz von eingebauten Tools, die ohne zusätzliche Infrastruktur verfügbar sind.

const response = await client.responses.create({
  model: "gpt-4o",
  input: "Search for the latest OpenAI news and summarize it.",
  tools: [
    { type: "web_search_preview" },
    { type: "file_search" },
    { type: "code_interpreter" },
  ],
});
Tool Zweck
web_search_preview Websuche äquivalent zu ChatGPT.
file_search RAG-Suche über hochgeladene Dateien.
code_interpreter Code-Ausführung und Datenanalyse.
computer_use Computer-Bedienungsagent.
mcp Verbindung mit Drittanbieter-MCP-Servern.

MCP (Model Context Protocol)-Integration

Connectors sind von OpenAI verwaltete MCP-Wrapper für beliebte Dienste wie Google Workspace oder Dropbox, während Remote MCP Server beliebige Server im öffentlichen Internet sind, die das Remote-MCP-Protokoll implementieren (Quelle: OpenAI Connectors and MCP Guide).

Die Responses API kann mit Remote-MCP-Servern integriert werden, die Streamable HTTP- oder HTTP/SSE-Transportprotokolle unterstützen. Wenn ein Tool angegeben wird, ruft die API zunächst die Liste der verfügbaren Tools vom Server ab (mcp_list_tools), und das Modell ruft dann die notwendigen Tools aus dieser Liste auf.

Grundlegendes Verbindungsbeispiel (Quelle: OpenAI Using tools Guide)

const response = await client.responses.create({
  model: "gpt-4o",
  input: "Roll 2d6 and tell me the result.",
  tools: [
    {
      type: "mcp",
      server_label: "dice_server",           // Bezeichner für den Server (beliebig)
      server_url: "https://example.com/mcp", // URL des MCP-Servers
      require_approval: "never",             // Tool-Aufrufe automatisch genehmigen
    },
  ],
});

console.log(response.output_text);

Genehmigungssteuerung mit require_approval

Standardmäßig erfordern alle Tool-Aufrufe die explizite Genehmigung des Entwicklers. Mit require_approval kann dieses Verhalten gesteuert werden (Quelle: OpenAI Connectors and MCP Guide).

require_approval-Wert Verhalten
"never" Alle Tool-Aufrufe automatisch genehmigen.
{ never: { tool_names: [...] } } Angegebene Tools automatisch genehmigen; andere erfordern Genehmigung.
Weggelassen (Standard) Alle Tool-Aufrufe erfordern Genehmigung.

2.8 Wichtige Anfrageparameter

Parameter Typ Beschreibung
model string Modellname (z. B. gpt-4o).
input string / array Text- oder multimodale Eingabe.
previous_response_id string Vorherige Antwort-ID für Multi-Turn.
tools array Definitionen der zu verwendenden Tools.
text.format object Spezifikation für Structured Outputs (siehe unten).
stream boolean Streaming aktivieren.
store boolean Ob die Antwort auf dem Server gespeichert werden soll (Standard: true).
reasoning_effort string Reasoning-Tiefe anpassen (low / medium / high).
background boolean Asynchrone Ausführung im Hintergrundmodus.

2.9 Vergleich mit Chat Completions

Funktion Chat Completions Responses API
Konversationsstatus Clientseitig (gesamter Verlauf erforderlich) Serverseitig (previous_response_id)
Websuche Manuelle Implementierung erforderlich Eingebaut (web_search_preview)
File Search / RAG Manuelle Implementierung erforderlich Eingebaut (file_search)
Code-Ausführung Manuelle Implementierung erforderlich Eingebaut (code_interpreter)
MCP-Verbindung Nicht unterstützt Native Unterstützung für Remote-MCP
Reasoning-Token-Persistenz Zwischen Turns verworfen Kann persistiert werden
output_text-Helfer Nein Ja
Format-Spezifikation response_format text.format
Neue Funktionslieferung Begrenzt Primäres Ziel

2.10 Reasoning-Modelle (o-Serie)

Distinct von der GPT-Serie bietet OpenAI eine Gruppe von Modellen namens Reasoning-Modelle an. Diese Modelle führen einen internen schrittweisen Denkprozess (Chain-of-Thought) aus, bevor sie eine Antwort generieren. Dieses interne Denken wird als Reasoning-Tokens gezählt, die nicht in der endgültigen Ausgabe enthalten sind.

Sie zeigen deutlich höhere Genauigkeit als GPT-4o für Aufgaben, die mehrstufiges Reasoning erfordern, wie Mathematik, Coding, logischen Schluss und komplexe Analyse. Andererseits sind Latenz und Kosten höher, weil das Denken Zeit braucht.

Wichtige Modelle 2025:

Modell Merkmale
o1 / o1-mini Erste Generation Reasoning-Modelle.
o3 / o3-mini Hochpräzise, hochperformante Nachfolge-Serie.
o4-mini Modell ausbalanciert für Kosten und Performance.

Die Reasoning-Tiefe kann mit dem Parameter reasoning_effort angepasst werden. low ist ein leichtgewichtiges Reasoning, das Latenz und Kosten reduziert, während high ein tiefes Reasoning für maximale Präzision ist.

const response = await client.responses.create({
  model: "o3",
  input: "Find the general term for this sequence: 1, 1, 2, 3, 5, 8, 13, ...",
  reasoning_effort: "high",
});

3. Structured Outputs

3.1 Übersicht und Hintergrund

LLM-Ausgaben zuverlässig in JSON-Format zu zwingen, war eine wichtige Herausforderung für die Anwendungsintegration. OpenAI hat dies schrittweise gelöst:

JSON-Modus (Legacy-Funktion) stellt syntaktisch korrektes JSON sicher, garantiert jedoch keine Schema-Einhaltung. Es bestand das Risiko, dass erforderliche Felder fehlen oder unerwünschte Felder hinzukommen.

Structured Outputs, veröffentlicht im August 2024, garantiert 100% die Einhaltung eines vom Entwickler angegebenen JSON-Schemas (Quelle: OpenAI Offizieller Blog).

Interne Evaluierungen bei OpenAI zeigen, dass gpt-4o-2024-08-06 100% Schema-Konformität bei komplexen JSON-Schemas mit Structured Outputs erreicht, ein massiver Sprung gegenüber den weniger als 40% von gpt-4-0613.

3.2 Funktionsweise

Die OpenAI API erreicht Structured Outputs durch Umwandlung des angegebenen JSON-Schemas in eine Context-Free Grammar (CFG). Diese Grammatik schränkt die Tokens ein, die während des Samplings generiert werden können, und erzwingt so die Schema-Konformität.

3.3 Zwei Verwendungsmöglichkeiten

Structured Outputs wird in zwei Formen über die API bereitgestellt.

Die erste ist über Function Calling (Tools), aktiviert durch Setzen von strict: true innerhalb der Funktionsdefinition. Diese ist für alle Modelle ab gpt-4-0613 aufwärts verfügbar.

Die zweite ist über den response_format / text.format-Parameter, wobei die Angabe eines json_schema geeignet ist, wenn das Modell dem Benutzer in einem strukturierten Format antworten soll.

3.4 Implementierungsbeispiel (Responses API)

In der Responses API wurde der Parameter von response_format zu text.format verschoben (Quelle: Offizieller Migrationsguide).

Schema-Definition mit Zod (Empfohlen)

import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const client = new OpenAI();

const Step = z.object({
  explanation: z.string().describe("Explanation of what is being done in this calculation step."),
  output: z.string().describe("The calculation result for this step (formula or numerical value)."),
});

const MathResponse = z.object({
  steps: z.array(Step).describe("A list of steps for the solution."),
  final_answer: z.string().describe("The final answer to the equation (e.g., x = -3.75)."),
});

const response = await client.responses.parse({
  model: "gpt-4o",
  input: [
    { role: "system", content: "You are a math tutor. Explain step-by-step." },
    { role: "user", content: "Solve 8x + 7 = -23" },
  ],
  text: { format: zodResponseFormat(MathResponse, "math_response") },
});

const result = response.output_parsed;
console.log(result.final_answer);
for (const step of result.steps) {
  console.log(step.explanation, "->", step.output);
}

JSON-Schema direkt angeben

const response = await client.responses.create({
  model: "gpt-4o",
  input: [
    { role: "system", content: "You are a math tutor." },
    { role: "user", content: "Solve 8x + 7 = -23" },
  ],
  text: {
    format: {
      type: "json_schema",
      name: "math_response",
      strict: true,
      schema: {
        type: "object",
        properties: {
          steps: {
            type: "array",
            items: {
              type: "object",
              properties: {
                explanation: { type: "string" },
                output: { type: "string" },
              },
              required: ["explanation", "output"],
              additionalProperties: false,
            },
          },
          final_answer: { type: "string" },
        },
        required: ["steps", "final_answer"],
        additionalProperties: false,
      },
    },
  },
});

3.5 Was Structured Outputs garantiert (und was nicht)

Element Status Ergänzung
Korrekte JSON-Syntax ✅ Garantiert
Einhaltung des angegebenen Schemas ✅ Garantiert (mit strict: true)
Vorhandensein erforderlicher Felder ✅ Garantiert
Verwendung von in enum angegebenen Werten ✅ Garantiert
Faktische Korrektheit ❌ Nicht garantiert Halluzinationen können für schemafremde Eingaben auftreten.
Befreiung von Sicherheitsrichtlinien ❌ Nicht garantiert Das Modell kann aus Sicherheitsgründen ein refusal zurückgeben.

3.6 Schema-Einschränkungen im strict-Modus

Im strict: true-Modus sind einige JSON-Schema-Funktionen eingeschränkt:

  • additionalProperties: false ist erforderlich.
  • Alle Eigenschaften müssen im required-Array enthalten sein.
  • Direkte Verwendung von anyOf beim Root-Objekt ist nicht erlaubt.

4. Realtime API

Die Realtime API, die 2025 GA erreichte, ist eine spezialisierte API für latenzarmes bidirektionales Sprach- und Text-Streaming via WebRTC, WebSocket oder SIP. Sie unterscheidet sich klar von der Responses API in ihren Anwendungsfällen. Weitere Details finden Sie im Offiziellen Realtime API Guide.


5. Streaming

Die Responses API unterstützt Streaming im Server-Sent Events (SSE)-Format, das den Empfang langer Antworten schrittweise ermöglicht.

const stream = await client.responses.stream({
  model: "gpt-4o",
  input: "Tell me in detail about the beginning of the universe.",
});

for await (const event of stream) {
  if (
    event.type === "response.output_text.delta" &&
    event.delta
  ) {
    process.stdout.write(event.delta);
  }
}

6. Rate Limits

Rate Limits werden pro Organisation und Projekt angewendet (nicht pro Benutzer).

  • RPM (Requests Per Minute): Anzahl der Anfragen pro Minute.
  • TPM (Tokens Per Minute): Anzahl der Tokens pro Minute.

Wenn 429 Too Many Requests zurückgegeben wird, wird Retry mit exponentiellem Backoff empfohlen.

import retry from "async-retry";

async function callApiWithBackoff(params) {
  return retry(
    async () => {
      return await client.responses.create(params);
    },
    {
      retries: 6,
      minTimeout: 1000,
      maxTimeout: 60000,
      randomize: true,
    }
  );
}

Zusammenfassung

Punkt Inhalt
Neue Projekte Responses API (POST /v1/responses) verwenden.
Chat Completions Weiterhin unterstützt. Keine sofortige Migration notwendig.
Assistants API Abschaltung am 26. August 2026. Migration zu Responses API empfohlen.
Structured Outputs 100% Schema-Konformität mit strict: true + additionalProperties: false.
Responses API-Verwendung text.format statt response_format verwenden.
Echtzeit-Sprache Realtime API (WebRTC / WebSocket / SIP) verwenden.
Rate Limits Headers überwachen und mit exponentiellem Backoff wiederholen.
Modellversionierung Snapshots pinnen und Evals in der Produktion durchführen.