Nothing in this group decides anything on its own judgment: the conditions and field maps you configure do that. The one exception is the optional Let AI pick the best match mode inside Search Salesforce records.

All four write steps show a Writes to Salesforce badge in the inspector and a red upload icon on the canvas card, and all four pause according to the workflow's Review policy. Each also offers Require approval for this write (or for this delete), which holds that one step for a person even when the workflow otherwise runs straight through. A step carrying it shows a Requires approval badge on its card. That setting can only add a hold; it never removes one the policy already requires.

Find a Salesforce record

Query records by conditions (like Flow's Get Records).

The exact-match lookup, and the one to reach for first. Fully deterministic: no AI is involved, so the same inputs always find the same record, in the same order, every time.

When to use it: the document carries a clean identifier that exists on your records: an account number, an external ID, an exact name. It's also the right step when the run already knows exactly which record it's about, because a Flow passed the Id in on the launch form.

  1. Choose a Salesforce object (any object you can read).
  2. Choose Condition logic: All conditions (AND), Any condition (OR), or Custom logic (reveals a Custom logic box for something like 1 AND (2 OR 3)).
  3. Click Add condition to add a row: a Field, an operator, and a Value or a ref. The value box hides for the two null operators. You need at least one condition, or you'll see Add at least one condition. To look up the record the run was launched against, set the field to Id, the operator to equals, and the value to the launch-form field carrying that Id, inserted from the reference picker as trigger.<field_name>.
  4. Optionally set a Sort field and Ascending / Descending direction. Leaving the field empty keeps results unsorted; this matters when you're returning only the first record.
  5. Under Records to return, choose Only the first record (default) or Multiple records, which reveals Max records (1–50, default 10).
  6. Under Return fields, add every field from the matched record that later steps need to read. Type a field's API name into Add a field to return and it appears in the list beneath, each entry with its own delete icon so you can drop one later. Id is always returned whether you list it or not. Anything you don't list here is simply not available downstream.

Operators: equals, not equals, greater than, greater or equal, less than, less or equal, contains, starts with, ends with, is null, is not null. (A Decision step's branch conditions cover similar ground under different names; see the operator table in Logic.)

Produces: the matched record (or a list, in Multiple mode), a match count, and an outcome to branch on. Inline warnings catch missing setup: Choose a Salesforce object. · Condition 2 needs a field. · Condition 2 needs a value.

A Find a Salesforce record step, with a single Id-equals-trigger-field condition and its inspector open.
A Find a Salesforce record step, with a single Id-equals-trigger-field condition and its inspector open.

Choosing your return fields

Return fields is not an optimization: it's the list of things this workflow is able to check. Every value the run will later compare the document against, write into a note, or branch on has to be requested here first. The inspector spells out the contract underneath the list: Id is always returned and is read as record.Id, and any extra fields you add from the matched record are read by later steps as record.FieldName.

So work backwards from the checks you intend to run: list the checks, then request one field per check. A review that verifies four things about a record requests exactly those four fields on the lookup: the name the document should carry, the amount it should agree with, the date it should fall within, and the status that decides whether it qualifies at all. Anything the run only needs in order to write the outcome (the record's Id) is already there.

Two things follow from this:

  • A field you forgot to request doesn't produce an error at build time; it just never shows up as a chip in the Values you can use here panel, and the step that needed it has nothing to compare against. If a comparison step looks like it has no reference available for the field you want, the lookup above it is where to fix it.
  • Requesting a field you never use costs nothing but noise in the picker. Prune the list rather than requesting every field on the object.

Reading the matched record later

Every value the lookup produced becomes a chip in the picker, grouped under that step's display name and its monospace reference name: Find a Salesforce record sf_getRecords_1. The group's count badge tells you how many values it holds: the requested fields, plus Id, plus the match count and the outcome. A lookup returning five fields shows a count of eight.

The reference shape is <step_ref>.record.<FieldName>:

  • sf_getRecords_1.record.Id: the matched record's Id, which is what you bind under Record to update on a later write step.
  • sf_getRecords_1.record.<FieldName>: any field you requested, ready to drop into a question, a condition, or a field map.

In Multiple records mode you get a list rather than a single record, so read it with a For each loop and reference the loop item's fields instead.

A workflow can hold as many lookups as it needs, and a later lookup can query on a field an earlier one returned. Put a second Find a Salesforce record step below the first, then bind its condition value to sf_getRecords_1.record.<FieldName> from the picker. That's how you walk from the record the document arrived on to its parent, or to a related record holding the rest of the values you want to check. Each lookup gets its own chip group (sf_getRecords_1, sf_getRecords_2, …), so there's never any ambiguity about which record a reference came from.

Once the fields are available, the comparison itself happens in an Ask the document step; see Comparing a document against a Salesforce record in Read documents (AI).

Several matches is not an error in "Only the first record" mode

The step takes the first row by your sort order when several conditions match, which is why leaving Sort empty makes "the first record" arbitrary. If you need "the right one out of several, judged on context," use Search Salesforce records with Let AI pick the best match instead.

Search Salesforce records

Fuzzy prefix search over a Salesforce object.

The tolerant lookup. Runs a prefix-based search across an object's name fields (or all searchable text fields), forgiving the small differences that break exact matching: "Acme Corp." on a document against "Acme Corporation" in Salesforce.

When to use it: the document carries a name or label that won't match your records character for character.

  1. Choose a Salesforce object (any searchable object).
  2. Under Search term, bind the value to search for (placeholder A value or a ref like ask_the_document_1.answer), normally something an earlier AI step read off the document.
  3. Under Return fields, add any fields beyond Id you want on each matching record.
  4. Choose a Search scope: Name fields (default) or All fields.
  5. Leave Let AI pick the best match off to get the full list of matches back and decide in a later step, or turn it on to have the AI resolve a single record (see below).

A Search Salesforce records step with its search term bound to an earlier AI step's answer.
A Search Salesforce records step with its search term bound to an earlier AI step's answer.

How it matches, mechanically: the search term is split on spaces, tokens shorter than two characters are dropped, and each remaining token is matched as a prefix against the search scope.

Produces: a match count and the list of records, at most 20 per object. The list carries the list tag in the picker, so it can feed a For each loop.

A blank or too-short search term returns zero matches rather than failing

Always branch on match count instead of assuming a search hit. A search step "succeeding" with zero results looks identical to one that never had anything to find.

Let AI pick the best match

The same fuzzy search, with one checkbox turned on and an instruction added. This is the only place in the group where AI decides which record matched.

When to use it: several candidates could plausibly match, and picking the right one depends on judgment a fixed rule can't express.

  1. Turn on Let AI pick the best match.
  2. Fill in How should the AI choose? (placeholder e.g. the account whose name best matches {{extractInvoice.vendor}}). Be specific: this is the only guidance the AI has to break a tie.
  3. Under Documents in scope, choose which documents the AI may read while deciding.

A Search Salesforce records step with
A Search Salesforce records step with "Let AI pick the best match" turned on and an instruction field filled in.

Produces: everything the fuzzy match produces, plus the resolved record, whether it picked one, and its confidence. The AI is allowed to abstain: if it can't confidently choose, it picks nothing and reports that it did not pick, rather than guessing. Branch on picked before assuming there's a record to write to.

Choosing a matching strategy

Which lookup to reach for depends on what the document carries, and on whether you can give the AI an instruction specific enough to break a tie. The table below compares the four routes.

What the document containsWhat you know at run timeUse
A unique identifier that exists on your recordsNothing else neededFind a Salesforce record
A company or person name only, close but not identical to your recordsNothing else needed; a single top match is good enough to use directlySearch Salesforce records
A name that could plausibly match more than one recordAn instruction specific enough for the AI to break the tie bySearch Salesforce records + Let AI pick the best match
A name that could plausibly match more than one recordNothing else needed, but you'd rather branch on the result yourself than let AI pickSearch Salesforce records, then a Decision on the returned list
Handling no match and multiple matches

Both matching steps succeed even when nothing matches: a lookup finding zero records is a valid outcome, not an error, and neither step throws. Always follow a matching step with a Decision step on its match count or outcome, rather than assuming a downstream write step has something valid to act on. A typical pattern:

  • Match count equals 1 (or AI picked equals true) → continue to update the matched record.
  • Match count equals 0 (or the outcome shows no match) → continue to create a new record instead.
  • Match count is greater than 1 and you're not using AI picking → route to a step that flags the run for a person, rather than guessing which one is right.

Create Salesforce record

Write a new record. Maps step values onto object fields.

  1. Choose a Salesforce object (placeholder e.g. Contact). Only objects you can create are listed.
  2. Build the Field map. It starts empty, with nothing but a + Add field link: click it to add a row, then pick a Field and supply a Value or ref for it. You need at least one row that resolves to a value, or the step fails with "no field values resolved."
  3. Optionally turn on Require approval for this write; its helper text says the write is held for a person to approve even when the workflow otherwise runs straight through.

Produces: the new record's Id and a created flag.

A Create Salesforce record step, showing the
A Create Salesforce record step, showing the "Writes to Salesforce" badge, the object field, and an empty field map with its "+ Add field" link.

Update Salesforce record

Update an existing record by id. Maps step values onto object fields.

  1. Choose a Salesforce object; only updatable objects are listed.
  2. Under Record to update, bind the target by clicking a ref chip or typing an Id. This is usually the Id from an earlier lookup step (sf_getRecords_1.record.Id), or the record the workflow launched from. Required: Choose the record to update.
  3. Build the Field map, same as Create. Only fields that resolve to a value are sent, so a blank never clears anything.
  4. Optionally turn on Require approval for this write.

Produces: the record's Id and an updated flag.

An Update Salesforce record step with Record to update bound to an earlier lookup's record Id, a field map of three fields set to literal values, and After this step set to End the run.
An Update Salesforce record step with Record to update bound to an earlier lookup's record Id, a field map of three fields set to literal values, and After this step set to End the run.

A field map row's value can be a fixed string as easily as a reference, which is what lets each outcome of a Decision have its own write step. An outcome step's map is often just two rows: the status field set to a literal status, and a notes field set to the literal reason. Because the reason is baked into that step rather than computed, a person reading the record later sees exactly which branch the run took.

Delete Salesforce record

Delete an existing record by id. Irreversible in Salesforce beyond the recycle bin.

  1. Choose a Salesforce object (placeholder e.g. Contact). Only deletable objects are listed.
  2. Under Record to delete, bind the target record: the inspector tells you to click a ref chip or type an id, and notes that the record goes to the Salesforce recycle bin. Leave it empty and the red Choose the record to delete. appears immediately.
  3. Optionally turn on Require approval for this delete; the helper text explains that the delete is held for a person to approve even when the workflow otherwise runs straight through.

There's no field map: a delete only needs a target.

Produces: the record's Id and a deleted flag.

A Delete Salesforce record step with an unbound Record to delete field showing the
A Delete Salesforce record step with an unbound Record to delete field showing the "Choose the record to delete." validation message.

The deleted record lands in the Salesforce recycle bin, so it's recoverable there for as long as your org retains it, but nothing in the workflow can put it back, and once the bin is emptied it's gone. Treat a delete as irreversible when you're deciding whether to force an approval on it.

Two safety checks run automatically: the bound Id has to actually look like a Salesforce record Id (15 or 18 characters), and it has to belong to the object you chose; pointing an Account delete at a Contact Id refuses and deletes nothing. Deleting an already-gone record is treated as a success, since the goal state ("gone") was already true.

Create Salesforce records (bulk)

One record per item in a list, in a single bulk write. One approval gates the whole batch.

  1. Choose a Salesforce object (placeholder e.g. OrderItem).
  2. Under Records source, bind the list you want one record created from each item of; the inspector asks you to click a 'list' chip below, or type a reference. This must reference an actual list, normally a list of items field from an Extract step, whose reference takes the form ai_extract_1.line_items.value (the field name plus .value), which is also the field's placeholder text. The builder shows the item shape when it knows it, for example "Each item has: description, quantity, unit_price."
  3. Build the Field map: each row's source is either a value from the current item (item.unit_price, inserted via the Item fields chips) or a fixed value or reference applied to every record, for example setting a parent Id on every row.
  4. Optionally set Max records: labelled Max records (optional), placeholder and default 1000, hard ceiling 2000.
  5. Optionally turn on Require approval for this write. Note the helper differs from the single-record steps: it says the whole batch is held for a person to approve, and one approval releases all the records.

A Create Salesforce records (bulk) step, showing the Records source field, the field map, Max records, and the batch-level approval checkbox.
A Create Salesforce records (bulk) step, showing the Records source field, the field map, Max records, and the batch-level approval checkbox.

Warnings catch bad wiring: "The records source must be a reference to a list (not a typed value)." · a warning that "quantity" is a number rather than a list, so the records source must be a list of items · "'Amount' reads item.total, but 'total' isn't a field of the extracted items."

Produces: a list of created record Ids (with a gap where a record failed), a success count, a failure count, and per-row failure reasons.

Partial success is a success

If 48 of 50 line items save and 2 are rejected by Salesforce, the step completes and reports 48 successes and 2 failures with the reason for each. It only fails outright if the list is empty, over the cap, or every single record was rejected. Add a Decision on the failure count if a partial result should change what happens next.

Bulk create vs. a loop

Both can write one record per item. Prefer Create Salesforce records (bulk) when the only thing you do per item is write it: it's a single write, and a single approval. Use a For each loop when each item needs its own reading, checking, or branching before anything is written.

  • Workflows: creating the workflow, the launch form, references, validating and publishing.
  • Read documents (AI): the steps that produce the values these lookups match against.
  • Logic: the Decision and For each steps that route and repeat around these lookups and writes.