Add email verification to your LangChain agent A developer integrated Verifly's email verification API into a LangChain agent to prevent the agent from sending emails to invalid addresses. The tool checks deliverability mid-loop, allowing the agent to skip bad addresses and suggest corrections, improving sending reputation and reducing bounces. If your LangChain agent sends email, books demos, or accepts signups, sooner or later it will act on an address that does not exist. A typo like gmial.com , a disposable mailinator.com throwaway, a dead domain. The agent has no way to know, so it sends anyway. The message bounces, your sending reputation drops, and the agent happily moves on to the next bad row. The fix is to give the agent a tool that checks an address before it acts on it. This walkthrough wires Verifly https://verifly.email into a LangChain agent so the model can verify deliverability mid-loop, the same way it would call any other tool. You hand an agent a list of leads scraped from a CSV and ask it to draft outreach. Some of those addresses are garbage. You want the agent to skip the bad ones and flag the fixable ones, on its own, without you writing bounce-handling glue. That decision needs a real deliverability signal, and that is exactly what a verification tool provides. pip install langchain-verifly langchain langchain-openai The langchain-verifly package ships a ready-made BaseTool called VeriflyEmailVerifier . You do not have to write a wrapper. Verifly is agent-native, so a key is one HTTP call away. No dashboard click-through required: curl -s -X POST https://verifly.email/api/v1/autonomous/register \ -H "Content-Type: application/json" \ -d '{"email":"you@example.com","password":"a-strong-password"}' The response contains an api key.key it starts with vf and 100 free credits. Export it: export VERIFLY API KEY="vf ..." Before handing it to an agent, run the tool directly so you can see the shape of what it returns. The class reads VERIFLY API KEY from the environment automatically: python from langchain verifly import VeriflyEmailVerifier verifier = VeriflyEmailVerifier picks up VERIFLY API KEY print verifier.run "jane.doe@gmial.com" That call against the live API returns: { 'email': 'jane.doe@gmial.com', 'result': 'undeliverable', 'reason': 'Invalid email: bad domain', 'confidence': 90, 'is valid': False, 'recommendation': 'do not send', 'did you mean': 'jane.doe@gmail.com', 'details': { 'syntax valid': True, 'domain exists': True, 'mx records': True, 'smtp valid': False, 'is disposable': False, 'is role account': False, 'is catch all': False, 'is free provider': False, 'provider': 'gmial.com' } } Two things matter for an agent here. recommendation is a flat instruction do not send , and did you mean proposes the correction jane.doe@gmail.com . The model can act on both without parsing anything fancy. A real address looks different: print verifier.run "james@sibscientific.com" { 'email': 'james@sibscientific.com', 'result': 'deliverable', 'reason': 'Email exists and accepts mail', 'confidence': 95, 'is valid': True, 'recommendation': 'safe to send', 'did you mean': None, 'details': {'smtp valid': True, 'is disposable': False, 'is catch all': False, ...} } Now give the tool to an agent and let the model decide when to call it. The tool's own description "Use before emailing a lead or accepting a signup to avoid bounces" is enough for the model to reach for it. python from langchain openai import ChatOpenAI from langchain.agents import create tool calling agent, AgentExecutor from langchain core.prompts import ChatPromptTemplate from langchain verifly import VeriflyEmailVerifier tools = VeriflyEmailVerifier prompt = ChatPromptTemplate.from messages "system", "You clean lead lists. For each address, verify it. " "Drop anything with recommendation 'do not send'. " "If did you mean is set, suggest the corrected address instead." , "human", "{input}" , "placeholder", "{agent scratchpad}" , llm = ChatOpenAI model="gpt-4o-mini", temperature=0 agent = create tool calling agent llm, tools, prompt executor = AgentExecutor agent=agent, tools=tools, verbose=True executor.invoke {"input": "Clean these: jane.doe@gmial.com, james@sibscientific.com, test@mailinator.com"} The agent verifies each address and reasons over the structured verdict. The typo gets the gmail.com correction surfaced, the real address passes, and the throwaway is dropped because Verifly flags it: verifier.run "test@mailinator.com" {'result': 'undeliverable', 'reason': 'Disposable/temporary email address', 'recommendation': 'do not send', 'details': {'is disposable': True, ...}} Syntax checks catch bad@@example . They do not catch gmial.com , dead domains, disposable providers, or full mailboxes, because those require DNS, MX, and SMTP probing at request time. That is the work the tool does, and it returns one field, recommendation , that the model can branch on directly. deliverable , undeliverable , risky , or unknown . Treat risky catch-all domains, confidence around 40 as "send with caution," not "drop." risky verdict there is honest, not a failure.That is the whole integration: one pip install , one tool in the tools list, and your agent stops sending into the void. Docs and the rest of the API live at verifly.email https://verifly.email .