AI-Entwicklung

JSON-Datenstrukturen der OpenAI Agents API: Wie Agent, Tool Call, Tool Result und Handoff zusammenhängen (2026)

Ca. 16 Min.

Nach der öffentlichen Beta ist das Schwere nicht „kann es ein Tool rufen“. Es ist, wie vier Objekte auf einer Kette sitzen. Es gibt kein Item vom Typ handoff. Die Stifte sind IDs: session_id, turn_id, call_id, agent_id. Dieser Text packt nur diese JSON-Kette aus.

Bevor Sie lesen

Objekt Offizielle Form Der Stift
Agent Modell, Tool-Tabelle, multi_agent Beim Session-Anlegen geschrieben
Tool Call function_call in required_actions turn_id + call_id
Tool Result agent.session.input.tool_result Dasselbe Paar zurück
Handoff create / send / wait / interrupt Items agent_id / subagent_id

Ein function_call in der Historie heißt nicht, dass noch ein Ergebnis fällig ist. Offene Arbeit steht in required_actions.

Vier Objekte sitzen auf IDs, nicht auf einem Absatz

In der Agents API ist Agent die Konfiguration beim Anlegen einer Session. Tool Call ist ein function_call in required_actions, wenn die Session hält. Tool Result ist agent.session.input.tool_result auf dem Ereignisstrom. „Handoff“ hier ist eine Gruppe von Koordinations-Items, nicht das SDK-Handoff-Objekt.

  • Dasselbe turn_id / call_id-Paar: Aufruf und Ergebnis müssen passen. Sonst läuft das Harness nicht weiter.
  • Historie reicht nicht: ein function_call in Items heißt nur, er fand statt. Noch wartend? required_actions lesen.
  • Handoff ist kein Typ: create_subagent_call und subagent_id ansehen. Kein Feld namens handoff suchen.

Wie Tools gerufen werden: OpenAI-Agents-API-Rundgang. Wie ein langer Auftrag weiterläuft: Langlebige Agents API. Wer die Schleife besitzen soll: Agents API vs. Responses API. Sind Agent und Function Calling noch ein Wort, zuerst AI-Agent, vollständiger Leitfaden.

Agent: ein Konfigurationsobjekt, keine Antwort

Anlegen schreibt Modell, Anweisungen, Tools und multi_agent einmal. Dieses Objekt ist das Subjekt aller späteren Items. Offiziell: POST /v1/agents/sessions mit OpenAI-Beta: agents=v1:

{
  "agent": {
    "model": "gpt-6-astra",
    "instructions": "Look up orders. Confirm before any refund.",
    "tools": [
      {
        "type": "function",
        "name": "lookup_order",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": { "type": "string", "pattern": "^[A-Z]-\\d{4}$" }
          },
          "required": ["order_id"],
          "additionalProperties": false
        }
      }
    ],
    "multi_agent": { "enabled": true, "max_concurrent_subagents": 3 }
  },
  "environment": { "type": "openai_hosted" },
  "input": [{ "role": "user", "content": [{ "type": "input_text", "text": "Look up A-1042." }] }]
}

Die Agent-Konfiguration bleibt bei der Session. Modell oder Reasoning zu ändern aktualisiert diese Session; eine gespeicherte Vorlage gilt nur für neue Sessions. Die Umgebung ist eine eigene Ressource: openai_hosted oder Ihre Sandbox. Die Session löschen räumt die Sandbox nicht.

Tool Call: required_actions vertrauen

Braucht es ein Funktionsergebnis, sendet die Session agent.session.requires_action. Offene Aufrufe stehen in required_actions als function_call mit turn_id / call_id:

{
  "type": "function_call",
  "turn_id": "turn_2",
  "call_id": "call_3c91",
  "name": "lookup_order",
  "arguments": { "order_id": "A-1042" }
}

Argumente müssen durch Schema. Ein weites object ist kein Tor. Siehe Warum AI JSON Schema braucht. Die Item-Historie kann ebenfalls function_call zeigen; offiziell: Historie allein beweist keine offene Warte.

Tool Result: dasselbe Paar auf den Ereignisstrom

Nach dem Lauf senden Sie agent.session.input.tool_result an den Events-Endpunkt. turn_id und call_id aus der offenen Aktion kopieren. Erfolg: success: true und ein String-output. Fehler: success: false und error:

{
  "type": "agent.session.input.tool_result",
  "turn_id": "turn_2",
  "call_id": "call_3c91",
  "success": true,
  "output": "{\"order_id\":\"A-1042\",\"status\":\"paid\"}"
}

Objekte zuerst serialisieren. Lief die Funktion vor dem Abbruch, dasselbe Paar erneut einreichen. Keine neue Session als „Retry“. Das Harness setzt den Turn erst fort, wenn die nötigen Ergebnisse da sind.

Handoff: Koordinations-Items, kein Feldname

Mit multi_agent.enabled liefert das Harness Create, Message, Wait und Interrupt. Diese Tools deklarieren Sie nicht. Koordination erscheint als Items:

