Every phone call runs on a turn budget. The speech pipeline has to finish its turn before the caller notices a pause, and n8n is an engine built for steps that are allowed to take seconds. Put those two in the same loop and the caller hears every network hop.
So the design rule we work from is simple: the voice agent owns the audio and n8n owns the business logic, with HTTP as the only thing passing between them. Here's how that split looks when you wire it up, and the one place where it gets tight.
No connector, just HTTP in and out
You don't need a named n8n node for your voice platform. A vendor connector ties your workflows to one platform's event format, and you end up writing a Code node to reshape its fixed payload into what your CRM expects.
Plain webhooks avoid that. In Dograh, an open-source, self-hostable AI voice agent platform, the post-call Webhook node posts a JSON template you write yourself, so you pick every field name and which call detail fills it. n8n receives fields already named the way your CRM names them. If you swap the voice side later, you change a URL and a template and leave the workflow alone. The same wiring works with Zapier or your own backend, since n8n is just a good HTTP citizen here.
Calls going out: one HTTP Request node
On the voice side you add an API Trigger node to the agent. It gets a UUID plus a test URL and a production URL. The production URL only runs a published workflow, so publish first. Create an API key and copy it right away, because the full key is shown only once.
The request n8n sends looks like this (swap in your own instance address):
curl -X POST https://your-dograh-instance/api/v1/public/agent/{uuid} \
-H "Content-Type: application/json" \
-H "X-API-Key: dgr_your_api_key" \
-d '{
"phone_number": "+1415555XXXX",
"initial_context": {
"customer_name": "Jane",
"appointment_date": "March 15"
}
}'
In the HTTP Request node, use Import cURL on the Parameters tab and paste that in. It fills the URL and body for you. Then move the key into a Header auth credential named X-API-Key so it sits in n8n's credential store and not in the node, and map the phone number and context from whatever step fired the workflow.
Anything in initial_context becomes a template variable in the agent's prompts, so {{customer_name}} lets it greet Jane by name. A good response comes back with "status": "initiated" and a workflow_run_id. Keep that ID. It's the join key for everything that happens later. A 401 means a wrong key, and a 404 means the trigger wasn't found, isn't active or hasn't been published.
Results coming back: answer first, work later
When the call ends, the agent's Webhook node posts to your n8n Webhook node. Set the n8n side to POST and set Respond to Immediately. The voice side expects a success reply within 30 seconds, and responding immediately means the CRM update and anything else slow runs after the reply instead of holding it up.
A payload template might look like this:
{
"call_id": "{{workflow_run_id}}",
"first_name": "{{initial_context.first_name}}",
"rsvp": "{{gathered_context.rsvp}}",
"disposition": "{{gathered_context.call_disposition}}",
"duration": "{{cost_info.call_duration_seconds}}",
"recording_url": "{{recording_url}}",
"transcript_url": "{{transcript_url}}"
}
gathered_context is whatever the agent extracted during the call. Variable names have to match your context fields exactly, or they show up as empty strings with no error.
The n8n gotcha that gets almost everyone: the Test URL listens for 120 seconds after you click Listen for Test Event and shows data in the editor, while the Production URL only registers once you publish, and its data lands in the Executions list. Since n8n 2.0, Save and Publish are separate buttons, so hitting Save leaves the live webhook exactly as it was.
Also assume some deliveries go wrong. Failed deliveries with a temporary cause are retried up to five attempts, but a long n8n outage can outlast that, and a wrong URL or credential isn't retried at all. Since you stored the workflow_run_id from the trigger, you can flag any run that never reported back. And the same payload can arrive twice, so dedupe on that ID before writing to the CRM.
The tight spot: n8n as a mid-call tool
This is where the clean split bends a little. The agent can call n8n during the conversation through an HTTP API tool pointed at an n8n production webhook. On the n8n side, set the Webhook node's Respond option to Using 'Respond to Webhook' Node and end the branch with a Respond to Webhook node returning JSON. Write the tool description carefully, because the LLM reads it to decide when to call the tool, and add a preset workflow_run_id parameter so n8n knows which call is asking.
The agent gets back the status code and the data. Anything 400 or above, or no reply in time, is reported to the agent as a failed request, so it won't treat a broken lookup as a real answer.
Here's the cost. In one team's field report, a calendar check through n8n took over a second, and caching it brought repeat checks under 50 ms. The lesson travels: a third-party API call rarely fits inside a conversational turn.
So keep that branch to one fast lookup between the Webhook node and Respond to Webhook. Cache what repeats. Push note-writing and emails to the post-call webhook, where nobody is waiting on the line. If a lookup still runs long, set the tool's Custom Message, a short line the agent says while the lookup runs, so the caller isn't sitting in dead air.
Build order
Wire the post-call webhook first. It's the lowest-risk connection and it shows you real call data straight away. Add the trigger after that. Build the mid-call tool last and time it on a real phone call, since it's the only connection the caller can actually hear.
Both sides can also run on your own servers. Our side is open source under BSD-2, and n8n is fair-code under its Sustainable Use License, which allows use only for your own internal business purposes, or for non-commercial or personal use, so read those terms before building a product on it.
How are you handling the mid-call side? Do you let n8n answer live tool calls, or keep it strictly to events before and after the call?
Self-hosting the model side and the full webhook setup are in our guide to n8n voice agent workflows and webhooks.

Top comments (0)