furuCRM
Back to Blog

Code-Free AI to Record Conversion with Generic Orchestration Framework

February 3, 2026
Code-Free AI to Record Conversion with Generic Orchestration Framework

🎯 Introduction

Salesforce Prompt Templates are a powerful feature for generating text and JSON using AI. However, automatically creating or updating Salesforce records (such as Opportunities, Tasks, and Contacts) based on that output has traditionally required complex Apex code.

In this article, we introduce how to create Salesforce records from AI-generated JSON output without writing any code, by using the Declarative Record Builder built on the GenericOrchestrationFramework.

πŸ“Έ What the Finished Experience Looks Like (Use Case: Demo screen that automatically creates opportunity-related records from meeting minutes)

GenericOrchestrationFramework overview
Use case diagram

πŸ—οΈ Architecture Overview

Traditional Approach vs Declarative Record Builder

Aspect Traditional Approach Declarative Record Builder
Implementation Create new Apex for each AI output Configuration only via Custom Metadata
Handling changes Code change + deployment Metadata change only
Reusability Low (per use case) High (just change the configuration)
Maintenance cost High Low
Required skill Apex required Admins can configure it

System Flow Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    GenericOrchestrationFramework                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Input Source  │───▢│  AI Agent    │───▢│ DeclarativeRecord   β”‚   β”‚
β”‚  β”‚ (e.g. minutes)β”‚    β”‚ (JSON output)β”‚    β”‚     Builder         β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                              β”‚                        β”‚              β”‚
β”‚                              β–Ό                        β–Ό              β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚                    β”‚ SchemaMapping    β”‚    β”‚   Salesforce     β”‚     β”‚
β”‚                    β”‚   __mdt          β”‚    β”‚    Records       β”‚     β”‚
β”‚                    β”‚ (JSON schema)    β”‚    β”‚ (Opp/Task/Event) β”‚     β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
GenericOrchestrationFramework overview
Overall view of GenericOrchestrationFramework and relationships between components

πŸ”§ Step 1: Define the Schema in Custom Metadata

SchemaMapping__mdt — the core of the mapping definition

The most important element is SchemaMapping__mdt. This is where you define the JSON schema passed to the AI as well as the extraction rules.

Example Configuration (Meeting_Minutes_Opportunity)

<?xml version="1.0" encoding="UTF-8"?>
<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Meeting Minutes Opportunity</label>
    <protected>false</protected>
    <values>
        <field>RootObjectApiName__c</field>
        <value>Opportunity</value>
    </values>
    <values>
        <field>Description__c</field>
        <value>Extract and create opportunity info, tasks, events, and contacts from meeting minutes</value>
    </values>
    <values>
        <field>IsActive__c</field>
        <value>true</value>
    </values>
    <values>
        <field>Version__c</field>
        <value>3.0</value>
    </values>
    <values>
        <field>JsonSchemaTemplate__c</field>
        <value><!-- JSON schema described later --></value>
    </values>
</CustomMetadata>
SchemaMapping Custom Metadata setting screen
SchemaMapping Custom Metadata configuration screen

πŸ“‹ Step 2: Express the Data Hierarchy to Register Using a JSON Schema

Structure of the JSON schema

