The form is data
form_schemaschemaVersionlt_role_schemasPATCH /api/roles/:roleltc roles save-schemaA role's form is a versioned JSON Schema; each row pins the edition it renders, so editing the form never breaks work in flight.
The situation
The review form gains a lot-number field on Tuesday. Two hundred rows created on Monday are still open, and the workflows waiting on them expect Monday’s answer shape. Nobody should write frontend code to ship the new field.
The recipe
Declare the form on the role:
roles: [{ role: 'reviewer', title: 'Reviewer', form_schema: { type: 'object', properties: { approved: { type: 'boolean', title: 'Approve' }, lotNumber: { type: 'string', title: 'Lot number' }, }, required: ['approved', 'lotNumber'], },}],Pin the edition a wait renders:
const decision = await conditional<{ approved: boolean; lotNumber: string }>(`review-${orderId}`, { role: 'reviewer', description: `Review order ${orderId}`, metadata: { orderId }, schemaVersion: 3,});Save a new edition with PATCH /api/roles/:role, ltc roles save-schema <role> --file schema.json, the update_role MCP tool, or the dashboard schema editor. Inspect editions with GET /api/roles/:role/schema/versions.
The guarantee
Every save that changes the schema appends an immutable snapshot to lt_role_schemas and advances the role’s version. The pin travels as metadata.schema_version, queryable like any facet, and a pin that names a missing version fails at creation with a 400 rather than falling through to another edition. Without a pin, the latest edition renders. The dashboard renders the form; the platform validates it. See Forms.
Related patterns
The escalation boundary
Pin the form edition per row
Each row renders and validates against the form version its code was written for, while the role's form keeps evolving.
Forms and configuration
Conditional fields
A field appears only when a condition holds, live as the person types, and a hidden required field is skipped by validation on both sides.
Forms and configuration
Code-owned configuration
Set configSource to code and every declared role, workflow, topic, agent and scan scheme is diffed and applied on each boot from git.
Identity
One-time user
Route one item to one named person with a self-scoped membership; they see and answer exactly that form and nothing else in the queue.
