Skip to main content

When to Use Structured Output

Use structured output when you need:
  • Responses that integrate with other systems
  • Consistent data formats for downstream processing
  • Type-safe responses in your application

Using answerFormat

The answerFormat field accepts a JSON Schema that defines the structure of the agent’s answer:
from subconscious import Subconscious

client = Subconscious(api_key="your-api-key")

run = client.run(
    engine="tim-gpt",
    input={
        "instructions": "Analyze the sentiment of this review: 'Great product, fast shipping!'",
        "tools": [],
        "answerFormat": {
            "type": "object",
            "title": "SentimentAnalysis",
            "properties": {
                "sentiment": {
                    "type": "string",
                    "enum": ["positive", "negative", "neutral"],
                    "description": "The overall sentiment"
                },
                "confidence": {
                    "type": "number",
                    "description": "Confidence score from 0 to 1"
                },
                "keywords": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Key phrases that influenced the sentiment"
                }
            },
            "required": ["sentiment", "confidence", "keywords"]
        }
    },
    options={"await_completion": True},
)

# Response is already a dict matching your schema
result = run.result.answer
print(result["sentiment"])   # "positive"
print(result["confidence"])  # 0.95
print(result["keywords"])    # ["Great product", "fast shipping"]
When using answerFormat, run.result.answer returns a parsed object (dict in Python, object in JavaScript), not a JSON string. You can access fields directly without parsing.

Using Pydantic Models (Python)

The Python SDK automatically converts Pydantic models to JSON Schema:
from subconscious import Subconscious
from pydantic import BaseModel
import os

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

client = Subconscious(api_key=os.environ.get("SUBCONSCIOUS_API_KEY"))

run = client.run(
    engine="tim-gpt",
    input={
        "instructions": "Analyze the sentiment of: 'Great product!'",
        "answerFormat": SentimentAnalysis,  # Pass the class directly
    },
    options={"await_completion": True},
)

print(run.result.answer["sentiment"])

Using Zod Schemas (TypeScript)

The TypeScript SDK provides a zodToJsonSchema helper to convert Zod schemas:
import { Subconscious, zodToJsonSchema } from "subconscious";
import { z } from "zod";

const SentimentAnalysis = z.object({
  sentiment: z.string().describe("The overall sentiment"),
  confidence: z.number().describe("Confidence score from 0 to 1"),
  keywords: z.array(z.string()).describe("Key phrases that influenced the sentiment"),
});

type SentimentAnalysis = z.infer<typeof SentimentAnalysis>;

const client = new Subconscious({
  apiKey: process.env.SUBCONSCIOUS_API_KEY!,
});

const run = await client.run({
  engine: "tim-gpt",
  input: {
    instructions: "Analyze the sentiment of: 'Great product!'",
    answerFormat: zodToJsonSchema(SentimentAnalysis, "SentimentAnalysis"),
  },
  options: { awaitCompletion: true },
});

const result = run.result?.answer as unknown as SentimentAnalysis;
console.log(result.sentiment);

Supported Zod Types

The zodToJsonSchema function supports the following Zod types:
Zod TypeConverts To
z.string(){ type: "string" }
z.number(){ type: "number" }
z.boolean(){ type: "boolean" }
z.array(z.T()){ type: "array", items: {...} }
z.object({...}){ type: "object", properties: {...} }
z.enum([...]){ type: "string", enum: [...] }
z.optional(z.T())Omits from required array
Use .describe() on Zod fields to add descriptions that help the agent understand what each field should contain.

Schema Requirements

Your JSON Schema must include:
FieldRequiredDescription
typeYesMust be "object"
titleYesA name for the schema
propertiesYesThe fields in your response
requiredYesArray of required field names
additionalPropertiesNoOptional (must be false if provided)

Supported Types

The following JSON Schema types are supported:
TypeExample
string{"type": "string"}
number{"type": "number"}
integer{"type": "integer"}
boolean{"type": "boolean"}
array{"type": "array", "items": {...}}
object{"type": "object", "properties": {...}}
enum{"type": "string", "enum": ["a", "b", "c"]}

Using reasoningFormat

You can also structure the reasoning output with reasoningFormat:
run = client.run(
    engine="tim-gpt",
    input={
        "instructions": "Research and compare two products",
        "tools": [{"type": "platform", "id": "web_search"}],
        "answerFormat": {...},
        "reasoningFormat": {
            "type": "object",
            "title": "ResearchSteps",
            "properties": {
                "steps": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "action": {"type": "string"},
                            "result": {"type": "string"}
                        }
                    }
                }
            },
            "required": ["steps"]
        }
    },
    options={"await_completion": True},
)