Replit Agent
Collaboration
Deployments
App Builder
Website Builder
Game Builder
Dashboard Builder
Chatbot Builder
Product Managers
Designers
Operations
Software Engineers
IT
SMB Owners
DevRel
Founders
TeamsPricingBlogCareers
Contact salesLog inSign up
  • Teams
  • Pricing
  • Blog
  • Careers
Contact salesLog in
Start building
GuidesHow to Build an AI Sales Development Representative (SDR) in Slack - Part 5: HubSpot CRM Integration

How to Build an AI Sales Development Representative (SDR) in Slack - Part 5: HubSpot CRM Integration

A guide by
Image of Horacio LopezHoracio Lopez
Cover image with title "Build an AI SDR - Part 5"
Get a demo
Try for free
Table of ContentsIntroductionGetting StartedBreaking Down the Enhanced AI Sales Assistant CodeDeploying Your AI SDRWhat's Next for Your AI Sales Assistant
Recent Posts
Slackbot Quickstart Guide
Create a virtual whiteboard with Roboflow vision models
How to Build Your Own Simple Poll Slack App
AI Support Specialist With Groq - Part I

Introduction #

In this fifth part of our AI SDR series, we'll enhance our AI sales assistant with HubSpot integration and multi-platform campaign execution capabilities. By the end of this guide, your AI SDR will be able to handle the entire process from lead generation to campaign creation across both Smartlead and log these leads in HubSpot.

This guide is Part 5 of a six-part series for how to build your own AI SDR (Sales Development Representative) in Slack. This template includes the code from Parts 1-4 and the subsequent guides are linked at the bottom of this post.

Getting Started #

To begin enhancing your AI sales assistant with HubSpot integration and multi-platform campaign execution capabilities, fork this template by clicking "Use Template" below:

Use the template

HubSpot Private App Key

Log in to your HubSpot account and go to Settings > Integrations > Private Apps.

HubSpot Private apps creation UI - 2024-06-28

Click Create a private app and give it a name.

HubSpot Private app naming UI - 2024-06-24

