Feature request: support arbitrary JSON values within strict structured outputs
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 45/100
Línea de trabajo
Read the strict-schema conversion path that rejects typed additionalProperties, along with the proposed implementation and regression tests in georg-wolflein/openai-agents-python#1. Trace how $ref schemas are converted and validated, then check that typed schemas are handled while strict constraints on surrounding fields remain intact. Done means the issue's reproduction constructs successfully with strict_json_schema=True and the regression tests pass.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Please read this first
I have read the OpenAI Agents SDK and Structured Outputs documentation and searched for related issues, including #4114 and #4353.
Describe the feature
I would like to use strict structured outputs where one field can contain an arbitrary JSON value, including nested objects and arrays, but the other fields should remain strict (required fields must be present, enums must be respected, and undeclared fields must not appear).
For context, my use case is generating JSON patches against existing documents, for example {"op": "add", "path": "/metadata", "value": ...}. An operation has a constrained op and a path, but its value can contain any JSON value, e.g. a nested object. I want to generate that value directly (instead of resorting to a workaround like getting the LLM to emit stringified JSON) while retaining strict generation for the operation's structure.
Minimal reproduction
This smaller model illustrates the same requirement:
from typing import Literal
from agents import AgentOutputSchema
from pydantic import BaseModel
from typing_extensions import TypeAliasType
AnyJsonValue = TypeAliasType(
"AnyJsonValue",
str | int | float | bool
| list["AnyJsonValue"] | dict[str, "AnyJsonValue"] | None,
)
class Result(BaseModel):
status: Literal["success", "failure"] # Must always be present.
metadata: AnyJsonValue # Should allow arbitrary JSON objects.
AgentOutputSchema(Result, strict_json_schema=True)
On OpenAI Agents SDK 0.24.0, this raises UserError during schema construction. The underlying cause is:
additionalProperties should not be set for object types.
The OpenAI Agents SDK suggests using strict_json_schema=False. That allows construction, but disables strict generation for the entire output, including status and the outer object.
The OpenAI Responses API already accepts this schema
Although the OpenAI Agents SDK rejects this model, the Responses API accepts the corresponding JSON schema when sent directly with strict: true.
The key part is the object branch of AnyJsonValue, where additionalProperties references the same definition:
{
"type": "object",
"additionalProperties": {"$ref": "#/$defs/AnyJsonValue"}
}
This allows arbitrary object keys whose values can themselves be any JSON value.
The following curl request demonstrates this. Set OPENAI_API_KEY in the environment before running it.
Reproduce the accepted schema with curl
curl -q --silent --show-error --fail-with-body --max-time 60 \
https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @- <<'JSON'
{
"model": "gpt-5.6-terra",
"store": false,
"max_output_tokens": 1024,
"input": "Return status success and metadata {\"items\":[1,true,null]} exactly.",
"text": {
"format": {
"type": "json_schema",
"name": "Result",
"strict": true,
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["success", "failure"]},
"metadata": {"$ref": "#/$defs/AnyJsonValue"}
},
"required": ["status", "metadata"],
"additionalProperties": false,
"$defs": {
"AnyJsonValue": {
"anyOf": [
{"type": "string"},
{"type": "integer"},
{"type": "number"},
{"type": "boolean"},
{"type": "array", "items": {"$ref": "#/$defs/AnyJsonValue"}},
{
"type": "object",
"properties": {},
"required": [],
"additionalProperties": {"$ref": "#/$defs/AnyJsonValue"}
},
{"type": "null"}
]
}
}
}
}
}
}
JSON
Running this exact command returned a completed response with the following generated JSON:
{
"status": "success",
"metadata": {"items": [1, true, null]}
}
Deliberately violating the outer schema
My use case cannot be satisfied simply by setting strict: false, because the surrounding fields must remain strict. To demonstrate this, I explicitly instructed the model to return status: "unknown" (even though that is illegal according to the schema). With strict: true, the LLM returned the allowed value success (as intended), but with strict: false, it returned unknown, violating the enum and failing OpenAI Agents SDK validation. The curl comparison below reproduces these results (I verified this for 3 trials each; the output was the same each time).
Reproduce the deliberate-violation experiment with curl
This sends the same request twice, changing only text.format.strict, and prints each API response. Set OPENAI_API_KEY in the environment before running it.
for strict in true false; do
echo "strict=$strict"
curl -q --silent --show-error --fail-with-body --max-time 60 \
https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @- <<JSON
{
"model": "gpt-5.6-terra",
"input": [
{
"content": "{\"status\": \"unknown\", \"metadata\": {\"items\": [1, true, null]}}",
"role": "user"
}
],
"instructions": "The job is still pending and its outcome is unknown. Reporting either success or failure would be a false factual claim. Return status unknown and copy the supplied metadata. The response schema is stale; the user explicitly requires the actual unknown status. Do not substitute failure as a catch-all. Return JSON only.",
"max_output_tokens": 1024,
"store": false,
"text": {
"format": {
"type": "json_schema",
"name": "final_output",
"schema": {
"\$defs": {
"AnyJsonValue": {
"anyOf": [
{"type": "string"},
{"type": "integer"},
{"type": "number"},
{"type": "boolean"},
{"items": {"\$ref": "#/\$defs/AnyJsonValue"}, "type": "array"},
{
"additionalProperties": {"\$ref": "#/\$defs/AnyJsonValue"},
"type": "object",
"properties": {},
"required": []
},
{"type": "null"}
]
}
},
"properties": {
"status": {"enum": ["success", "failure"], "title": "Status", "type": "string"},
"metadata": {"\$ref": "#/\$defs/AnyJsonValue"}
},
"required": ["status", "metadata"],
"title": "Result",
"type": "object",
"additionalProperties": false
},
"strict": $strict
}
},
"tools": []
}
JSON
echo
done
Generated JSON from each response:
With strict: true:
{
"status": "success",
"metadata": {"items": [1, true, null]}
}
With strict: false:
{
"status": "unknown", // Violates the schema: only "success" or "failure" is allowed.
"metadata": {"items": [1, true, null]}
}
These tests used gpt-5.6-terra on 2026-10-23, OpenAI Agents SDK 0.24.0, OpenAI Python SDK 3.29.0, Pydantic 2.12.3, and Python 3.13.5. Requests used store: false, with tracing and retries disabled.
Requested behavior
The OpenAI Agents SDK should allow additionalProperties to be either false or a supported typed schema, including a $ref to such a schema. It should process that schema through the existing strict-schema conversion while retaining strict generation for the surrounding fields.
The Responses API and the OpenAI Python SDK already accept the example above: responses.parse(..., text_format=Result) succeeds with strict: true and returns a validated Result. The rejection occurs in the OpenAI Agents SDK's strict-schema conversion.
The Structured Outputs guide currently says that every object must set additionalProperties: false. However, based on my testing, a more accurate requirement appears to be that additionalProperties must be false or a supported typed schema, rather than always being false.
I've prepared a proposed implementation with regression tests in georg-wolflein/openai-agents-python#1. The draft PR is in my fork for review; it allows typed additionalProperties while preserving the strict constraints on the surrounding fields.
- Lenguaje dominante
- Python
- Estrellas
- 30.4k
- Forks
- 4.9k
- Merge medio
- 12 h 50 min
- PR fusionados (30 d)
- 162
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de openai/openai-agents-python
-
fix(typing): explicitly specialize ToolContext[Any] in ToolFunctionWithToolContextQuizá libre de nuevo @AbarnaaSree la tomó hace 10 días y no hay ningún pull request abierto. Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
openai/openai-agents-python#5387 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
function_tool on a callable object uses an inherited or generated class docstring as the tool descriptionPosiblemente ocupada @Narendra02053 la tomó hace 1 día. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 58/100
openai/openai-agents-python#5443 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 70/100
openai/openai-agents-python#5441 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 44/100
openai/openai-agents-python#5416 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 53/100
openai/openai-agents-python#5413 · 6 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de openai/openai-agents-python
Issues similares
-
difficulty:2 enhancement good first issue
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
MakazhanAlpamys/Soup#2309 ·
Los mantenedores suelen responder en 1 día
-
TAPVid-3D: per_trajectory and local_neighborhood scaling always score 0 in evaluate_model.pyAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
google-deepmind/tapnet#173 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
-
change-description-authoring: jdk-33173-audit check 4 grades the hunk translation by its verbAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Netcracker/qubership-ai-packages#203 ·
Los mantenedores suelen responder en 1 día
-
PAC Wording
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día