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
| Method | Signature | Example |
|---|---|---|
string | string(desc, constraints?) | s.string('name', { pattern: '^@' }) |
number | number(desc, constraints?) | s.number('age', { minimum: 0 }) |
integer | integer(desc, constraints?) | s.integer('count', { maximum: 10 }) |
boolean | boolean(desc: string) | s.boolean('active') |
literal | literal<T>(value: T) | s.literal('success') |
object | object(desc, shape) | s.object('user', {}) |
array | array(desc, item, constraints?) | s.array('items', s.string(), { minItems: 1 }) |
anyOf | anyOf(options) | s.anyOf([s.string(), s.number()]) |
enumeration | enumeration(desc, entries) | s.enumeration('status', ['a', 'b']) |
nullish | nullish() | s.nullish() |
Primitive Values
// 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
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'),
});
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
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
s.enumeration('Task priority level', ['low', 'medium', 'high', 'urgent']);
Nullish
s.anyOf([s.string('A string value'), s.nullish()]);
Inferring Types
Skillet infers a static type from a schema using s.Infer<T>.
// 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:
stringwithpatternandformat(date-time, time, date, duration, email, hostname, ipv4, ipv6, uuid)number/integerwithmultipleOf,minimum,maximum,exclusiveMinimum,exclusiveMaximumboolean,nullconstfor string/number/boolean onlyenumfor string values onlyobjectwithproperties(all required) andadditionalProperties: falsearraywith a singleitemsschema and optionalminItems/maxItemsanyOfunions
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',
});
patternis enforced in Hashbrown validation.formatis forwarded to the model provider but not validated client-side.- Supported
formatvalues: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.
// 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.