Cold outreach automation is the process of automatically contacting prospects who have not previously engaged with you, using scripted messages and data-driven targeting. In this guide you will assemble a fully autonomous cold outreach AI agent that pulls leads, crafts a personalized pitch with the Perplexity API, and sends the email through an SMTP server - all orchestrated by n8n. By the end you will have a repeatable workflow that generates leads, writes copy, and delivers messages without manual intervention.
what you need
| Tool | Plan/Price | Role |
|---|---|---|
| n8n (self-hosted) | Community (free) | Workflow engine |
| Perplexity API | Pay-as-you-go (check the provider's current pricing) | AI-generated copy |
| SMTP provider (e.g., SendGrid, Mailgun, or your own server) | Check provider's current pricing | Email delivery |
| Google Sheets (or any CSV storage) | Free tier (subject to Google limits) | Lead list and result logging |
| Docker (for n8n) | Free | Container runtime |
Estimated build time: 3-4 hours, assuming you are comfortable with Docker and API keys.
Key point: n8n's visual node editor lets you wire API calls together without writing glue code, which is why it's the backbone of a low-code cold outreach agent.
how to build cold outreach ai agents: n8n + Perplexity workflow
1. Spin up a self-hosted n8n instance
The quickest way to run n8n locally is with Docker. Open a terminal and execute:
This command pulls the latest n8n image, maps port 5678 to your host, and persists workflow data in ~/.n8n. After the container starts, open http://localhost:5678 in a browser and complete the initial setup wizard.
2. Obtain a Perplexity API key
Visit the Perplexity API documentation and register for an account. Once approved, generate an API key in the dashboard. Store the key in n8n's Credentials store under Perplexity API - use the API Key field and give it a label like PerplexityKey.
3. Create the lead source node (Google Sheets)
Add a Google Sheets node, set the Operation to Read Rows, and point it to a sheet that contains columns company, contact_name, and domain. Use the built-in OAuth2 credentials (create them in the Credentials tab) to grant n8n read access.
Below is a minimal JSON export of that node, which you can import via Import/Export → Import from JSON:
Replace YOUR_SHEET_ID with the ID from the sheet's URL. When the node runs, it outputs an array of lead objects that will feed the rest of the workflow.
4. Generate a personalized pitch with Perplexity
Add an HTTP Request node right after Read Leads. Configure it as follows:
- Method:
POST - URL:
https://api.perplexity.ai/v1/completions - Authentication: Header Auth using the
Bearer {{ $credentials.PerplexityKey }}token. - Headers:
Content-Type: application/json - Body:
JSON(raw) with the prompt that injects lead data.
Here is the JSON body you will paste into the node's Body Parameters field:
The node returns choices[0].text, which is the AI-crafted email body. Map that output to a new variable email_body using n8n's expression editor: {{ $json.choices[0].text }}.
5. Send the email via SMTP
Add an SMTP Email node and link it to the Perplexity node. Fill in the fields:
- SMTP Host: e.g.,
smtp.sendgrid.net(or your provider's host) - Port:
587 - User / Password: credentials stored under SMTP Credentials in n8n.
- From Email:
sales@yourcompany.com - To:
{{ $json.contact_name }} <{{ $json.email }}(assuming the lead sheet also has anemailcolumn) - Subject:
Quick idea for {{ $json.company }} - Text:
{{ $node["Perplexity Request"].json.email_body }}
When the node executes, the email is dispatched to the prospect. n8n logs success or failure in the node's output.
6. Log the outcome back to Google Sheets
Finally, attach another Google Sheets node set to Append Row. Map the fields:
| Column | Value |
|---|---|
| Timestamp | {{ $now }} |
| Company | {{ $json.company }} |
| Contact | {{ $json.contact_name }} |
| Email Sent | {{ $node["SMTP Email"].json.success ? "Yes" : "No" }} |
| AI Copy | {{ $node["Perplexity Request"].json.email_body }} |
This creates an audit trail you can review later. Optionally, you can add a Set node before appending to format dates or sanitize strings.
7. Schedule the workflow
Add a Cron trigger at the top of the canvas to run the entire flow every day at 09:00 UTC. This makes the agent fully autonomous: it wakes, pulls new leads, writes copy, sends mail, and logs results without any human touch.
8. Test end-to-end
Before going live, enable Execute Workflow manually and inspect each node's output. Look for:
- Proper JSON in the Perplexity response (
choices[0].textpresent) - SMTP node returning a 250 OK status
- A new row added to the Google Sheet
Fix any mismatches, then activate the Cron trigger.
where this breaks
Rate limits on the Perplexity API - The free tier (if any) can be very low, and the pay-as-you-go tier charges per 1,000 tokens. If you exceed the limit you'll receive a 429 response. Mitigation: add a Wait node that spaces requests (e.g., 5 seconds) or batch leads to stay under the daily budget.
SMTP authentication failure - Many providers rotate passwords or require domain verification. Symptoms include 535 or 550 errors in the SMTP node's output. Fix: double-check the credential record in n8n, and verify SPF/DKIM settings for your sending domain.
Google Sheets quota exhaustion - The free Google Sheets API allows 500 read/write calls per project per minute. A burst of 200 leads could hit this ceiling. Solution: add a Rate Limit node to throttle to 4 calls per second, or split the lead set across multiple executions.
Token expiry for Perplexity key - API keys may be revoked after 90 days if unused. An expired key returns 401 Unauthorized. Schedule a monthly reminder to rotate the key and update the n8n credential.
Cost blow-up - If you set max_tokens too high or run the workflow hourly, token usage can skyrocket. Track usage in the Perplexity dashboard and set a hard cap in the workflow by adding an If node that checks {{$node["Perplexity Request"].json.usage.total_tokens}} against a threshold.
Email deliverability - Cold emails often land in spam. Ensure you respect CAN-SPAM laws, include an unsubscribe link in the email body, and warm up the sending IP before large-scale sends.