z3t.ai

Schema Builder

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.

MethodWidget renderedKey options
s.string()Text inputdisplay: 'textarea' | 'markdown' | 'code', minLength, maxLength, pattern
s.email()Email input
s.url()URL input
s.date()Date pickermin, max
s.datetime()Date + time pickermin, max
s.number()Number inputdisplay: 'slider', min, max, multipleOf
s.integer()Integer inputdisplay: 'slider', min, max
s.boolean()Checkboxdisplay: 'toggle'
s.enum(['a','b'])Dropdowndisplay: 'radio'
s.array(s.string())Tag / chip inputminItems, maxItems
s.array(s.object({...}))Repeatable form groupminItems, maxItems
s.object({...})Nested section
s.fileUri()File upload pickeraccept (MIME list), maxSizeMb
s.taxonomyRef()Taxonomy dropdowntaxonomySlug

In TypeScript, pass enum values as consts.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.

MethodFrontend 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 with PdfReference.create({ file, page?, hint? }).
  • s.typedValue() — a self-describing value; the frontend picks the renderer from its format. Construct with TypedValue.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:


Continue learning

Next step

For creators