Most important point: The structure of the JSON schema becomes the hierarchy of Salesforce records as-is.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "description": "Schema to extract opportunity-related information from meeting minutes",
  "properties": {
    "opportunity": {
      "type": "object",
      "description": "Basic opportunity info (root object)",
      "properties": {
        "accountName": {
          "type": "string",
          "description": "Account name - maps to Account.Name"
        },
        "name": {
          "type": "string",
          "description": "Opportunity name - maps to Opportunity.Name"
        },
        "stageName": {
          "type": "string",
          "description": "Stage name",
          "enum": [
            "Prospecting",
            "Qualification",
            "Needs Analysis",
            "Value Proposition",
            "Proposal/Price Quote",
            "Negotiation/Review",
            "Closed Won",
            "Closed Lost"
          ]
        },
        "amount": {
          "type": "number",
          "description": "Amount (numbers only)"
        },
        "closeDate": {
          "type": "string",
          "format": "date",
          "description": "Close date (YYYY-MM-DD)"
        }
      },
      "required": ["accountName", "name"]
    },
    "contacts": {
      "type": "array",
      "description": "List of contacts related to the opportunity",
      "items": {
        "type": "object",
        "properties": {
          "lastName": {
            "type": "string",
            "description": "Last name"
          },
          "firstName": {
            "type": "string",
            "description": "First name"
          },
          "title": {
            "type": "string",
            "description": "Title"
          },
          "role": {
            "type": "string",
            "description": "Role in the opportunity",
            "enum": [
              "Decision Maker",
              "Evaluator",
              "Influencer",
              "Technical Buyer",
              "Economic Buyer"
            ]
          }
        },
        "required": ["lastName"]
      }
    },
    "tasks": {
      "type": "array",
      "description": "List of tasks (related to the opportunity)",
      "maxItems": 10,
      "items": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string",
            "description": "Subject"
          },
          "description": {
            "type": "string",
            "description": "Details"
          },
          "activityDate": {
            "type": "string",
            "format": "date",
            "description": "Due date"
          },
          "priority": {
            "type": "string",
            "enum": ["High", "Normal", "Low"]
          }
        },
        "required": ["subject"]
      }
    },
    "nextMeeting": {
      "type": "object",
      "description": "Next meeting (Event)",
      "properties": {
        "subject": {
          "type": "string",
          "description": "Subject"
        },
        "startDateTime": {
          "type": "string",
          "format": "date-time"
        },
        "endDateTime": {
          "type": "string",
          "format": "date-time"
        },
        "location": {
          "type": "string",
          "description": "Location"
        }
      }
    },
    "summary": {
      "type": "string",
      "description": "Meeting minutes summary (within 200 characters)"
    }
  },
  "required": ["opportunity", "summary"]
}

Schema → Record Hierarchy Mapping (JSON schema structure vs Salesforce record hierarchy)

JSON Schema Structure                  Salesforce Record Hierarchy
─────────────────                   ─────────────────────────────
{
  "opportunity": {...}      ───▢   Level 1: Opportunity (root)
                                           β”‚
  "contacts": [...]         ───▢   Level 2: β”œβ”€ OpportunityContactRole
                                           β”‚     └─ Contact (referenced)
  "tasks": [...]            ───▢   Level 2: β”œβ”€ Task (WhatId → Opportunity)
                                           β”‚
  "nextMeeting": {...}      ───▢   Level 2: └─ Event (WhatId → Opportunity)
  "products": [...]         ───▢   Level 2: OpportunityLineItem
}

🎨 Step 3: Prompt Template Image

Prompt composition passed to the AI

The SchemaMapper class automatically generates a prompt like the following:

# Meeting Minutes Extraction

You are an assistant that extracts opportunity-related information from meeting minutes.

## Input
From the following meeting minutes text, extract information related to the opportunity.

{Meeting minutes text}

## Output Format
Output structured JSON according to the following JSON schema.

### JSON Schema
{Contents of JsonSchemaTemplate__c}

### Extraction Rules
{Contents of ExtractionRules__c}

## Important Constraints
- Always populate required fields (required)
- Output dates in YYYY-MM-DD format
- Use only values defined by enum
- Amount must be numbers only (remove currency symbols and separators)
- If information is unknown, set it to null

## Output Example
{Contents of JsonOutputExample__c}

Example of Extraction Rules (ExtractionRules__c)

1. Opportunity base info (opportunity)

  • accountName: Account name (company name) — extract from phrases like company name, organization name, client name, etc.
  • name: Opportunity name / project name — extract from project title, deal name, proposal name, etc.
  • stageName: Sales stage — select the best match from the schema’s enum
  • amount: Amount (numbers only; remove currency symbols and separators)
  • closeDate: Expected close date (YYYY-MM-DD)

2. Attendee info (contacts)

For each attendee:

  • lastName: Last name
  • firstName: First name
  • title: Title
  • role: Role in the opportunity (select from schema enum)

3. Tasks / To-Dos (tasks)

