
Generating Custom Lightning Type
- 1.5k installs
- 763 repo stars
- Updated July 24, 2026
- forcedotcom/afv-library
This is a copy of generating-custom-lightning-type by forcedotcom - installs and ranking accrue to the original listing.
Generating Custom Lightning Type is a Salesforce agent skill that produces correct Custom Lightning Type (CLT) metadata with JSON Schema definitions for developers building Einstein Agent structured inputs and outputs on
About
Generating Custom Lightning Type is a Salesforce-focused agent skill (version 1.0) that generates Custom Lightning Types (CLTs) for Einstein Agent actions and structured input/output schemas on the Lightning Platform. The skill triggers on mentions of CLT, Custom Lightning Types, JSON schemas for agents, lightning__objectType, or editor/renderer configurations. Developers reach for Generating Custom Lightning Type whenever CLT work is required because the metadata is complex and error-prone without guided generation. Output includes JSON Schema-based type definitions, editor configurations, and renderer setups aligned to Salesforce agent action contracts. Always use this skill for CLT work rather than improvising schema metadata.
- Generates JSON Schema-based Custom Lightning Types (CLTs) for Einstein Agent actions
- Creates reusable referenced CLT patterns using lightning:type references for nested objects
- Configures editor and renderer definitions for custom UI experiences
- Troubleshoots deployment errors related to Custom Lightning Types
- Always invoked when users mention CLT, Custom Lightning Types, or lightning__objectType
Generating Custom Lightning Type by the numbers
- 1,546 all-time installs (skills.sh)
- +1 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/forcedotcom/afv-library --skill generating-custom-lightning-typeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.5k |
|---|---|
| repo stars | ★ 763 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 24, 2026 |
| Repository | forcedotcom/afv-library ↗ |
How do you create Custom Lightning Types for Einstein Agent actions?
Generate correct Custom Lightning Types for Einstein Agent actions and structured input/output schemas on the Salesforce Lightning Platform.
Who is it for?
Salesforce developers defining structured Einstein Agent action schemas who need correct CLT metadata instead of hand-written JSON Schema.
Skip if: Developers building standard Lightning tabs, FlexiPages, or React UI bundles without agent-structured type requirements.
When should I use this skill?
The user mentions CLT, Custom Lightning Types, JSON schemas for agents, lightning__objectType, or editor/renderer configuration for Einstein Agent actions.
What you get
Deployable CLT metadata with JSON Schema type definitions, lightning__objectType configs, and editor/renderer configurations.
- CLT metadata XML/JSON
- editor configuration
- renderer configuration
By the numbers
- Skill metadata version 1.0 in forcedotcom/afv-library
Files
When to Use This Skill
Use this skill when you need to:
- Create Custom Lightning Types (CLTs) for structured inputs/outputs
- Generate JSON Schema-based type definitions for Lightning Platform
- Configure CLTs for Einstein Agent actions
- Set up editor and renderer configurations for custom UI
- Create CLTs with widget/mosaic/fragment rendition
- Troubleshoot deployment errors related to Custom Lightning Types
Specification
CustomLightningType Metadata Specification
Overview & Purpose
Custom Lightning Types (CLTs) are JSON Schema-based type definitions used by the Lightning Platform (including Einstein Agent actions) to describe structured inputs/outputs and drive editor/renderer experiences.
Configuration
- Choose referenced CLT pattern for nested objects - When you need a reusable or separately deployed nested type, create a CLT for that shape and reference it with
"lightning:type": "c__<CLTName>". That string is the referenced type’s `lightning:type` value / FQN / registered identifier — not the JSON Schematitle. - Choose standard Lightning types when the structure is simple and can be expressed with properties and supported primitive
lightning:typeidentifiers. - Choose Apex class types (
@apexClassType/...) when the structure already exists server-side and you want the Apex class to define the shape. - Include editor/renderer config only when you need custom UI behavior (custom LWC input/output components). Otherwise, omit.
Critical Rules (Read First)
- CRITICAL: NEVER include the `"$schema"` field in schema.json
- Salesforce CLT validator WILL REJECT schemas with this field, even if it's a valid JSON Schema
$schemadeclaration. - Root object schemas MUST include:
"type": "object""title""lightning:type": "lightning__objectType""unevaluatedProperties": false"unevaluatedProperties"is enforced asfalseby the CLT metaschema. Do not set it totrue.- Root object schemas MUST NOT include
"examples"when"unevaluatedProperties": falseis set. - Nested objects (inside `properties`) MUST NOT set
"lightning:type": "lightning__objectType". - Nested objects can be: references to other CLTs using
c__<CLTName>syntax. - List/array properties are highly restricted by the CLT metaschema:
- CRITICAL LIMITATION: the CLT metaschema may reject the
itemskeyword entirely. Treatitemsas disallowed by default. - Root-level arrays (direct children of the root
properties): - MUST include
"lightning:type": "lightning__listType" - MUST NOT include
"items" - OPTIONAL
"type": "array" - Nested arrays (arrays inside nested objects) are the most common failure:
- MUST include
"type": "array" - MUST NOT include
"lightning:type": "lightning__listType" - MUST NOT include
"items" - When `"unevaluatedProperties": false` is set, any unknown keyword will fail validation. Prefer removing keywords over relaxing strictness.
- Apex class CLTs are minimal:
- Include only
title,description(optional), andlightning:typeset to@apexClassType/.... - Do not add
type,properties,required, orunevaluatedProperties.
Additional CLT Metaschema Validations
- Org namespace validation: titles/descriptions and other string fields may be validated to ensure you are not using an org namespace in places that are disallowed.
- Lightning type validation: CLTs are validated to prevent referencing internal namespaces (for example, disallowing types from internal namespaces like
sfdc_cmswhere not permitted). - Object type validation: the CLT root is validated to ensure
lightning:typeis exactlylightning__objectType.
Primitive Types & Constraints
When you need the full list of supported primitive lightning:type identifiers, their constraints, and the allowed property-level keywords, read assets/primitive-types-and-constraints.md in this skill's directory.
Generation Workflow
1. Confirm the CLT approach
- If referencing Apex: capture the exact class reference (
@apexClassType/namespace__ClassName$InnerClass). - If using standard primitives: list the fields, their Lightning primitive types, and which fields are required.
2. Draft `schema.json`
- DO NOT include `"$schema"` at the top
- Start with the root object structure (required root fields).
- Add
propertiesusing valid primitivelightning:typeidentifiers. - For nested-object properties, use CLT Reference pattern:
"lightning:type": "c__<CLTName>"to reference another CLT- The referenced CLT must be deployed to the org before the parent CLT.
- For Apex-based nested objects: Use
@apexClassType/...when structure exists server-side. - If the prompt explicitly requires true nested object output, prefer an Apex-based CLT (
@apexClassType/...) for deploy-safe nested structures. - For arrays: follow the strict list rules (avoid
items; avoidlightning:typeon nested arrays). - Before deployment, verify exact
lightning:typespellings (for example, uselightning__richTextType, not misspelled variants).
3. (Optional) Draft `editor.json` (only if custom UI is required)
- Supported shape: Top-level
editorobject witheditor.componentOverridesandeditor.layout. - Top-level
editorobject. - Use
editor.componentOverridesfor component overrides. - Use
editor.layoutfor layout. - DEPRECATED: Do NOT use
propertyRenderersorview— these are legacy keys. Always usecomponentOverridesandlayoutinstead. - Root override pattern (most common for fully custom editing UI):
editor.componentOverrides["$"] = { "definition": "c/<yourEditorComponent>", "attributes": { ... } }- When passing schema data into a custom LWC, use attribute mapping with the
{!$attrs.<name>}syntax: e.g."attributes": { "myField": "{!$attrs.value}" }so the runtime binds schema values to your component's attributes. - CRITICAL: The
<name>in{!$attrs.<name>}must be a property defined in your type schema. For example, if your schema has a property calledtemperature, use{!$attrs.temperature}, not{!$attrs.value}unlessvalueis an actual property. - Property-level override pattern (for individual fields):
editor.componentOverrides["<propertyName>"] = { "definition": "es_property_editors/<...>" }- Valid editor components (examples):
es_property_editors/inputText,es_property_editors/inputNumber,es_property_editors/inputRichText,es_property_editors/inputImage,es_property_editors/inputTextarea. Do not usees_property_editors/inputList. - Collection editor (for root-level
lightning__listTypeproperties): Use a collection-level override so the list is edited by a custom component:collection.editor.componentOverrides["$"] = { "definition": "c/<yourCollectionEditorComponent>" }. Alternatively, useeditor.layoutwithlightning/propertyLayoutandattributes.property = "<listPropertyName>"for default list editing. - Layout pattern:
editor.layout.definition = "lightning/verticalLayout"editor.layout.children[*].definition = "lightning/propertyLayout"withattributes.property = "<propertyName>"- CRITICAL:
lightning/propertyLayoutonly accepts thepropertyattribute. Do NOT addlabel,title, or any other attributes — these will fail validation withadditionalProperties: falseerrors. - Avoid known-invalid patterns:
- Do not use
es_property_editors/inputList. - Do not use
itemSchemaattributes.
4. (Optional) Draft `renderer.json` (only if custom UI or mosaic rendition is required)
- Supported shape: Top-level
rendererobject withrenderer.componentOverridesandrenderer.layout. - Top-level
rendererobject. - Use
renderer.componentOverridesfor component overrides. - Use
renderer.layoutfor layout. - DEPRECATED: Do NOT use
propertyRenderersorview— these are legacy keys. Always usecomponentOverridesandlayoutinstead. - Root override pattern (most common for fully custom rendering UI):
renderer.componentOverrides["$"] = { "definition": "c/<yourRendererComponent>", "attributes": { ... } }- Use
{!$attrs.<name>}in attribute mappings when binding schema data to custom renderer component attributes. - CRITICAL: Attribute mappings like
{!$attrs.propertyName}must reference properties that actually exist in your type schema. Referencing non-existent properties will fail validation. - Type matching: Attribute values must match the expected type for the component. For example, if a component expects a string attribute, passing an integer will fail validation.
- Widget renderer pattern (for widget rendition):
- When to use: Use this when users request "mosaic", "widget", "fragment", or "cross-platform rendering" for their CLT.
- Structure:
renderer.componentOverrides["$"] = { "type": "mosaic", "definition": "tile/mosaic", "children": [ /* UEM tree of blocks and regions */ ] } - REQUIRED workflow:
- STOP: Do NOT attempt to create the widget renderer yourself.
- MANDATORY FIRST STEP: You MUST fetch the reference file
references/widget-rendition.mdlocated in this skill's directory before proceeding. - Follow the complete workflow documented in
widget-rendition.mdusing the generated CLT schema as the grounding schema. - The
widget-rendition.mdreference contains the full widget generation workflow: discovering UEM blocks via discoverUiComponents, calling getUiComponentSchemas, building the UEM tree, and writing renderer.json. - Do not attempt to generate widget rendition without first fetching the
widget-rendition.mdreference file. - Property-level override pattern:
renderer.componentOverrides["<propertyName>"] = { "definition": "es_property_editors/outputText" | "es_property_editors/outputNumber" | "es_property_editors/outputImage" | ... }. Valid renderer components (examples):es_property_editors/outputText,es_property_editors/outputNumber,es_property_editors/outputImage. Avoid input-style components in the renderer.- Layout pattern for renderer:
renderer.layout.definition = "lightning/verticalLayout"renderer.layout.children[*].definition = "lightning/propertyLayout"withattributes.property = "<propertyName>"- CRITICAL: Same as editor layouts,
lightning/propertyLayoutonly accepts thepropertyattribute. Do NOT addlabel,title, or any other attributes. - Collection renderer (for root-level
lightning__listTypeproperties): Usecollection.renderer.componentOverrides["$"] = { "definition": "c/<yourListRendererComponent>" }ores_property_editors/genericListTypeRendererto render the list.
5. Place files in the correct bundle structure
lightningTypes/<TypeName>/schema.json- (Optional)
lightningTypes/<TypeName>/lightningDesktopGenAi/editor.json - (Optional)
lightningTypes/<TypeName>/lightningDesktopGenAi/renderer.json - For Gen AI / Copilot the standard path is
lightningDesktopGenAi/. Other targets (e.g. Experience Builder, Mobile Copilot, Enhanced Web Chat) use different subfolders when supported:experienceBuilder/,lightningMobileGenAi/,enhancedWebChat/.
6. Configure custom LWC components (if using custom components)
- CRITICAL: Custom LWC components referenced in editor/renderer configs MUST have the correct target configuration in their
-meta.xmlfiles: - For editor components (
c/<componentName>used ineditor.json): The LWC's-meta.xmlfile must include<target>lightning__AgentforceInput</target> - For renderer components (
c/<componentName>used inrenderer.json): The LWC's-meta.xmlfile must include<target>lightning__AgentforceOutput</target> - Without the correct target, deployment will fail with:
Invalid target configuration. To use 'c/componentName' as a renderer/editor, your js-meta.xml file must include valid target 'lightning__AgentforceOutput/Input'. - Example
-meta.xmlfor a renderer component:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>60.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AgentforceOutput</target>
</targets>
</LightningComponentBundle>Common Deployment Errors
| Error / Symptom | Likely Cause | Fix |
|---|---|---|
| Schema validation fails due to unknown keyword | unevaluatedProperties: false + disallowed keyword (commonly examples, items) | Remove the offending keyword; keep schema minimal |
| Nested object validation failure | Org/channel validation rejects nested object typing in LightningTypeBundle | Use CLT reference (c__<CLTName>) or Apex class types |
| Invalid CLT reference | Referenced CLT doesn't exist in org or incorrect syntax | Deploy the referenced CLT first; c__<CLTName> must match the referenced type’s `lightning:type` value / FQN / registered identifier, not title |
Invalid or misspelled lightning:type (for example, lightning__richtextType instead of lightning__richTextType) | Incorrect generated type name | Cross-check all lightning:type values against supported type names and correct them before deployment |
| Array property rejected | Use of items (or lightning:type in nested arrays) rejected by validator | For nested arrays: keep only type: "array". For root arrays: use minimal structure; remove items if rejected |
| Apex-based CLT rejected | Extra fields added (e.g., type, properties) | Use only title, optional description, and lightning:type |
| Editor config rejected | Use of invalid patterns (es_property_editors/inputList, itemSchema) or unrecognized top-level keys | Use editor.componentOverrides and editor.layout; keep config minimal |
additionalProperties error on layout attributes | Adding label or other attributes to lightning/propertyLayout | Only use property attribute in lightning/propertyLayout. Remove label, title, or any other attributes |
| Invalid target configuration for custom LWC | Custom LWC component's -meta.xml missing required target (lightning__AgentforceInput or lightning__AgentforceOutput) | Add correct target to LWC's -meta.xml: use lightning__AgentforceInput for editors, lightning__AgentforceOutput for renderers |
| Attribute mapping doesn't exist in type schema | Using {!$attrs.propertyName} where propertyName is not defined in schema | Ensure all attribute mappings reference actual properties in your type schema's properties section |
additionalProperties error with deprecated keys | Using propertyRenderers or view in editor/renderer config | Replace deprecated propertyRenderers with componentOverrides and view with layout |
| Type mismatch in component attributes | Passing wrong type for component attribute (e.g., integer instead of string) | Ensure attribute values match the expected type defined by the component |
Verification Checklist
- [ ] Root schema has
type: "object",title,lightning:type: "lightning__objectType", andunevaluatedProperties: false - [ ] Root schema does not include
exampleswhen strict validation is enabled - [ ] No nested object includes
lightning:type: "lightning__objectType" - [ ] Arrays are defined minimally (especially nested arrays)
- [ ] Only supported primitive
lightning:typeidentifiers are used for leaf properties - [ ] Apex class CLTs contain only
title/descriptionandlightning:type: "@apexClassType/..." - [ ] Bundle structure and filenames match Lightning Types requirements
- [ ] Editor config uses only allowed patterns (no
es_property_editors/inputList, noitemSchema); use valid components (e.g.es_property_editors/inputText,es_property_editors/inputNumber) or customc/components - [ ] Renderer config uses output-style components (e.g.
es_property_editors/outputText,es_property_editors/outputNumber) where applicable, not input editors - [ ] Layout configurations use
lightning/propertyLayoutwith ONLY thepropertyattribute (nolabel,title, or other attributes) - [ ] All attribute mappings (
{!$attrs.propertyName}) reference properties that exist in the type schema - [ ] Custom LWC components have correct targets in
-meta.xml:lightning__AgentforceInputfor editors,lightning__AgentforceOutputfor renderers - [ ] Root schema does NOT include
"$schema"field
Primitive Types & Constraints
Reference for all supported Lightning primitive types and their allowed constraints. Read this when authoring property-level lightning:type identifiers or determining which keywords are valid on a given property.
Supported Types
lightning__textType- Max length 255
lightning__multilineTextType- Max length 2000
lightning__richTextType- Max length 100000
lightning__urlType- Max length 2000
- Optional
lightning:allowedUrlSchemesenum values:https,http,relative,mailto,tel lightning__dateType- Data pattern: YYYY-MM-DD
lightning__timeType- Data pattern: HH:MM:SS.sssZ
lightning__dateTimeType- Data shape is an object with required
dateTimeand optionaltimeZone lightning__numberType- Decimal numbers; optional
maximum,minimum,multipleOf lightning__integerType- Whole numbers only; optional
maximum,minimum lightning__booleanType- true/false
Allowed Property-Level Keywords
When strict validation is enabled (unevaluatedProperties: false), keep each property minimal and prefer only keywords known to be allowed:
title,description,einstein:descriptiontype(when used, ensure it matches the chosenlightning:type)lightning:typemaximum,minimum,multipleOf(numeric)maxLength,minLength(string)const,enumlightning:textIndexed,lightning:supportsPersonalization,lightning:localizablelightning:uiOptions,lightning:allowedUrlSchemeslightning:tags(metaschema restricts values; currentlyflowis the only known allowed tag)
Widget Generation Guide
📋 Overview
Widgets are reusable pieces of UI similar to templates, with placeholders for actual data values. The purpose of this file is to assist developers in creating mosaic renditions for CLTs.
🎯 Purpose
Widgets render data in a structured and unified way across various Salesforce experiences like Slack, Mobile, LEX etc.
Schema Grounding
Widget generation is always schema-grounded using a CLT's schema. The schema describes the data shape the widget should render. Extract property names, types, required vs optional, and nesting from the schema; then follow the full Workflow below, using this extracted structure to guide every step. Do not add or remove properties relative to the schema.
⚙️ Composition
A widget is a UEM (Unified Experience Model) tree of blocks and regions. The widget you return must follow the Typescript interfaces below:
interface BlockType {
type: 'block'
definition: string // {namespace}/{blockName}
attributes?: Record<string, any>
children?: (BlockType | RegionType)[]
}
interface RegionType {
type: 'region'
name: string
children: BlockType[]
}---
🔧 Available Metadata Actions
When to Use Each Action
discoverUiComponents
Purpose: Discover the palette of available blocks that can be used in widget composition.
Use for: Finding available blocks before building your widget structure.
Input Parameters:
actionName(required*): "discoverUiComponents"metadataType(required): "FRAGMENT"parameters(required): JSON object with the below fieldspageType(required): "FRAGMENT"pageContext(optional): JSON object - not required for FRAGMENT typesearchQuery(optional): String to filter components by name or description
Returns: List of components with:
definition: Fully qualified name (e.g., "namespace/definiton")description: Component descriptionlabel: Human-readable labelattributes: Optional attribute metadata
getUiComponentSchemas
Purpose: Get detailed JSON schemas for component configuration, including property types, required vs optional fields, and validation rules.
Use for: You know which components you want but need to understand their properties before adding them to your widget.
Input Parameters:
actionName(required*): "getUiComponentSchemas"metadataType(required): "FRAGMENT"parameters(required): JSON object with the below fieldspageType(required): "FRAGMENT"componentDefinitions(required): List of fully qualified names (e.g., ["namespace/definition"])- CRITICAL: NEVER include "tile/mosaic" in this list. "tile/mosaic" is a container component used in renderer.json structure and should not be passed to getUiComponentSchemas
pageContext(optional): JSON object - not required for FRAGMENT typeincludeKnowledge(optional): Boolean, defaults to true - includes additional component-specific guidance
Returns:
componentSchemas: List of results (supports partial failures)- Success entries: Contains JSON schema with property definitions, types, constraints
- Failure entries: Contains error message explaining why schema couldn't be retrieved
$defs: Schema definitions and references (if schema transformation applied)
Key Feature: Supports partial failures - if some components can't be found, you still get schemas for the successful ones.
---
Attribute binding using placeholder syntax
- Where to use: When block properties must display or pass runtime data from the grounding schema, use the Placeholder Syntax below so that the runtime binds values into the widget. Check each block's schema (from
getUiComponentSchemas) for the correct property name (e.g.value,text,label). - Placeholder Syntax: Use
{!$attrs.<attrName>}as the placeholder for each block property that should receive data.
<attrName> must match the property name from the grounding schema so that the runtime can resolve its value. Example: for a schema property title, set the block property to {!$attrs.title}.
- List / iterative data: Only the children (list items) hold bound values; the parent list block does not. For each item inside a list (e.g.
tile/listItem), use{!$attrs.<listAttrName>.item}so the runtime binds the current item.<listAttrName>MUST match the schema property name of the list. Example: foricons, use"{!$attrs.icons.item}"on the list item.
---
💡Workflow
1. Schema Parsing
- Parse the schema and extract: property names, types, required vs optional, and nested structure. Use this as the widget spec.
2. Discover Available Blocks (REQUIRED - do NOT skip)
- Use discoverUiComponents metadata action above to explore what blocks are available.
- Use property types from the widget spec to inform
searchQuery(e.g. text → "text", number → "number").
3. Select Components
- Choose blocks that can represent each property in the widget spec from the results of step 2.
4. Get Component Schemas (REQUIRED - do NOT skip)
- Use getUiComponentSchemas metadata action with the selected block definitions from step 3 and review block properties' metadata.
5. Build Widget
- Construct the UEM tree. Map each property in the widget spec to block properties and preserve order of the widget spec.
- For block properties that must show or pass runtime data, use the placeholder syntax (see Attribute binding using placeholder syntax above).
- Use block properties from the schemas retrieved in step 4.
6. Write output to CLT Bundle
- Always write to
lightningTypes/<TypeName>/lightningDesktopGenAi/renderer.json(or the correct target subfolder for the product surface, e.g.experienceBuilder/,lightningMobileGenAi/,enhancedWebChat/when applicable).
Check required root override pattern below - renderer.componentOverrides["$"] = { "type": "mosaic", "definition": "tile/mosaic", "children": [ ... ] — array of UEM nodes - contains the widget UEM generated using the **Workflow** steps 1-5 above }
---
⚠️ Important Notes
- widget spec includes both required and optional attributes - review carefully to ensure valid configuration.
- When using `execute_metadata_action` tool, always supply `parameters` with the required fields above; missing
parametersor required keys causes hard failures, not partial results. - Block definitions always follow the
{namespace}/{blockName}convention. - Use the same definition format returned by
discoverUiComponentswhen callinggetUiComponentSchemas - Placeholder syntax for non-list properties is
{!$attrs.<attrName>}and for list properties is{!$attrs.<listAttrName>.item}.
Related skills
How it compares
Use Generating Custom Lightning Type instead of general Salesforce metadata skills when the deliverable is specifically CLT schemas for Einstein Agent structured I/O.
FAQ
What does Generating Custom Lightning Type produce?
Generating Custom Lightning Type produces Custom Lightning Type metadata with JSON Schema-based definitions, lightning__objectType configuration, and editor/renderer setups for Einstein Agent structured inputs and outputs on Salesforce.
When must developers use Generating Custom Lightning Type?
Developers should always use Generating Custom Lightning Type for CLT work because Custom Lightning Types are complex metadata; the skill triggers on CLT, JSON schema for agents, and editor/renderer configuration mentions.
Is Generating Custom Lightning Type safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.