AI Voice Agent With n8n + Salesforce troubleshooting

I am following this guide - https://www.youtube.com/watch?v=5j9MVl2ntdA - to automate calls to Leads already existing in Salesforce. I’ve set up the workflow, integrating OpenAI, Retell, and Salesforce, but I’m having inconsistent results in my simple web form submissions that trigger the workflow. Specifically, I receive responses that state the phone number is missing. Ocassionally, it does recognize the phone number, but then says it can’t find any SF Leads associated w/ the number.

Here’s the form code:

<form method="POST" action="[n8n workflow production URL]"><input type="tel" id="phone" name="phone" placeholder="" required data-contact="phone"><input type="submit" value="Submit"</form>

What is the error message (if any)?

Right now, the workflow executes “successfully,” however the resulting response from the Chat Model is either that I havent entered a phone number or that the number isn’t in the Leads database.

My workflow:

Output returned by the last node

I can do that, but I’m missing the required inputs.\n\nPlease provide:\n1) The lead’s phone number (exactly as you have it), and \n2) The note text you want added to the lead.\n\nOnce I have those, I’ll look up the Lead ID by phone number and add the note to that lead in Salesforce.

  • n8n Version 2.3.5
  • Running n8n via browser interface.
  • Mac OS 15.2

Hi, @mroncetwice

It looks like the workflow is technically “working,” but there’s a breakdown in how the data is being passed to the AI.

Here are the three main things you should check:

  1. The “Missing Input” Message That response you’re getting from the Chat Model means the AI thinks it’s in a blank conversation. It doesn’t “see” the phone number from the form automatically. You need to explicitly map it in the AI node.
    The fix: In your n8n AI node, update the prompt to say: “The user just submitted this phone number: {{ $json.body.phone }}. Use this to find the Lead ID.” Without this, the AI is just waiting for someone to tell it the number.

  2. Why Salesforce isn’t finding the Lead If it recognizes the number but says “no lead found,” it’s almost certainly a formatting issue.

Salesforce is very picky. If your Lead in the CRM is stored as +1 555-123-4567 but your web form sends 5551234567 (without the plus or country code), the search will return zero results.
The fix: Try to make sure your form and Salesforce are both using the same format (ideally E.164, like +1234567890).

  1. Check your Webhook node in n8n. Since your HTML form is a standard POST, the data is likely arriving in the body.

Make sure your Salesforce “Find Lead” node is looking at {{ $json.body.phone }} and not {{ $json.query.phone }}.

Quick test for you: Open your n8n Execution Log, click on the Webhook node, and check the “Output” tab. If the phone field is empty there, the issue is the HTML form. If the phone is there but the AI says it’s missing, you just need to update your prompt mapping.

This is great and makes a lot of sense, even to this n00b :slight_smile:

I’ll get to your suggestions and report back.

Thank you!

Glad it makes sense!

If this solves your issue, please mark my response as the solution - it really helps others who might face the same problem find the answer quickly.

Looking forward to hearing your results. Good luck! :rocket:

@tamy.santos

Ugh, so far no good. Here’s what I’ve done since this afternoon:

  1. Changed the Salesforce Lead phone number to E.164 format and ensured it matches in the form submission.

  2. Updated AI Agent to use “Expression” (it was set to “Fixed”), and edited the prompt to only get the Lead ID for now and added the language you suggested, including the JSON object reference.

  3. Toyed with removing and then putting back the Edit Fields node. Doesn’t seem to have changed the output.

  4. Tried changing the Get Lead operation to simply “Get” instead of “Get Many” and tried both “{{ $(‘Webhook’).item.json.body.phone }}” and {{ json.body.phone }} in the Lead ID field (it was set to the AI model previously).

Right now, the typical response is:

”I can’t retrieve the Lead ID from the phone number yet because the phone value wasn’t provided (the placeholder `{{ $json.body.phone }}` didn’t resolve) and the Salesforce leads query returned no data.\n\nSend me the actual phone number (in E.164 like `+15551234567` or whatever format you captured), and I’ll look up and return the matching Lead ID."

… with the occasional one like this:

”I can’t retrieve a Lead ID from that phone number right now because the Salesforce “Get many leads” lookup returned no data.\n\nPlease provide the actual phone number value (in E.164 like `+15551234567`, or the exact format stored in Salesforce), or tell me the lead’s name/email—then I can locate and recite the Lead ID."

Latest workflow:

Just bumping my thread to the top for the (USA) morning crowd :innocent: :hot_beverage::chipmunk:

Sorry @mroncetwice !
I didn’t see your mention before.

The issue isn’t the phone format or the Salesforce query. The problem is that the AI Agent is still part of the Lead resolution path, which makes the workflow non-deterministic.