Action items extracted from the meeting minutes:

  • subject: Task subject
  • description: Detailed description
  • activityDate: Due date (YYYY-MM-DD)
  • priority: Priority (High/Normal/Low)

4. Next meeting schedule (nextMeeting)

  • subject: Meeting subject
  • startDateTime: Start date/time (ISO 8601)
  • endDateTime: End date/time (ISO 8601)
  • location: Location
Prompt template setting example
Prompt template configuration image

πŸ“Š Step 4: Example Output from the AI

Input: Meeting minutes text

Meeting Minutes
Date/Time: January 15, 2026 14:00–15:30
Location: ABC Corporation, Head Office Meeting Room
Attendees:
- Taro Yamada, Director (Information Systems Dept.), ABC Corporation
- Hanako Suzuki, Manager (Information Systems Dept.), ABC Corporation
- Ichiro Tanaka (Our Company)

[Topic]
CRM System Implementation

[Discussion]
1. Director Yamada explained issues with the current system
 - Customer data is not centrally managed
 - Sales activities are difficult to visualize

2. We demonstrated our CRM system
 - Received positive feedback on core features
 - Questions were asked about customizability

3. Budget
 - Target budget is around JPY 5,000,000
 - They want to implement in the first half of FY2026

[Action Items]
- Tanaka: Send proposal by 1/21
- Tanaka: Create estimate by 1/25
- Director Yamada: Brief internal stakeholders (planned for 1/28)

[Next Meeting]
January 28, 2026 14:00 — Proposal Review Meeting

Output: Structured JSON

{
  "opportunity": {
    "accountName": "ABC Corporation",
    "name": "CRM System Implementation Project",
    "stageName": "Proposal/Price Quote",
    "amount": 5000000,
    "closeDate": "2026-06-30",
    "probability": 60,
    "description": "Discussed CRM system implementation. They are considering adopting our CRM to solve current issues (no centralized customer data and poor visibility into sales activities)."
  },
  "contacts": [
    {
      "lastName": "Yamada",
      "firstName": "Taro",
      "title": "Director, Information Systems",
      "role": "Decision Maker"
    },
    {
      "lastName": "Suzuki",
      "firstName": "Hanako",
      "title": "Manager, Information Systems",
      "role": "Evaluator"
    }
  ],
  "tasks": [
    {
      "subject": "Send proposal",
      "description": "Create a proposal for CRM system implementation and send it to ABC Corporation",
      "activityDate": "2026-01-21",
      "priority": "High"
    },
    {
      "subject": "Create estimate",
      "description": "Create a rough estimate for CRM system implementation",
      "activityDate": "2026-01-25",
      "priority": "High"
    }
  ],
  "nextMeeting": {
    "subject": "Proposal Review Meeting",
    "startDateTime": "2026-01-28T14:00:00+09:00",
    "endDateTime": "2026-01-28T15:00:00+09:00",
    "location": "ABC Corporation, Head Office Meeting Room"
  },
  "summary": "Discussed CRM system implementation. Budget is JPY 5 million and they want to implement in the first half of FY2026. Our demo was well received. Proposal and estimate will be prepared, and a review meeting is scheduled for 1/28."
}

πŸ”„ Step 5: Define Parent–Child Relationships with ObjectHierarchy__mdt

A JSON schema alone does not tell you the external-key relationships in Salesforce (i.e., which field links parent and child records). That’s where ObjectHierarchy__mdt is used.

<!-- Task → Opportunity relationship -->
<CustomMetadata>
    <label>Task to Opportunity</label>
    <values>
        <field>SchemaMapping__c</field>
        <value>Meeting_Minutes_Opportunity</value>
    </values>
    <values>
        <field>ObjectApiName__c</field>
        <value>Task</value>
    </values>
    <values>
        <field>ParentObjectApiName__c</field>
        <value>Opportunity</value>
    </values>
    <values>
        <field>RelationshipFieldApiName__c</field>
        <value>WhatId</value>
    </values>
    <values>
        <field>HierarchyLevel__c</field>
        <value>2</value>
    </values>
