Salesforce Custom Field Generator and Validator
Overview
Generates and validates Salesforce CustomField metadata XML, with special handling for the highest-failure-rate types — Roll-Up Summary and Master-Detail. The agent must verify the constraints below before outputting XML to prevent Metadata API deployment errors.
1. Universal Mandatory Attributes
Every generated field must include these tags:
<description> and <inlineHelpText> are mandatory even though the Metadata API does not enforce them — omitting them yields low-quality metadata.
File path (SFDX source format): save each field as force-app/main/default/objects/<Object>/fields/<FieldName>__c.field-meta.xml, where <Object> is the object's API name (Account, Opportunity, or a custom Inventory_Item__c). A correct XML at the wrong path is never seen by the Metadata API.
External ID Configuration
Trigger: If the user mentions "integration," "importing data," "external system ID," or "unique key from [System Name]," set <externalId>true</externalId>.
Applicable Types: Text, Number, Email
2. Precision, Scale, and Length Rules
To ensure deployment success, follow these mathematical constraints:
Precision vs. Scale Rules
precisionis the total digits;scaleis the decimal digits- Rule:
precision ≤ 18ANDscale ≤ precision - Calculation: Digits to the left of decimal =
precision - scale
The "Fixed 255" Rule
TextArea: do NOT include <length> — the API fixes it at 255 implicitly and rejects an explicit value ("Can not specify 'length' for a CustomField of type TextArea"). The field needs only <fullName>, <label>, and <type>TextArea</type>.
Visible Lines
Mandatory for Long/Rich text and Multi-select picklists to control UI height.
3. Field Data Types
3.1 Simple Attribute Types
3.2 Computed & Multi-Value Types
3.3 Specialized Types
Picklist restricted default
Always set <restricted>true</restricted> inside <valueSet> unless the user explicitly says the picklist should accept custom values not in the admin-defined list (e.g. "unrestricted"/"open"). Restricted sets are capped at 1,000 total values (active + inactive). Minimal inline shape:
3.4 Advanced Picklists
The inline <valueSetDefinition> above is the simple case. Full rules and worked correct/incorrect
examples for everything below are in
references/advanced-picklists.md [blocked] — load it for any
non-trivial picklist. Section numbers in parentheses below (e.g. "ref §1") point to that
reference file, not to this skill. The hard rules:
- Value-set reference (ref §1). A
<valueSet>holds EITHER<valueSetName>(reference) OR<valueSetDefinition>(inline) — never both. Reference by the bare developer name — Standard setIndustry, GlobalValueSetPriority_Levelswith NO__gvsand no__c(the__gvssuffix is org-storage display only; the Metadata API uses the bare name). A value-set-backed field is<restricted>true</restricted>. Creating the value set is theplatform-value-set-generateskill's job; this one only references it. - Value-name fidelity (ref §3). A picklist value's
<fullName>/<label>keep the user's exact text including spaces (Closed Won, neverClosed_Won). The space→_+__crule is for the FIELD name only. - Dependent picklists (ref §2). Use the modern API 38.0+ form:
<controllingField>+ one<valueSettings>(<controllingFieldValue>+<valueName>) per pair; never the legacy<picklist>/<picklistValues>/<controllingFieldValues>tags. Both controlling and dependent fields MUST be<restricted>true</restricted>, even if the request doesn't say so. - Enhanced value attributes (ref §3).
<value>entries also accept<color>(hex, leading#),<isActive>(falseretires a value), and a value-level<description>. - Scoping a picklist to a record type (ref §5). Per-record-type value visibility lives on the
RecordType (
<picklistValues>), not the field. The RecordType file carries its own<fullName>(bare developer name). First decide if the object needs a BusinessProcess: only Opportunity / Lead / Case / Solution require one — they won't deploy without a<businessProcess>(Required field is missing: businessProcess), even when only a custom picklist is filtered. There you emit two coupled files: thebusinessProcesses/<Name>.businessProcess-meta.xmlfile AND a matching<businessProcess><Name></businessProcess>inside the<RecordType>(after<active>, before<picklistValues>; the<fullName>in the BP file is bare, never object-qualified). Custom objects (*__c) and all other standard objects (Account, Contact, …) need NO BusinessProcess — emit the RecordType alone; do not invent one. Scope limit: picklist-value visibility per record type only — NOT general record-type authoring (compact layouts, page layouts, branding).
4. Master-Detail Relationship Rules CRITICAL
Master-Detail fields have strict attribute restrictions that differ from Lookup fields. Violating these rules causes deployment failures.
Forbidden Attributes on Master-Detail Fields
NEVER include these attributes on Master-Detail fields:
Master-Detail vs Lookup Comparison
INCORRECT — Master-Detail with forbidden attributes:
Errors: Master-Detail Relationship Fields Cannot be Optional or Required · Can not specify 'deleteConstraint' for a CustomField of type MasterDetail · Lookup filters are only supported on Lookup Relationship Fields
CORRECT — Master-Detail field:
CORRECT — Lookup field (with optional attributes):
Additional Master-Detail Rules
- Relationship Order: First Master-Detail on object =
0, second =1 - Relationship Name: Must be a plural PascalCase string (e.g.,
Travel_Bookings) - Junction Objects: Use two Master-Detail fields for standard many-to-many (enables Roll-ups)
- Limit: Maximum 2 Master-Detail relationships per object. Use Lookup for additional relationships.
5. Roll-Up Summary Field Rules CRITICAL
Roll-up Summary fields have the highest deployment failure rate. Follow these rules exactly.
Required Elements for Roll-Up Summary
Forbidden Elements on Roll-Up Summary
NEVER include these attributes on Roll-Up Summary fields:
Format Rules for summaryForeignKey and summarizedField
CRITICAL: Both summaryForeignKey and summarizedField MUST use the fully qualified format:
Decision Logic:
summaryForeignKey=ChildObject__c.MasterDetailFieldOnChild__csummarizedField=ChildObject__c.FieldToSummarize__c
INCORRECT — Roll-Up Summary with common errors:
Errors:
Can not specify 'precision' for a CustomField of type SummaryMust specify the name in the CustomObject.CustomField format (e.g. Account.MyNewCustomField)
CORRECT — Roll-Up Summary (SUM operation):
COUNT: like SUM but omit <summarizedField> (keep <summaryForeignKey>). MIN / MAX: like SUM with <summaryOperation>min</summaryOperation> or max.
Roll-Up Summary Quick Reference
Roll-Up Summary Prerequisites
- Roll-Up Summary fields can ONLY be created on the parent object in a Master-Detail relationship
- The child object MUST have a Master-Detail field pointing to this parent
- The summarized field must exist on the child object
6. Formula Field Rules
Formula Result Types
A Formula is not a type itself. The <formula> tag is added to a field whose <type> is the result data type (Checkbox, Currency, Date, DateTime, Number, Percent, Text).
- A formula field never carries
<length>— not even a Text-result formula. The API rejects it:Can not specify a length for CustomFields that have a formula.
Formula XML Generation Rules
- The contents of the
<formula>tag MUST be wrapped in<![CDATA[ ... ]]>, so the parser does not read formula operators (&,<,>) as XML markup. - If the formula text itself contains the literal sequence
]]>, escape it by breaking the CDATA block: e.g.,<![CDATA[Text_Field__c & "]]]]><![CDATA[>"]]> - NEVER use an attribute or tag named
returnType. This does not exist in the Metadata API. The<type>tag defines the return data type of the formula result.
formulaTreatBlanksAs Rule
Decision Logic:
- IF formula result type =
Number,Currency, orPercent→ set<formulaTreatBlanksAs>BlankAsZero</formulaTreatBlanksAs> - IF formula result type =
Text,Date, orDateTime→ set<formulaTreatBlanksAs>BlankAsBlank</formulaTreatBlanksAs>
INCORRECT — Using Formula as type:
CORRECT — Formula field:
Formula Field Dependencies & Functions
- Formula fields that reference other fields fail deployment if the referenced field doesn't exist or hasn't deployed yet — deploy referenced fields first.
- Use
ISPICKVAL()(not==) for picklist comparisons. - For the full formula-function reference (TEXT/VALUE/CASE/DAY/MONTH/DATEVALUE/ISCHANGED type rules), defer to the
platform-validation-rule-generateskill, which owns formula-function correctness.
7. Common Deployment Errors
8. Verification Checklist
Before generating CustomField XML, verify:
Universal Checks
- Does
<fullName>use valid format and end in__c? - Are
<description>and<inlineHelpText>both populated and meaningful? - Is
<label>in Title Case? - Are there no XML comments (
<!-- ... -->) before the root<CustomField>element? (Comments before the root element break SDR's parser)
Master-Detail Field Checks CRITICAL
- Is
<required>attribute ABSENT? (Master-Detail is always required) - Is
<deleteConstraint>attribute ABSENT? (Master-Detail always cascades) - Is
<lookupFilter>block ABSENT? (Only for Lookup fields) - Is
<relationshipOrder>set to0or1? - Is parent object's
<sharingModel>set toControlledByParent?
Lookup Field Checks
- Is
<deleteConstraint>set toSetNull,Restrict, orCascade? - Is
<relationshipName>in plural PascalCase?
Picklist Field Checks
- Does each
<valueSet>contain EITHER<valueSetName>OR<valueSetDefinition>— never both? - For a value-set reference: is
<restricted>true</restricted>set? - For a StandardValueSet reference: is the name the bare enum with NO
__c(e.g.Industry)? - For a GlobalValueSet reference: is the name the bare developer name with NO
__gvssuffix? - For dependent picklists: is
<controllingField>set, with one<valueSettings>(<controllingFieldValue>+<valueName>) per pair? - For dependent picklists: is the deprecated
<picklist>/<picklistValues>/<controllingFieldValues>form ABSENT? - Are all picklist value
<fullName>values unique, start with a letter, and free of hyphens? (spaces are allowed — do NOT replace them with underscores, per the §3.4 value-name fidelity rule)
Roll-Up Summary Field Checks CRITICAL
- Is
<precision>attribute ABSENT? - Is
<scale>attribute ABSENT? - Is
<summaryForeignKey>in formatChildObject__c.MasterDetailField__c? - For SUM/MIN/MAX: Is
<summarizedField>in formatChildObject__c.FieldName__c? - For COUNT: Is
<summarizedField>ABSENT? - Does the child object have a Master-Detail field to this parent?
Formula Field Checks
- Is
<type>set to result type (NOT "Formula")? - Is
<formula>content wrapped in<![CDATA[ ... ]]>? - Is
<returnType>attribute ABSENT? (does not exist in Metadata API) - Is
<length>ABSENT? (formula fields never carry a length, even Text-result formulas) - Is
<formulaTreatBlanksAs>set toBlankAsZerofor numeric results orBlankAsBlankfor text/date results? - Do all referenced fields exist and deploy before this field?
Numeric Field Checks
- Is
scale ≤ precision? - Is
precision ≤ 18?
Text Area Checks
- For TextArea: Is
<length>omitted? (The API rejects an explicit<length>value on TextArea fields.) - For LongTextArea/Html: Is
<visibleLines>set?
Relationship Limit Checks
- Are there 2 or fewer Master-Detail relationships on the object?
- Are there 15 or fewer Lookup relationships on the object?
Naming Checks
- Is the API name free of reserved words (
Order,Group,Select, etc.)? - Is the API name unique on this object?


