The schema builder (s) is how you declare your Agent's contract in the SDK.
Instead of writing raw JSON Schema, you compose fields with s.* helpers.
The builder emits standard JSON Schema plus the x-z3t-* extensions the platform uses to render your fields — and, in TypeScript, gives you a fully inferred input type in your handler.
Required by default
Every field is required unless you explicitly mark it optional.
s.object({
document: s.fileUri(), // required
notes: s.string().optional(), // optional
})
In Python, call .optional() the same way: s.string().optional().
Marking a field optional removes it from the schema's required array — it never adds it.
Input fields
Input fields become form controls when a buyer runs your Agent, and they define what the platform validates before your handler is called.
| Method | Widget rendered | Key options |
|---|---|---|
s.string() | Text input | display: 'textarea' | 'markdown' | 'code', minLength, maxLength, pattern |
s.email() | Email input | — |
s.url() | URL input | — |
s.date() | Date picker | min, max |
s.datetime() | Date + time picker | min, max |
s.number() | Number input | display: 'slider', min, max, multipleOf |
s.integer() | Integer input | display: 'slider', min, max |
s.boolean() | Checkbox | display: 'toggle' |
s.enum(['a','b']) | Dropdown | display: 'radio' |
s.array(s.string()) | Tag / chip input | minItems, maxItems |
s.array(s.object({...})) | Repeatable form group | minItems, maxItems |
s.object({...}) | Nested section | — |
s.fileUri() | File upload picker | accept (MIME list), maxSizeMb |
s.taxonomyRef() | Taxonomy dropdown | taxonomySlug |
In TypeScript, pass enum values as const — s.enum(['en', 'fr'] as const) — so your handler input is typed as the literal union.
Output fields
Output fields tell the platform how to render a successful Run's result.
| Method | Frontend rendering |
|---|---|
s.string() | Plain text |
s.markdown() | Rendered Markdown |
s.html() | Sanitized HTML |
s.url() | Clickable link |
s.code({ language: 'python' }) | Syntax-highlighted code block |
s.json() | Syntax-highlighted JSON |
s.image() | Inline image |
s.number() / s.integer() | Locale-formatted number |
s.percent() | Progress bar (value 0–1) |
s.boolean() | ✓ / ✗ badge |
s.enum([...], { colorMap: { A: 'green' } }) | Colored status badge |
s.fileOutput() | Download button |
s.pdfReference() | Clickable chip → PDF preview |
s.typedValue() | Renderer chosen from the value's format |
Array layouts
Pass layout to s.array() to control how a collection is rendered in the output. The default stacks items vertically as cards.
// Table — columns come from the object's properties
results: s.array(s.object({
name: s.string({ title: 'Name' }),
score: s.number({ title: 'Score' }),
status: s.enum(['pass', 'fail'] as const, { colorMap: { pass: 'green', fail: 'red' } }),
}), { layout: 'table', sortable: true, searchable: true })
// Gallery — equal-sized image tiles
images: s.array(s.image(), { layout: 'gallery' })
// Grid — compact multi-column cards
products: s.array(s.object({ name: s.string(), price: s.number() }), { layout: 'grid' })
// File download list — automatic when items are s.fileOutput()
reports: s.array(s.fileOutput())
Composite output values
Two field types carry both a value and its rendering.
s.pdfReference()— a clickable chip that opens a specific page of an uploaded PDF. Construct values withPdfReference.create({ file, page?, hint? }).s.typedValue()— a self-describing value; the frontend picks the renderer from itsformat. Construct withTypedValue.markdown(str),TypedValue.number(str), and so on.
The exact wire shape for both is in the Schema Specification.
Common metadata
Every field accepts the same presentation metadata.
s.string({
title: 'Contract file', // label in the form / output view
description: 'Upload a PDF', // longer text shown on hover
hint: 'Max 20 MB', // short helper text below the field
order: 1, // sort order within the form
group: 'Input documents', // visual grouping label
})
Under the hood
The builder is only a convenience. What crosses the wire to the platform is plain JSON Schema plus x-z3t-* keys.
If you ever need to know exactly what a field compiles to — or you're building your own SDK — read: