> ## Documentation Index
> Fetch the complete documentation index at: https://docs.subconscious.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Structured Output

> Get typed JSON responses with schema validation

Structured output lets you define a JSON schema for the model's response, ensuring you get
consistently typed data back. The **OpenAI** format uses the standard `response_format`
parameter. The **Anthropic** Messages format has no `response_format`; instead you achieve the
same result with **forced tool use** — define a tool whose `input_schema` is your target
schema, require it via `tool_choice`, and read the typed `tool_use` block from the response.

## JSON Schema

Pass a JSON schema via `response_format` (OpenAI) or a forced tool (Anthropic) to constrain the
model's output:

<CodeGroup>
  ```python Python (OpenAI) theme={null}
  from openai import OpenAI
  import json

  client = OpenAI(
      api_key="your-api-key",
      base_url="https://api.subconscious.dev/v1",
  )

  response = client.chat.completions.create(
      model="subconscious/tim-qwen3.6-27b",
      messages=[{"role": "user", "content": "Extract the key facts from: 'Tesla reported $25.5B in Q3 2024 revenue, up 8% year-over-year.'"}],
      response_format={
          "type": "json_schema",
          "json_schema": {
              "name": "financial_extract",
              "schema": {
                  "type": "object",
                  "properties": {
                      "company": {"type": "string"},
                      "revenue": {"type": "string"},
                      "period": {"type": "string"},
                      "growth": {"type": "string"},
                  },
                  "required": ["company", "revenue", "period", "growth"],
              },
          },
      },
  )

  result = json.loads(response.choices[0].message.content)
  print(result)
  # {"company": "Tesla", "revenue": "$25.5B", "period": "Q3 2024", "growth": "8% YoY"}
  ```

  ```typescript Node.js (OpenAI) theme={null}
  import OpenAI from "openai";

  const client = new OpenAI({
    apiKey: "your-api-key",
    baseURL: "https://api.subconscious.dev/v1",
  });

  const response = await client.chat.completions.create({
    model: "subconscious/tim-qwen3.6-27b",
    messages: [
      {
        role: "user",
        content:
          "Extract the key facts from: 'Tesla reported $25.5B in Q3 2024 revenue, up 8% year-over-year.'",
      },
    ],
    response_format: {
      type: "json_schema",
      json_schema: {
        name: "financial_extract",
        schema: {
          type: "object",
          properties: {
            company: { type: "string" },
            revenue: { type: "string" },
            period: { type: "string" },
            growth: { type: "string" },
          },
          required: ["company", "revenue", "period", "growth"],
        },
      },
    },
  });

  const result = JSON.parse(response.choices[0].message.content!);
  console.log(result);
  ```

  ```python Python (Anthropic) theme={null}
  from anthropic import Anthropic

  client = Anthropic(
      auth_token="your-api-key",
      base_url="https://api.subconscious.dev",
  )

  schema = {
      "type": "object",
      "properties": {
          "company": {"type": "string"},
          "revenue": {"type": "string"},
          "period": {"type": "string"},
          "growth": {"type": "string"},
      },
      "required": ["company", "revenue", "period", "growth"],
  }

  message = client.messages.create(
      model="subconscious/tim-qwen3.6-27b",
      max_tokens=1024,
      tools=[{
          "name": "financial_extract",
          "description": "Record the extracted financial facts.",
          "input_schema": schema,
      }],
      tool_choice={"type": "tool", "name": "financial_extract"},
      messages=[{"role": "user", "content": "Extract the key facts from: 'Tesla reported $25.5B in Q3 2024 revenue, up 8% year-over-year.'"}],
  )

  result = next(b.input for b in message.content if b.type == "tool_use")
  print(result)
  # {"company": "Tesla", "revenue": "$25.5B", "period": "Q3 2024", "growth": "8% YoY"}
  ```

  ```typescript Node.js (Anthropic) theme={null}
  import Anthropic from "@anthropic-ai/sdk";

  const client = new Anthropic({
    authToken: "your-api-key",
    baseURL: "https://api.subconscious.dev",
  });

  const message = await client.messages.create({
    model: "subconscious/tim-qwen3.6-27b",
    max_tokens: 1024,
    tools: [
      {
        name: "financial_extract",
        description: "Record the extracted financial facts.",
        input_schema: {
          type: "object",
          properties: {
            company: { type: "string" },
            revenue: { type: "string" },
            period: { type: "string" },
            growth: { type: "string" },
          },
          required: ["company", "revenue", "period", "growth"],
        },
      },
    ],
    tool_choice: { type: "tool", name: "financial_extract" },
    messages: [
      {
        role: "user",
        content:
          "Extract the key facts from: 'Tesla reported $25.5B in Q3 2024 revenue, up 8% year-over-year.'",
      },
    ],
  });

  const block = message.content.find((b) => b.type === "tool_use");
  console.log(block?.input);
  ```
</CodeGroup>

## With Pydantic (Python)

Use Pydantic models to define your schema and parse the response. The same
`model_json_schema()` output works as the OpenAI `json_schema` or as an Anthropic tool's
`input_schema`:

