We raised $6M in Seed FundingRead more
+
+
+
+
+
+
+
+
Blog/Engineering

Build an Email Agent with Google ADK and AgentMail

ASAdi Singh

How to wire Google's ADK into AgentMail's MCP server so your agents can send and receive email without touching SMTP or OAuth. Python setup, stdio transport, and a few things worth knowing before you ship it.

Guide
Engineering
google adk
agent development kit
agentmail
mcp
+8

Many agent frameworks overlook communication. While AI agents can reason, plan, and handle complex tasks, they often struggle with everyday communication tools that people rely on. Email is still the internet’s universal protocol, and now your Google ADK agents can use it too.

Today, we’re excited to introduce our integration with Google’s Agent Development Kit (ADK), one of the most promising new agent frameworks. It offers multi-agent orchestration, built-in MCP support, and works with more than just Gemini models. Now, your ADK agents can send, receive, and manage emails on their own using the AgentMail MCP server.

This guide shows you how to build an intelligent email assistant using a multi-agent architecture.

No SMTP config, no OAuth rabbit hole, no inbox wiring. The agent sends email. Done.

What is Google ADK?

Google’s Agent Development Kit is an open-source framework for building AI agents. It’s designed to make agent development feel like traditional software development rather than experimental AI work.

Key features of Google ADK:

  • Multi-language support: Build agents in Python, TypeScript, Go, or Java
  • Model agnostic: Works with Gemini, Claude, Vertex AI, Ollama, and other LLMs
  • Multi-agent orchestration: Create hierarchical agent systems with specialized sub-agents
  • Rich tool ecosystem: Pre-built tools, custom functions, and MCP server integrations
  • Deployment ready: Container support for Cloud Run, GKE, or local execution.

ADK provides three ways for agents to coordinate:

  1. Shared session state: Agents read and write to a common context
  2. LLM-driven delegation: Agents dynamically route tasks using function calls
  3. Explicit invocation: Agents call other agents as tools

Thanks to this flexibility, ADK works well for both simple single-agent tasks and more complex multi-agent workflows.

The AgentMail + Google ADK Integration

The AgentMail MCP server gives your Google ADK agents full email capabilities:

Inbox Management

  • Create new inboxes programmatically.
  • List and retrieve existing inboxes.
  • Delete inboxes when no longer needed.

Message Operations

  • Send emails to any recipient.
  • Receive and read incoming messages.
  • Reply to messages within threads.
  • Forward emails to other addresses.

Thread and Attachment Handling

  • Access full conversation threads.
  • Download and process attachments.
  • Update message properties (read/unread status)

Your agent now handles email independently, with no need for manual inbox setup, OAuth flows, or token refreshes, just simple API calls. This provides a plug-and-play email solution, unique among agent frameworks, that lets you deploy human-like communication in minutes.

AgentMail gives your agents real inboxes. Create inboxes via API. Send and receive Emails with 0 complexity. Free to start.

Step-by-Step Guide to Building Multi-Agent Email Applications

Let’s get started building an intelligent email assistant using Google ADK and AgentMail. We’ll walk through setting up your environment, structuring your agent, adding core features, and orchestrating multiple agents.

Prerequisites

Before starting, you’ll need:

  1. Python 3.10+ (or TypeScript/Node.js for the TypeScript version)
  2. An AgentMail account: Sign up at agentmail.to
  3. An AgentMail API key: Generate one from your dashboard
  4. A Google AI Studio API key or Vertex AI credentials for Gemini access

Let's set up your intelligent email assistant using Google ADK and AgentMail. We'll cover environment setup, configuring your agent, adding features, and multi-agent orchestration.

Step 1: Setting Up Your ADK Project Environment

ADK projects follow a specific directory structure. For our email assistant, we’ll use this structure:

email-agent/
├── .env                    # API keys
├── agent.py                # Main agent application
└── email_assistant/        # Agent package (optional, for ADK web UI)
    ├── __init__.py
    └── multi_agent.py

Setting Up the Environment

Make sure Python 3.10+ is installed. MCP won’t work on older versions:

python3 --version

# If you need a newer version on macOS with Homebrew:
# brew install python@3.12

Create a new project directory and virtual environment:

