Architecture¶
The agent has two halves that talk over an authenticated webhook:
- Salesforce — the Lightning app, custom objects, Apex services and the LWC UI. It decides when to enrich and owns the write-back rules.
- n8n — the workflow that does the external research and writes results back into the enrichment objects.
flowchart TB
subgraph SF[Salesforce]
APP[Data Enrichment app\nDashboard · Config · Help]
REC[Lead / Contact / Account]
ENR[LeadEnrichment__c\nContactEnrichment__c\nAccountEnrichment__c]
RUN[EnrichmentRun__c\nrun log]
APEX[Apex services\ncallout + write-back]
end
subgraph N8N[n8n workflow]
WH[Webhook\n/enrichment-agent]
RES[Research nodes\nApify · SerpAPI · Gemini]
NORM[Normalize + map]
end
REC -->|start run| APEX
APP --> APEX
APEX -->|POST data.entity/id\nX-Enrichment-Token| WH
WH --> RES --> NORM
NORM -->|write-back| ENR
ENR -->|accepted values| REC
APEX --> RUN
The request/response contract¶
Salesforce sends a deliberately small payload — just the entity type and record Id. n8n loads the current record itself before enriching, so the request never carries stale field data.
n8n responds fast (HTTP 202/200) and enriches asynchronously, then writes the
result back. The full contract, including recommended source fields per object, is
in Payload contract.
Write-back objects¶
| Source object | Enrichment object |
|---|---|
| Lead | LeadEnrichment__c |
| Contact | ContactEnrichment__c |
| Account | AccountEnrichment__c |
The enrichment object holds everything the agent found. Salesforce trigger logic
then syncs accepted values to the source record and updates the related
EnrichmentRun__c. See the write-back model.
Security¶
- The webhook is protected with a shared-secret header (
X-Enrichment-Token) so only Salesforce can trigger runs. An open webhook would let anyone burn Apify/SerpAPI/Gemini credits. See Webhook authentication. - Access is gated by three permission sets.
- Runtime configuration lives in
OrgSettings__c, so it survives package upgrades and never ships secrets.
Configuration storage¶
| Layer | Stored in | Editable by |
|---|---|---|
| Deploy-time defaults | Custom metadata | Developers (deployment) |
| Runtime behaviour (pause, branding, webhook token) | OrgSettings__c custom setting |
Admins (no deployment) |
| Value translations | DataEnrichmentValueMapping__c records |
Admins (list view) |