<CodeGroup>
  ```python Python (OpenAI) theme={null}
  from openai import OpenAI
  from pydantic import BaseModel

  client = OpenAI(
      api_key="your-api-key",
      base_url="https://api.subconscious.dev/v1",
  )

  class SentimentAnalysis(BaseModel):
      sentiment: str
      confidence: float
      keywords: list[str]

  response = client.chat.completions.create(
      model="subconscious/tim-qwen3.6-27b",
      messages=[{"role": "user", "content": "Analyze: 'The new update is fantastic, everything runs so smoothly now!'"}],
      response_format={
          "type": "json_schema",
          "json_schema": {
              "name": "sentiment_analysis",
              "schema": SentimentAnalysis.model_json_schema(),
          },
      },
  )

  result = SentimentAnalysis.model_validate_json(response.choices[0].message.content)
  print(result.sentiment)    # "positive"
  print(result.confidence)   # 0.95
  print(result.keywords)     # ["fantastic", "smoothly"]
  ```

  ```python Python (Anthropic) theme={null}
  import json
  from anthropic import Anthropic
  from pydantic import BaseModel

  client = Anthropic(
      auth_token="your-api-key",
      base_url="https://api.subconscious.dev",
  )

  class SentimentAnalysis(BaseModel):
      sentiment: str
      confidence: float
      keywords: list[str]

  message = client.messages.create(
      model="subconscious/tim-qwen3.6-27b",
      max_tokens=1024,
      tools=[{
          "name": "sentiment_analysis",
          "description": "Record the sentiment analysis result.",
          "input_schema": SentimentAnalysis.model_json_schema(),
      }],
      tool_choice={"type": "tool", "name": "sentiment_analysis"},
      messages=[{"role": "user", "content": "Analyze: 'The new update is fantastic, everything runs so smoothly now!'"}],
  )

  raw = next(b.input for b in message.content if b.type == "tool_use")
  result = SentimentAnalysis.model_validate(raw)
  print(result.sentiment)    # "positive"
  print(result.confidence)   # 0.95
  print(result.keywords)     # ["fantastic", "smoothly"]
  ```
</CodeGroup>

## With Zod (TypeScript)

Use Zod schemas with `zodResponseFormat` (OpenAI), or convert the Zod schema to JSON Schema and
use it as an Anthropic tool's `input_schema`:

<CodeGroup>
  ```typescript Node.js (OpenAI) theme={null}
  import OpenAI from "openai";
  import { zodResponseFormat } from "openai/helpers/zod";
  import { z } from "zod";

  const client = new OpenAI({
    apiKey: "your-api-key",
    baseURL: "https://api.subconscious.dev/v1",
  });

  const SentimentAnalysis = z.object({
    sentiment: z.enum(["positive", "negative", "neutral"]),
    confidence: z.number(),
    keywords: z.array(z.string()),
  });

  const response = await client.chat.completions.create({
    model: "subconscious/tim-qwen3.6-27b",
    messages: [
      {
        role: "user",
        content:
          "Analyze: 'The new update is fantastic, everything runs so smoothly now!'",
      },
    ],
    response_format: zodResponseFormat(SentimentAnalysis, "sentiment_analysis"),
  });

  const result = SentimentAnalysis.parse(
    JSON.parse(response.choices[0].message.content!)
  );
  console.log(result.sentiment); // "positive"
  ```

  ```typescript Node.js (Anthropic) theme={null}
  import Anthropic from "@anthropic-ai/sdk";
  import { z } from "zod";
  import { zodToJsonSchema } from "zod-to-json-schema";

  const client = new Anthropic({
    authToken: "your-api-key",
    baseURL: "https://api.subconscious.dev",
  });

  const SentimentAnalysis = z.object({
    sentiment: z.enum(["positive", "negative", "neutral"]),
    confidence: z.number(),
    keywords: z.array(z.string()),
  });

  const message = await client.messages.create({
    model: "subconscious/tim-qwen3.6-27b",
    max_tokens: 1024,
    tools: [
      {
        name: "sentiment_analysis",
        description: "Record the sentiment analysis result.",
        input_schema: zodToJsonSchema(SentimentAnalysis) as Anthropic.Tool.InputSchema,
      },
    ],
    tool_choice: { type: "tool", name: "sentiment_analysis" },
    messages: [
      {
        role: "user",
        content:
          "Analyze: 'The new update is fantastic, everything runs so smoothly now!'",
      },
    ],
  });

  const block = message.content.find((b) => b.type === "tool_use");
  const result = SentimentAnalysis.parse(block?.input);
  console.log(result.sentiment); // "positive"
  ```
</CodeGroup>

## JSON Mode

JSON mode is specific to the OpenAI format. For simpler cases where you just need valid JSON
without a specific schema, use JSON mode. (The Anthropic Messages format has no JSON mode — use
the forced tool-use pattern shown above when you need structured JSON.)

```python Python theme={null}
response = client.chat.completions.create(
    model="subconscious/tim-qwen3.6-27b",
    messages=[
        {"role": "system", "content": "Respond only in JSON."},
        {"role": "user", "content": "List three programming languages and their main use cases."},
    ],
    response_format={"type": "json_object"},
)
```

<Note>
  When using JSON mode without a schema, include "respond in JSON" or similar instructions in your prompt. The model needs to know you expect JSON output.
</Note>
