hashbrown

Skillet Schema Language

Skillet is a Zod-like schema language that is LLM-optimized.

  • Skillet is strongly typed
  • Skillet purposefully limits the schema to that which is supported by LLMs
  • Skillet optimizes the schema for processing by an LLM
  • Skillet tightly integrates streaming

Methods

MethodSignatureExample
stringstring(desc, constraints?)s.string('name', { pattern: '^@' })
numbernumber(desc, constraints?)s.number('age', { minimum: 0 })
integerinteger(desc, constraints?)s.integer('count', { maximum: 10 })
booleanboolean(desc: string)s.boolean('active')
literalliteral<T>(value: T)s.literal('success')
objectobject(desc, shape)s.object('user', {})
arrayarray(desc, item, constraints?)s.array('items', s.string(), { minItems: 1 })
anyOfanyOf(options)s.anyOf([s.string(), s.number()])
enumerationenumeration(desc, entries)s.enumeration('status', ['a', 'b'])
nullishnullish()s.nullish()

Primitive Values

examples
// string
s.string("The user's full name");

// number
s.number("The user's age in years");

// integer
s.integer('The number of items in the cart');

// boolean
s.boolean('Whether the user account is active');

// literal
s.literal('success');

Compound Values

objects
s.object('A user profile', {
  name: s.string("The user's name"),
  age: s.number("The user's age"),
  active: s.boolean('Whether the user is active'),
});
array
s.array(
  'A list of users',
  s.object('A user', {
    name: s.string("The user's name"),
    email: s.string("The user's email"),
  }),
);

AnyOf

anyOf
s.anyOf([
  s.object('Success response', {
    status: s.literal('success'),
    data: s.string('The response data'),
  }),
  s.object('Error response', {
    status: s.literal('error'),
    message: s.string('The error message'),
  }),
]);

Enumeration

enumeration
s.enumeration('Task priority level', ['low', 'medium', 'high', 'urgent']);

Nullish

nullish
s.anyOf([s.string('A string value'), s.nullish()]);

Inferring Types

Skillet infers a static type from a schema using s.Infer<T>.

infer
// 1. define the schema
const schema = s.streaming.object('The result', {
  code: s.streaming.string('The JavaScript code to run'),
});

// 2. define static type using s.Infer<T>
type Result = s.Infer<schema>;

// 3. use the type
const mockResult: Result = {
  code: 'let i = 0',
};

Standard JSON Schema

Hashbrown can ingest Standard JSON Schema objects (the ~standard spec) alongside Skillet when defining tools, structured outputs, and component inputs. Internally, Hashbrown normalizes Standard JSON Schema to draft-07 JSON Schema and then converts it to Skillet for streaming and validation.

If you need explicit conversion, use s.fromStandardJsonSchema(schema, { mode: 'input' | 'output' }). To type a schema regardless of whether it is Skillet or Standard JSON Schema, use s.InferSchemaInput<T> and s.InferSchemaOutput<T>. For Standard JSON Schema types specifically, use s.StandardJSONSchemaV1.InferInput<T> and s.StandardJSONSchemaV1.InferOutput<T>.

Standard JSON Schema support is limited to the Skillet-compatible subset and throws on unsupported keywords:

  • string with pattern and format (date-time, time, date, duration, email, hostname, ipv4, ipv6, uuid)
  • number / integer with multipleOf, minimum, maximum, exclusiveMinimum, exclusiveMaximum
  • boolean, null
  • const for string/number/boolean only
  • enum for string values only
  • object with properties (all required) and additionalProperties: false
  • array with a single items schema and optional minItems/maxItems
  • anyOf unions

Numeric Types

Skillet supports numeric types using either the number() or integer() function. The number() function allows for floating-point numbers, while the integer() function restricts the value to integers.

Skillet also supports optional numeric constraints like minimum, maximum, exclusiveMinimum, exclusiveMaximum, and multipleOf.


String Constraints

s.string('Username', {
  pattern: '^@[a-z0-9_]+$',
  format: 'email',
});
  • pattern is enforced in Hashbrown validation.
  • format is forwarded to the model provider but not validated client-side.
  • Supported format values: date-time, time, date, duration, email, hostname, ipv4, ipv6, uuid.

Numeric Constraints

s.number('Score', {
  minimum: 0,
  exclusiveMaximum: 10,
  multipleOf: 0.5,
});

Array Constraints

s.array('Tags', s.string('Tag'), {
  minItems: 1,
  maxItems: 5,
});

Streaming

We saved the best bite for last. Skillet supports streaming responses out of the box.

To enable streaming, simply add the streaming keyword to your schema.

streaming
// stream strings
s.streaming.string();

// stream objects
s.streaming.object();

// stream arrays
s.streaming.array();

Skillet eagerly parses fragments of the streamed response from the LLM.


Next Steps

Skillet Schema LanguageMethodsPrimitive ValuesCompound ValuesAnyOfEnumerationNullishInferring TypesStandard JSON SchemaNumeric TypesString ConstraintsNumeric ConstraintsArray ConstraintsStreamingNext Steps