A contact panel says “saved.” The CRM now contains an email address. That still leaves an important question unanswered: which existing record did the handoff select, and which fields did it change?
The gap matters when a person is already in your CRM. An enrichment result might propose a different employer, replace a manually reviewed field, or create a second contact. A successful request does not establish that the final record matches the researcher's intention.
Design the handoff around an explicit change proposal and a readback of the destination. The examples below describe an application-side integration with fictional records. They are not a test of an extension, a CRM connector, or a live contact lookup.
Resolve the destination before proposing a write
Give the research item an internal identifier and keep it through the handoff. Separately record the CRM contact identifier you intend to update. These identifiers serve different purposes: one tracks the research work, while the other identifies the destination record.
Do not resolve the destination from a display name alone. If your matching process produces several candidates, pause the write and ask for review. Keep the candidate references so the reviewer can explain the selection.
Creating a new contact should be an explicit disposition, not the automatic fallback for an uncertain match. Otherwise, every matching failure can become a duplicate that somebody must clean up later.
Represent the proposed changes field by field
Preserve the incoming observation separately from the current CRM value. Then define the exact changes the application is allowed to make. For example, you might allow adding a source note while protecting an existing employer association from automatic replacement.
Here is a fictional proposal for that narrow operation:
{
"handoff_id": "handoff-example-12",
"research_item_id": "research-example-31",
"target_contact_id": "crm-example-77",
"target_revision": "revision-example-4",
"operation": "update_existing",
"changes": {
"research_source_note": "Approved company page reviewed"
},
"protected_fields": ["employer_id", "primary_email"],
"state": "proposed"
}
The revision field is an application contract, not a claim that every CRM supplies native revision tokens. Use the destination's documented concurrency mechanism where available. If the interface cannot prevent a conflicting update reliably, keep sensitive or destructive field replacements behind manual review.
A small proposal is easier to inspect than an entire enriched contact object. It also makes omissions meaningful: a field absent from the proposal should not be cleared merely because a provider returned an empty value.
Check the current record again before applying
Between research and delivery, another operator may edit the contact. Compare the current destination with the version used to prepare the proposal. If a relevant field changed, invalidate the proposal and regenerate it from the new state.
Where conditional writes are supported, use them to enforce the comparison at write time. A preliminary read followed by an unconditional update still leaves a race window. Do not describe that pattern as protection against simultaneous edits.
Keep the review boundary visible. “The address was found” and “this field replacement was approved” are separate decisions, even when one person performs both.
Read back the fields that define success
After an acknowledged write, read the selected destination record. Verify its identifier, the fields in the change proposal, and any protected fields your acceptance contract requires to remain intact. Record the observed values and the time of the check.
| Observation | Handoff state | Next action |
|---|---|---|
| Intended record contains the approved change | Verified | Close the handoff |
| Request acknowledged but record is not yet readable | Awaiting readback | Check within a bounded window |
| Destination identifier differs | Needs review | Stop further writes |
| Approved field differs from the proposal | Needs review | Inspect mapping and concurrent edits |
| Request timed out with an unknown result | Outcome unknown | Inspect the destination before retrying |
Some destinations may expose changes after a delay. Define a bounded readback window and an owner for unresolved outcomes. An exhausted window should produce a visible exception, not an automatic claim of success or an endless polling job.
Make retries refer to the same intention
Reuse the handoff identifier while resolving an uncertain result. Do not create a fresh logical operation just because the network request timed out. If the destination supports idempotency keys, use its documented mechanism; otherwise, the application must inspect the current record before deciding whether another write is appropriate.
That inspection needs to consider side effects too. Repeating an update that sets the same field might still trigger a notification, an activity entry, or a downstream workflow. Equal final values do not prove that duplicate execution is harmless.
Test the handoff design with an existing contact, an ambiguous match, a concurrent edit, and a timeout after a write. Check the destination evidence for each case rather than judging only the connector's response message.
Our email finder extension comparison starts from the full research-to-delivery task. This design focuses on the last boundary: turning a proposed contact change into a specific, verified CRM result.
The useful completion record names the destination, the approved change, and the observed outcome. A “saved” animation cannot substitute for those three facts.
Top comments (0)