Flightpath is a Salesforce-native product that scans your CRM for the data-quality issues that specifically break Agentforce agents, blank fields, duplicates, stale records, inconsistent picklist values, then auto-fixes the safe ones, routes the risky ones for human approval, and escalates the rest. It runs on its own schedule and reacts to data drift in real time, so it finds and fixes the fields that quietly degrade agent performance before a customer notices the agent giving a bad answer.
The core insight: an Agentforce agent is only as good as the data it reads. Flightpath is the layer that keeps that data agent-ready.
- Why Flightpath
- The three surfaces
- Architecture
- How scoring & classification work
- Data model
- Component inventory
- The employee agent
- Install & deploy
- Configuration reference
- Testing
- Project structure
- Security & safety
- License
Most record-hygiene tooling hard-codes one query per object and reports problems for a human to chase. Flightpath inverts both halves of that:
- All object-specific knowledge lives in Custom Metadata, so a single Apex engine serves Account, Contact, Lead, or anything you configure, with zero per-object code.
- It doesn't just report; it acts. Every issue is classified by risk and either fixed silently, routed through a native Approval Process, or escalated as a pre-populated Task.
- Three surfaces, one brain. A headless engine, an admin app, and a chat agent all read and write the same four objects through the same Apex/Flow layer, so the outcome and the audit trail are identical no matter who acts.
Runs on a schedule and on real-time drift. For every watched object it scores completeness, staleness, and duplicate risk, records per-field risks, then classifies each issue into one of three lanes:
| Lane | What it means | Examples | Action |
|---|---|---|---|
| Auto-Fix | Safe, low-risk, non-destructive | Standardise picklist casing, backfill a blank field from a related record | Executed immediately, no human |
| Approval-Required | Riskier, reversible with judgement | Merge near-duplicate accounts, overwrite a populated field | Routed through a native Salesforce Approval Process (email / mobile) |
| Human-Only | Needs real judgement | Stale record needs re-engagement | Becomes a Task/Case, pre-filled with exactly what's wrong |
Every finding and every fix is written to a record, the record itself is the audit trail, not a separate log.
A dedicated Lightning app so an admin can review and tune everything without touching Setup:
- Flightpath Home, a custom LWC landing page: an SVG score ring, org-wide completeness / freshness / duplicate-safety meters, pending-approval / escalation / auto-applied tiles, and per-object health bars.
- Object Scores / Scan Runs, list views over the raw score and run history.
- Remediations, a custom LWC console to filter by status and approve / reject / inspect before-and-after in place (things a report can't do).
- Config, a friendly editor over
Flightpath_Config__mdt(toggle auto-fix per object, set thresholds) that writes back to custom metadata.
An Agentforce employee agent on top of the same engine, it never duplicates logic, it just gives a person a way to ask and act. Five topics, each backed by a Flow: Check Hygiene Score, Explain Field Risk, Fix This (with a required confirmation before anything destructive runs), Review Pending Remediations, Trend Report. The chat layer never invents data, every answer comes from an action that reads real records.
Schedule / Drift ─► Flightpath_ScanScheduler ─► Flightpath_ScanRunQueueable
│ (one object per chained invocation,
│ governor-safe regardless of object count)
▼
Flightpath_ScanService ──► Object_Score + Field_Risk records
│
▼
Flightpath_RemediationClassifier ─► Remediation drafts (lanes)
│
Flightpath_RemediationService.route()
├─ Auto_Fix ─► auto-fixer runs now (Auto_Applied)
├─ Approval_Required ─► native Approval Process (Pending → Approved)
└─ Human_Only ─► Task escalation (Escalated)
Approved (native email │ console LWC │ chat agent)
└─► Flightpath_Execute_On_Approval (record-triggered flow) ─► executes the fix
Agent / App / Invocables ─► thin Flows (flow://) ─► shared Apex services ─► the 4 custom objects
Approving a remediation, by native email, in the console, or via the agent, all just sets the
record to Approved; a single record-triggered flow then runs the fix. One execution path,
one audit trail.
Scoring (Flightpath_ScanService), per watched object, capped at Max_Records_Per_Scan__c:
- Completeness, for each watched field,
% of records that are non-blank; the object score is the average across fields. - Freshness / staleness,
% of records whose Date_Field__c is within Staleness_Threshold_Days__c. - Duplicate safety, records grouped by
Duplicate_Match_Fields__c;% of records not sharing a key. - Overall, the average of the three,
0–100.
Field-level risks are recorded for blanks, inconsistent picklist spellings (same value, different casing/whitespace), staleness, and duplicate keys.
Classification (Flightpath_RemediationClassifier) maps each risk → lane + fix type:
| Risk | Fix type | Default lane |
|---|---|---|
| Inconsistent picklist | Picklist_Normalize |
Auto-Fix (non-destructive) |
| Blank field | Lookup_Backfill |
Auto-Fix (only fills empties) |
| Duplicate | Duplicate_Merge |
Approval-Required (destructive) |
| Stale | n/a | Human-Only (needs re-engagement) |
The global kill switch and per-object Auto_Fix_Enabled__c can demote any Auto-Fix to Approval.
| Object | Purpose | Key fields |
|---|---|---|
Flightpath_Scan_Run__c |
One row per scan execution | Status, Trigger_Type, Objects_Scanned, Issues_Found, Auto_Fixed/Approval/Escalated counts, Overall_Score |
Flightpath_Object_Score__c |
Per-object health for a run | Completeness / Staleness / Duplicate_Risk / Overall score, Records_Evaluated, Issues_Found |
Flightpath_Field_Risk__c |
Per-field risk detail | Risk_Type, Risk_Score, Blank_Count, Affected_Record_Count, Detail |
Flightpath_Remediation__c |
A proposed or executed fix (the audit trail) | Fix_Type, Lane, Status, Old/New value, Applied_At/By, Escalation_Reference |
| Type | Members |
|---|---|
| Custom objects | The 4 above + Flightpath_Drift_Event__e platform event |
| Custom metadata | Flightpath_Config__mdt (per-object/field guardrails), Flightpath_Global_Settings__mdt (kill switch, cadence) + seed records for Account / Contact / Lead |
| Engine Apex | Flightpath_ScanScheduler, Flightpath_ScanRunQueueable, Flightpath_ScanService, Flightpath_RemediationClassifier, Flightpath_RemediationService, Flightpath_ScoreService, Flightpath_ConfigService, Flightpath_SchemaGuard, Flightpath_AutoFix interface + Flightpath_AutoFix_PicklistNormalizer / _DuplicateMerger / _LookupBackfiller, Flightpath_CDCTriggerHandler |
| Agent-facing | 6 invocables + Flightpath_GetObjectScore / GetFieldRisk / ClassifyAndExecuteFix / ListPendingRemediations / DecideRemediation / GetTrendSummary Flows + Flightpath_Approval_Submit subflow + Flightpath_Execute_On_Approval record-triggered flow |
| Approval | Flightpath_Remediation_Approval process + Set-Approved / Set-Rejected field updates |
| Eventing | Flightpath_Drift_Event__e + trigger (drift alternative/complement to CDC) |
| Agentforce | Flightpath_Agent bundle, router + 5 topics |
| UI | LWCs flightpathScoreBadge, flightpathHomeDashboard, flightpathRemediationConsole, flightpathConfigEditor + controllers Flightpath_HomeDashboardController, Flightpath_RemediationConsoleController, Flightpath_ConfigEditorController; Flightpath app, 5 tabs, 3 flexipages, "All" list views |
| Reporting | Flightpath_Trend_Report, Flightpath_Remediation_Volume_Report, Flightpath_Leadership_Dashboard + 2 custom report types (secondary/export) |
| Security | Flightpath_Admin, Flightpath_Agent_User permission sets |
| Tests | One _Test class per area, 28 methods, ~90% coverage |
Flightpath_Agent (Employee Agent) routes to five topics:
| Topic | Ask it | Backed by |
|---|---|---|
| Check Hygiene Score | "what's my Account object's score?" | Flightpath_Get_Object_Score |
| Explain Field Risk | "why does this blank field matter?" | Flightpath_Get_Field_Risk |
| Fix This | "clean up Account" (confirmation required) | Flightpath_Classify_And_Execute_Fix |
| Review Pending Remediations | "what's waiting for approval?" → approve/reject | Flightpath_List_Pending_Remediations, Flightpath_Decide_Remediation |
| Trend Report | "what's degrading this quarter?" | Flightpath_Get_Trend_Summary |
# 1. Deploy the metadata (report types deploy before the reports that use them)
sf project deploy start -o <your-org>
# 2. Assign permission sets
sf org assign permset -n Flightpath_Admin
sf org assign permset -n Flightpath_Agent_User --on-behalf-of <agent-user>
# 3. Schedule the weekly scan (idempotent)
sf apex run --file scripts/apex/schedule_flightpath.apex- Activate the approval process.
Flightpath_Remediation_Approvalships inactive with a manager-hierarchy approver, activate it and set an approver appropriate to your org, or approval-lane items stayPendingfor manual handling in the console. - Assign permission sets,
Flightpath_Adminto admins,Flightpath_Agent_Userto the agent's running/integration user. - Review config records in the Config tab so watched objects,
Date_Field__c, thresholds and duplicate-match fields fit your org. ShippedDate_Field__c = LastActivityDatemust be queryable on each object. - Pick the "All" list view on the Object Scores / Scan Runs tabs (they default to the empty "Recently Viewed").
- (Optional) real-time drift, enable Change Data Capture on watched objects, or publish
Flightpath_Drift_Event__efrom your own automation.
Deployment notes / gotchas learned the hard way
- Custom report types deploy before reports. A report referencing a report type created in the same deploy fails with
invalid report type; deployreportTypesfirst, thenreports+dashboards.- Custom-metadata records occasionally fail a CLI metadata deploy on some orgs with a detail-less
UNKNOWN_EXCEPTION. If that happens, seed them through the runtime Apex Metadata API instead (theFlightpath_ConfigEditorController.saveConfigpath), a different, reliable code path.- Custom report type field references use the
$separator (Object__c$Field__c), not..
Flightpath_Config__mdt, one row per object (blank Field_API_Name__c) or per field:
| Field | Meaning |
|---|---|
Object_API_Name__c |
Object to scan |
Field_API_Name__c |
Blank = object-level row; set = field-level rule |
Is_Active__c |
Include in scans |
Auto_Fix_Enabled__c |
Allow the Auto-Fix lane for this object |
Date_Field__c |
Field used for staleness (e.g. LastActivityDate) |
Staleness_Threshold_Days__c |
Records older than this are stale |
Drift_Sensitivity_Pct__c |
Drift trigger sensitivity |
Duplicate_Match_Fields__c |
Comma-separated match key |
Watched_Fields__c |
Comma-separated fields to score for completeness |
Flightpath_Global_Settings__mdt.Default, Is_Enabled__c (master kill switch), Auto_Fix_Globally_Enabled__c, Default_Scan_Frequency__c, Max_Records_Per_Scan__c, Min_Score_Alert_Threshold__c.
sf apex run test -o <your-org> --code-coverage --result-format human \
--class-names Flightpath_ScanService_Test Flightpath_AutoFixers_Test \
Flightpath_RemediationService_Test Flightpath_Engine_Test \
Flightpath_Invocables_Test Flightpath_Controllers_Test \
Flightpath_DriftAndScore_Test Flightpath_Coverage_Test28 test methods, all passing, ~90% average coverage across the engine, auto-fixers, invocables, controllers, drift handling, and score/trend logic. Tests build real Account/Contact/Lead data and exercise the full scan → classify → route → execute path.
force-app/main/default/
├── objects/ # 4 custom objects, 2 CMDTs, 1 platform event, list views
├── customMetadata/ # seed config + global-settings records
├── classes/ # engine, services, auto-fixers, invocables, controllers, tests
├── triggers/ # drift platform-event trigger
├── flows/ # 6 action flows + approval-submit + execute-on-approval
├── aiAuthoringBundles/ # Flightpath_Agent
├── lwc/ # 4 components
├── approvalProcesses/ # Flightpath_Remediation_Approval
├── workflows/ # Set-Approved / Set-Rejected field updates
├── applications/ tabs/ flexipages/ # the Flightpath app
├── reports/ reportTypes/ dashboards/ # secondary reporting
└── permissionsets/ # Flightpath_Admin, Flightpath_Agent_User
scripts/apex/ # schedule_flightpath.apex
manifest/ # package.xml
- Injection-safe by construction, every dynamic SOQL/DML identifier passes through
Flightpath_SchemaGuard, which keeps only real, accessible schema names. No user/config string reaches a query unvalidated. - Governor-safe, the scan chains one object per queueable invocation and caps every query at
Max_Records_Per_Scan__c; merges are budgeted per transaction. - Non-destructive by default, only the explicitly destructive lane (merges, overwrites) can be destructive, and it never runs silently.
- Confirmation-gated agent, the "Fix This" action refuses to run without an explicit
confirmedflag. - Least privilege,
Flightpath_Agent_Useris an execute-only permission set for the agent's running user.
MIT © 2026 VurtuoLabs