Validar y enriquecer registros antes de un upsert en CRM con Jitterbit Studio
Introducción
Escribir un registro en un CRM sin validar primero su contenido corre el riesgo de crear entradas duplicadas, almacenar datos incompletos o sobrescribir valores precisos con información obsoleta. Esta guía muestra cómo crear un pipeline de pre-escritura de múltiples etapas que valide campos requeridos, verifique registros existentes para decidir entre crear y actualizar, y opcionalmente enriquezca los datos entrantes con información de contacto de terceros antes del upsert final.
Un segundo patrón añade una puerta de aprobación por LLM para flujos de trabajo agenticos. Cuando un modelo de lenguaje controla la escritura en el CRM, el prompt del sistema aplica un flujo de dos fases (confirmar y ejecutar) para que el modelo siempre solicite aprobación explícita del usuario antes de crear o actualizar un registro. Esto evita que una frase del usuario como "añade este contacto" desencadene una escritura inmediata sin confirmación.
Esta guía utiliza Salesforce como destino CRM y ZoomInfo como fuente de enriquecimiento. Los patrones de validación de campos y verificación de existencia aplican a cualquier conector CRM o API.
Patrón de diseño
El pipeline basado en código se ejecuta secuencialmente. Cada etapa continúa hacia la siguiente o genera un error antes de llegar a la escritura:
required fields"] --> B["Check for
existing record
(SfLookupAll)"] B --> C{"Record
exists?"} C -- Yes --> D["Enrich
(ZoomInfo)"] C -- No --> D D --> E{"Create or
update?"} E -- Create --> F["Salesforce
Create activity"] E -- Update --> G["Salesforce
Update activity"]
La puerta de aprobación por LLM envuelve la etapa de ejecución en flujos de trabajo agenticos:
(create/update)"] --> B["LLM checks
conversation history"] B --> C{"Prior approval
request made?"} C -- No --> D["confirm_create_contact
(ask for approval)"] C -- "Yes + approved" --> E["execute_create_contact
(write to Salesforce)"] C -- "Yes + rejected" --> F["process_response
(inform user)"]
Parte 1: Validar campos requeridos
Antes de consultar o escribir en Salesforce, confirma que el registro entrante tiene los campos mínimos necesarios para identificar y crear un contacto. Para un Lead de Salesforce, los campos requeridos suelen ser correo electrónico, nombre y apellido. Rechaza de inmediato los registros que carezcan de alguno de estos campos para evitar escrituras parciales o no identificables.
Paso 1: Escribe el script de validación de campos
Añade un paso Script al inicio de la operación de pre-escritura. El script verifica cada campo requerido, acumula los mensajes de campos faltantes y genera un error si el registro no puede continuar:
// Validate required fields before any CRM operation
$errors = "";
If(Length(Trim($lead.email)) == 0,
$errors = $errors + "Email is required. ";
);
If(Length(Trim($lead.firstName)) == 0,
$errors = $errors + "First name is required. ";
);
If(Length(Trim($lead.lastName)) == 0,
$errors = $errors + "Last name is required. ";
);
If(Length($errors) > 0,
RaiseError("Record validation failed: " + $errors)
);
// Normalize the email address before the lookup
$lead.email = ToLower(Trim($lead.email));
WriteToOperationLog("Required field validation passed for: " + $lead.email);
Trim elimina espacios en blanco al inicio y final. Normalizar el correo electrónico a minúsculas antes de la búsqueda evita discrepancias sensibles a mayúsculas/minúsculas al comparar con registros de Salesforce.
Paso 2: Verifica el formato de correo electrónico
Para detectar direcciones mal formadas antes de que lleguen a Salesforce, añade una verificación de formato usando RegExMatch:
If(!RegExMatch($lead.email, "^[^@]+@[^@]+\\.[^@]+$"),
RaiseError("Invalid email format: " + $lead.email)
);
Esta verificación detecta errores obvios de formato (falta el símbolo @, falta el dominio) sin rechazar direcciones válidas que contengan caracteres inusuales.
Parte 2: Verificar registros existentes
Después de la validación, consulta Salesforce para determinar si ya existe un registro con el mismo correo electrónico. El resultado controla si la operación posterior crea un nuevo registro o actualiza el existente.
Paso 1: Consulta Salesforce para un lead coincidente
Utiliza SfLookupAll para buscar un lead con la misma dirección de correo electrónico. SfLookupAll devuelve un array bidimensional: cada array interno es una fila coincidente, y cada elemento es un valor de campo en el orden especificado en la consulta.
Añade un paso Script después del script de validación:
// Query Salesforce for an existing lead by email
$sf.existingLeadId = "";
$result = SfLookupAll(
"<TAG>endpoint:salesforce/Salesforce</TAG>",
"SELECT Id FROM Lead WHERE Email = '" + $lead.email + "' AND IsConverted = false LIMIT 1"
);
If(Length($result) > 0,
// Row 0, column 0 is the Id field
$sf.existingLeadId = $result[0][0];
WriteToOperationLog("Existing lead found: " + $sf.existingLeadId);
,
WriteToOperationLog("No existing lead found for: " + $lead.email);
);
LIMIT 1 evita que el array de resultados contenga múltiples coincidencias si el mismo correo electrónico aparece más de una vez, lo que puede suceder en datos CRM con duplicados históricos. Para el patrón de consulta SOQL, consulta Consultar registros de Salesforce usando SOQL.
Paso 2: Configura la variable de enrutamiento
Después de la búsqueda, configura una variable que las operaciones posteriores usan para ramificar hacia la actividad de escritura correcta:
If(Length($sf.existingLeadId) > 0,
$sf.operation = "update";
,
$sf.operation = "create";
);
En el script del controlador u operación descendente, verifica sf.operation para llamar a la actividad de Salesforce apropiada. Para obtener orientación sobre cómo ramificarse entre operaciones basadas en una variable, consulta Administrar flujos de trabajo usando scripts de controlador.
Parte 3: Enriquecer el registro antes de escribir
Con los campos requeridos validados y la decisión de crear o actualizar tomada, opcionalmente enriquece el registro entrante con datos de contacto adicionales de una fuente de terceros antes de la escritura. Este paso completa los campos faltantes e identifica valores que pueden haber cambiado desde la última sincronización.
Paso 1: Llamar al enriquecimiento de ZoomInfo
Si el registro tiene un nombre de empresa asociado, utiliza ZoomInfo para recuperar el puesto de trabajo actual del contacto, número de teléfono directo y correo electrónico. Para la configuración completa de integración de ZoomInfo, incluida la autenticación y el enrutador de recursos, consulta Enriquecer datos de contacto usando ZoomInfo.
Después de ejecutar la operación de enriquecimiento de ZoomInfo, aplica los valores devueltos a las variables de preparación, preservando cualquier valor ya presente en el registro entrante:
// Apply enrichment results — fill gaps only, do not overwrite existing values
If(Length(Trim($zoom.enriched.phone)) > 0 && Length(Trim($lead.phone)) == 0,
$lead.phone = $zoom.enriched.phone
);
If(Length(Trim($zoom.enriched.title)) > 0 && Length(Trim($lead.title)) == 0,
$lead.title = $zoom.enriched.title
);
La If protege cualquier valor que el sistema de origen ya haya proporcionado. El enriquecimiento de ZoomInfo completa las brechas en lugar de sobrescribir datos.
Paso 2: Detectar valores de campo obsoletos en registros existentes
Al actualizar un registro de Salesforce existente, compara los valores enriquecidos contra los valores almacenados para identificar campos que han cambiado. Registra cualquier discrepancia para que las operaciones descendentes puedan decidir si aplicar el valor actualizado:
// Compare enriched title against the Salesforce stored value
If($sf.operation == "update"
&& Length(Trim($zoom.enriched.title)) > 0
&& $zoom.enriched.title != $sf.existing.title,
WriteToOperationLog(
"Title change detected for " + $lead.email
+ ": Salesforce has [" + $sf.existing.title + "]"
+ ", ZoomInfo has [" + $zoom.enriched.title + "]"
);
$lead.titleChanged = true;
);
Si aplicar el nuevo valor o marcarlo para revisión manual depende de tus reglas comerciales. El principio clave es comparar antes de sobrescribir para que una fuente de enriquecimiento no reemplace silenciosamente datos precisos.
Paso 3: Ejecutar la operación de escritura
Pasa el registro validado y enriquecido a la operación de escritura de Salesforce. Utiliza sf.operation para llamar a la operación correcta:
If($sf.operation == "create",
RunOperation("<TAG>operation:Salesforce - Create Lead</TAG>");
,
RunOperation("<TAG>operation:Salesforce - Update Lead</TAG>");
);
Para ambas operaciones, utiliza una transformación que asigne variables $lead.* a los campos de Lead correspondientes en Salesforce. Para la operación de actualización, también asigna sf.existingLeadId al campo Id para que Salesforce pueda identificar qué registro actualizar.
Parte 4: Implementar una puerta de aprobación con LLM
En flujos de trabajo con agentes donde un modelo de lenguaje procesa solicitudes del usuario y las enruta a operaciones de escritura en CRM, añade un flujo explícito de dos etapas: confirmar y luego ejecutar. La puerta de aprobación asegura que la intención del usuario de crear o actualizar un contacto siempre se confirme antes de la escritura. Una afirmación como "añade este contacto" no cuenta como aprobación por sí sola.
Este patrón utiliza la invocación de funciones de LLM para enrutar entre etapas. Para una introducción al llamado de funciones en Studio, consulta Enrutar respuestas de LLM a operaciones de Studio usando invocación de funciones.
Paso 1: Definir las reglas de aprobación en la indicación del sistema
Añade una sección de reglas de aprobación a la indicación del sistema que instruya al modelo sobre cómo determinar si se ha otorgado aprobación explícita. Incluye este texto como un bloque distinto dentro del mensaje del sistema, antes de la descripción de las funciones disponibles:
Approval rules (important):
- A user request to "clean", "update", "create", "add", or "insert" contacts does NOT
count as approval by itself.
- Approval is valid ONLY IF:
a) The assistant explicitly asked for confirmation to create or update a contact
in a previous message, AND
b) The user responded with a clear approval phrase such as: "yes", "proceed",
"approved", or "go ahead".
- If the assistant has NOT asked for confirmation previously, you MUST select
"confirm_create_contact" or "confirm_update_contact" depending on whether the
action is a create or an update.
- If the assistant previously asked for confirmation and the user responds with
"no", "not approved", or "do not create", route to "process_response".
La distinción entre "solicitado" y "aprobado" es la regla clave. El modelo verifica el historial de conversación para determinar cuál es el caso en cada turno.
Paso 2: Definir las funciones de enrutamiento
Registra cuatro funciones de enrutamiento en el manifiesto de herramientas que se pasa al LLM:
| Nombre de función | Cuándo llamar |
|---|---|
confirm_create_contact |
El usuario ha solicitado una creación pero el modelo aún no ha pedido confirmación en esta conversación. |
confirm_update_contact |
El usuario ha solicitado una actualización pero el modelo aún no ha pedido confirmación en esta conversación. |
execute_create_contact |
El modelo anteriormente pidió confirmación Y el usuario ha dado aprobación explícita. |
execute_update_contact |
El modelo anteriormente pidió confirmación Y el usuario ha dado aprobación explícita. |
Describe cada función claramente en el manifiesto. Las descripciones de las funciones tienen el mismo peso que las reglas del prompt del sistema cuando el modelo decide qué función llamar.
Paso 3: Asignar las respuestas de enrutamiento a operaciones de Studio
En el script del controlador que se ejecuta después de cada respuesta del LLM, extrae el function_name de la llamada de herramienta y ejecuta la operación correspondiente:
$route = TrimChars(
GetJSONString($jitterbit.response, "/choices/[0]/message/tool_calls/[0]/function/name"),
"\""
);
Case(
$route == "confirm_create_contact",
RunOperation("<TAG>operation:LLM - Confirm Create Contact</TAG>");
,
$route == "confirm_update_contact",
RunOperation("<TAG>operation:LLM - Confirm Update Contact</TAG>");
,
$route == "execute_create_contact",
RunOperation("<TAG>operation:Validate and Enrich Lead</TAG>");
RunOperation("<TAG>operation:Salesforce - Create Contact</TAG>");
,
$route == "execute_update_contact",
RunOperation("<TAG>operation:Validate and Enrich Lead</TAG>");
RunOperation("<TAG>operation:Salesforce - Update Contact</TAG>");
,
true,
RunOperation("<TAG>operation:LLM - Process Response</TAG>");
);
La operación Validate and Enrich Lead ejecuta la canalización de validación y enriquecimiento de campos (Partes 1–3) antes de la escritura en Salesforce. Separar la validación del script de enrutamiento hace que el paso de validación sea reutilizable fuera del contexto del agente.
Paso 4: Incluir el historial de conversación en cada llamada al LLM
La puerta de aprobación depende de que el modelo sepa si ya ha solicitado confirmación en la conversación actual. Para que las reglas de aprobación funcionen correctamente, cada llamada al LLM debe incluir el historial de conversación completo en el array messages, no solo el mensaje actual del usuario.
Para conocer el patrón usado para acumular y almacenar el historial de conversación entre ejecuciones de operaciones, consulta Construir un chat LLM multiturno con historial de conversación.
Verifica la integración
-
Ejecuta la canalización previa a la escritura con un registro de prueba que no tenga dirección de correo electrónico. Confirma que el script de validación genera un error y que la operación de escritura en Salesforce nunca se llama. Consulta los operation logs para ver el mensaje de error.
-
Ejecuta la canalización con una dirección de correo electrónico válida que coincida con un cliente potencial existente en Salesforce. Confirma que
sf.existingLeadIdse completa y quesf.operationse establece enupdate. -
Ejecuta la canalización con una dirección de correo electrónico que no tenga un registro coincidente en Salesforce. Confirma que
sf.existingLeadIdesté vacío y quesf.operationse estableza encreate. -
Si usas enriquecimiento de ZoomInfo: ejecuta el paso de enriquecimiento para un contacto conocido y confirma que
zoom.enriched.phoneyzoom.enriched.titlese completan antes de que se ejecute la operación de escritura en Salesforce. -
Para probar la puerta de aprobación del LLM: envía al agente un mensaje como "create a contact for Jane Smith at Acme Corp". Confirma que el modelo enrute a
confirm_create_contacten lugar deexecute_create_contact. -
Responde al mensaje de confirmación con "yes, go ahead" y confirma que el modelo enrute a
execute_create_contacten el siguiente turno. -
Para probar el rechazo: después de que el modelo solicite confirmación, responde con "no, don't create it". Confirma que el modelo enrute a
process_responsey que la operación de escritura en Salesforce no se llame.