Set the required scopes (you'll need access to deals, contacts, companies, and owners). For this app you will need to give the following scopes:

crm.schemas.contacts.write

crm.schemas.contacts.read

crm.schemas.custom.read

crm.schemas.custom.write

crm.schemas.companies.read

crm.schemas.companies.write

crm.objects.goals.read

Click Create app and you'll receive a private app access token.

In Replit, add this token to the Secrets tab as HUBSPOT_API_KEY.

Replit Secrets UI adding a HUBSPOT_ACCESS_TOKEN

Breaking Down the Enhanced AI Sales Assistant Code #

Let's explore the key components that make our AI SDR a more powerful tool for lead generation, qualification, email sequence generation, and multi-platform campaign execution:

HubSpot Integration

We've added a new function in utils.py to handle the upload of leads to HubSpot:

python

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 def upload_leads_to_hubspot(campaign_id, leads): print(f"Uploading {len(leads)} contacts to HubSpot CRM for campaign {campaign_id}") # HubSpot API settings api_key = os.environ['HUBSPOT_API_KEY'] base_url = "https://api.hubapi.com" endpoint = "/crm/v3/objects/contacts/batch/create" # Headers headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } # Convert leads into HubSpot contact objects contacts = [] for lead in leads: contact = { "properties": { "email": lead.get("email", ""), "firstname": lead.get("first_name", ""), "lastname": lead.get("last_name", ""), "company": lead.get("company_name", "") } } contacts.append(contact) # Split contacts into batches of 100 (HubSpot's recommended batch size) max_retries = 5 retry_delay = 1 batch_size = 100 batches = [contacts[i:i + batch_size] for i in range(0, len(contacts), batch_size)] total_uploaded = 0 for batch in batches: retry_count = 0 while retry_count < max_retries: try: # Prepare the request body request_body = {"inputs": batch} # Make the API request response = requests.post( f"{base_url}{endpoint}", headers=headers, data=json.dumps(request_body) ) # Check the response if response.status_code == 201 or response.status_code == 200: total_uploaded += len(batch) print(f"Batch uploaded successfully. Total uploaded: {total_uploaded}") break else: print(f"Error uploading batch. Status code: {response.status_code}") print(response.text) retry_count += 1 time.sleep(retry_delay) except Exception as e: print(f"An error occurred: {str(e)}") retry_count += 1 time.sleep(retry_delay) # Respect rate limits (10 requests per second for free plans) time.sleep(0.1) print(f"Upload complete. Total contacts uploaded: {total_uploaded}")

This function handles the process of uploading leads to HubSpot, ensuring that we respect API rate limits and handle potential errors.

Multi-Platform Campaign Execution

We've updated the post_final_email_sequence function in main.py to handle campaign execution across both Smartlead and HubSpot:

python

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 def post_final_email_sequence(client, csv_ts): channel = app.state[csv_ts]["channel"] thread_ts = app.state[csv_ts]["thread_ts"] client.chat_postMessage(text="Drafting campaign and adding leads to CRM...", channel=channel, thread_ts=thread_ts) print(f"Starting post_final_email_sequence for csv_ts: {csv_ts}") email_sequence = app.state[csv_ts]["emails"] enriched_csv = app.state[csv_ts]["enriched_csv"] print(f"Email sequence count: {len(email_sequence)}") print(f"Enriched CSV length: {len(enriched_csv.splitlines())}") # Create Smartlead campaign campaign_name = f"Campaign-{csv_ts}" try: print(f"Creating Smartlead campaign: {campaign_name}") campaign_id = create_smartlead_campaign(campaign_name) print(f"Smartlead campaign created with ID: {campaign_id}") # Prepare leads for upload leads = [] for row in csv.DictReader(io.StringIO(enriched_csv)): lead = { "first_name": row.get("first_name", ""), "last_name": row.get("last_name", ""), "email": row.get("email", ""), "company_name": row.get("company_name", ""), "website": row.get("company_website", ""), "location": f"{row.get('city', '')}, {row.get('state', '')}, {row.get('country', '')}".strip(", "), "custom_fields": { "Title": row.get("title", ""), "Company Industry": row.get("company_industry", ""), "Company Size": row.get("company_size", ""), "Seniority": row.get("seniority", ""), "Departments": row.get("departments", ""), "Functions": row.get("functions", "") }, "linkedin_profile": row.get("linkedin_url", "") } leads.append(lead) print(f"Prepared {len(leads)} leads for upload") # Upload leads to Smartlead print(f"Uploading leads to Smartlead campaign {campaign_id}") upload_result = upload_leads_to_smartlead(campaign_id, leads) print(f"Smartlead Upload result: {upload_result}") # Upload leads to HubSpot print("Uploading leads to HubSpot") hs_upload_result = upload_leads_to_hubspot(campaign_id, leads) print(f"HubSpot Upload result: {hs_upload_result}") # Save campaign sequence print(f"Saving campaign sequence for campaign {campaign_id}") sequence_result = save_campaign_sequence(campaign_id, email_sequence) print(f"Sequence save result: {sequence_result}") # Get campaign details print(f"Fetching campaign details for campaign {campaign_id}") campaign_details = get_campaign_by_id(campaign_id) print(f"Campaign details: {campaign_details}") message = f"I have now prepared this campaign in Smartlead and added these leads as Contacts in HubSpot. I look forward to seeing the returns this has for your business. Please feel free to come back anytime if you have any other sales or outreach needs:\n\n" message += f":point_right: <https://app.smartlead.ai/app/email-campaign/{campaign_id}/analytics|Smartlead Campaign - {campaign_name}>\n\n" message += f"Campaign Status: {campaign_details['status']}\n" message += f"Uploaded Leads: {upload_result['upload_count']}\n" message += f"Total Emails in Sequence: {len(email_sequence)}\n" except Exception as e: print(f"Error in post_final_email_sequence: {str(e)}") message = f"An error occurred while creating the Smartlead campaign: {str(e)}" client.chat_postMessage(channel=channel, thread_ts=thread_ts, text=message)

This function now handles the uploading leads to both Smartlead and HubSpot, and provides a summary of the actions taken across both platforms.

Deploying Your AI SDR #

In order to keep your AI SDR running 24/7 and receive requests whenever someone mentions it in Slack, you'll need to deploy it on a hosted server.

Open a new tab in the Workspace and search for “Deployments” or open the control console by typing ⌘ + K (or Ctrl + K) and type "deploy". You should find a screen like this.

Replit Deployments selection UI

For bots like this that need always need to be up listening to requests, we recommend using a Reserved VM. On the next screen, click Approve and configure build settings most internal bots work fine with the default machine settings but if you need more power later, you can always come back and change these settings later. You can monitor your usage and billing at any time at: replit.com/usage.

On the next screen, you’ll be able to set your primary domain and edit the Secrets that will be in your production deployment. Usually, we keep these settings as they are.

Finally, click Deploy and watch your bot go live!

What's Next for Your AI Sales Assistant #

With these enhancements, your AI SDR is now a comprehensive tool for lead generation, email address enrichment, email sequence generation, and CRM syncs. In the next part of this series, we'll be adding the ability for the assistant to add your leads and into your HubSpot CRM. The other parts of the series include:

  • AI SDR - Part 1 - Lead List Creation
  • AI SDR - Part 2 - Lead Enrichment
  • AI SDR - Part 3 - Draft Email Copy
  • AI SDR - Part 4 - Create Smartlead campaign
  • AI SDR - Part 5 (this guide) - Add Leads to HubSpot
  • AI SDR - Part 6 (Final) - Agent Mode

It is important to note that HubSpot's Acceptable Use Policy (Section 2c) prohibits the emailing of purchased emails like those pulled from Apollo in Part 1 of this six-part tutorial. Therefore, we recommend only emailing these leads from tools like Smartlead.

If you'd like to discuss how to enable your team to build and implement tools like these, feel free to schedule some time with the Replit team for a quick demo of our product.

Happy coding and selling!

Replit

  • Mobile App
  • Desktop App
  • Blog
  • Careers
  • About
  • Pricing
  • Guides

Features

  • Replit Agent
  • Collaboration
  • Deployments
  • Teams

Legal

  • Terms of service
  • Teams agreement
  • Privacy
  • Subprocessors
  • DPA
  • Report abuse

Connect

  • X / Twitter
  • Tiktok
  • Facebook
  • Instagram
  • Linkedin

Languages

  • Python
  • Javascript
  • TypeScript
  • Node.js
  • Nix
  • HTML, CSS, JS
  • C++
  • Golang

Handy Links

  • Vibe Coding 101
  • Languages
  • Docs
  • Help
  • Status
  • Import from Glitch
  • Import from Heroku
  • Copilot alternative
  • Brand kit
  • Partnerships
All rights reserved. Copyright © 2025 Replit, Inc.