mkdir email-agent && cd email-agent

# Create virtual environment with Python 3.10+
python3 -m venv .venv

# On macOS, you may need to specify the version explicitly:
# /opt/homebrew/bin/python3.12 -m venv .venv

# Activate the environment
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

Install the required packages:

pip install google-adk python-dotenv litellm

Create a .env file with your API keys:

# Gemini API Key - get from https://aistudio.google.com/apikey
GEMINI_API_KEY=your_gemini_api_key

# AgentMail API Key - get from https://console.agentmail.to
AGENTMAIL_API_KEY=your_agentmail_api_key

Why does this structure matter?

This directory structure isn’t just a convention; it’s how ADK finds and loads your agents. Separating configuration (.env), application logic (agent.py), and agent definitions helps with the following:

  • Modularity: Each component can be developed and tested independently
  • Security: API keys stay in .env, never committed to version control
  • Deployment flexibility: The same structure works for local development and cloud deployment

Step 2: Configuring the AgentMail MCP Server

The AgentMail MCP server runs as a subprocess that your ADK agent communicates with. Create the file agent.py:

import os
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
from google.genai.types import Content, Part
from mcp import StdioServerParameters

load_dotenv()

# Configure the AgentMail MCP server
agentmail_mcp = McpToolset(
    connection_params=StdioConnectionParams(
        server_params=StdioServerParameters(
            command="npx",
            args=["-y", "agentmail-mcp"],
            env={"AGENTMAIL_API_KEY": os.getenv("AGENTMAIL_API_KEY")}
        ),
        timeout=30  # Allow time for npx to download package on first run
    )
)

This configuration:

  • Uses npx to run the AgentMail MCP server (automatically downloads on first use)
  • Passes your API key through environment variables
  • Sets a 30-second timeout to allow for initial package download
  • Establishes a stdio connection for communication between ADK and the MCP server

How MCP connections work

MCP uses a client-server architecture in which your ADK agent is the client, and AgentMail’s MCP server provides the tools. The StdioConnectionParams establishes communication over standard input/output streams, which is:

  • Secure: No network ports exposed
  • Simple: Works the same locally and in containers.
  • Reliable: Process lifecycle managed by ADK

The McpToolset automatically finds all available tools from the MCP server and makes them accessible to your agent. You don’t have to define each email operation yourself, since the MCP server provides them all.

Step 3: Creating the Email Agent

Now define your agent with the AgentMail tools. Add this to your agent.py:

# Create the email agent
email_agent = Agent(
    name="email_assistant",
    model="gemini-2.5-flash",
    description="An AI assistant that can send, receive, and manage emails.",
    instruction="""You are an email assistant with access to email tools.

    You can:
    - Create new email inboxes
    - Send emails to any recipient
    - Check for new messages in inboxes
    - Reply to emails within threads
    - Forward messages to other addresses
    - List and manage existing inboxes

    When asked to perform email tasks:
    1. First check if an inbox exists or create one if needed
    2. Use the appropriate email tool for the task
    3. Confirm the action was completed
    4. Provide relevant details (message ID, inbox address, etc.)

    Always be helpful and confirm actions clearly.
    If you need more information to complete a task, ask for it.""",
    tools=[agentmail_mcp],
)

Let’s break down the key components:

  • name: Unique identifier for this agent
  • model: The LLM powering the agent’s reasoning (Gemini 2.5 Flash)
  • description: Brief summary of the agent’s purpose
  • instruction: Detailed guidance for the agent’s behavior
  • tools: List of tool providers (our AgentMail MCP toolset)

Agent instructions as system prompts

The instruction field is critical—it defines your agent’s personality, capabilities, and decision-making process. Well-crafted instructions:

  • Set boundaries: What the agent can and cannot do
  • Establish workflow: The sequence of actions for common tasks.
  • Handle edge cases: What to do when information is missing.
  • Define tone: How the agent communicates with users.

You can think of instructions as programming in plain language. The clearer and more structured your instructions are, the more reliable and helpful your agent will be.

Step 4: Building a Multi-Agent System

For more complex workflows, you can create specialized agents that work together. Here’s an example with three agents: a classifier, a responder, and a coordinator:

from google.adk.agents import Agent

