As developers, we’re always looking for ways to automate repetitive tasks and build scalable solutions that drive real-world impact. In the sales domain, Sales Development Representatives (SDRs) spend hours qualifying leads, crafting personalized emails, and updating CRMs—tasks ripe for automation. Enter the AI Sales Development Representative (SDR) Agent, powered by the Agent Development Kit (ADK), an open-source framework from Google that simplifies building multi-agent systems.
In this blog, we’ll walk through how to create an AI SDR Agent using ADK to automate lead qualification, outreach, and CRM updates. We’ll share the complete Python code, break it down step by step, and show you how to extend it for your own projects. Whether you’re a seasoned developer or just dipping your toes into AI, this guide will help you harness ADK’s power to revolutionize sales automation.
Why ADK for AI SDR Agents?
ADK is designed to make multi-agent development intuitive and flexible. Here’s why it’s a game-changer for building AI SDR Agents:
- Multi-Agent Architecture: Compose specialized agents (e.g., for greetings or farewells) into a cohesive system for seamless task delegation.
- Rich Tool Ecosystem: Integrate tools like database queries, email APIs, or third-party libraries (e.g., LangChain) to extend functionality.
- Model Flexibility: Choose from models like Gemini, Anthropic’s Claude, or others via LiteLLM to balance performance and cost.
- Developer-Friendly Tools: Use ADK’s CLI, Web UI, and evaluation framework to build, test, and debug with ease.
- Scalable Deployment: Deploy agents to any runtime or Google Cloud’s Vertex AI for enterprise-grade scalability.
Ready to dive in? Let’s build an AI SDR Agent and explore the code.
The AI SDR Agent: What It Does
Our AI SDR Agent automates key sales tasks:
- Lead Qualification: Queries a lead database to retrieve details (e.g., job title, company, interests).
- Personalized Outreach: Sends tailored emails to leads based on their profiles.
- CRM Updates: Logs interactions in a CRM for pipeline visibility.
- Task Delegation: Routes non-sales tasks (e.g., greetings) to specialized sub-agents.
The agent is built as a multi-agent system, with a main SDR agent coordinating tasks and sub-agents handling auxiliary tasks like greetings and farewells.
The Code: AI SDR Agent with ADK
Here’s the complete Python code for the AI SDR Agent. Save it as AISDRAgent.py
and follow along as we break it down.
from google.adk.agents import LlmAgent
from google.adk.tools import search_lead_database, send_email, update_crm
from typing import Dict
# Tool to search lead database
def search_lead_database(lead_name: str) -> Dict:
"""Search the internal lead database for lead details."""
print(f"--- Tool: search_lead_database called for lead: {lead_name} ---")
lead_normalized = lead_name.lower().replace(" ", "")
# Mock lead database
lead_db = {
"johnsmith": {"status": "success", "details": "John Smith, CTO, TechCorp, [email protected], interested in AI solutions"},
"sarahjones": {"status": "success", "details": "Sarah Jones, VP Sales, GrowFast, [email protected], seeking CRM integration"},
"mikebrown": {"status": "success", "details": "Mike Brown, CEO, StartUp, [email protected], needs lead gen tools"},
}
if lead_normalized in lead_db:
return lead_db[lead_normalized]
else:
return {"status": "error", "error_message": f"No lead found for '{lead_name}'."}
# Tool to send personalized email
def send_email(lead_email: str, message: str) -> Dict:
"""Send a personalized email to the lead."""
print(f"--- Tool: send_email called for lead: {lead_email} ---")
# Mock email sending
return {"status": "success", "message": f"Email sent to {lead_email}: {message}"}
# Tool to update CRM
def update_crm(lead_id: str, details: str) -> Dict:
"""Update CRM with lead interaction details."""
print(f"--- Tool: update_crm called for lead: {lead_id} ---")
# Mock CRM update
return {"status": "success", "message": f"CRM updated for lead {lead_id} with: {details}"}
# Define specialized sub-agents
greeting_agent = LlmAgent(
model="anthropic/claude-3-sonnet-20240229",
name="greeting_agent",
instruction="Provide a friendly greeting to the user. Do not engage in other tasks.",
description="Handles simple greetings like 'Hi' or 'Hello'",
)
farewell_agent = LlmAgent(
model="anthropic/claude-3-sonnet-20240229",
name="farewell_agent",
instruction="Provide a polite goodbye message. Do not perform other actions.",
description="Handles simple farewells like 'Bye' or 'Goodbye'",
)
# Define the main AI SDR Agent
ai_sdr_agent = LlmAgent(
model="gemini-2.0-flash-exp",
name="ai_sdr_agent",
description="You are the main AI Sales Development Representative (SDR) Agent, coordinating a team to automate lead qualification, outreach, and CRM updates. "
"- Main tasks: Qualify leads using `search_lead_database`, send personalized emails using `send_email`, and update CRM using `update_crm`. "
"- Delegation Rules: "
"- Delegate greetings (e.g., 'Hi', 'Hello') to `greeting_agent`. "
"- Delegate farewells (e.g., 'Bye', 'Goodbye') to `farewell_agent`. "
"- Handle lead queries, outreach, and CRM updates yourself. "
"- For unsupported queries, state clearly that you cannot assist.",
instruction="""You are an AI-powered Sales Development Representative. Use `search_lead_database` to qualify leads, `send_email` to send personalized outreach, and `update_crm` to log interactions. Delegate greetings and farewells to respective agents. For other queries, politely decline to assist.""",
tools=[search_lead_database, send_email, update_crm],
sub_agents=[greeting_agent, farewell_agent]
)
# Example usage
if __name__ == "__main__":
# Simulate lead qualification
user_query = "Qualify lead John Smith"
response = ai_sdr_agent.process_query(user_query)
print(response)
# Simulate personalized outreach
user_query = certaine
response = ai_sdr_agent.process_query(user_query)
print(response)
# Simulate CRM update
user_query = "Update CRM for lead 12345 with 'Sent AI solution email'"
response = ai_sdr_agent.process_query(user_query)
print(response)
# Simulate greeting
user_query = "Hi"
response = ai_sdr_agent.process_query(user_query)
print(response)
Step-by-Step Code Breakdown
Let’s dissect the code to understand how it works and why each part matters. This section is designed for developers who want to grasp the mechanics and adapt the code for their own use cases.
Step 1: Import Dependencies
from google.adk.agents import LlmAgent
from google.adk.tools import search_lead_database, send_email, update_crm
from typing import Dict
-
What’s Happening: We import
LlmAgent
from ADK to create agents powered by large language models (LLMs). Thesearch_lead_database
,send_email
, andupdate_crm
tools are placeholders (assumed to be part of ADK’s tool ecosystem or custom-defined). Thetyping.Dict
is used for type hints in tool functions. - Why It Matters: These imports set up the foundation for building agents and defining their capabilities. In a real implementation, you’d replace placeholder tools with actual integrations (e.g., a CRM API).
Step 2: Define the Lead Database Search Tool
def search_lead_database(lead_name: str) -> Dict:
"""Search the internal lead database for lead details."""
print(f"--- Tool: search_lead_database called for lead: {lead_name} ---")
lead_normalized = lead_name.lower().replace(" ", "")
# Mock lead database
lead_db = {
"johnsmith": {"status": "success", "details": "John Smith, CTO, TechCorp, [email protected], interested in AI solutions"},
"sarahjones": {"status": "success", "details": "Sarah Jones, VP Sales, GrowFast, [email protected], seeking CRM integration"},
"mikebrown": {"status": "success", "details": "Mike Brown, CEO, StartUp, [email protected], needs lead gen tools"},
}
if lead_normalized in lead_db:
return lead_db[lead_normalized]
else:
return {"status": "error", "error_message": f"No lead found for '{lead_name}'."}
- What’s Happening: This function simulates querying a lead database. It normalizes the input (e.g., “John Smith” to “johnsmith”) and checks a mock dictionary for lead details. If found, it returns a success response; otherwise, it returns an error.
- Why It Matters: This tool enables lead qualification, a core SDR task. In production, you’d replace the mock database with a real CRM (e.g., Salesforce) or B2B database API.
- Developer Tip: Add error handling for API failures and logging for debugging, as shown with the print statement.
Step 3: Define the Email Sending Tool
def send_email(lead_email: str, message: str) -> Dict:
"""Send a personalized email to the lead."""
print(f"--- Tool: send_email called for lead: {lead_email} ---")
# Mock email sending
return {"status": "success", "message": f"Email sent to {lead_email}: {message}"}
- What’s Happening: This function simulates sending a personalized email to a lead. It takes an email address and message, returning a success response.
- Why It Matters: Personalized outreach is critical for engaging leads. In a real system, you’d integrate with an email service (e.g., SendGrid, Gmail API).
-
Developer Tip: Enhance this tool with templates or dynamic content generation using lead data from
search_lead_database
.
Step 4: Define the CRM Update Tool
def update_crm(lead_id: str, details: str) -> Dict:
"""Update CRM with lead interaction details."""
print(f"--- Tool: update_crm called for lead: {lead_id} ---")
# Mock CRM update
return {"status": "success", "message": f"CRM updated for lead {lead_id} with: {details}"}
- What’s Happening: This function simulates updating a CRM with interaction details (e.g., “Sent AI solution email”). It returns a success response.
- Why It Matters: Keeping the CRM updated ensures sales pipeline visibility. In production, integrate with CRM APIs like HubSpot or Salesforce.
-
Developer Tip: Add validation to ensure
lead_id
exists in the CRM before updating.
Step 5: Define Specialized Sub-Agents
greeting_agent = LlmAgent(
model="anthropic/claude-3-sonnet-20240229",
name="greeting_agent",
instruction="Provide a friendly greeting to the user. Do not engage in other tasks.",
description="Handles simple greetings like 'Hi' or 'Hello'",
)
farewell_agent = LlmAgent(
model="anthropic/claude-3-sonnet-20240229",
name="farewell_agent",
instruction="Provide a polite goodbye message. Do not perform other actions.",
description="Handles simple farewells like 'Bye' or 'Goodbye'",
)
-
What’s Happening: We create two sub-agents using
LlmAgent
:-
greeting_agent
: Responds to greetings (e.g., “Hi”) with a friendly message. -
farewell_agent
: Handles farewells (e.g., “Goodbye”) with a polite response. - Both use Anthropic’s Claude model for specialized, high-quality responses.
-
-
Why It Matters: Sub-agents keep the main SDR agent focused on sales tasks by delegating non-core interactions. The
description
field guides the main agent’s delegation logic. - Developer Tip: Use different models for sub-agents based on task complexity (e.g., a lighter model for simple greetings).
Step 6: Define the Main AI SDR Agent
ai_sdr_agent = LlmAgent(
model="gemini-2.0-flash-exp",
name="ai_sdr_agent",
description="You are the main AI Sales Development Representative (SDR) Agent, coordinating a team to automate lead qualification, outreach, and CRM updates. "
"- Main tasks: Qualify leads using `search_lead_database`, send personalized emails using `send_email`, and update CRM using `update_crm`. "
"- Delegation Rules: "
"- Delegate greetings (e.g., 'Hi', 'Hello') to `greeting_agent`. "
"- Delegate farewells (e.g., 'Bye', 'Goodbye') to `farewell_agent`. "
"- Handle lead queries, outreach, and CRM updates yourself. "
"- For unsupported queries, state clearly that you cannot assist.",
instruction="""You are an AI-powered Sales Development Representative. Use `search_lead_database` to qualify leads, `send_email` to send personalized outreach, and `update_crm` to log interactions. Delegate greetings and farewells to respective agents. For other queries, politely decline to assist.""",
tools=[search_lead_database, send_email, update_crm],
sub_agents=[greeting_agent, farewell_agent]
)
-
What’s Happening: The main
ai_sdr_agent
is created with:- Model: Gemini 2.0 Flash Experimental for fast, cost-effective processing.
- Name and Description: Clearly define the agent’s role and delegation rules, which the LLM uses to route tasks.
- Instruction: Provides detailed guidance on how to handle queries, use tools, and delegate.
- Tools: The three custom tools for lead qualification, email sending, and CRM updates.
- Sub-Agents: The greeting and farewell agents for task delegation.
-
Why It Matters: This is the heart of the system, coordinating all tasks and ensuring the right agent or tool handles each query. The clear
description
andinstruction
fields enable intelligent routing. - Developer Tip: Keep descriptions concise yet specific to avoid misrouting by the LLM.
Step 7: Example Usage
if __name__ == "__main__":
# Simulate lead qualification
user_query = "Qualify lead John Smith"
response = ai_sdr_agent.process_query(user_query)
print(response)
# Simulate personalized outreach
user_query = "Send email to [email protected] about our AI solution"
response = ai_sdr_agent.process_query(user_query)
print(response)
# Simulate CRM update
user_query = "Update CRM for lead 12345 with 'Sent AI solution email'"
response = ai_sdr_agent.process_query(user_query)
print(response)
# Simulate greeting
user_query = "Hi"
response = ai_sdr_agent.process_query(user_query)
print(response)
-
What’s Happening: This block simulates user interactions by sending queries to the
ai_sdr_agent
and printing responses. It demonstrates:- Lead qualification (“Qualify lead John Smith”).
- Email outreach (“Send email to [email protected]...”).
- CRM update (“Update CRM for lead 12345...”).
- Greeting delegation (“Hi”).
- Why It Matters: This shows how the agent processes real-world queries, making it easy to test and debug locally.
-
Developer Tip: Use ADK’s Web UI (
adk web
) or CLI (adk run
) for interactive testing instead of hardcoding queries.
How It Works in Action
Here’s what happens when you run the code:
-
Lead Qualification: For “Qualify lead John Smith,” the agent calls
search_lead_database
, retrieves “John Smith, CTO, TechCorp, [email protected], interested in AI solutions,” and returns the details. -
Email Outreach: For “Send email to [email protected] about our AI solution,” the agent uses
send_email
to simulate sending a tailored email and returns a success message. -
CRM Update: For “Update CRM for lead 12345 with ‘Sent AI solution email’,” the agent calls
update_crm
and logs the interaction. -
Greeting Delegation: For “Hi,” the agent delegates to
greeting_agent
, which responds with a friendly greeting. - Unsupported Queries: For irrelevant queries (e.g., “What’s the weather?”), the agent politely declines.
ADK’s dynamic routing ensures tasks are handled by the right agent or tool, leveraging the LLM’s understanding of the description
and instruction
fields.
Extending the AI SDR Agent
The code is a starting point, but you can enhance it for production use:
-
Real Integrations: Replace mock tools with actual APIs (e.g., Salesforce for
search_lead_database
, SendGrid forsend_email
). - Multi-Channel Outreach: Add tools for SMS, LinkedIn messaging, or voice calls using ADK’s streaming capabilities.
- Advanced Personalization: Use external APIs to pull recent company news or LinkedIn activity for hyper-personalized emails.
-
Evaluation: Use ADK’s
AgentEvaluator.evaluate()
to test the agent against datasets (e.g.,evaluation.test.json
) and optimize performance. - Compliance: Add guardrails for GDPR/CCPA compliance, ensuring secure data handling.
Getting Started
To run the AI SDR Agent:
- Install ADK: Follow the setup guide in the Official ADK Documentation.
-
Save the Code: Copy the code into
AISDRAgent.py
. -
Test Locally: Run
adk run AISDRAgent.py
(CLI) oradk web
(Web UI) to test queries interactively. - Debug: Use ADK’s Web UI to inspect agent state and execution steps.
- Deploy: Containerize the agent and deploy to Vertex AI or another runtime for production.
Explore the code, tweak the tools, and adapt it to your business needs. The ADK documentation provides examples for adding new tools, models, or workflows.
Why Developers Love ADK
ADK’s developer-centric features make it a joy to work with:
- Pythonic Simplicity: Write clean, modular code with minimal boilerplate.
- Local Testing: Debug with CLI or Web UI before deploying.
- Extensibility: Integrate with any model, tool, or API.
- Open-Source: Customize and contribute to the framework.
For sales automation, ADK’s multi-agent design and enterprise-grade integrations (e.g., Google Cloud connectors) make it a standout choice.
The Future of AI-Powered Sales
The AI SDR Agent is just the beginning. Imagine agents that predict lead behavior, optimize campaigns in real-time, or integrate with virtual assistants for end-to-end sales workflows. With ADK, you have the tools to build these innovations.
We’re excited to see what you create! Share your AI SDR Agent projects with the community, and let’s push the boundaries of sales automation together.