LangChain is the most popular framework for building LLM-powered applications. Its tool abstraction makes it straightforward to extend any agent with new capabilities, and email is no exception. With AgentSend, you can give your LangChain agent a real email address and the ability to send, receive, and manage threaded email conversations, all through a simple tool wrapper.
This guide walks through building a LangChain tool that wraps AgentSend's REST API, so your agent can autonomously compose and send emails, check its inbox, and reply to ongoing threads. The same approach works with LangGraph, LCEL chains, and any LangChain-compatible agent executor.
Why LangChain Agents Need Email
Most LangChain agents interact with APIs, databases, and search engines. But when an agent needs to communicate with a human outside your application, email is often the most practical channel. Consider these use cases:
- Customer support agents that receive support requests via email, look up account information, and reply with resolutions, all without human intervention.
- Sales outreach agents that send personalized follow-ups based on CRM data and respond to replies in context.
- Research assistants that email stakeholders with summaries, then handle clarification questions in threaded replies.
- Monitoring agents that detect anomalies and email relevant team members with detailed reports.
Without a proper email tool, developers resort to hacks: piping output through SMTP libraries, hardcoding credentials, or building brittle email integrations from scratch. AgentSend eliminates this by providing a clean API purpose-built for agent communication.
Setting Up AgentSend
Before writing the LangChain tool, you need an AgentSend account and an API key. Sign up at agentsend.io, create an inbox, and grab your API key from the dashboard. The free tier includes 10 emails per day, enough to build and test your integration.
Install the required packages:
pip install langchain langchain-openai requests
Building the LangChain Email Tool
LangChain's StructuredTool class lets you define tools with typed input schemas. Here is a complete tool that wraps AgentSend's send and receive endpoints:
import os import requests from typing import Optional from pydantic import BaseModel, Field from langchain.tools import StructuredTool AGENTSEND_API_KEY = os.environ["AGENTSEND_API_KEY"] AGENTSEND_BASE = "https://agentsend.io" class SendEmailInput(BaseModel): to: str = Field(description="Recipient email address") subject: str = Field(description="Email subject line") body: str = Field(description="Plain text email body") inbox_id: str = Field(description="AgentSend inbox ID") thread_id: Optional[str] = Field( default=None, description="Thread ID for replies (omit for new conversations)" ) def send_email( to: str, subject: str, body: str, inbox_id: str, thread_id: Optional[str] = None, ) -> str: """Send an email via AgentSend.""" payload = { "inboxId": inbox_id, "to": to, "subject": subject, "text": body, } if thread_id: payload["threadId"] = thread_id resp = requests.post( f"{AGENTSEND_BASE}/messages", json=payload, headers={"Authorization": f"Bearer {AGENTSEND_API_KEY}"}, ) resp.raise_for_status() data = resp.json() return f"Email sent. Message ID: {data['id']}, Thread: {data['threadId']}" class CheckInboxInput(BaseModel): inbox_id: str = Field(description="AgentSend inbox ID to check") def check_inbox(inbox_id: str) -> str: """Check for new messages in an AgentSend inbox.""" resp = requests.get( f"{AGENTSEND_BASE}/inboxes/{inbox_id}/messages", headers={"Authorization": f"Bearer {AGENTSEND_API_KEY}"}, ) resp.raise_for_status() messages = resp.json().get("messages", []) if not messages: return "No new messages." summary = [] for msg in messages[:5]: summary.append( f"From: {msg['from']}, Subject: {msg['subject']}" ) return "\n".join(summary) # Create the LangChain tools send_email_tool = StructuredTool.from_function( func=send_email, name="send_email", description="Send an email to a recipient via AgentSend", args_schema=SendEmailInput, ) check_inbox_tool = StructuredTool.from_function( func=check_inbox, name="check_inbox", description="Check for new emails in an AgentSend inbox", args_schema=CheckInboxInput, )
Using the Tool with a LangChain Agent
With the tools defined, you can attach them to any LangChain agent. Here is a complete example using the OpenAI functions agent:
from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_openai_functions_agent from langchain_core.prompts import ChatPromptTemplate from langchain_agentsend import send_email_tool, check_inbox_tool llm = ChatOpenAI(model="gpt-4o", temperature=0) tools = [send_email_tool, check_inbox_tool] prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant with email capabilities. " "Your inbox ID is inbox_abc123."), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ]) agent = create_openai_functions_agent(llm, tools, prompt) executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # The agent can now send email autonomously result = executor.invoke({ "input": "Send an email to team@example.com summarizing " "today's project status. Subject: Weekly Update" }) print(result["output"])
When you run this, the agent will use its reasoning capabilities to compose an appropriate email body, then invoke the send_email tool to deliver it through AgentSend. The entire flow happens without human intervention.
Handling Incoming Email
AgentSend delivers incoming messages to your webhook endpoint in real time. You can set up a simple Flask or FastAPI server that receives the webhook payload and feeds it into your LangChain agent for processing:
from fastapi import FastAPI, Request app = FastAPI() @app.post("/webhook/email") async def handle_email(request: Request): payload = await request.json() sender = payload["message"]["from"] subject = payload["message"]["subject"] body = payload["message"]["text"] thread_id = payload["message"]["threadId"] # Feed into your LangChain agent result = executor.invoke({ "input": f"You received an email from {sender}. " f"Subject: {subject}. Body: {body}. " f"Thread ID: {thread_id}. Reply appropriately." }) return {"status": "processed"}
This creates a closed loop: humans email your agent, your agent processes the message through LangChain, and replies through AgentSend. The thread ID ensures all replies stay in the same conversation thread in the sender's email client.
Tip: Store the thread_id alongside your agent's conversation memory. This lets the agent reference previous email exchanges when composing replies, maintaining context across multi-turn email conversations.
LangGraph Integration
If you are using LangGraph for stateful, multi-step workflows, the same tools work out of the box. Define email send and receive as nodes in your graph, and LangGraph's persistence layer will track conversation state across email exchanges. This is particularly powerful for workflows that span multiple email rounds, such as negotiation agents or iterative feedback loops.
Next Steps
Once your LangChain agent has email capabilities, you can extend the integration further:
- Add attachment support by passing file data through AgentSend's attachment API.
- Implement inbox routing by creating multiple inboxes for different agent roles (support, sales, ops).
- Connect to your custom domain so your agent sends from your-agent@yourdomain.com instead of an @agentsend.io address.
- Use webhooks with LangGraph to build event-driven email workflows that persist state across conversations.
Frequently Asked Questions
Can LangChain agents send email?
Yes. By wrapping AgentSend's REST API as a LangChain tool, any LangChain agent can send email, receive incoming messages via webhook, and manage threaded conversations. The tool integrates natively with LangChain's agent executor and works with any LLM backend.
How do I create a LangChain email tool?
Create a StructuredTool or BaseTool subclass that calls AgentSend's /messages endpoint. Define input parameters for recipient, subject, and body. The agent can then invoke the tool during its reasoning loop to compose and send email autonomously.
Does AgentSend work with LangGraph?
Yes. Since LangGraph builds on LangChain's tool abstraction, the same AgentSend tool works in LangGraph workflows. You can add email send and receive nodes to any graph, enabling multi-step workflows that include email communication.
Give Your LangChain Agent an Email Address
Free tier available. No credit card required. Build your LangChain email tool in under 5 minutes.
Start for Free →