# Table of Contents - [Welcome | AgentMail | Documentation](#welcome-agentmail-documentation) - [Welcome | AgentMail | Documentation](#welcome-agentmail-documentation) - [API Welcome | AgentMail | Documentation](#api-welcome-agentmail-documentation) - [Message Sent | AgentMail | Documentation](#message-sent-agentmail-documentation) - [Message Delivered | AgentMail | Documentation](#message-delivered-agentmail-documentation) - [Message Bounced | AgentMail | Documentation](#message-bounced-agentmail-documentation) - [Message Rejected | AgentMail | Documentation](#message-rejected-agentmail-documentation) - [Message Complained | AgentMail | Documentation](#message-complained-agentmail-documentation) - [Quickstart | AgentMail | Documentation](#quickstart-agentmail-documentation) - [Domain Verified | AgentMail | Documentation](#domain-verified-agentmail-documentation) - [Message Received | AgentMail | Documentation](#message-received-agentmail-documentation) - [Introduction | AgentMail | Documentation](#introduction-agentmail-documentation) - [Threads | AgentMail | Documentation](#threads-agentmail-documentation) - [Drafts | AgentMail | Documentation](#drafts-agentmail-documentation) - [Inboxes | AgentMail | Documentation](#inboxes-agentmail-documentation) - [Messages | AgentMail | Documentation](#messages-agentmail-documentation) - [MCP | AgentMail | Documentation](#mcp-agentmail-documentation) - [Attachments | AgentMail | Documentation](#attachments-agentmail-documentation) - [Labels | AgentMail | Documentation](#labels-agentmail-documentation) - [Guide: Sending & Receiving Email | AgentMail | Documentation](#guide-sending-receiving-email-agentmail-documentation) - [Replit | AgentMail | Documentation](#replit-agentmail-documentation) - [Pods | AgentMail | Documentation](#pods-agentmail-documentation) - [Connect | AgentMail | Documentation](#connect-agentmail-documentation) - [Integrate LiveKit Agents | AgentMail | Documentation](#integrate-livekit-agents-agentmail-documentation) --- # Welcome | AgentMail | Documentation ##### Welcome to AgentMail! We’re thrilled to have you here! Dive in to learn how to give your AI agents their own email inboxes. ![We're excited to have you onboard!](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2F9594f1f7c411d8f6e6a3d1e6de0661b1c8b82a57d29de765f0f90dc9da66149b%2Fassets%2Fdoc-intro.png&w=3840&q=75) We're excited to have you onboard! AgentMail is an API platform for giving AI agents their own inboxes to send, receive, and act upon emails. This allows agents to assume their own identity and communicate via the universal protocol of email with services, people, and other agents. Get Started ----------- [Introduction\ \ Learn about the core concepts and what makes AgentMail unique.](https://docs.agentmail.to/introduction) [Quickstart\ \ Create your first inbox and send an email in minutes.](https://docs.agentmail.to/quickstart) [API Reference\ \ Explore the full API with interactive examples.](https://docs.agentmail.to/api-reference) Need Help? ---------- [Join our Discord\ \ Ask questions and share your projects with the community.](https://discord.gg/hTYatWYWBc) [Email Support\ \ Get in touch with our team for personalized help.](mailto:support@agentmail.cc) --- # Welcome | AgentMail | Documentation ##### Welcome to AgentMail! We’re thrilled to have you here! Dive in to learn how to give your AI agents their own email inboxes. ![We're excited to have you onboard!](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2F9594f1f7c411d8f6e6a3d1e6de0661b1c8b82a57d29de765f0f90dc9da66149b%2Fassets%2Fdoc-intro.png&w=3840&q=75) We're excited to have you onboard! AgentMail is an API platform for giving AI agents their own inboxes to send, receive, and act upon emails. This allows agents to assume their own identity and communicate via the universal protocol of email with services, people, and other agents. Get Started ----------- [Introduction\ \ Learn about the core concepts and what makes AgentMail unique.](https://docs.agentmail.to/introduction) [Quickstart\ \ Create your first inbox and send an email in minutes.](https://docs.agentmail.to/quickstart) [API Reference\ \ Explore the full API with interactive examples.](https://docs.agentmail.to/api-reference) Need Help? ---------- [Join our Discord\ \ Ask questions and share your projects with the community.](https://discord.gg/hTYatWYWBc) [Email Support\ \ Get in touch with our team for personalized help.](mailto:support@agentmail.cc) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # API Welcome | AgentMail | Documentation Introduction ------------ AgentMail provides a powerful API for managing email communications programmatically. Whether you’re building automated testing systems, handling customer support workflows, or developing email-based applications, our API offers the tools you need! Available SDKs -------------- [Python SDK\ \ Use our Python SDK for seamless integration with your Python applications.](https://github.com/agentmail-to/agentmail-python) [Node SDK\ \ Use our Node SDK for seamless integration with your Node applications.](https://github.com/agentmail-to/agentmail-node) Contribute ---------- We welcome contributions to our SDKs. If you have any suggestions or improvements, please feel free to open a pull request! If you have any other languages you would like us to support, please [reach out to us](mailto:support@agentmail.cc) . License ------- All of our SDKs are open source and available under the MIT license. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Message Sent | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"message.sent"Required event\_idstringRequired ID of event. sendobjectRequired Show 5 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Message Delivered | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"message.delivered"Required event\_idstringRequired ID of event. deliveryobjectRequired Show 5 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Message Bounced | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"message.bounced"Required event\_idstringRequired ID of event. bounceobjectRequired Show 7 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Message Rejected | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"message.rejected"Required event\_idstringRequired ID of event. rejectobjectRequired Show 5 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Message Complained | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"message.complained"Required event\_idstringRequired ID of event. complaintobjectRequired Show 7 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Quickstart | AgentMail | Documentation This guide will walk you through installing the AgentMail SDK, authenticating with your API key, and creating your first email inbox. [1](https://docs.agentmail.to/quickstart#access-the-agentmail-console) ### Access the AgentMail Console First, you’ll need to access the AgentMail Console to manage your account and API keys. Click the link below to get started. [Open AgentMail Console](https://console.agentmail.to/) If you don’t have an account yet, you can sign up directly from the console. Once you’re logged in, you’ll be able to manage your inboxes, view analytics, and create API keys. [2](https://docs.agentmail.to/quickstart#create-an-api-key) ### Create an API Key Now that you’re in the console, you’ll need to create an API key to authenticate your requests. Navigate to the API Keys section in your console dashboard. ![API Key Creation Screenshot](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2F4e665f546efdf08d30178fcfbd996298ed7b3d1d44709fc742ed5315fed9532e%2Fassets%2Fapi-key-creation.png&w=3840&q=75) Click “Create New API Key” and give it a descriptive name. Once created, copy the API key and store it securely. Create a `.env` file in your project’s root directory and add your key to it. We recommend using environment variables to keep your keys secure. [3](https://docs.agentmail.to/quickstart#install-the-sdk) ### Install the SDK Install the AgentMail SDK using your preferred package manager. We’ll also use a library to load the environment variable from the `.env` file. PythonNode | | | | --- | --- | | $ | pip install agentmail python-dotenv | [4](https://docs.agentmail.to/quickstart#create-an-inbox-and-send-an-email) ### Create an inbox and send an email Now you’re ready to make your first API call. Create a new file (e.g., `quickstart.py` or `quickstart.ts`) and add the following code. This script will initialize the AgentMail client, create a new inbox, and then send a test email. PythonTypeScript | | | | --- | --- | | 1 | import os | | 2 | from dotenv import load\_dotenv | | 3 | from agentmail import AgentMail | | 4 | | | 5 | \# Load the API key from the .env file | | 6 | load\_dotenv() | | 7 | api\_key = os.getenv("AGENTMAIL\_API\_KEY") | | 8 | | | 9 | \# Initialize the client | | 10 | client = AgentMail(api\_key=api\_key) | | 11 | | | 12 | \# Create an inbox | | 13 | print("Creating inbox...") | | 14 | inbox = client.inboxes.create() # domain is optional | | 15 | print("Inbox created successfully!") | | 16 | print(inbox) | | 17 | | | 18 | \# Send Email | | 19 | | | 20 | client.inboxes.messages.send( | | 21 | inbox\_id="your-email@example.com", | | 22 | to="contact@agentmail.to", | | 23 | subject="Hello from AgentMail!", | | 24 | text="This is my first email sent with the AgentMail API." | | 25 | | | 26 | ) | The `domain` parameter is optional. If not provided, AgentMail will use the default `@agentmail.to` domain. If you would like a custom domain, please [upgrade to a paid plan](https://agentmail.to/pricing) . [5](https://docs.agentmail.to/quickstart#run-the-code) ### Run the code Execute the script from your terminal. PythonTypeScript | | | | --- | --- | | $ | python quickstart.py | You should see the details of your newly created inbox printed to the console. Congratulations, you’ve successfully created your first AgentMail inbox! Next Steps ---------- Congrats, you sent your first email via AgentMail. But this isn’t our strength. Explore the full power of creating agents that can autonomously reply, take action, parse attachments, semantically search your inbox, by exploring our docs and tutorials below. Looking for a different language? Email us at [support@agentmail.cc](mailto:support@agentmail.cc) and we’ll get you set up. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Domain Verified | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"domain.verified"Required event\_idstringRequired ID of event. domainobjectRequired Show 8 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Message Received | AgentMail | Documentation ### Headers svix-idstringRequired ID of webhook message. svix-signaturestringRequired Signature of webhook message. svix-timestampdatetimeRequired Timestamp of webhook message. ### Payload The payload of this webhook request is an object. type"event"Required event\_type"message.received"Required event\_idstringRequired ID of event. messageobjectRequired Show 23 properties threadobjectRequired Show 16 properties ### Response 200 any Return a 200 status to indicate that the data was received successfully. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Introduction | AgentMail | Documentation What is AgentMail? ------------------ AgentMail is an API platform for giving AI agents their own inboxes to send, receive, and act upon emails. We handle the infrastructure so you can focus on building email agents. **Email agents** can: * Have conversations with users in their inboxes * Automate email-based workflows for enterprises * Authenticate with third party applications * Act as first-class users on the internet The Problem with Traditional Email ---------------------------------- Existing email infrastructure was built for humans. Legacy providers such as Gmail and Outlook have several limitations for agentic use cases: No API for Inboxes Legacy providers lack API support for creating new inboxes on-demand. Per-Inbox Pricing They charge monthly subscriptions per inbox($12/inbox/month !!), which is costly for agents. Restrictive Limits They impose restrictive rate and sending limits not suitable for automation. Poor DX Overall, they offer a poor developer experience for building on top of email. The Gmail API sucks! The Solution ------------ AgentMail is an API-first email provider that is designed for agents. Think of it like Gmail, but with: [1](https://docs.agentmail.to/introduction#api-first-infrastructure) ### API-First Infrastructure **Programmatic Inboxes**: Create and manage inboxes via API. **Usage-Based Pricing**: Pay only for what you use. **High-Volume Ready**: No restrictive rate or sending limits. **Real-Time Events**: Get notified instantly with webhooks and websockets. **Simple Authentication**: Use API keys, no complex OAuth flows. [2](https://docs.agentmail.to/introduction#ai-native-features) ### AI-Native Features **Built-in Security**: Use API permissions and agent guardrails to control access. **Semantic Search**: Search across all inboxes in your organization by meaning. **Automatic Labeling**: Automatically categorize emails with user-defined prompts. **Structured Data Extraction**: Pull structured data from unstructured emails. And more on the way… Our customers use AgentMail for agent identity, authentication, and communication. To get started make an account on our [console](https://console.agentmail.to/) and please email [support@agentmail.cc](mailto:support@agentmail.cc) if you run into any issues. Get Started ----------- [Quickstart](https://docs.agentmail.to/quickstart) [API Reference](https://docs.agentmail.to/api-reference) Support ------- [Discord](https://discord.gg/hTYatWYWBc) [Email](mailto:support@agentmail.cc) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Threads | AgentMail | Documentation What is a Thread? ----------------- A `Thread` is an API resource that represents a single conversation. It acts as a container, grouping a series of related `Messages` together in chronological order, just like a conversation thread in a traditional email client. `Threads` are created automatically. When your agent sends a `Message` that isn’t a reply to a previous one, a new `Thread` is initiated. Any subsequent replies are automatically added to this same `Thread`, allowing your agent to easily maintain the context of a conversation over time. Querying `Threads` ------------------ While `Threads` are created implicitly, you can retrieve them in two powerful ways: scoped to a single `Inbox` or across your entire `Organization`. ### Listing `Threads` per `Inbox` This is the standard way to retrieve all the conversations associated with a single agent or `Inbox`. PythonTypeScript | | | | --- | --- | | 1 | \# You'll need an inbox ID to list threads from. | | 2 | inbox\_id = "inbound-agent@agentmail.to" | | 3 | | | 4 | \# This retrieves all threads within the specified Inbox | | 5 | | | 6 | inbox\_threads = client.inboxes.threads.list(inbox\_id=inbox\_id) | ### Listing `Threads` Across an `Organization` This is one of AgentMail’s most powerful features. By omitting the `inbox_id`, you can retrieve a list of `Threads` from **every `Inbox`** in your `Organization`. This org-wide querying capability is essential for building: * **Supervisor Agents:** An agent that monitors conversations from a fleet of other agents. * **Analytics Dashboards:** Building something where you need visibility across all inboxes across the organization * **Advanced Workflows:** Systems that can route or escalate conversations between different agents with different permissions. PythonTypeScript | | | | --- | --- | | 1 | \# By not providing an inbox\_id, we get all threads in the organization | | 2 | all\_threads = client.threads.list() | | 3 | | | 4 | print(f"Found {all\_threads.count} threads across the entire organization.") | ##### Coming Soon: Org-Wide Semantic Search We are actively developing semantic search for the organization-wide thread listing endpoint. Soon, you’ll be able to find `Threads` based on the meaning and concepts within the `Messages`, not just keywords. ### Getting a Single `Thread` You can also retrieve a single `Thread` by its ID. This will return the `Thread` object, which typically contains a list of all its associated `Messages` and their ID’s. A common workflow is listing the messages in a thread and calling the `messages.reply` method on the last one. PythonTypeScript | | | | --- | --- | | 1 | thread\_id = "thread\_456def" | | 2 | | | 3 | \# This retrieves a single thread and its messages | | 4 | | | 5 | thread = client.threads.get( | | 6 | thread\_id="thread\_id" | | 7 | ) | | 8 | | | 9 | print(f"Retrieved thread {thread.thread\_id} with {len(thread.messages)} messages.") | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Drafts | AgentMail | Documentation What is a Draft? ---------------- A `Draft` is an unsent `Message`. It’s a resource that allows your agent to prepare the contents of an email—including recipients, a subject, a body, and `Attachments`—without sending it immediately. We know agent reliability is big these days—with `Drafts` you can have agents have ready-to-send emails and only with your permission it can send them off into the world. `Drafts` are a key component for building advanced agent workflows. They enable: * **Human-in-the-Loop Review:** An agent can create a `Draft` for a sensitive or important `Message`, which a human can then review and approve before it’s sent. * **Scheduled Sending:** Your agent can create a `Draft` and then have a separate process send it at a specific time, such as during business hours for the recipient. * **Complex Composition:** For `Messages` that require multiple steps to build (e.g., fetching data from several sources, generating content), `Drafts` allow you to save the state of the email as it’s being composed. The `Draft` Lifecycle --------------------- You can interact with `Drafts` throughout their lifecycle, from creation to the moment they are sent. ### 1\. Create a `Draft` This is the first step. You create a `Draft` in a specific `Inbox` that will eventually be the sender. PythonTypeScript | | | | --- | --- | | 1 | \# You'll need an inbox ID to create a draft in. | | 2 | | | 3 | new\_draft=client.inboxes.drafts.create( | | 4 | inbox\_id="outbound@domain.com", | | 5 | to=\["review-team@example.com"\], | | 6 | subject="\[NEEDS REVIEW\] Agent's proposed response" | | 7 | ) | | 8 | | | 9 | print(f"Draft created successfully with ID: {new\_draft.draft\_id}") | ### 2\. Get `Draft` Once a `Draft` is created, you can retrieve it by its ID PythonTypeScript | | | | --- | --- | | 1 | \# Get the draft | | 2 | draft = client.inboxes.drafts.get(inbox\_id = “my\_inbox@domain.com”, draft\_id = “draft\_id\_123”) | ### 3\. Send a `Draft` This is the final step that converts the `Draft` into a sent `Message`. Once sent, the `Draft` is deleted. PythonTypeScript | | | | --- | --- | | 1 | \# This sends the draft and deletes it | | 2 | | | 3 | sent\_message = client.inboxes.drafts.send(inbox\_id = 'my\_inbox@domain.com', draft\_id = 'draft\_id\_123') | | 4 | | | 5 | print(f"Draft sent! New message ID: {sent\_message.message\_id}") | Note that now we access it by message\_id now because now its a message!! Org-Wide `Draft` Management --------------------------- Similar to `Threads`, you can list all `Drafts` across your entire `Organization`. This is perfect for building a central dashboard where a human supervisor can view, approve, or delete any `Draft` created by any agent in your fleet. PythonTypeScript | | | | --- | --- | | 1 | \# Get all drafts across the entire organization | | 2 | all\_drafts = client.drafts.list() | | 3 | | | 4 | print(f"Found {all\_drafts.count} drafts pending review.") | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Inboxes | AgentMail | Documentation What is an Inbox? ----------------- People are used to the traditional Gmail limitations — only having one inbox. That’s of the past. An `Inbox` is now a fully loaded, programmatically accessible API resource re-designed for the scale of AI Agents. Think of it as being similar to a Gmail or Outlook account, but built API-first. Each `Inbox` has a unique email address and serves as the primary resource your agent uses to send and receive emails, giving it a first-class identity on the internet. Unlike traditional email providers that are designed for human scale, AgentMail `Inboxes` are built to scale horizontally. You can create tens, hundreds, or even thousands of `Inboxes` for your agents on demand. Psst! Rather than sending 1000 emails from 1 `Inbox`, sending 10 emails across 100 `Inboxes` actually improves deliverability! Read more about optimizing for deliverability [here](https://docs.agentmail.to/best-practices/email-deliverability) ### The AgentMail Hierarchy As the diagram below illustrates, your `organization` is the top-level container that holds all your resources. You can provision many `Inboxes` within your `organization`, each with its own `Threads`, `Messages`, and `Attachments`, allowing you to manage a large fleet of agents seamlessly. ![AgentMail Organizational Hierarchy](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2F800085ec8545f404e194c8c6e463be1677715204ac5705be777fa95ace0e6d26%2Fassets%2Fhierarchy-diagram.png&w=3840&q=75) [1](https://docs.agentmail.to/inboxes#organization) ### Organization Your `organization` is the highest-level entity. It acts as a container for all your `Inboxes`, `Domains`, and API keys, allowing you to manage everything in one place. [2](https://docs.agentmail.to/inboxes#inbox) ### Inbox An `Inbox` is a single, scalable “email account” for your agent. You can create thousands of `Inboxes` within your organization, each with its own unique email address. [3](https://docs.agentmail.to/inboxes#thread) ### Thread A `Thread` represents a single conversation. It groups together all replies and forwards related to an initial email, keeping your interactions organized. [4](https://docs.agentmail.to/inboxes#message) ### Message A `Message` is an individual email. It contains the content, sender, recipients, and any associated metadata or `Attachments`. You can cc humans at any point in time to keep a “human-in-the-loop” [5](https://docs.agentmail.to/inboxes#attachment) ### Attachment An `Attachment` is a file that is sent along with a `Message`. You can programmatically access and download attachments from incoming `Messages`. Core Capabilities ----------------- Here at AgentMail we’ve now made an `Inbox` an API resource, meaning you can perform standard CRUD operations on it. Here are the core capabilities you’ll use to manage your `Inboxes`. PythonTypeScript | | | | --- | --- | | 1 | from agentmail import AgentMail | | 2 | | | 3 | \# Initialize the client | | 4 | client = AgentMail(api\_key="YOUR\_API\_KEY") | | 5 | | | 6 | \# --- Create an Inbox --- | | 7 | \# Creates a new inbox with a default agentmail.to domain | | 8 | new\_inbox = client.inboxes.create() | | 9 | print(f"Created Inbox: {new\_inbox.inbox\_id}") | | 10 | | | 11 | \# --- Retrieve an Inbox --- | | 12 | \# Gets a specific inbox by its ID | | 13 | retrieved\_inbox = client.inboxes.get(inbox\_id = 'my\_name@domain.com') | | 14 | print(f"Retrieved Inbox: {retrieved\_inbox.inbox\_id}") | | 15 | | | 16 | \# --- List Inboxes --- | | 17 | \# Lists all inboxes in your organization | | 18 | all\_inboxes = client.inboxes.list() | | 19 | | | 20 | print(f"Total Inboxes: {all\_inboxes.count}") | When creating an `Inbox`, the `username` and `domain` are optional. If you don’t provide them, AgentMail will generate a unique address for you using our default domain. Check out our [guide on managing domains](https://docs.agentmail.to/guides/domains/managing-domains) to learn more. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Messages | AgentMail | Documentation What is a Message? ------------------ In the AgentMail ecosystem, a `Message` is the API-first representation of a traditional email. It’s a structured object containing all the elements you’d expect: a sender, recipients, a subject line, and the body of the email. Every `Message` lives inside a `Thread` to keep conversations organized. When you send a new `Message`, a new `Thread` is created. When you reply, the new `Message` is added to the existing `Thread`. Literally a normal email thread as we know it. One of the powerful features of AgentMail is the ability to seamlessly include humans in agent-driven conversations. You can `cc` or `bcc` a real person on any message your agent sends, creating a “human-in-the-loop” workflow for oversight, escalations, or quality assurance. Core Capabilities ----------------- You can interact with `Message` resources in several ways, from sending new `Messages` to listing a history of correspondence. ### 1\. Initialize the Client First, you need to initialize the AgentMail client with your API key. This client object is your gateway to interacting with the AgentMail API. PythonTypeScript | | | | --- | --- | | 1 | from agentmail import AgentMail | | 2 | | | 3 | client = AgentMail(api\_key="YOUR\_API\_KEY") | ### 2\. Send a New `Message` To start a new conversation, you can send a `Message` from one of your inboxes. This action will create a new `Thread` and return the `Message` object. PythonTypeScript | | | | --- | --- | | 1 | \# You'll need an inbox ID to send from. | | 2 | \# Let's assume we have one: | | 3 | | | 4 | sent\_message = client.inboxes.messages.send( | | 5 | inbox\_id = 'my\_inbox@domain.com', | | 6 | to = 'recipient@domain.com', | | 7 | labels=\[ |\ | 8 | "outreach", |\ | 9 | "startup" |\ | 10 | \], | | 11 | subject="\[YC S25\] Founder Reachout ", | | 12 | text="Hello, I'm Michael, and I'm a founder at AgentMail...", | | 13 | html="
Hello,