{
  "data": [
    {
      "type": "create_subagent_call",
      "agent_id": "agent_main",
      "task": "Compare A-1042 packing notes with the invoice."
    },
    {
      "type": "send_subagent_input_call",
      "subagent_id": "sub_7a12",
      "input": "Focus on line items only."
    },
    {
      "type": "agent_message",
      "from": "sub_7a12",
      "text": "Invoice lines match packing notes for A-1042."
    }
  ]
}
  • create_subagent_call: entsenden. agent_id ist, wer gefragt hat. Fertig heißt nicht, die Teilaufgabe sei zu Ende.
  • send / wait / interrupt: sprechen, warten, stoppen. agent_message kann sichtbaren Text tragen; der Strom ist kein volles Transkript.
  • Das SDK-Handoff-Objekt: das lebt in Ihrem Prozess-Runner. Es ist nicht dieselbe Ressource wie diese Items.

Was Sie dem nächsten Subjekt übergeben, soll prüfbares JSON sein: Bestellnummer, Absicht, Beleg. Als Schema fassen: JSON Schema und Agent-Workflows.

Die Kette hält nur, wenn die Stifte passen

Die vier Objekte zu einer Kette falten, die Sie lokal neu aufbauen. Fiktive Bestellung — keine echten Geheimnisse:

{
  "session_id": "sess_8f21",
  "links": [
    { "object": "agent", "id": "agent_main" },
    { "object": "turn", "id": "turn_2" },
    { "object": "function_call", "call_id": "call_3c91" },
    { "object": "tool_result", "call_id": "call_3c91" },
    { "object": "subagent", "id": "sub_7a12", "via": "create_subagent_call" }
  ]
}
Objekt Typ, den Sie sehen Geheftet an Übliche Verschiebung
Agent session.agent session_id Neue Session als „Retry“
Tool Call function_call turn_id + call_id Nur die Item-Historie lesen
Tool Result input.tool_result Dasselbe Paar output noch ein Objekt, kein String
Handoff create_subagent_call agent_id / subagent_id Ein Feld namens handoff suchen
Turn turn.completed / failed turn_id; root subagent_id ist null Idle als Erfolg lesen

Eine MCP-Zeile ist eine weitere Tool-Tabelle. Sie erfindet kein zweites ID-Schema. Grenze: MCP Tool Schema vs. Function Calling.

Die Kette prüfen: zwei JSON-Spuren ausbreiten

Die meisten Verschiebungen sind driftende Stifte, kein dümmeres Modell.

  • required_actions und das Rückschreib-Ereignis formatieren. Die call_id muss genau passen.
  • Mit JSONPath extrahieren turn_id, call_id, subagent_id ziehen.
  • Aufruf und Ergebnis derselben Bestellung JSON Diff. Driftet es, zuerst die IDs.
  • Items des Hauptagenten und eines Subagenten getrennt listen. Gemischt hängt Koordination am falschen Akteur.
  • Keine Bestellungen, Sessions oder Intranet-MCP in einen öffentlichen Formatter. JSONSort läuft lokal im Browser.

Lassen sich beide Spuren über IDs neu aufbauen, lesen Sie Struktur. Sonst Slogans.

Häufige Fallen

  • Einen function_call in Items als noch offen lesen. Offen ist required_actions.
  • Ein anderes ID-Paar zurückschreiben. Das Harness kann nicht matchen; der Turn bleibt stehen.
  • output als rohes Objekt senden. Offiziell: String oder unterstütztes Content-Array.
  • type: handoff im Payload suchen. Die Agents API nutzt create / send / wait / interrupt.
  • Ihre Funktion an einen Subagent schicken. Subagents haben keine Function-Tools. Lookups bleiben beim Hauptagenten.
  • SDK-Handoff und Session-Items als eine Ressource behandeln. Eine löschen räumt die andere nicht.

FAQ

Muss jeder Tool Call ein Tool Result haben?

Jeder offene Aufruf muss zurückgeschrieben werden. Ein historischer function_call, der schon fertig ist, braucht kein weiteres Ergebnis. Der Test ist required_actions, nicht die Länge der Items.

Gibt es in der Agents API ein JSON-Feld namens handoff?

Nicht als Item-Typ erster Klasse. Koordination: create_subagent_call, send_subagent_input_call, wait_for_subagents_call, interrupt_subagent_call. Das SDK-Handoff ist ein anderes Objekt.

Worin unterscheiden sich call_id und item_id?

call_id heftet einen Funktionsaufruf an sein Ergebnis. item_id benennt das gespeicherte Item. Der Strom hängt Text-Deltas mit item_id an denselben Teil. Zwei Stifte — nicht mischen.

Wie kann ein Turn fertig sein, wenn ein Tool fehlschlug?

Offiziell: completed heißt nicht, jedes Tool sei gelungen. Auch success am tool_result und die Items dieses Turns lesen.

Darf ich eigenes Handoff-JSON in der App führen?

Ja, und Sie sollten. Das ist Ihr Geschäftsobjekt: Bestellnummer, Absicht, Beleg. Erwarten Sie nicht, dass offizielle Items Beträge merken. Als Schema schreiben und getrennt von Session-Items lagern.

Schluss

Agent, Tool Call, Tool Result und Handoff sind keine vier Absätze. Sie sind vier Objekte auf einer JSON-Kette, geheftet durch IDs. Offizielles Rückschreiben ist ein Ereignis; offizielle Übergabe ist ein Koordinations-Item.

Schreiben Sie fest, ob Sie Aufruf und Ergebnis allein aus call_id zuordnen können. Wenn ja, hält die Struktur. Modelle wechseln; die Stifte sollten zuerst stehen.

Weiterlesen

Änderungsprotokoll: Erstveröffentlichung