# `Omni.Schema`
[🔗](https://github.com/aaronrussell/omni/blob/v1.2.1/lib/omni/schema.ex#L1)

Builders and validation for JSON Schema maps.

Each builder returns a plain map following JSON Schema conventions. Property
keys are preserved as-is — use atoms for idiomatic Elixir, and JSON
serialisation handles stringification on the wire.

Option keywords accept snake_case and are normalized to camelCase JSON Schema
keywords automatically (e.g. `min_length:` becomes `minLength`). Keys without
a known mapping pass through unchanged.

## Example

    iex> Omni.Schema.object(%{
    ...>   city: Omni.Schema.string(description: "City name"),
    ...>   temp: Omni.Schema.number()
    ...> }, required: [:city])
    %{
      type: "object",
      properties: %{
        city: %{type: "string", description: "City name"},
        temp: %{type: "number"}
      },
      required: [:city]
    }

# `any_of`

```elixir
@spec any_of(
  [map()],
  keyword()
) :: map()
```

Builds a JSON Schema `anyOf` — valid when at least one subschema matches.

# `array`

```elixir
@spec array(keyword()) :: map()
```

Builds a JSON Schema array type.

# `array`

```elixir
@spec array(
  map(),
  keyword()
) :: map()
```

Builds a JSON Schema array with the given `items` schema.

# `boolean`

```elixir
@spec boolean(keyword()) :: map()
```

Builds a JSON Schema boolean type.

# `enum`

```elixir
@spec enum(
  list(),
  keyword()
) :: map()
```

Builds a JSON Schema enum — a list of allowed literal values.

# `integer`

```elixir
@spec integer(keyword()) :: map()
```

Builds a JSON Schema integer type.

# `number`

```elixir
@spec number(keyword()) :: map()
```

Builds a JSON Schema number type.

# `object`

```elixir
@spec object(keyword()) :: map()
```

Builds a JSON Schema object type.

# `object`

```elixir
@spec object(
  map(),
  keyword()
) :: map()
```

Builds a JSON Schema object with the given `properties` map.

# `string`

```elixir
@spec string(keyword()) :: map()
```

Builds a JSON Schema string type.

# `update`

```elixir
@spec update(
  map(),
  keyword()
) :: map()
```

Merges additional options into an existing schema map.

    Schema.string() |> Schema.update(min_length: 1, max_length: 100)

# `validate`

```elixir
@spec validate(map(), term()) :: {:ok, term()} | {:error, term()}
```

Validates input against a schema.

Enforces types, required fields, string constraints (`minLength`, `maxLength`,
`pattern`), numeric constraints (`minimum`, `maximum`, `exclusiveMinimum`,
`exclusiveMaximum`), and `anyOf` unions. Array item types are validated, but
array-level constraints (`minItems`, `maxItems`, `uniqueItems`) and
`multipleOf` are not — these are still sent to the LLM in the schema but
skipped during local validation.

Property key types are preserved: atom-keyed schemas validate and cast
string-keyed JSON input back to atom keys, so validated output uses the same
key types as the schema definition. Builder option keywords (e.g.
`min_length:`) must be atoms.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