</CustomMetadata>
HierarchyLevel = 1: Opportunity (root - created first)
                    β”‚
                    β–Ό (Get OpportunityId)
                    β”‚
HierarchyLevel = 2: β”œβ”€β”€ Task (WhatId = OpportunityId)
                    β”œβ”€β”€ Event (WhatId = OpportunityId)
                    └── OpportunityContactRole (OpportunityId = OpportunityId)
                              β”‚
                              β–Ό (If ContactId is needed)
HierarchyLevel = 3:           └── Contact (AccountId = AccountId)
ObjectHierarchy execution order control
Controlling creation order with ObjectHierarchy__mdt

πŸ–₯️ Step 6: Configure Field Mapping with FieldMapping__mdt

JSON Path → Salesforce Field Mapping

<!-- opportunity.amount → Opportunity.Amount -->
<CustomMetadata>
    <label>Opportunity Amount</label>
    <values>
        <field>SchemaMapping__c</field>
        <value>Meeting_Minutes_Opportunity</value>
    </values>
    <values>
        <field>ObjectApiName__c</field>
        <value>Opportunity</value>
    </values>
    <values>
        <field>FieldApiName__c</field>
        <value>Amount</value>
    </values>
    <values>
        <field>JsonPath__c</field>
        <value>opportunity.amount</value>
    </values>
    <values>
        <field>PurposeDescription__c</field>
        <value>Opportunity amount (numbers only)</value>
    </values>
    <values>
        <field>IsRequired__c</field>
        <value>false</value>
    </values>
</CustomMetadata>

Mapping List

JSON Path Salesforce Object Field Required
opportunity.accountName Account Name βœ“
opportunity.name Opportunity Name βœ“
opportunity.stageName Opportunity StageName βœ“
opportunity.amount Opportunity Amount  
opportunity.closeDate Opportunity CloseDate βœ“
contacts[].lastName Contact LastName βœ“
contacts[].firstName Contact FirstName  
contacts[].title Contact Title  
tasks[].subject Task Subject βœ“
tasks[].activityDate Task ActivityDate  
tasks[].priority Task Priority  
nextMeeting.subject Event Subject βœ“
nextMeeting.startDateTime Event StartDateTime βœ“
nextMeeting.location Event Location  

🎬 Step 7: Execution Results

Records created

βœ… Completed: 6 records created

πŸ“Š Opportunity
└─ Name: CRM System Implementation Project
└─ Amount: ¥5,000,000
└─ Stage: Proposal/Price Quote
└─ CloseDate: 2026-06-30

πŸ‘₯ OpportunityContactRole (2)
β”œβ”€ Taro Yamada (Decision Maker)
└─ Hanako Suzuki (Evaluator)

βœ”οΈ Task (2)
β”œβ”€ Send proposal [Due: 2026-01-21] πŸ”΄ High
└─ Create estimate [Due: 2026-01-25] πŸ”΄ High

πŸ“… Event (1)
└─ Proposal Review Meeting [2026-01-28 14:00]

πŸ“ Complete Metadata Structure Diagram