Fix:
Resolve the Lead before the AI Agent, using only n8n logic and Salesforce nodes.

Recommended flow:

  1. Webhook → extract and normalize phone
  2. Salesforce “Get Many Leads” → filter by Phone, limit 1
  3. IF node → Lead found / not found
  4. AI Agent (last step only) → format the response using the resolved Lead ID

The AI Agent should not reference {{$json.body.phone}}, decide if the Lead exists, or attempt to call Salesforce tools. Its role should be limited to formatting the final message.

Once the Lead ID is resolved outside the agent, the lookup will work consistently.

@tamy.santos Thank you for continuing to help on this :slight_smile:

I’ve tried to follow your latest instructions, but I’m pretty sure I’m not doing it correctly.

The latest responses are pretty similar to before:

I can’t retrieve the Lead ID yet because the phone number value wasn’t actually provided (the message contains the placeholder `{{ $json.body.phone }}`), and the Salesforce leads lookup returned no data.\n\nSend the actual phone number (preferably in E.164 format, e.g., `+14155552671`), and I’ll return the matching Lead ID.

However, I noticed that executing workflow step-by-step after using the Webhook testing URL results in this response from the AI Node:

I can’t tell you a Lead ID from your message alone—I don’t have access to your Salesforce org or any Lead record details.\n\nIf you provide **one of the following**, I can tell you exactly how to get the Lead ID (or interpret it if you paste it):\n\n- The **Lead record URL** from Salesforce (e.g., the address bar link)\n- The Lead’s **Name/Email/Company** you’re looking up (and whether you’re in Lightning or Classic)\n- A screenshot of the Lead record page (redact sensitive info if needed)\n\nFastest way to get it yourself:\n\n**Lightning Experience**\n1. Open the Lead record.\n2. Click the dropdown next …

Here is the latest workflow– I must say it looks way different than the Youtube tutorial I was following :zany_face:

@mroncetwice
In the Edit Fields node, you are currently using: {{ $json.body.phone }}
However, the actual input of this node does not contain body.phone, so this expression never resolves.

Step 1: Inspect the Webhook input

Execute only the Webhook node and check the real JSON payload it receives.

Common examples:

{
  "phone": "+14155552671"
}

or

{
  "data": {
    "phone": "+14155552671"
  }
}

You must confirm this before changing any expressions.

Step 2: Correct the Edit Fields node

In Edit Fields, create a flat, deterministic field:

Field name

phone

Value (expression)
Use the correct path based on the Webhook payload:

{{ $json.phone }}

or

{{ $json.data.phone }}

After this:

  • Do not use body.phone
  • Do not use nested paths downstream
  • From this point forward, always reference:
{{ $json.phone }}

So

Once the phone value is fixed upstream:

  • The Salesforce Get Many Leads node should filter using {{ $json.phone }}
  • Add an IF node to check if a Lead was found
  • Move the AI Agent to the very last step
  • The AI Agent must only format the final response using already-resolved data

The AI Agent should never:

  • Resolve expressions
  • Decide whether a Lead exists
  • Reference {{ $json.body.phone }} or call Salesforce indirectly
1 Like

Thanks, @tamy.santos. You have definitely helped me make a breakthrough in my progress.

The phone field in the webhook output looks like this:

[
{
  
"headers": {
...yada yada...
},
  
"params": {
}, 
  
"query": {
},

"body": {
"phone": "+13456789999"
  
},
...
]

Trying {{ json.phone }} in the Edit node returns a null value when executing the step, whereas {{ $json.body.phone }} correctly returns the phone number entered in the HTML form.

But you were on the money with the Get Lead node— changing the Condition Value to {{ $json.phone }} correctly returns data for the Lead that has the submitted phone number.

And I exposed the AI node to the ID from Get Lead data and reconnected my Add Note node which successfully executed, which I verified in Salesforce.

But I don’t need the AI node to do that, do I? Specifically, I could remove the AI node and go directly to the Add Note node?

___

Here’s the latest workflow for posterity:

@mroncetwice :tada:

I’m really glad to hear that helped , nice progress!!

And yes, you’re right: you don’t need the AI Agent here.
Since the Lead is already found and you have the Lead ID, you can go directly from Get Lead → Add Note.

The AI node is only useful if you want it to generate or transform text. If you’re just adding a note with known data, removing it will make the workflow simpler and more reliable.

Happy to help — and feel free to reach out if you get stuck again.

@tamy.santos

Cool, OK, I’m starting to get the hang of this :grinning_face_with_smiling_eyes:

While this was a success in terms of learning the n8n system and properly executing a workflow, it is far from my end goal. However, the help you’ve provided has given me a better understanding of how to get to that goal.

Thank you so much :raising_hands:

I’m glad I could help, thanks for letting me know :tada: