aiml docs
Guides

Structured output

Ask for JSON that matches a schema, then validate it anyway.

response_format: { type: "json_schema" } is honoured natively where the provider supports it and degraded elsewhere (schema appended to the prompt plus validation on the way out, warning feature_degraded). x-aiml-warnings says which happened.

cookbook/ts/structured.ts#L3-L29
import OpenAI from "openai";

const client = new OpenAI({ baseURL: (process.env.AIML_BASE_URL ?? "https://api.ai.ml") + "/v1", apiKey: process.env.AIML_API_KEY });

const schema = {
  type: "object",
  properties: { city: { type: "string" }, population_millions: { type: "number" } },
  required: ["city", "population_millions"],
  additionalProperties: false,
};

const completion = await client.chat.completions.create({
  model: process.env.AIML_MODEL ?? "openai/gpt-5-mini",
  messages: [{ role: "user", content: "Give the largest city in India as JSON. JSON_SCHEMA" }],
  response_format: { type: "json_schema", json_schema: { name: "city", schema, strict: true } },
});

const raw = completion.choices[0]?.message.content ?? "";
let ok = false;
try {
  const parsed = JSON.parse(raw) as { city?: unknown; population_millions?: unknown };
  ok = typeof parsed.city === "string" && typeof parsed.population_millions === "number";
} catch {
  ok = false;
}
console.log(raw);
console.log(`schema_ok=${ok}`);

What the gateway does with the schema

  • Normalises it. Local definitions become $defs, keywords no provider accepts ($dynamicRef, unevaluatedProperties) are rejected with schema_invalid, and keywords a particular provider rejects (patternProperties on strict decoders) are dropped with a schema_rewritten warning.
  • Strict subset. With strict: true every property becomes required (optional ones turn nullable), additionalProperties is set to false everywhere and a root oneOf becomes anyOf; the rewrites are listed in the schema_rewritten warning.
  • Picks the mechanism per endpoint. Native constrained decoding where the catalog says so (OpenAI response_format, Anthropic output_format, Gemini responseJsonSchema), tool-forcing on Anthropic endpoints without native support (an emit_output tool whose call is returned to you as text; extended thinking is dropped with a warning), guided_json on vLLM-style hosts, and a prompt suffix everywhere else. The warning feature_degraded says which emulation ran.
  • Validates the answer. Every response is validated against the schema in the gateway. A non-conforming answer ends with stop reason schema_violation and a schema_violation warning naming the failing paths. Non-streaming requests get one corrective retry against the same endpoint (both calls are billed; the schema_retried warning marks it) unless aiml.route.schema_retry is off; streams cannot be retried and report the violation on the final chunk.

Validate on your side regardless: strict: true is a contract with the provider, not a guarantee across every model, and the gateway never rewrites model output.

JSON_SCHEMA in the prompt is a hint for the mock provider; drop it in production prompts.

On this page