Skip to content

The form is data

Forms and configurationSDKHTTPCLIMCPDashboardform_schemaschemaVersionlt_role_schemasPATCH /api/roles/:roleltc roles save-schema

A 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:

start.ts
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:

workflows/review.ts
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.