# Agent 1: Email Classifier
classifier_agent = Agent(
    name="email_classifier",
    model="gemini-2.5-flash",
    description="Classifies incoming emails by type and priority",
    instruction="""You classify emails into categories and priorities.

    Categories:
    - "support": Customer questions, bug reports, help requests
    - "sales": Pricing inquiries, demos, partnerships
    - "spam": Unwanted emails, promotions, newsletters
    - "internal": Team communications, updates, announcements

    Priorities:
    - "urgent": Needs response within hours
    - "normal": Needs response within 1-2 days
    - "low": Can wait or may not need response

    For each email, output JSON:
    {
        "category": "...",
        "priority": "...",
        "summary": "one sentence summary",
        "suggested_action": "what should be done"
    }
    """,
    tools=[agentmail_mcp],
)

# Agent 2: Email Responder
responder_agent = Agent(
    name="email_responder",
    model="gemini-2.5-flash",
    description="Drafts and sends email responses",
    instruction="""You draft and send professional email responses.

    Guidelines:
    - Be helpful and professional
    - Keep responses concise but complete
    - Include relevant details from the original email
    - Ask clarifying questions if needed
    - Sign off appropriately

    For support emails: Acknowledge the issue, provide help or escalate
    For sales emails: Thank them, provide requested info or schedule follow-up
    For internal emails: Respond appropriately to the context

    Always use the appropriate inbox to send from.""",
    tools=[agentmail_mcp],
)

# Agent 3: Root Coordinator
root_agent = Agent(
    name="email_coordinator",
    model="gemini-2.5-flash",
    description="Coordinates email handling between specialized agents",
    instruction="""You coordinate email handling for the organization.

    Your sub-agents:
    - email_classifier: Use to categorize and prioritize new emails
    - email_responder: Use to draft and send responses

    Workflow for handling emails:
    1. When asked to check emails, use classifier to categorize them
    2. Based on classification, decide if response is needed
    3. For emails needing response, use responder to draft and send
    4. Report back with summary of actions taken

    For general email tasks (create inbox, send email), handle directly.
    For batch processing (check and respond to all), use sub-agents.""",
    sub_agents=[classifier_agent, responder_agent],
    tools=[agentmail_mcp],
)

Looking at the bigger picture: Multi-agent orchestration

Multi-agent systems offer several advantages over monolithic agents:

  1. Separation of Concerns: Each agent specializes in one task
  2. Maintainability: Update one agent without affecting others
  3. Scalability: Add new capabilities by adding new agents
  4. Debugging: Easier to identify which agent caused an issue

ADK supports multiple orchestration patterns:

  • Hierarchical: Parent agent delegates to child agents (our example)
  • Sequential: Agents run in a defined order
  • Parallel: Multiple agents work simultaneously
  • Loop: Agents repeat until a condition is met

The root agent serves as the orchestrator, choosing which specialist agent to use for each task.

Step 5: Creating the Application Runtime

Add the runtime code to execute your agent. This handles the conversation loop:

async def main():
    # Create a session service to maintain conversation state
    session_service = InMemorySessionService()

    # Create a runner to execute the agent
    runner = Runner(
        agent=email_agent,  # or root_agent for multi-agent
        app_name="email_assistant",
        session_service=session_service,
    )

    # Start a new session
    session = await session_service.create_session(
        app_name="email_assistant",
        user_id="user_1"
    )

    print("Email Assistant ready. Type 'quit' to exit.\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() == 'quit':
            break

        # Create the message content
        user_content = Content(
            role="user",
            parts=[Part(text=user_input)]
        )

        # Process the request and stream events
        async for event in runner.run_async(
            user_id="user_1",
            session_id=session.id,
            new_message=user_content
        ):
            if event.is_final_response():
                # Extract and display the response
                if event.content and event.content.parts:
                    response_text = event.content.parts[0].text
                    print(f"\nAssistant:{response_text}\n")

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Event-driven architecture

The runner.run_async() method returns an asynchronous stream of events, not just a final response. This architecture enables:

  • Real-time feedback: Show users what’s happening as it happens
  • Tool visibility: See when tools are called and their results
  • Agent transfers: Track when control passes between agents
  • Error handling: Catch and handle issues at each step

Event types include:

  • is_final_response(): The agent’s complete answer
  • Tool invocation events: When the agent uses a tool
  • Agent transfer events: When delegating to sub-agents
  • Thinking events: The agent’s reasoning process

For production apps, you’ll want to handle more event types to give users a better experience.

Step 6: Running and Testing Your Agent

Run your email assistant:

python agent.py

Test with these prompts:

Create an inbox:

You: Create a new inbox called "support"

List existing inboxes:

You: What inboxes do I have?

Send an email:

You: Send an email from my support inbox to vivekksonar2000@gmail.com with subject
"Welcome!" and body "Thanks for signing up. Let us know if you have questions."

Check for messages:

You: Check my support inbox for new messages

Reply to a message:

You: Reply to the last message saying "Thanks for your feedback!"

Testing Multi-Agent Systems

When testing multi-agent systems, verify:

  1. Delegation works: The root agent correctly routes to specialists.
  2. Context passes: Sub-agents receive the necessary information.
  3. Results return: Final responses reflect sub-agent work.
  4. Errors are handled gracefully: Failures in one agent don’t crash the system.

For the multi-agent version, test classification and response workflows:

You: Check my inbox and respond to any urgent support emails

This tests the entire process: reading emails, classifying them, and generating responses.

Step 7: Production Considerations

For production deployments, consider these enhancements:

Persistent Sessions

Replace InMemorySessionService with a database-backed implementation:

from google.adk.sessions import DatabaseSessionService

session_service = DatabaseSessionService(
    connection_string="postgresql://..."
)

Error Handling

Wrap agent calls with proper error handling:

try:
    async for event in runner.run_async(...):
        # process events
except Exception as e:
    logger.error(f"Agent error:{e}")
    # Handle gracefully

Rate Limiting

For high-volume applications, implement rate limiting on email operations to stay within AgentMail quotas.

Logging and Monitoring

Add structured logging to track agent performance:

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Log tool calls, agent transfers, response times

Complete Code

Here’s the complete agent.py file:

import os
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
from google.genai.types import Content, Part
from mcp import StdioServerParameters

load_dotenv()

# Configure the AgentMail MCP server
agentmail_mcp = McpToolset(
    connection_params=StdioConnectionParams(
        server_params=StdioServerParameters(
            command="npx",
            args=["-y", "agentmail-mcp"],
            env={"AGENTMAIL_API_KEY": os.getenv("AGENTMAIL_API_KEY")}
        ),
        timeout=30
    )
)

# Create the email agent
email_agent = Agent(
    name="email_assistant",
    model="gemini-2.5-flash",
    description="An AI assistant that can send, receive, and manage emails.",
    instruction="""You are an email assistant with access to email tools.

    You can:
    - Create new email inboxes
    - Send emails to any recipient
    - Check for new messages in inboxes
    - Reply to emails within threads
    - Forward messages to other addresses
    - List and manage existing inboxes

    When asked to perform email tasks:
    1. First check if an inbox exists or create one if needed
    2. Use the appropriate email tool for the task
    3. Confirm the action was completed
    4. Provide relevant details (message ID, inbox address, etc.)

    Always be helpful and confirm actions clearly.
    If you need more information to complete a task, ask for it.""",
    tools=[agentmail_mcp],
)

async def main():
    session_service = InMemorySessionService()

    runner = Runner(
        agent=email_agent,
        app_name="email_assistant",
        session_service=session_service,
    )

    session = await session_service.create_session(
        app_name="email_assistant",
        user_id="user_1"
    )

    print("Email Assistant ready. Type 'quit' to exit.\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() == 'quit':
            break

        user_content = Content(
            role="user",
            parts=[Part(text=user_input)]
        )

        async for event in runner.run_async(
            user_id="user_1",
            session_id=session.id,
            new_message=user_content
        ):
            if event.is_final_response():
                if event.content and event.content.parts:
                    response_text = event.content.parts[0].text
                    print(f"\nAssistant:{response_text}\n")

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Use Cases

Here are practical applications you can build with AgentMail and Google ADK:

Customer Support Automation

support_agent = Agent(
    name="support_agent",
    instruction="""You handle customer support emails.

    For common questions (password reset, billing):
    - Send automated responses with clear instructions
    - Include relevant help links

    For complex issues:
    - Acknowledge receipt
    - Gather necessary information
    - Escalate to support-team@company.com with summary

    Always be empathetic and professional.""",
    model="gemini-2.5-flash",
    tools=[agentmail_mcp],
)

Sales Follow-Up Pipeline

sales_agent = Agent(
    name="sales_agent",
    instruction="""You manage sales outreach and follow-ups.

    For new leads:
    - Send personalized initial outreach
    - Track responses in threads

    For follow-ups:
    - If no response in 48 hours, send follow-up
    - After 3 attempts, mark as cold and notify sales team

    For interested prospects:
    - Schedule demos via calendar link
    - CC sales-team@company.com on all replies""",
    tools=[agentmail_mcp],
)

Automated Reporting

reporting_agent = Agent(
    name="reporting_agent",
    instruction="""You generate and send automated reports.

    Daily digest:
    - Compile statistics from the day
    - Send to team-leads@company.com at 6pm

    Weekly summary:
    - Aggregate daily data
    - Include trends and highlights
    - Send to leadership@company.com Monday 9am

    Format reports with clear sections and bullet points.""",
    tools=[agentmail_mcp],
)

What sets this apart

Traditional email integrations require:

  • OAuth setup and token management
  • SMTP server configuration
  • Custom code for threading and storage
  • Manual inbox provisioning

With AgentMail + Google ADK:

  • API key authentication: No OAuth complexity
  • Managed infrastructure: No SMTP servers to configure
  • Built-in threading: Conversations stay organized automatically
  • Programmatic inboxes: Create inboxes via API as needed
  • MCP standard: Works with the growing MCP ecosystem

Your agent gets a real inbox, not just the ability to send emails. It has full inbox features, including threads, storage, and message history.

Conclusion and next steps

This tutorial showed how Google ADK makes it possible to build effective multi-agent email systems. To create even more advanced agents, try exploring ADK features such as:

  • Artifacts: Managing binary data and attachments
  • Events: Controlling agent execution flow
  • Context: Handling conversation state
  • Callbacks: Implementing safety filters and logging

For deployment, ADK integrates with:

  • Vertex AI Agent Engine: Managed agent hosting
  • Cloud Run: Containerized deployment
  • GKE: Kubernetes orchestration

AgentMail gives your agents real inboxes. Create inboxes via API. Send and receive Emails with 0 complexity. Free to start.


FAQs

What is Google ADK?

Google ADK (Agent Development Kit) is an open-source framework for building AI agents. It supports Python, TypeScript, Go, and Java, and works with various LLMs, including Gemini, Claude, and models via Vertex AI. ADK provides tools for multi-agent orchestration, tool integration, and deployment.

What is MCP, and why does it matter for AI agents?

MCP (Model Context Protocol) is an open standard for connecting AI applications to external systems. Think of it like USB-C for AI: a standardized way to plug in tools, data sources, and services. MCP lets agents access capabilities without custom integrations for each tool.

Can I use AgentMail with other agent frameworks?

Yes. AgentMail provides native integrations for LangChain, LlamaIndex, CrewAI, and now Google ADK. The AgentMail MCP server works with any framework that supports MCP toolsets, making it easy to add email capabilities to existing agents.

Do I need to manage SMTP servers or email infrastructure?

No. AgentMail handles all email infrastructure: SMTP, deliverability (SPF, DKIM, DMARC), storage, and threading. Your agent interacts with a simple API. You focus on building agent logic, not managing email servers.

How does email help with multi-agent coordination?

Email provides a natural communication layer for multi-agent systems. Each agent can have its own inbox, send messages to other agents or humans, and maintain conversation history. Email threads preserve context across interactions, and the audit trail shows which agent did what.

What email operations can my Google ADK agent perform?

With the AgentMail MCP integration, your agent can: create and manage inboxes, send emails, receive and read messages, reply to and forward emails, access conversation threads, download attachments, and update message properties like read status.

Ready to build? Start integrating AgentMail into your AI agents today.

© 2026 AgentMail, Inc. All rights reserved.

Privacy PolicyTerms of ServiceSOC 2Subprocessors