Skip to main content
While Instructor can automatically generate schemas from PHP classes via reflection, you can also define schemas manually. This is useful when the data shape is determined at runtime, when you need fine-grained control over the exact schema sent to the LLM, or when you want to avoid the overhead of reflection.

Using a Raw Schema Array

The simplest approach is to pass a plain JSON Schema array as the response model.
When a schema array is provided instead of a class name, the result is returned as an associative array. You can also call ->get() which will return a Structure object with dynamic property access.

Using the JsonSchema Builder

For more complex schemas, the JsonSchema class provides a fluent API with static factory methods for every JSON Schema type.

Object Schemas

Primitive Types

Arrays and Collections

Enums

Parsing an Existing Array

If you already have a JSON Schema as an array, you can parse it into a JsonSchema object for further manipulation.

Using JsonSchema with StructuredOutput

JsonSchema implements CanProvideJsonSchema, so you can pass it directly as a response model.

Complex Example

Nested schemas with multiple types compose naturally.

When to Use Manual Schemas

Manual schemas are the right choice when:
  • Dynamic shapes — the structure is determined at runtime based on user input or configuration
  • Provider optimization — you need to tweak schemas for specific LLM providers
  • Legacy integration — you are working with existing JSON Schema specifications
  • No class needed — the data shape is simple or used once, so defining a PHP class adds unnecessary ceremony
For most cases, defining a PHP class and letting Instructor generate the schema via reflection is simpler, type-safe, and easier to refactor. Choose the approach that best fits your use case.

Best Practices

  1. Use meaningful descriptions — LLMs use property descriptions to understand what data to extract
  2. Mark required fields explicitly — do not rely on defaults
  3. Extract common sub-schemas — assign reusable parts to variables to keep schemas DRY
  4. Inspect generated output — call $schema->toJsonSchema() to verify the schema looks correct