Skip to content

Versioned lookups

Forms and configurationSDKDashboardCLIMCPlookupsx-lt-optionsenvelope.lookupslist_knowledge_versionsGET /api/escalations/:id/lookups

Option lists live once in the knowledge store as immutable editions; rows carry a three-field ref and forms read the edition through it.

The situation

Ten thousand open rows offer the same list of reject reasons. The list changes monthly. Copying it onto every row wastes space and freezes stale options; reading it live makes old records lie about what the person saw.

The recipe

Reference the list on the wait:

workflows/inspect.ts
const result = await conditional<{ reasonId: string }>(`inspect-${orderId}`, {
role: 'inspection',
metadata: { orderId },
lookups: [
{ domain: 'catalog', key: 'reasons' }, // follows the newest edition
{ domain: 'catalog', key: 'materials', version: 2 }, // pinned
],
});

Address it from the role’s form:

form_schema
"reasonId": { "type": "string", "title": "Reason", "x-lt-options": "lookup.reasons.items" }

Every write that changes an entry’s data mints a new immutable edition. A current ref on a pending row shows the newest edition on its next render; a resolved row reads the edition that was current when it closed. Inspect lineage with ltc kb versions catalog reasons or list_knowledge_versions. Paths may interpolate an answer, lookup.geo.regions.{{resolver.country}}, for cascading selects.

The guarantee

The refs on the row are the grant: anyone who may read the row may fetch exactly the editions it names, through GET /api/escalations/:id/lookups. A value picked from a current list is validated against the edition in force at submit, so an option removed while the form was open is refused with the canonical 422. Refs live on the unindexed envelope, never on the metadata facets. See Lookups.