
Building an Autonomous Lead Generation Agent using Eve.dev
Discover how to build an AI sales assistant that scores leads, crafts personalized emails, and uses durable wait states to manage multi-day follow-up sequences using Eve.dev.
Summary
TL;DR: Drip campaigns are static and boring. Learn how to build an autonomous AI sales agent with Eve.dev that researches leads, writes hyper-personalized emails, and durably waits days before following up.
Traditional sales automation tools rely on static email templates and rigid flowcharts. If a prospect replies, the sequence breaks, and a human has to take over.
What if you could build an agent that behaves like an actual Sales Development Representative (SDR)? An agent that looks at a lead's LinkedIn, writes a custom email, waits 3 days, checks if they replied, and writes a contextual follow-up if they didn't?
Eve.dev makes this possible. Because Eve.dev workflows are durable, an agent can naturally "sleep" for days without consuming server resources, waking up exactly when needed with its memory intact.
The Agent Architecture
We will create an Eve.dev agent called sdr.
/eve
/agents
/sdr
instructions.md
/tools
research_company.ts
send_email.ts
wait_days.ts
Step 1: The SDR Instructions
In /eve/agents/sdr/instructions.md, we define the strategy:
# Autonomous SDR
You are a top-performing Sales Development Representative. Your goal is to get prospects to book a meeting.
## Workflow
1. Use `research_company` to find recent news about the prospect's company.
2. Write a highly personalized cold email based on that news and use `send_email`.
3. Use `wait_days` to pause execution for 3 days.
4. After waking up, evaluate if they replied (this context will be provided to you).
5. If no reply, write a shorter, polite follow-up. Do not be pushy.
Step 2: The Multi-Day Wait Tool
This is where Eve.dev shines. We will create a tool that suspends the agent and instructs the underlying system to wake it up later.
Create /eve/agents/sdr/tools/wait_days.ts:
import { tool, suspend } from '@eve/core';
import { z } from 'zod';
export default tool({
name: 'wait_days',
description: 'Pause the campaign and wait for a specified number of days before following up.',
schema: z.object({
days: z.number().min(1).max(14)
}),
execute: async ({ days }) => {
// We calculate the timestamp for when the agent should wake up
const wakeUpAt = new Date();
wakeUpAt.setDate(wakeUpAt.getDate() + days);
// suspend() saves the agent state and stops execution
return suspend({
type: 'scheduled_sleep',
wakeUpAt: wakeUpAt.toISOString(),
message: `Sleeping for ${days} days.`
});
}
});
Step 3: Sending the Email
Create /eve/agents/sdr/tools/send_email.ts:
import { tool } from '@eve/core';
import { z } from 'zod';
// e.g. import { Resend } from 'resend';
export default tool({
name: 'send_email',
description: 'Send an email to the prospect.',
schema: z.object({
to: z.string().email(),
subject: z.string(),
body: z.string()
}),
execute: async ({ to, subject, body }) => {
console.log(`Sending email to ${to}...`);
// await resend.emails.send({ ... });
return { success: true, timestamp: new Date().toISOString() };
}
});
Step 4: The Orchestrator (Cron Job)
Since the agent is suspending itself, how does it wake up? You need a simple background worker or a Cron job that checks the database for sleeping agents whose wakeUpAt time has passed.
import { Eve } from '@eve/core';
const eve = new Eve({ workspace: './eve' });
// This function runs every hour via a Cron job
async function wakeUpSleepingAgents() {
// 1. Query your database for workflows where wakeUpAt <= NOW()
const sleepingWorkflows = await getReadyWorkflowsFromDB();
for (const workflow of sleepingWorkflows) {
const agent = await eve.getAgent('sdr');
// Check if the user replied via your email provider API
const hasReplied = await checkInboxForReply(workflow.prospectEmail);
// Resume the agent with the new context!
await agent.resume({
id: workflow.id,
injectedMessage: hasReplied
? "The prospect replied! STOP the automated sequence immediately."
: "The prospect has not replied yet. It is time to send the follow-up."
});
}
}
Conclusion
With Eve.dev, you aren't just building chatbots; you are building autonomous employees. By using the suspend primitive, your agent can manage complex drip campaigns over weeks. And because it's powered by an LLM, the copy is dynamic, contextual, and deeply personalized—something traditional marketing software simply cannot do.
FAQ
How does Eve.dev remember what it emailed 3 days ago?
When the suspend function is called, Eve.dev serializes the entire conversation history (including the exact email drafted by the LLM) into your database. When the agent resumes, this history is reloaded into the LLM's context window.
What happens if the prospect replies early?
Your email webhook (e.g., from SendGrid or Postmark) can trigger an endpoint that finds the sleeping workflow by ID and calls agent.resume() early, injecting a message like "Prospect replied, stop campaign." This prevents the agent from sending an awkward follow-up.
Related reading
Build an AIOps on-call agent with Eve.dev that triages alerts, runs diagnostics, and gates risky remediation behind human approval—surviving restarts.
Use Eve.dev's multi-agent orchestration to build an accounts-payable pipeline: a supervisor delegates invoice extraction, 3-way matching, and durable approvals.
Learn how to use Eve.dev to build a durable, crash-resistant AI customer support agent that can pause, wait for user input, and resume seamlessly within a Next.js application.
Let's build something great.
Have a project in mind? We are an elite software and AI development studio ready to bring your ideas to production. Let's talk about your roadmap.