How to Build an AI SDR Agent
in 60 Lines of Code.
Most AI-SDR tutorials are 500 lines of glue code. Four vendors, three SDKs, ten environment variables, two webhook handlers, a Postgres table to track state. By line 200 you've forgotten what you were building.
Here's the real architecture in 60 lines. Funding signal in, personalized email out. Working code you can paste into a Node project and run today.
What's in this post
The architecture
Every AI SDR agent that actually works has the same four-step loop:
- Detect intent. Watch a signal feed. New funding, new hire, new role, new tech adoption.
- Find the buyer. Resolve the signal to the specific human you should email at that company.
- Get the contact. Verified email. Mobile phone. Personalization hooks.
- Personalize and send. LLM writes the email. Mail provider sends it. Log the outcome.
Most tutorials build this loop by stitching together 4 different vendors (ZoomInfo for enrichment, Hunter for emails, Champify for job-change signals, a custom scraper for LinkedIn posts). That's where the 500 lines come from. Account creation, schema translation, rate-limit dancing, error handling per vendor.
AgentEnrich collapses all four into one API key. The 4-step loop becomes 4 endpoint calls. The "tutorial" becomes 60 lines.
The 60 lines
Save this as sdr.ts. npm install hono zod and you're good. Or use Bun and skip npm.
import Anthropic from "@anthropic-ai/sdk"; import { Resend } from "resend"; const AE = "https://api.agentenrich.com/v1"; const H = { "Authorization": `Bearer ${process.env.AGENTENRICH_KEY}`, "Content-Type": "application/json" }; const claude = new Anthropic(); const resend = new Resend(process.env.RESEND_KEY); async function get(url: string) { return (await fetch(`${AE}${url}`, { headers: H })).json(); } async function post(url: string, body: any) { return (await fetch(`${AE}${url}`, { method: "POST", headers: H, body: JSON.stringify(body) })).json(); } // 1. DETECT: poll the funding-radar combo, returns funded co + decision maker async function findFundedBuyers(role: string, days = 30) { const r = await post("/funding-radar", { rounds: ["series_a", "series_b"], days_window: days, decision_maker_title: role, limit: 50, }); return r.results; } // 2. ENRICH: get verified email + phone + peers + personalization hooks async function getKit(linkedinUrl: string) { return await post("/prospect-package", { linkedinUrl }); } // 3. PERSONALIZE: pull the announcement post they wrote (if any) async function getHook(linkedinUrl: string) { const r = await post("/congrats-trigger", { linkedinUrl }); return r.results?.[0]?.announcement_text; } // 4. WRITE + SEND: Claude composes, Resend delivers async function sendEmail(kit: any, funding: any, hook: string | undefined) { const { content } = await claude.messages.create({ model: "claude-sonnet-4-5", max_tokens: 500, messages: [{ role: "user", content: `Write a 4-sentence cold email to ${kit.person.fullName}, ${kit.person.title} at ${kit.person.company.name}. They just raised ${funding.round} (\$${funding.amount_usd}). ${hook ? `They posted: "${hook}". Reference it directly.` : ""} Pitch our load-testing tool. Conversational. No fluff. No em dashes.` }], }); const body = (content[0] as any).text; await resend.emails.send({ from: "[email protected]", to: kit.person.email, subject: `Congrats on the ${funding.round}, ${kit.person.firstName}`, text: body, }); } // Main loop const targets = await findFundedBuyers("VP of Engineering"); for (const t of targets) { const kit = await getKit(t.decision_maker.linkedinUrl); if (!kit.person?.email) continue; const hook = await getHook(t.decision_maker.linkedinUrl); await sendEmail(kit, t.funding, hook); console.log(`sent to ${kit.person.email}`); }
That's it. 60 lines including comments and imports. Run bun sdr.ts and you have an AI SDR processing the last 30 days of funding rounds.
Walkthrough: what each line does
Lines 1-7: Setup
Two SDKs. Anthropic's for Claude (you write the prompt, Claude writes the email). Resend for delivery (Postmark or SendGrid work identically). One bearer token for AgentEnrich. That's the entire vendor surface for a production AI SDR.
Three API keys: AgentEnrich, Anthropic, Resend. No ZoomInfo procurement call. No Hunter usage gate. No Champify webhook setup.
Lines 9-14: HTTP helpers
Two-line wrappers around fetch. No need for an SDK because our endpoints are flat REST. The official @agentenrich/sdk npm package exists if you want typed responses, but for a tutorial the helpers keep everything visible.
Lines 16-25: Detect intent
One call to /v1/funding-radar. This is a combo endpoint that internally hits our triggers layer for the funding feed and our identity layer for the decision-maker resolution at each funded company. Returns a tuple of (company, funding, decision_maker) per row.
Without this combo you'd be writing two separate pollers, joining results, and handling the case where Crunchbase has a company but ZoomInfo doesn't have the right VP. We orchestrate it internally.
Lines 27-30: Enrich the buyer
One call to /v1/prospect-package. Returns verified email, mobile phone, 3 peers at the company, and 4 personalization hooks (recent posts, follower count, badges, headline). 12 credits flat.
The "personalization hooks" array is the secret weapon. Each hook is something specific about this person you can reference. "Posted about React Server Components last week." "LinkedIn Influencer." "Just hit 10k followers."
Lines 32-35: Get the post they wrote
Optional but high-leverage. /v1/congrats-trigger returns the actual LinkedIn announcement post text the person wrote about their new role or funding round. This is unique to AgentEnrich. Quoting their own writing back to them is the highest-converting cold email format we've benchmarked.
Lines 37-50: Write and send
Claude gets a short prompt: who you're emailing, what just happened to them, what they said about it (if anything), and your pitch. Returns a 4-sentence draft. Resend ships it.
Tip: cap max_tokens: 500. Forces brevity. AI SDRs that ramble get ignored.
Lines 52-60: The main loop
Nine lines of orchestration. Find targets, enrich each, get the personalization hook, send. No queue. No retry harness. No state management. This is a cron job, not a distributed system.
Cost per lead at every tier
The credit math for this exact 60-line agent:
| Step | Endpoint | Cost per lead |
|---|---|---|
| 1. Find funded buyers | POST /v1/funding-radar | 3 credits |
| 2. Enrich the buyer | POST /v1/prospect-package | 12 credits |
| 3. Get the post they wrote | POST /v1/congrats-trigger | 2 credits |
| 4. LLM compose + send | Claude + Resend | ~$0.003 (not AgentEnrich) |
| Total | — | 17 credits per fully-enriched lead |
Translating credits to leads per tier (using AgentEnrich's current founding-rate pricing):
| Tier | Price | Credits/mo | Leads/mo (at 17 cr each) |
|---|---|---|---|
| Builder | $49 | 65,000 | ~3,800 |
| Pro | $97 | 130,000 | ~7,600 |
| Scale | $199 | 270,000 | ~15,800 |
| Agency | $399 | 550,000 | ~32,300 |
| Agency (UGC) | $199 | 550,000 | ~32,300 |
Cost per lead on Pro: $0.0128. On Agency UGC: $0.006. A human SDR at $60k loaded salary processing 100 emails/day = $2.40 per outbound. We're three orders of magnitude cheaper before reply rates.
Benchmark reply rates
Numbers from agencies and GTM teams running this exact stack in 2026 (n ≈ 50, take with salt):
- Generic congrats email, no personalization: 1.5-2% reply
- Congrats + recent post reference: 2-4% reply
- Congrats + quote the post they wrote (using
/v1/congrats-trigger): 4-7% reply - Funding congrats + role-specific pitch + post quote: 5-9% reply
The differentiator is the post quote. Cold prospects pattern-match "AI cold email" within 2 seconds. Quoting their own writing back to them breaks the pattern. It signals you actually read what they wrote.
Variations
AI voice agent
Swap step 4 (Resend) for Vapi / Retell / Bland. Use kit.person.phone instead of kit.person.email. Claude generates the script, the voice provider dials. Same enrichment stack, different output channel.
AI recruiter
Swap step 1 from /funding-radar to /bundles/recruiter-pack. Returns a target candidate plus 8 lookalike candidates at other companies. Compose outreach. Send via LinkedIn API or InMail-replacement tooling.
AI customer success
Swap step 1 from /funding-radar to /champion-just-moved. Pre-load your customer-power-user list as a watch list. The endpoint cross-references against the live job-change feed and returns champions who switched companies in the last N days. Re-pitch them in their new seat.
AI investor sourcing
Same loop, different prompt. Step 1: /funding-radar filtered by stage. Step 4: Claude writes a partner-style email instead of a sales pitch. Run nightly. Wake up with a brief on every Series A in your verticals.
Common pitfalls
1. No deduplication state
The 60-line script will re-email the same person if you run it twice. Add a SQLite table or a Redis SET keyed by kit.person.email before you ship. Two lines.
2. Sender domain reputation
You're sending cold. Warm up the domain for 2 weeks before high-volume sends. SPF + DKIM + DMARC. Resend has a guide. Skip this and you're spam-folder bait regardless of how good the data is.
3. Catch-all detection
Some companies use catch-all email setups (info@, sales@, anything@ all accept). The /v1/find-email response includes catch_all: true when this happens. Skip these. They look deliverable but never land in a real inbox.
4. Reply handling
4-7% reply rate means on a 1,000-email run you get 40-70 replies. Have a routing strategy. Auto-route to your CRM. Pipe to Slack. Have a human review before sending the second touch. AI SDRs that auto-reply without context burn relationships.
5. Compliance
Comply with CAN-SPAM (US): unsubscribe link, physical address, accurate sender. GDPR (EU): legitimate interest basis or opt-in. CASL (Canada): explicit opt-in required for cold. We surface data sourced from public web; you're responsible for outreach compliance. Read our acceptable use policy.
FAQ
What's the cost per lead?
17 credits per fully-enriched lead. That's $0.013 on Pro, $0.006 on Agency UGC. Plus ~$0.003 in Claude tokens for the email draft. Plus your email provider's per-send cost (Resend $1/3,000 sends ≈ $0.0003).
Does Claude actually call the API on its own?
Yes, via the MCP server. Run npx @agentenrich/mcp with your API key. Claude sees 12 tools and decides which to call based on the conversation. Or run the 60-line script as a standalone cron without Claude in the orchestration layer at all. Both work.
Can I run this on Claude Desktop locally without writing any code?
Yes. Install npx @agentenrich/mcp in your Claude Desktop config. Then prompt: "Find companies that raised Series A in the last 30 days, get the VP of Engineering at each, draft personalized congrats emails referencing their funding announcement." Claude calls the right endpoints and returns drafts. No code.
What about deliverability?
Out of scope for this post but critical. Use a dedicated sending domain. Warm it for 2 weeks. SPF + DKIM + DMARC properly configured. Send under 100 emails/day per IP for the first week. Tools like Mailwarm or Lemwarm automate this.
What if I want to use OpenAI instead of Claude?
Swap the Anthropic SDK for OpenAI SDK. The prompt stays the same. Both work equally well for cold email drafting. We slightly prefer Claude for tone control but it's a coin flip.
How does this compare to Clay or Apollo's AI features?
Clay's AI columns run in their workflow runtime, billed per row. Apollo's AI is locked behind their UI. Neither ships an MCP server. If you want an agent that runs autonomously on a cron without a human-in-the-loop UI, you need API-and-MCP-first infrastructure. That's us. See also: The 3 enrichment APIs every Clay user is wrong about.
Build it tonight.
Builder is $49/mo with a 7-day free trial, no card. Or use the public sandbox first.
Start free trial See the live demos← All posts · Next: The 3 enrichment APIs every Clay user is wrong about →