Lunos logoLunos

Structured Outputs

Structured Outputs help you request type-safe, machine-readable JSON from your model. Instead of parsing free-form text, you provide a JSON Schema, and the model returns data that follows that schema.

This is useful when you need stable outputs for:

  • Form filling and UI rendering
  • Tool inputs and workflow automation
  • Database writes where a fixed structure is required

Lunos is OpenAI-compatible, so you use the standard response_format field with your POST /v1/chat/completions request.

Overview

Structured Outputs let you:

  • Constrain the model response to a specific JSON Schema
  • Reduce parsing errors caused by unexpected text
  • Avoid missing or extra fields in your downstream code

Using Structured Outputs

To enable Structured Outputs, include response_format in your request. Use:

  • type: "json_schema"
  • json_schema containing name, strict, and schema

Example request body:

{
  "model": "openai/gpt-4o",
  "messages": [
    { "role": "user", "content": "Return a weather summary for London." }
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "weather",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "City or location name"
          },
          "temperature": {
            "type": "number",
            "description": "Temperature in Celsius"
          },
          "conditions": {
            "type": "string",
            "description": "Weather conditions description"
          }
        },
        "required": ["location", "temperature", "conditions"],
        "additionalProperties": false
      }
    }
  }
}

When supported by the chosen model, the response content will be a JSON object that matches your schema.

Example output:

{
  "location": "London",
  "temperature": 18,
  "conditions": "Partly cloudy with light drizzle"
}

Model support

Structured Outputs are available only on compatible models.

To confirm support in Lunos:

  1. Call GET /v1/models
  2. Check that your model’s supportedParameters includes response_format
  3. Use response_format with type: "json_schema"

If response_format is not listed for your model, Lunos will reject the request as an unsupported parameter.

Best practices

  • Use clear description values in your schema so the model understands intent.
  • Set "strict": true when you need the response to match the schema exactly.
  • Keep the schema tight:
    • Use required for fields your app needs
    • Use additionalProperties: false to prevent unexpected keys

Example request (Lunos)

curl -X POST "https://api.lunos.tech/v1/chat/completions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [
      { "role": "user", "content": "Return a weather summary for London." }
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "weather",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "City or location name"
            },
            "temperature": {
              "type": "number",
              "description": "Temperature in Celsius"
            },
            "conditions": {
              "type": "string",
              "description": "Weather conditions description"
            }
          },
          "required": ["location", "temperature", "conditions"],
          "additionalProperties": false
        }
      }
    }
  }'
import requests

url = "https://api.lunos.tech/v1/chat/completions"
headers = {
  "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json",
}
payload = {
  "model": "openai/gpt-4o",
  "messages": [
    { "role": "user", "content": "Return a weather summary for London." }
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "weather",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "location": { "type": "string", "description": "City or location name" },
          "temperature": { "type": "number", "description": "Temperature in Celsius" },
          "conditions": { "type": "string", "description": "Weather conditions description" }
        },
        "required": ["location", "temperature", "conditions"],
        "additionalProperties": false
      }
    }
  }
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "openai/gpt-4o",
    messages: [
      { role: "user", content: "Return a weather summary for London." },
    ],
    response_format: {
      type: "json_schema",
      json_schema: {
        name: "weather",
        strict: true,
        schema: {
          type: "object",
          properties: {
            location: { type: "string", description: "City or location name" },
            temperature: { type: "number", description: "Temperature in Celsius" },
            conditions: { type: "string", description: "Weather conditions description" },
          },
          required: ["location", "temperature", "conditions"],
          additionalProperties: false,
        },
      },
    },
  }),
});

const data = await response.json();
console.log(data);

Streaming with Structured Outputs

Structured Outputs can also be used with streaming. Add stream: true to the request:

{
  "stream": true,
  "model": "openai/gpt-4o",
  "messages": [
    { "role": "user", "content": "Return a weather summary for London." }
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "weather",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "location": { "type": "string" },
          "temperature": { "type": "number" },
          "conditions": { "type": "string" }
        },
        "required": ["location", "temperature", "conditions"],
        "additionalProperties": false
      }
    }
  }
}

In this mode, the client receives incremental chunks, but the overall content should still represent valid JSON that matches your schema once complete.

Error handling

You may encounter:

  1. Model does not support response_format (request rejected by Lunos)
  2. Invalid JSON Schema (request rejected or an error returned by the upstream model)

If either happens, adjust the model or fix the schema.

Response validation

Even with Structured Outputs, validate the final JSON on your side before using it.

  • Parse with a JSON parser
  • Optionally validate again against the same schema (or a compiled validator) before writing to your database or triggering actions