force-app/main/default/
β”œβ”€β”€ customMetadata/
β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β”‚  β”‚              SchemaMapping__mdt                         β”‚
β”‚   β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  β”‚  β”‚ Meeting_Minutes_Opportunity                     β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β”œβ”€ RootObjectApiName__c: Opportunity            β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β”œβ”€ JsonSchemaTemplate__c: {...}                 β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β”œβ”€ ExtractionRules__c: "..."                    β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β”œβ”€ JsonOutputExample__c: {...}                  β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ └─ HtmlTemplate__c: "<div>..."                  β”‚   β”‚
β”‚   β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β”‚  β”‚              FieldMapping__mdt                          β”‚
β”‚   β”‚  β”‚  β”œβ”€ Opportunity_AccountName (→ opportunity.accountName) β”‚
β”‚   β”‚  β”‚  β”œβ”€ Opportunity_Name (→ opportunity.name)               β”‚
β”‚   β”‚  β”‚  β”œβ”€ Opportunity_Amount (→ opportunity.amount)           β”‚
β”‚   β”‚  β”‚  β”œβ”€ Task_Subject (→ tasks[].subject)                    β”‚
β”‚   β”‚  β”‚  β”œβ”€ Task_ActivityDate (→ tasks[].activityDate)          β”‚
β”‚   β”‚  β”‚  β”œβ”€ Event_Subject (→ nextMeeting.subject)               β”‚
β”‚   β”‚  β”‚  └─ ... (other fields)                                  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β”‚  β”‚              ObjectHierarchy__mdt                       β”‚
β”‚   β”‚  β”‚  β”œβ”€ Level1_Opportunity (HierarchyLevel: 1)              β”‚
β”‚   β”‚  β”‚  β”œβ”€ Level2_Task (→ Opportunity via WhatId)              β”‚
β”‚   β”‚  β”‚  β”œβ”€ Level2_Event (→ Opportunity via WhatId)             β”‚
β”‚   β”‚  β”‚  └─ Level2_ContactRole (→ Opportunity via OpportunityId)β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚   β”‚
β”‚   └── ...
β”‚
β”œβ”€β”€ classes/
β”‚   β”œβ”€β”€ SchemaMapper.cls              # Schema generation
β”‚   β”œβ”€β”€ PromptResponseParser.cls      # Parse AI output
β”‚   β”œβ”€β”€ DeclarativeRecordBuilder.cls  # Record builder
β”‚   β”œβ”€β”€ UpsertService.cls             # Database upsert
β”‚   └── DeclarativeRecordAgent.cls    # IAgent implementation
β”‚
└── lwc/
    └── meetingMinutesProcessor/      # UI (LWC)

πŸš€ Key Implementation Takeaways

1. JSON Schema Design Best Practices

{
  "properties": {
    "fieldName": {
      "type": "string",
      "description": "Write clear instructions for the AI",
      "enum": ["Option 1", "Option 2"],
      "format": "date"
    }
  },
  "required": ["RequiredField"]
}

2. Principles for Designing Hierarchy Levels

Level Description Examples
Level 1 Root object (created first) Account, Opportunity
Level 2 Objects directly related to the root Task, Event, Contact
Level 3 Objects related to Level 2 Attachments, comments, etc.

3. Error Handling

// Validation in DeclarativeRecordBuilder
ValidationResult result = parser.validate(jsonData, schemaMappingName);
if (!result.isValid) {
    // Notify users of missing required fields, type mismatches, etc.
    throw new ValidationException(result.errors);
}

🎯 Use-Case Templates

Use Case 1: Email → Lead + Task

{
  "lead": {
    "type": "object",
    "properties": {
      "firstName": {"type": "string"},
      "lastName": {"type": "string"},
      "email": {"type": "string", "format": "email"},
      "company": {"type": "string"}
    }
  },
  "task": {
    "type": "object",
    "properties": {
      "subject": {"type": "string"},
      "priority": {"type": "string", "enum": ["High","Normal","Low"]}
    }
  }
}

Use Case 2: Invoice PDF → Account + Order + OrderItem

{
  "vendor": {
    "type": "object",
    "properties": {
      "name": {"type": "string"},
      "address": {"type": "string"}
    }
  },
  "order": {
    "type": "object",
    "properties": {
      "orderNumber": {"type": "string"},
      "orderDate": {"type": "string", "format": "date"}
    }
  },
  "lineItems": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "productName": {"type": "string"},
        "quantity": {"type": "number"},
        "unitPrice": {"type": "number"}
      }
    }
  }
}

πŸ“š Summary

With Declarative Record Builder, you can:

  • βœ… Code-free: Achieve AI → record transformation using only Custom Metadata configuration
  • βœ… Flexible: Add new fields by changing metadata only
  • βœ… Reusable: Use the same engine across multiple use cases
  • βœ… Maintainable: No need to maintain Apex code
  • βœ… Visible: Configuration is transparent and manageable as metadata

Next Steps

  1. Create SchemaMapping__mdt and define your JSON schema
  2. Configure field mapping in FieldMapping__mdt
  3. Define parent–child relationships in ObjectHierarchy__mdt
  4. Embed DeclarativeRecordAgent into your orchestration
  5. Run a test!