Blog • Open Responses
Nachdem Open Responses der AAIF beigetreten ist: welche type-, arguments- und status-Prüfungen vor dem Replay eines Tool-Call-Items?
Am 22. Oktober 2026 machte die Agentic AI Foundation Open Responses zum gehosteten Projekt. Die Spec fasst eine Runde in Items: message, function_call und function_call_output sind der portable Kern; ein type mit Anbieter-Präfix gehört zu dieser Implementierung.
Bevor ein geloggtes Item an ein anderes Modell geht, drei Felder lokal prüfen. Ein Doppelpunkt in type heißt: kein portables function_call. In den Spec-Beispielen ist arguments ein JSON-String: erst parse, dann Tool-JSON-Schema. Ist status nicht completed, kein function_call_output anhängen.
Der gestrige Text Bedrock Structured Outputs behandelt die Form des Modelltexts. Chat Completions speichert arguments oft auch als String, in einem anderen Umschlag—siehe AI Agent und JSON Schema. Schema-Bestanden heißt nicht ausführen—siehe die Rechteentscheidung. Dieser Artikel behandelt nur das Open-Responses-Item.
- Portable Typen: message, function_call oder function_call_output.
- Ein type mit Doppelpunkt ist eine Anbieter-Erweiterung, kein portabler Tool-Call.
- arguments muss ein String sein; das geparste Objekt gegen das Tool-Schema prüfen, inklusive region.
- Bei in_progress oder incomplete stoppen. function_call_output nur bei completed, und call_id muss stimmen.
Zuerst dies: Die AAIF hat eine gemeinsame Item-Form übernommen. Ein JSON-Datensatz kann weiter nur einem Anbieter gehören. Unten der Reihe nach: type, arguments, status, und welches Feld das Replay stoppt.
Am 22. Oktober wechselte das gemeinsame Item in offene Governance
Bei AGNTCon und MCPCon kündigte die AAIF vier Projekte an. Open Responses, beigetragen von OpenAI, steht neben MCP und A2A unter Linux-Foundation-Governance. Die Meldung: AAIF-Ankündigung. Am selben Tag kamen Anthropic Agent Skills, Hugging Face OpenEnv und Alibaba OpenSandbox dazu. Dieser Text behandelt weder deren Kataloge noch das Skill-Format, nur das Item-JSON von Open Responses.
Ein AWS-Open-Source-Beitrag vom selben Tag schreibt, Amazon Bedrock unterstütze die Responses API und beteilige sich an der Spec. Siehe den AWS-Open-Source-Beitrag. Feldbedeutungen folgen der Open-Responses-Spezifikation. Nicht gestreamte Körper sind application/json, Items unterscheiden sich über type. Die Frage: ein function_call liegt schon im Log; welche drei Felder stoppen die nächste Anfrage vor Anbieterwechsel oder Replay am nächsten Tag.
Welche Felder braucht ein replaybares function_call mindestens?
Ein function_call für den nächsten Check trägt mindestens type, id, name, call_id, status und arguments. Der Wert von arguments ist ein String; die Tool-Parameter stecken darin. Unten ist region apac, geprüft mit demselben Schema.
{
"type": "function_call",
"id": "fc_001",
"name": "get_latest_sales_report",
"call_id": "call_123",
"status": "completed",
"arguments": "{\"region\":\"apac\"}"
}
Nach der lokalen Tool-Ausführung hängt die nächste Anfrage function_call_output an, kein tool_calls-Array aus Chat Completions. Das Fortsetzungsbeispiel der Spec behält dieselbe call_id und setzt output. Kommt das Ergebnis später als Item zurück, folgen id und status.
{
"type": "function_call_output",
"call_id": "call_123",
"output": "sales report for apac"
}
Warum blockiert ein Doppelpunkt in type den Wechsel des Anbieters?
Die Spec erlaubt eigene Items, doch type braucht ein Anbieter-Slug-Präfix, zum Beispiel openai:web_search_call. Der Datensatz kann in der ursprünglichen Sitzung bleiben und zum selben Anbieter zurück. Portabilität auf einen anderen Open-Responses-Server wird nicht angenommen. Lokal: Doppelpunkt heißt namespaced, kein function_call_output.
{
"type": "openai:web_search_call",
"id": "ws_001",
"status": "completed",
"action": { "type": "search", "query": "apac sales report" }
}
| Sichtbarer type | Replay bei anderem Anbieter? | Lokale Aktion |
|---|---|---|
function_call | Weiter zum nächsten Check | Danach arguments und status prüfen. |
message | Kann in input | Als Gesprächstext, nicht als Tool-Ergebnis. |
openai:web_search_call | Nicht portabel | Beim Originalanbieter lassen oder aus dem anbieterübergreifenden Log nehmen. |
Warum muss arguments erst ein String sein, dann das Schema?
Das Streaming-Event response.function_call_arguments.delta hängt Text an, bevor das Objekt fertig ist. Gespeichertes arguments ist daher ein String, kein Objekt. Ein Log mit Objekt in arguments scheitert beim nächsten Parse oder wird von einer anderen Implementierung abgelehnt. Erst String prüfen, dann json.loads, dann das Tool-JSON-Schema. Das Schema unten erlaubt nur apac, emea und amer.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["region"],
"properties": {
"region": {
"type": "string",
"enum": ["apac", "emea", "amer"]
}
}
}
Der String unten lässt sich parse, aber region ist global und nicht im enum. Das Gate soll arguments_schema liefern, das Tool läuft nicht.
{
"type": "function_call",
"id": "fc_009",
"name": "get_latest_sales_report",
"call_id": "call_129",
"status": "completed",
"arguments": "{\"region\":\"global\"}"
}
| Sichtbares arguments | Gate-Ergebnis | Lokale Aktion |
|---|---|---|
| String, Objekt mit region apac | ok | Tool ausführen, dann function_call_output schreiben. |
| arguments ist selbst ein Objekt | arguments_type | Ablehnen. Erst wieder zum String, dann parse. |
| Parse gelingt, region ist global | arguments_schema | Nicht ausführen. Validierungsfehler zurückschreiben, keine Region raten. |
Warum kein Tool-Ergebnis, wenn status nicht completed ist?
Die Spec macht jedes Item zu einer Zustandsmaschine. in_progress heißt, die Ausgabe läuft noch. incomplete ist terminal, muss das letzte Item dieser Response sein, und die Response selbst muss incomplete sein. Nach completed ändert sich das Item nicht mehr. Bei incomplete kann arguments abgeschnitten sein; halbes JSON darf nicht laufen.
| status | function_call_output schreiben? |
|---|---|
in_progress | Nein. Warten, bis der Strom endet. |
incomplete | Nein. Terminal, Argumente können abgeschnitten sein. |
completed | Ja. Danach: kein Doppelpunkt in type, arguments besteht das Schema, call_id stimmt mit dem nächsten Item. |
| Jeder andere Wert, auch failed | Nein. Keinen Seiteneffekt ausführen. |
Das Gate unten ist derselbe Code, der die Beispiele dieses Artikels prüft. Es liefert den Grund in dieser Reihenfolge: Doppelpunkt, kein function_call, status, Typ von arguments, Parse, Schema. Nur ok darf das Tool ausführen und function_call_output anhängen.
def actual_type(data: object) -> str:
if data is None:
return "null"
if isinstance(data, bool):
return "boolean"
if isinstance(data, list):
return "array"
if isinstance(data, int):
return "integer"
if isinstance(data, float):
return "number"
if isinstance(data, str):
return "string"
if isinstance(data, dict):
return "object"
raise TypeError(type(data))
def validate(data: object, schema: dict) -> list[str]:
errors: list[str] = []
if not isinstance(schema, dict):
return errors
types = schema.get("type")
if isinstance(types, str):
types = [types]
actual = actual_type(data)
if types and not any(t == actual or (t == "number" and actual == "integer") for t in types):
errors.append("type")
if "enum" in schema and not any(value == data for value in schema["enum"]):
errors.append("enum")
if isinstance(data, dict) and schema.get("properties"):
for key in schema.get("required") or []:
if key not in data:
errors.append(f"required:{key}")
if schema.get("additionalProperties") is False:
for key in data:
if key not in schema["properties"]:
errors.append(f"additional:{key}")
for key, sub in schema["properties"].items():
if key in data:
errors.extend(validate(data[key], sub))
if isinstance(data, list) and schema.get("items"):
for item in data:
errors.extend(validate(item, schema["items"]))
return errors
def replay_gate(item: dict, schema: dict) -> str:
item_type = item.get("type")
if not isinstance(item_type, str) or ":" in item_type:
return "namespaced"
if item_type != "function_call":
return "not_function_call"
if item.get("status") != "completed":
return "status"
arguments = item.get("arguments")
if not isinstance(arguments, str):
return "arguments_type"
try:
parsed = json.loads(arguments)
except json.JSONDecodeError:
return "arguments_parse"
if validate(parsed, schema):
return "arguments_schema"
return "ok"
Wie prüft man die drei Felder in JSONNote?
- 1Zuerst: ist arguments ein String?
Öffnen Sie JSON formatieren. Das ganze Item einfügen. Entfaltet sich arguments zu einem Objekt statt einem String, ist die Speicherform schon falsch und das Gate liefert arguments_type.
- 2Dann die geparsten Parameter prüfen
Das aus dem arguments-String geparste Objekt in JSON Schema. Als Schema das region-Enum von oben. global wird markiert; vor der Ausführung nicht auf apac ändern.
- 3Zuletzt die Items beider Anbieter vergleichen
Öffnen Sie JSON Diff. Links das Item des Originalanbieters, rechts das zum Replay. Wechselt type von function_call zu einer Erweiterung mit Doppelpunkt, oder call_id stimmt nicht, die nächste Anfrage nicht senden.
Häufige Fragen
Kann dasselbe JSON nach dem AAIF-Beitritt direkt zu Bedrock oder einer anderen Implementierung?
Nein. Portabel sind message, function_call und function_call_output. Ein Item mit Anbieter-Präfix gilt nicht als serverübergreifend replaybar. Claude Structured Outputs auf Bedrock betreffen eine andere Schicht: JSON Schema für Modelltext, nicht diesen Item-Umschlag.
Warum wird arguments nicht als Objekt gespeichert?
Die Spec-Beispiele speichern arguments als JSON-String. Streaming hängt per function_call_arguments.delta an, und vor completed kann der String unvollständig sein. Nicht vorzeitig parse und ausführen.
Darf ich das Tool ausführen, wenn status incomplete ist?
Nein. incomplete ist terminal. Die Spec verlangt, dass es das letzte Item dieser Response ist und die Response selbst incomplete ist. Abgeschnittenes arguments scheitert meist am Schema; selbst bei zufälligem Bestehen nicht als fertigen Aufruf ausführen.
Brauche ich ein lokales Schema, wenn allowed_tools die Tool-Namen schon begrenzt?
Ja. allowed_tools begrenzt, welche Tool-Namen in dieser Anfrage wirklich laufen dürfen; die Definitionen können weiter vollständig in tools stehen. Es prüft nicht, ob region in arguments im Enum liegt. Ein erlaubter Name braucht weiter Parse und Schema.
Dürfen tool_calls aus Chat Completions im selben Array wie Open-Responses-Items stehen?
Nein. Open Responses nutzt type, call_id und arguments als String. Chat Completions nutzt ein tool_calls-Array. In einem Log vermischt, schickt das Replay den falschen Umschlag zum nächsten Anbieter. Die zwei Dokumente per Diff getrennt vergleichen.
Fazit
Nachdem Open Responses der AAIF beigetreten ist, teilen Anbieter die Item-Form, nicht jede Logzeile.
Entscheidung: Doppelpunkt in type heißt kein portables function_call; arguments erst als String bestätigen, dann mit dem Tool-Schema prüfen; ist status nicht completed, kein function_call_output.
Als Nächstes: formatieren, ob arguments ein String ist, die geparsten Parameter per Schema prüfen, die beiden Items per Diff vergleichen.