I'm Michael, and I'm a founder at AgentMail..." | | 14 | ) | | 15 | print(f"Message sent successfully with ID: {sent\_message.message\_id}") | ### 3\. List `Messages` in an `Inbox` You can retrieve a list of all `Messages` within a specific `Inbox`. This is useful for getting a history of all correspondence. PythonTypeScript | | | | --- | --- | | 1 | all\_messages = client.inboxes.messages.list(inbox\_id='my\_inbox@agentmail.to') | | 2 | | | 3 | print(f"Found {all\_messages.count} messages in the inbox.") | ### 4\. Reply to a `Message` Replying to an existing `Message` adds your new `Message` to the same `Thread`, keeping the conversation organized. PythonTypeScript | | | | --- | --- | | 1 | \# Python example | | 2 | reply = client.inboxes.messages.reply( | | 3 | inbox\_id='my\_inbox@domain.com' | | 4 | message\_id='msg\_id', | | 5 | text="Thanks for the referral!", | | 6 | attachments=\[ |\ | 7 | SendAttachment( |\ | 8 | content="resume" # this would obviously be your resume content, refer to the attachment section of the core-concepts for more details |\ | 9 | ) |\ | 10 | \] | | 11 | ) | | 12 | | | 13 | print(f"Reply sent successfully with ID: {reply.message\_id}") | Note that the `inbox_id` in reply is different from send, in that this is the `inbox_id` we are sending FROM. Remember we can have potentially infinite `Inboxes` to send from, so we need to tell the api which one we are sending from. ### 5\. Get a `Message` You can retrieve the details of any specific `Message` by providing its ID along with the `inbox_id` it belongs to. PythonTypeScript | | | | --- | --- | | 1 | message = client.inboxes.messages.get(inbox\_id = 'my\_inbox@agentmail.to', message\_id = 'msg\_id') | | 2 | | | 3 | print(f"Retrieved message with subject: {message.subject}") | ### Crafting Your Message: HTML, Text, and CSS When sending a `Message`, you can provide the body in two formats: `text` for a plain-text version and `html` for a rich, styled version. * **`text`**: A simple, unformatted string. This is a fallback for email clients that don’t render HTML, ensuring your message is always readable. * **`html`**: A full HTML document. This allows you to create visually rich emails with custom layouts, colors, fonts, and images. **Best Practice**: Always send both `text` and `html` versions. ”Why both text and HTML?” ------------------------- Most modern email clients will display the HTML version, not all of them can render HTML — a text fallback makes sure your message is displayed regardless. Furthermore it significantly improves deliverability. #### Styling with CSS To style your HTML in the `Message`, you should embed your CSS directly inside a ` | | 88 | | | 89 | | | 90 |
| | 91 | | | 94 | | | 113 |
| | 114 | | | 118 | | | 119 | | ![rendered css](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa598fc722b5882421ffb977dc567bd75b4f4541b1e4ff7ab18657c7435b300dc%2Fassets%2Fcss-rendered.png&w=3840&q=75) Look how pretty this message looks! Receiving `Messages` -------------------- While you can periodically list `Messages` to check for new emails, the most efficient way to handle incoming `Messages` for your agents is with `Webhooks`. By configuring a `Webhook` endpoint, AgentMail can notify your application/agent in real-time as soon as a new `Message` arrives, so you can take action on them. [Guide: Webhooks\ \ Learn how to set up webhooks for real-time message processing.](https://docs.agentmail.to/overview) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # MCP | AgentMail | Documentation Getting started --------------- The Model Context Protocol (MCP) is an open standard that enables AI applications to connect with external tools and data sources. AgentMail provides an MCP server that allows any MCP-compatible client to interact with the AgentMail API. ### Setup To get started with the AgentMail MCP server, visit [mcp.agentmail.to](https://mcp.agentmail.to/) for installation instructions and configuration details. Features -------- The AgentMail MCP server provides tools for: * **Inbox management:** Create, list, and delete inboxes * **Message operations:** Send, receive, and reply to emails * **Thread management:** Access and manage email threads * **Attachments:** Handle email attachments Compatible clients ------------------ The AgentMail MCP server works with any MCP-compatible client, including: * Claude Desktop * Cursor * Windsurf * Other MCP-enabled AI applications For detailed setup instructions and available tools, visit [mcp.agentmail.to](https://mcp.agentmail.to/) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Attachments | AgentMail | Documentation What are `Attachments`? ----------------------- An `Attachment` is a file that is associated with a `Message`. This can be anything from a PDF invoice to a CSV report or an image(though we don’t recommend sending images in the first email sent. We go more into this in the [deliverability section](https://docs.agentmail.to/email-deliverability) ). Your agents can both send `Attachments` in outgoing `Messages` and process `Attachments` from incoming `Messages`. Sending `Attachments` --------------------- To send a file, you include it in an `Attachments` array when sending a `Message`. Each object in the array represents one file and must have a `content` property. * **`content`** (required): The Base64 encoded content of your file. * **`filename`** (optional): The name of the file (e.g., `invoice.pdf`). * **`content_type`** (optional): The MIME type of the file (e.g., `application/pdf`). PythonTypeScript | | | | --- | --- | | 1 | import base64 | | 2 | | | 3 | \# A simple text file for this example | | 4 | | | 5 | file\_content = "This is the content of our report." | | 6 | | | 7 | \# You must Base64 encode the file content before sending | | 8 | | | 9 | encoded\_content = base64.b64encode(file\_content.encode()).decode() | | 10 | | | 11 | sent\_message = client.inboxes.messages.send( | | 12 | inbox\_id="reports@agentmail.to", | | 13 | to=\["supervisor@example.com"\], | | 14 | subject="Q4 Financial Report", | | 15 | text="Please see the attached report.", | | 16 | attachments=\[{ |\ | 17 | "content": encoded\_content, |\ | 18 | "filename": "Q4-report.txt", |\ | 19 | "content\_type": "text/plain" |\ | 20 | }\] | | 21 | ) | Retrieving `Attachments` ------------------------ To retrieve an `Attachment`, you first need its `attachment_id`. You can get this ID from the `attachments` array on a `Message` object. Once you have the ID, you can download the file. The API response for getting an attachment is the raw file itself, which you can then save to disk or process in memory. ### From a Specific `Message` If you know the `Message` an `Attachment` belongs to, you can retrieve it directly. PythonTypeScript | | | | --- | --- | | 1 | inbox\_id = "inbox\_123" | | 2 | message\_id = "msg\_456" | | 3 | attachment\_id = "attach\_789" # From the message object | | 4 | | | 5 | file\_data = client.inboxes.messages.get\_attachment( | | 6 | inbox\_id=inbox\_id, | | 7 | message\_id=message\_id, | | 8 | attachment\_id=attachment\_id | | 9 | ) | | 10 | | | 11 | \# Now you can save the file | | 12 | | | 13 | with open("downloaded\_file.pdf", "wb") as f: | | 14 | f.write(file\_data) | ### From a Specific `Thread` Similarly, you can retrieve an `Attachment` if you know the `Thread` it’s in, which can be more convenient for multi-message conversations. PythonTypeScript | | | | --- | --- | | 1 | inbox\_id = "inbox\_123" | | 2 | thread\_id = "thread\_abc" | | 3 | attachment\_id = "attach\_789" # From a message within the thread | | 4 | | | 5 | file\_data = client.inboxes.threads.get\_attachment( | | 6 | inbox\_id=inbox\_id, | | 7 | thread\_id=thread\_id, | | 8 | attachment\_id=attachment\_id | | 9 | ) | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Labels | AgentMail | Documentation What are `Labels`? ------------------ `Labels` are simple, string-based tags that you can attach to your `Messages` and `Threads`. They are the primary mechanism for organizing, categorizing, and managing the state of your conversations, whether its automatically bucketing threads into specific categories for your outbound campaign, to segmenting warm leads for your outreach, to categorizing inbound into low-ticket, medium-ticket, high-ticket customers. A `Message` can have multiple `Labels`, allowing you to create a flexible and powerful system for managing complex workflows. Use Cases for `Labels` ---------------------- By strategically applying `Labels`, you can build sophisticated agent systems. Here are a few common use cases: [1](https://docs.agentmail.to/labels#state-management) ### State Management Use `Labels` to track the state of a conversation. For example, an agent could apply `needs-human-review` when it’s unsure how to respond, or a supervisor could apply `approved-to-send` to a `Draft`. [2](https://docs.agentmail.to/labels#campaign-tracking) ### Campaign Tracking When running outbound campaigns, tag every `Message` with a unique campaign `Label` like `q4-2024-outreach`, or `mercor-campaign` and adding a second tag as `warm-lead`. This allows you to easily filter for and analyze the performance of that specific campaign later on. [3](https://docs.agentmail.to/labels#automated-triage) ### Automated Triage An inbound agent can classify incoming `Messages` with `Labels` like `billing-question`, `feature-request`, or `bug-report`, allowing specialized agents or human teams to handle them efficiently. Core Capabilities ----------------- Here’s how you can programmatically work with `Labels`. ### 1\. Adding `Labels` When Sending a `Message` You can attach an array of `Labels` directly when you send a `Message`. PythonTypeScript | | | | --- | --- | | 1 | sent\_message = client.inboxes.messages.send( | | 2 | inbox\_id="outbound@agentmail.to", | | 3 | to=\["test@example.com"\], | | 4 | subject="Following up on our conversation", | | 5 | text="Here is the information you requested.", | | 6 | labels=\["follow-up", "q4-campaign"\] | | 7 | ) | ### 2\. Adding or Removing `Labels` on an Existing `Message` You can modify the `Labels` on a `Message` that has already been sent using the `update` (PATCH) method. This is perfect for changing the state of a conversation as your agent works on it. PythonTypeScript | | | | --- | --- | | 1 | \# Let's add a 'resolved' label to a message | | 2 | | | 3 | client.messages.update( | | 4 | inbox\_id='outbound@domain.com', | | 5 | message\_id='msg\_id\_123', | | 6 | add\_labels=\["resolved"\], | | 7 | remove\_labels=\['unresolved'\] | | 8 | ) | ### 3\. Filtering by `Labels` This is where `Labels` become truly powerful. You can list `Threads`, `Messages`, and `Drafts` by filtering for one or more `Labels`, allowing you to create highly targeted queries. PythonTypeScript | | | | --- | --- | | 1 | \# Find all threads from a specific campaign that need a follow-up | | 2 | filtered\_threads = client.inboxes.threads.list( | | 3 | inbox\_id = 'outbound-agent@domain.com', | | 4 | labels=\[ |\ | 5 | "q4-campaign", |\ | 6 | "follow\_up" |\ | 7 | \] | | 8 | ) | | 9 | | | 10 | print(f"Found {filtered\_threads.count} threads that need a follow-up.") | Best Practices -------------- * **Be Consistent:** Establish a clear and consistent naming convention for your labels (e.g., `kebab-case`, `snake_case`). * **Use Prefixes:** For state management, consider using prefixes like `status-pending` or `priority-high` to create an organized system. * **Don’t Over-Label:** While you can add many `Labels`, aim for a concise and meaningful set to keep your system manageable. ##### Coming Soon: AI-Powered Auto-Labeling We are actively developing an AI-powered auto-labeling feature. Soon, your agents will be able to provide a set of `Labels` and instructions, and AgentMail will automatically apply the correct `Labels` to incoming `Messages` based on their content. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Guide: Sending & Receiving Email | AgentMail | Documentation This guide walks you through the complete, practical workflow of an agent having a conversation. While the `Core Concepts` pages detail the individual API calls, this guide shows you how to stitch them together to create a functional conversational loop. The Foundation: Sending HTML & Text ----------------------------------- As a quick reminder from our `Messages` documentation, it’s a critical best practice to always provide both an `html` and a `text` version of your email. This ensures readability on all email clients and significantly improves deliverability. | | | | --- | --- | | 1 | \# Always provide both html and text when possible | | 2 | client.inboxes.messages.send( | | 3 | inbox\_id="outreach@agentmail.to", | | 4 | to=\["potential-customer@example.com"\], | | 5 | subject="Following up", | | 6 | text="Hi Jane,\\n\\nThis is a plain-text version of our email.", | | 7 | html="

Hi Jane,

This is a rich HTML version of our email.

", | | 8 | labels=\["outreach-campaign"\] | | 9 | ) | The Conversational Loop ----------------------- A common task for an agent is to check for replies in an `Inbox` and then respond to them. While using `Webhooks` is the most efficient method for this, you can also build a simple polling mechanism. Here’s the step-by-step logic for a polling-based conversational agent. [1](https://docs.agentmail.to/sending-receiving-email#1-find-a-thread-that-needs-a-reply) ### 1\. Find a Thread that Needs a Reply First, you need to identify which conversations have new messages that your agent hasn’t responded to. A great way to manage this is with `Labels`. You can list `Threads` in a specific `Inbox` that have an `unreplied` `Label`. PythonTypeScript | | | | --- | --- | | 1 | \# Find all threads in this inbox that are marked as unreplied | | 2 | threadsRes = client.threads.list( | | 3 | labels = \["unreplied"\] | | 4 | ) | | 5 | if threadsRes.count == 0: | | 6 | print("No threads need a reply.") | | 7 | else: | | 8 | # Let's work on the first unreplied thread | | 9 | thread\_to\_reply\_to = threadsRes.thread\[0\] | [2](https://docs.agentmail.to/sending-receiving-email#2-get-the-last-message-id-from-the-thread) ### 2\. Get the Last Message ID from the Thread To reply to a conversation, you need to reply to the _most recent message_ in the `Thread`. You can get a specific `Thread` by its ID, which will contain a list of all its `Messages`. You’ll then grab the ID of the last `Message` in that list. PythonTypeScript | | | | --- | --- | | 1 | \# Get the full thread object to access its messages | | 2 | thread\_details = client.threads.get(thread\_to\_reply\_to.thread\_id) | | 3 | | | 4 | \# The last message in the list is the one we want to reply to | | 5 | last\_message = thread\_details.messages\[-1\] | | 6 | message\_id\_to\_reply\_to = last\_message.message\_id | [3](https://docs.agentmail.to/sending-receiving-email#3-send-the-reply-and-update-labels) ### 3\. Send the Reply and Update Labels Now that you have the `message_id` to reply to, you can send your agent’s response. It’s also a best practice to update the `Labels` on the original `Message` at the same time, removing the `unreplied` `Label` and adding a `replied` `Label` to prevent the agent from replying to the same message twice. PythonTypeScript | | | | --- | --- | | 1 | \# Send the reply | | 2 | client.inboxes.messages.reply( | | 3 | inbox\_id="support@agentmail.to", | | 4 | message\_id=message\_id\_to\_reply\_to, | | 5 | text="This is our agent's helpful reply!" | | 6 | ) | | 7 | | | 8 | \# Update the labels on the original message | | 9 | client.inboxes.messages.update( | | 10 | inbox\_id="support@agentmail.to", | | 11 | message\_id=message\_id\_to\_reply\_to, | | 12 | add\_labels=\["replied"\], | | 13 | remove\_labels=\["unreplied"\] | | 14 | ) | ##### Real-Time Processing with Webhooks For production applications, polling is inefficient. The best way to handle incoming replies is to use `Webhooks`. This allows AgentMail to notify your agent instantly when a new `Message` arrives, so you can reply in real-time. [**Learn how to set up `Webhooks` →**](https://docs.agentmail.to/overview) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Replit | AgentMail | Documentation Getting started --------------- Replit is a cloud-based app and agent builder with a built in IDE, AI assistant, and deployment infrastructure. AgentMail is a “connector” integration on Replit, meaning your Replit apps and agents can use it directly. ### Setup Navigate to the Intregrations tab in the Replit builder. Find AgentMail and click Connect/Sign in. Then paste in your AgentMail API key from the AgentMail Console. That’s it. How it works ------------ Replit uses Mastra, a TypeScript framework for building agents. Everytime you create a new app/agent Replit will generate a set of Mastra tools to interface with the AgentMail API, based on your use case and requirements. Below is a collections of prebuilt tools that Replit can use out of the box to serve virtually any use case. ### Tools TypeScript | | | | --- | --- | | 1 | import { createTool } from '@mastra/core/tools' | | 2 | import { z } from 'zod' | | 3 | | | 4 | import { AgentMailClient } from 'agentmail' | | 5 | | | 6 | const ListItemsInput = z.object({ | | 7 | limit: z.number().optional().describe('Max number of items to return'), | | 8 | pageToken: z.string().optional().describe('Pagination page token'), | | 9 | }) | | 10 | | | 11 | const InboxId = z.string().describe('ID of inbox') | | 12 | | | 13 | const GetInboxInput = z.object({ inboxId: InboxId }) | | 14 | | | 15 | const CreateInboxInput = z.object({ | | 16 | username: z.string().optional().describe('Username'), | | 17 | domain: z.string().optional().describe('Domain'), | | 18 | displayName: z.string().optional().describe('Display name'), | | 19 | }) | | 20 | | | 21 | const ListInboxItemsInput = ListItemsInput.extend({ | | 22 | inboxId: InboxId, | | 23 | labels: z.array(z.string()).optional().describe('Filter items with labels'), | | 24 | before: z.coerce.date().optional().describe('Filter items before datetime'), | | 25 | after: z.coerce.date().optional().describe('Filter items after datetime'), | | 26 | }) | | 27 | | | 28 | const GetThreadInput = GetInboxInput.extend({ | | 29 | threadId: z.string().describe('ID of thread'), | | 30 | }) | | 31 | | | 32 | const MessageId = z.string().describe('ID of message') | | 33 | | | 34 | const BaseMessageInput = z.object({ | | 35 | inboxId: InboxId, | | 36 | text: z.string().optional().describe('Plain text body'), | | 37 | html: z.string().optional().describe('HTML body'), | | 38 | labels: z.array(z.string()).optional().describe('Labels'), | | 39 | }) | | 40 | | | 41 | const SendMessageInput = BaseMessageInput.extend({ | | 42 | to: z.union(\[z.string(), z.array(z.string())\]).describe('To recipients'), | | 43 | cc: z | | 44 | .union(\[z.string(), z.array(z.string())\]) | | 45 | .optional() | | 46 | .describe('CC recipients'), | | 47 | bcc: z | | 48 | .union(\[z.string(), z.array(z.string())\]) | | 49 | .optional() | | 50 | .describe('BCC recipients'), | | 51 | subject: z.string().optional().describe('Subject'), | | 52 | }) | | 53 | | | 54 | const ReplyToMessageInput = BaseMessageInput.extend({ messageId: MessageId }) | | 55 | | | 56 | const UpdateMessageInput = z.object({ | | 57 | inboxId: InboxId, | | 58 | messageId: MessageId, | | 59 | addLabels: z.array(z.string()).optional().describe('Labels to add'), | | 60 | removeLabels: z.array(z.string()).optional().describe('Labels to remove'), | | 61 | }) | | 62 | | | 63 | const listInboxesTool = createTool({ | | 64 | id: 'list-inboxes', | | 65 | description: 'List inboxes', | | 66 | inputSchema: ListItemsInput, | | 67 | execute: ({ context }) => { | | 68 | const client = new AgentMailClient() | | 69 | return client.inboxes.list(context) | | 70 | }, | | 71 | }) | | 72 | | | 73 | const createInboxTool = createTool({ | | 74 | id: 'create-inbox', | | 75 | description: 'Create inbox', | | 76 | inputSchema: CreateInboxInput, | | 77 | execute: ({ context }) => { | | 78 | const client = new AgentMailClient() | | 79 | return client.inboxes.create(context) | | 80 | }, | | 81 | }) | | 82 | | | 83 | const deleteInboxTool = createTool({ | | 84 | id: 'delete-inbox', | | 85 | description: 'Delete inbox', | | 86 | inputSchema: GetInboxInput, | | 87 | execute: ({ context }) => { | | 88 | const client = new AgentMailClient() | | 89 | return client.inboxes.delete(context.inboxId) | | 90 | }, | | 91 | }) | | 92 | | | 93 | const listThreadsTool = createTool({ | | 94 | id: 'list-threads', | | 95 | description: 'List threads', | | 96 | inputSchema: ListInboxItemsInput, | | 97 | execute: ({ context }) => { | | 98 | const client = new AgentMailClient() | | 99 | return client.inboxes.threads.list(context.inboxId, context) | | 100 | }, | | 101 | }) | | 102 | | | 103 | const getThreadTool = createTool({ | | 104 | id: 'get-thread', | | 105 | description: 'Get thread and its messages', | | 106 | inputSchema: GetThreadInput, | | 107 | execute: ({ context }) => { | | 108 | const client = new AgentMailClient() | | 109 | return client.inboxes.threads.get(context.inboxId, context.threadId) | | 110 | }, | | 111 | }) | | 112 | | | 113 | const sendMessageTool = createTool({ | | 114 | id: 'send-message', | | 115 | description: 'Send message', | | 116 | inputSchema: SendMessageInput, | | 117 | execute: ({ context }) => { | | 118 | const client = new AgentMailClient() | | 119 | return client.inboxes.messages.send(context.inboxId, context) | | 120 | }, | | 121 | }) | | 122 | | | 123 | const replyToMessageTool = createTool({ | | 124 | id: 'reply-to-message', | | 125 | description: 'Reply to message', | | 126 | inputSchema: ReplyToMessageInput, | | 127 | execute: ({ context }) => { | | 128 | const client = new AgentMailClient() | | 129 | return client.inboxes.messages.reply(context.inboxId, context.messageId, context) | | 130 | }, | | 131 | }) | | 132 | | | 133 | const updateMessageTool = createTool({ | | 134 | id: 'update-message', | | 135 | description: 'Update message', | | 136 | inputSchema: UpdateMessageInput, | | 137 | execute: ({ context }) => { | | 138 | const client = new AgentMailClient() | | 139 | return client.inboxes.messages.update(context.inboxId, context.messageId, context) | | 140 | }, | | 141 | }) | | 142 | | | 143 | export const tools = { | | 144 | listInboxesTool, | | 145 | createInboxTool, | | 146 | deleteInboxTool, | | 147 | listThreadsTool, | | 148 | getThreadTool, | | 149 | sendMessageTool, | | 150 | replyToMessageTool, | | 151 | updateMessageTool, | | 152 | } | About AgentMail --------------- AgentMail is the email inbox API for AI agents. It gives agents their own email inboxes, like Gmail does for humans. Unlike other email APIs, AgentMail is for both sending and receiving, supporting two-way email conversations. Email is critical to identity and communication on the internet. Much of the context that people use for their work exists within email. AgentMail enables AI agents to meet people where they work and use the internet like humans do. ### Features 1. **Programmatic inboxes:** Create, manage, and delete inboxes via API 2. **Threads and replies:** Facilitate 2-way emals conversations with persistant and relevant context 3. **Attachments:** Send, receive, and download attachments so agents can work with documents 4. **Realtime events:** Build event-driven agents and systems with Webhooks and Websockets 5. **Custom domains:** Whitelabel your or your customers’ inboxes to automate client-facing work 6. **Language/Framework SDKs:** Use your prefered language and framework ### Use cases 1. **Process inbound:** Receive, triage, and process inbound emails 2. **Automate outbound:** Draft, schedule, and send outbound emails 3. **Join conversations:** Address an agent directly or CC it in an existing email thread 4. **Identify and authenticate:** Agents can sign up, receive 2FA code, and authenticate with any application ### Verticals 1. **Operations:** Automate internal workflows, vendor communications, and cross-team coordination 2. **Support:** Handle customer inquiries, ticket management, and automated responses at scale 3. **Procurement:** Streamline vendor onboarding, RFP processes, and purchase order management 4. **Sales:** Automate lead qualification, follow-ups, and customer outreach campaigns 5. **Recruiting:** Automate candidate outreach, interview scheduling, and applicant communication These are just a few select verticals, but we have seen AgentMail be effective in automating any email task across every function. If a human does it with email, it can be automated with AgentMail. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Pods | AgentMail | Documentation What are Pods? -------------- Pods are an isolated abstraction that sits between your **organization** and your **inboxes**, providing a method to segment and organize email infrastructure for multi-tenant applications. If you’re building a service that offers email functionality to your customers, pods are your key to ensure customer resource isolation. ### The Hierarchy | | | --- | | Organization (Your Business) | | └── Pod (Your Customer A) | | ├── Inbox 1 | | ├── Inbox 2 | | └── Domain 1 | | └── Pod (Your Customer B) | | ├── Inbox 3 | | ├── Inbox 4 | | └── Domain 2 | **Organization**: Your company’s AgentMail account * You have one organization that represents your business **Pod**: Each of your customers * Create one pod per customer/tenant in your system * Pods provide complete isolation between your customers’ data * All resources (inboxes, domains, threads, drafts) can be scoped to a pod **Inbox**: Individual email accounts within a pod * Your customers can have multiple inboxes within their pod * It is on you to provision resources for each of your customers Why Use Pods? ------------- ### Multi-Tenancy Pods enable you to offer AgentMail’s email infrastructure to your own customers while maintaining strict data isolation. Here’s how our customers use pods: **SaaS/Agency Platforms**: Create a pod for each customer account. Each customer gets their own isolated email workspace. **White-Label Email**: Offer email services under your own brand. Each end-user gets their own pod with complete data isolation. **AI Agent Platforms**: Give each AI agent with its own purpose its own pod with dedicated inboxes and domains. How Pods Work ------------- ### Pod Lifecycle As a basis, here are a couple of logistical stuff that happens on the API side when you create resources. * When you sign up, you are automatically created a `Default Pod`, and all resources created whether its `Inboxes` or `Domains` all are associated with this `Default Pod`. * You cannot delete a `Pod` that has existing children resources. Make sure to delete any existing `Inboxes` or `Domains` before deleting a `Pod`. ### What You Can Do With Pods #### Creating Resources You can create the following resources **within** a pod: * **Inboxes** * **Domains** NOTE: as of now domains can only be either scoped to one pod, or all pods. I.E it is not possible to create a domain scoped to more than one but not all pods. TIP: specify a `client_id` when creating a `Pod` so that you can decide how to uniquely identify pods. That way you don’t need to create a table mapping your `organization_id`’s for your customers or segment of your business to our `pod_id`’s you can just set the `client_id` as your internal id so you can access the resource using a unique identifier determined by you! These resources are automatically associated with the pod and inherit its isolation guarantees. #### Listing Resources You can list the following resources **scoped to** a pod: * **Inboxes** (`GET /pods/{pod_id}/inboxes`) - View all inboxes in a pod * **Threads** (`GET /pods/{pod_id}/threads`) - View all email conversations across all inboxes in the pod * **Drafts** (`GET /pods/{pod_id}/drafts`) - View all draft emails across all inboxes in the pod * **Domains** (`GET /pods/{pod_id}/domains`) - View all custom domains in the pod This gives you a unified view of all activity within a customer’s workspace, making it easy to build features like: * “Show me all unread emails for Customer X” (use labels here too!) * “List all threads across all of Customer Y’s team inboxes” * “Display all pending drafts for Customer Z” Important Considerations ------------------------ ### Pod Deletion Constraints **Critical**: You cannot delete a pod that has resources still attached to it. You must delete all inboxes and domains within the pod before you can delete the pod itself. This is a safety mechanism to prevent accidental data loss. Here’s the correct deletion sequence: | | | | --- | --- | | 1 | // This will FAIL if the pod has any resources | | 2 | await client.pods.delete(podId); | | 3 | | | 4 | // Correct approach: Clean up resources first | | 5 | async function offboardCustomer(podId: string) { | | 6 | // 1. Delete all inboxes | | 7 | const inboxRes = await client.inboxes.list(podId); | | 8 | for (const inbox of inboxRes.inboxes) { | | 9 | await client.inboxes.delete(inbox.inbox\_id); | | 10 | } | | 11 | | | 12 | // 2. Delete all domains | | 13 | const domainRes = await client.domains.list({ podId }); | | 14 | for (const domain of domainRes.domains) { | | 15 | await client.domains.delete(domain.domain\_id); | | 16 | } | | 17 | | | 18 | // 3. Now you can delete the pod | | 19 | await client.pods.delete(podId); | | 20 | } | When you delete an inbox or domain, all associated data (messages, threads, drafts) is automatically cleaned up. You don’t need to manually delete individual threads or messages. **What’s NOT Isolated to a Pod:** * API keys (these are organization-level and can access any resources in any pod) Common Patterns and Use Cases ----------------------------- ### Pattern 1: Multi-Tenant SaaS Each company using your platform gets their own pod: | | | | --- | --- | | 1 | // Customer A's workspace | | 2 | Pod: "Acme Corp" | | 3 | ├── Inbox: support@acme.com | | 4 | ├── Inbox: sales@acme.com | | 5 | └── Domain: acme.com | | 6 | | | 7 | // Customer B's workspace | | 8 | Pod: "TechStart Inc" | | 9 | ├── Inbox: hello@techstart.io | | 10 | ├── Inbox: team@techstart.io | | 11 | └── Domain: techstart.io | ### Pattern 2: Agency Client Management Each client gets their own isolated pod: | | | | --- | --- | | 1 | // Client 1 | | 2 | Pod: "Client - Retail Co" | | 3 | ├── Inbox: info@retailco.com | | 4 | └── Domain: retailco.com | | 5 | | | 6 | // Client 2 | | 7 | Pod: "Client - FinTech" | | 8 | ├── Inbox: support@fintech.ai | | 9 | └── Domain: fintech.ai | ### Pattern 3: AI Agent Platform Each AI agent gets its own pod with dedicated email infrastructure: | | | | --- | --- | | 1 | // Agent 1: Customer Support Agent | | 2 | Pod: "Support-Agent" | | 3 | ├── Inbox: support@mycompany.com | | 4 | ├── Inbox: help@mycompany.com | | 5 | └── Inbox: tickets@mycompany.com | | 6 | | | 7 | // Agent 2: Sales Outreach Agent | | 8 | Pod: "Sales-Agent" | | 9 | ├── Inbox: sales@mycompany.com | | 10 | ├── Inbox: outreach@mycompany.com | | 11 | └── Inbox: leads@mycompany.com | | 12 | | | 13 | // Agent 3: Marketing Agent | | 14 | Pod: "Marketing-Agent" | | 15 | ├── Inbox: newsletter@mycompany.com | | 16 | ├── Inbox: campaigns@mycompany.com | | 17 | └── Inbox: events@mycompany.com | FAQ --- ###### Can inboxes communicate between pods? Yes! Inboxes in different pods can send and receive emails from each other just like any other email addresses. Pods only provide organizational isolation, not network isolation. ###### Can I move an inbox from one pod to another? No, inboxes cannot be moved between pods. You will need to create a new inbox in the pod you want. ###### How many pods can I create? There’s no hard limit on the number of pods. You can create as many as you need for your customers. ###### Do I need to use pods? Pods are optional but highly recommended for multi-tenant applications. If you’re only managing email for your own organization, you can work directly with inboxes without creating pods. ###### Can I set custom permissions per pod? Pod isolation is upon the caller (you). As of now we don’t support pod-scoped API keys so it will be on you to make the calls to AgentMail. Next Steps ---------- * Learn about [Inboxes](https://docs.agentmail.to/inboxes) and how to create email accounts within pods * Explore [Domains](https://docs.agentmail.to/custom-domains) to set up custom email domains for your pods [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Connect | AgentMail | Documentation Handshake[Try it](https://docs.agentmail.to/api-reference/websockets/websockets?explorer=true) ----------------------------------------------------------------------------------------------- WSS wss://ws.agentmail.to/v0 ### Query parameters auth\_tokenstringOptional Your API key. Required if Authorization header is not set. ### Send subscribeobjectRequired Show 4 properties ### Receive subscribedobjectRequired Show 4 properties OR message\_receivedobjectRequired Show 5 properties OR message\_sentobjectRequired Show 4 properties OR message\_deliveredobjectRequired Show 4 properties OR message\_bouncedobjectRequired Show 4 properties OR message\_complainedobjectRequired Show 4 properties OR message\_rejectedobjectRequired Show 4 properties OR domain\_verifiedobjectRequired Show 4 properties [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) --- # Integrate LiveKit Agents | AgentMail | Documentation Overview -------- This guide walks you through building a voice assistant with real time email capabilites. We use the LiveKit Agents SDK to build the voice functionality. Prequisites ----------- Follow the [LiveKit voice AI quickstart](https://docs.livekit.io/agents/start/voice-ai/) to build a simple voice assistant. In this guide we will extend the functionality to this assistant to email. You should have a file named `agent.py` which we will modify. Setup ----- Install python packages | | | | --- | --- | | $ | pip install agentmail agentmail-toolkit | Set environment variables | | | | --- | --- | | 1 | AGENTMAIL\_API\_KEY= | | 2 | AGENTMAIL\_USERNAME= | Code ---- To the `agent.py` file add the following imports | | | | --- | --- | | 1 | import os | | 2 | import asyncio | | 3 | | | 4 | from agentmail import AgentMail, AsyncAgentMail, Subscribe, MessageReceivedEvent | | 5 | from agentmail\_toolkit.livekit import AgentMailToolkit | Then add the `EmailAssistant` class | | | | --- | --- | | 1 | class EmailAssistant(Agent): | | 2 | inbox\_id: str | | 3 | ws\_task: asyncio.Task \| None = None | | 4 | | | 5 | def \_\_init\_\_(self) -> None: | | 6 | client = AgentMail() | | 7 | | | 8 | # By setting the client\_id the inbox is created only once. | | 9 | username = os.getenv("AGENTMAIL\_USERNAME") | | 10 | inbox = client.inboxes.create(username=username, client\_id=f"{username}-inbox") | | 11 | | | 12 | self.inbox\_id = inbox.inbox\_id | | 13 | | | 14 | super().\_\_init\_\_( | | 15 | instructions=f""" | | 16 | You are a helpful voice and email AI assistant. Your name is AgentMail. You can receive emails at {self.inbox\_id}. You can also send and reply to emails. | | 17 | When using email tools, use "{self.inbox\_id}" as the inbox\_id parameter. When writing emails, include "AgentMail" in the signature. | | 18 | Always speak in English. | | 19 | IMPORTANT: {self.inbox\_id} is your inbox, not the user's inbox. | | 20 | """, | | 21 | # The AgentMail Toolkit has ready-to-go tools for LiveKit agents. | | 22 | tools=AgentMailToolkit(client=client).get\_tools( | | 23 | \[ |\ | 24 | "list\_threads", |\ | 25 | "get\_thread", |\ | 26 | "get\_attachment", |\ | 27 | "send\_message", |\ | 28 | "reply\_to\_message", |\ | 29 | \] | | 30 | ), | | 31 | ) | | 32 | | | 33 | async def \_websocket\_task(self): | | 34 | # Open a websocket connection to AgentMail. | | 35 | async with AsyncAgentMail().websockets.connect() as socket: | | 36 | # Subscribe to events from the inbox. | | 37 | await socket.send\_subscribe(Subscribe(inbox\_ids=\[self.inbox\_id\])) | | 38 | | | 39 | while True: | | 40 | data = await socket.recv() | | 41 | | | 42 | # If a message is received by the inbox, interrupt the current conversation and generate a reply. | | 43 | if isinstance(data, MessageReceived): | | 44 | self.session.interrupt() | | 45 | | | 46 | await self.session.generate\_reply( | | 47 | instructions=f"""Say "I've received an email" and then read the email.""", | | 48 | user\_input=data.message.model\_dump\_json(), | | 49 | ) | | 50 | | | 51 | # Open the websocket connection and generate a greeting when the agent enters the call. | | 52 | async def on\_enter(self): | | 53 | self.ws\_task = asyncio.create\_task(self.\_websocket\_task()) | | 54 | | | 55 | await self.session.generate\_reply( | | 56 | instructions=f"""In English, greet the user, introduce yourself as AgentMail, inform them that you can "receive emails" at {self.inbox\_id}, and offer your assistance.""", | | 57 | allow\_interruptions=False, | | 58 | ) | | 59 | | | 60 | # Close the websocket connection when the agent exits the call. | | 61 | async def on\_exit(self): | | 62 | if self.ws\_task: | | 63 | self.ws\_task.cancel() | Finally update the `entrypoint` function | | | | --- | --- | | 1 | await session.start( | | 2 | room=ctx.room, | | 3 | agent=EmailAssistant(), # Replace Assistant with EmailAssistant. | | 4 | room\_input\_options=RoomInputOptions( | | 5 | noise\_cancellation=noise\_cancellation.BVC() | | 6 | ), | | 7 | ) | That’s It --------- Run your agent inside the terminal and send it an email | | | | --- | --- | | $ | python agent.py console | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fagentmail-production.docs.buildwithfern.com%2Fa2c13461e6ac727fd49c2914d55cc11ed173a3358c332751cfb97d21664e09da%2Fassets%2Flogos%2Fagentmail-logo-landscape.png&w=3840&q=100)](https://docs.agentmail.to/) [contact@agentmail.cc](mailto:contact@agentmail.cc) [Discord](https://discord.gg/hTYatWYWBc) ---