E-mail versturen vanuit LangGraph
Modelleer je e-mailworkflow als een toestandsgraph en laat AI-nodes zelfstandig beslissingen nemen over wanneer en wat er verstuurd wordt.
Vereisten
- Wesender-account met geverifieerd verzenddomein
- API-sleutel van Wesender (WESENDER_API_KEY)
- OpenAI of Anthropic API-sleutel
- Python 3.11 of nieuwer
Stap 1: Installeer de benodigde packages
Installeer LangGraph, LangChain en de requests-bibliotheek voor de Wesender REST API.
pip install langgraph langchain-openai python-dotenv requests Stap 2: Definieer de toestand en de graph-nodes
Maak een TypedDict voor de graph-toestand. Elke node is een Python-functie die de toestand leest, verwerkt en bijgewerkt teruggeeft.
from typing import TypedDict
from langchain_openai import ChatOpenAI
class EmailState(TypedDict):
recipient: str
subject: str
body: str
sent: bool
def compose_email(state: EmailState) -> EmailState:
llm = ChatOpenAI(model="gpt-4o-mini")
reply = llm.invoke(
f"Schrijf een welkomstmail voor {state['recipient']}. Reageer alleen met de HTML-inhoud."
)
return { **state, "body": reply.content }
def send_email(state: EmailState) -> EmailState:
import requests, os
requests.post(
"https://api.wesender.nl/v1/emails",
headers={ "Authorization": f"Bearer {os.environ['WESENDER_API_KEY']}" },
json={
"from": "noreply@jouwdomein.nl",
"to": state["recipient"],
"subject": state["subject"],
"html": state["body"],
},
).raise_for_status()
return { **state, "sent": True } Stap 3: Bouw en compileer de graph
Voeg de nodes toe, stel de edges in en compileer de graph tot een uitvoerbare agent. Roep de graph aan met een beginstand.
from langgraph.graph import StateGraph, END
graph = StateGraph(EmailState)
graph.add_node("compose", compose_email)
graph.add_node("send", send_email)
graph.set_entry_point("compose")
graph.add_edge("compose", "send")
graph.add_edge("send", END)
app = graph.compile()
result = app.invoke({
"recipient": "lisa@voorbeeld.nl",
"subject": "Welkom bij ons platform",
"body": "",
"sent": False,
})
print("Verstuurd:", result["sent"]) Volledig voorbeeld
Hier is de volledige implementatie in langgraph_email.py:
import os, requests
from typing import TypedDict
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
class EmailState(TypedDict):
recipient: str
subject: str
body: str
sent: bool
def compose_email(state: EmailState) -> EmailState:
llm = ChatOpenAI(model="gpt-4o-mini")
reply = llm.invoke(
f"Schrijf een welkomstmail voor {state['recipient']}. Reageer alleen met de HTML-inhoud."
)
return { **state, "body": reply.content }
def send_email(state: EmailState) -> EmailState:
requests.post(
"https://api.wesender.nl/v1/emails",
headers={ "Authorization": f"Bearer {os.environ['WESENDER_API_KEY']}" },
json={
"from": "noreply@jouwdomein.nl",
"to": state["recipient"],
"subject": state["subject"],
"html": state["body"],
},
).raise_for_status()
return { **state, "sent": True }
graph = StateGraph(EmailState)
graph.add_node("compose", compose_email)
graph.add_node("send", send_email)
graph.set_entry_point("compose")
graph.add_edge("compose", "send")
graph.add_edge("send", END)
app = graph.compile()
result = app.invoke({
"recipient": "lisa@voorbeeld.nl",
"subject": "Welkom bij ons platform",
"body": "",
"sent": False,
})
print("Verstuurd:", result["sent"]) Bezorgstatussen via webhooks
LangGraph kan bezorg-, bounce- en klachtsignalen ontvangen via webhooks. Configureer een webhook-endpoint in je LangGraph-workflow dat POST-verzoeken van Wesender accepteert. Zie Webhooks instellen voor de volledige configuratiestappen en het payload-formaat.
Veelgestelde vragen
Kan ik conditionele edges gebruiken om te beslissen of een e-mail wordt verstuurd?
Ja. LangGraph ondersteunt conditionele edges via add_conditional_edges. Je kunt een routeringsfunctie schrijven die de toestand beoordeelt en beslist of de e-mail wordt verstuurd of dat de flow naar een andere node gaat.
Hoe voeg ik menselijke goedkeuring toe aan de graph?
Gebruik LangGraph's interrupt-mechanisme. Voeg interrupt_before=['send'] toe bij het compileren van de graph. De uitvoering pauzeert dan voor de send-node zodat een mens de e-mail kan controleren voordat hij wordt verstuurd.
Kan ik de graph persistent maken over meerdere aanroepen?
Ja. LangGraph ondersteunt checkpointing via SqliteSaver of PostgresSaver. Zo bewaar je de toestand tussen aanroepen en kan de agent doorgaan waar hij gebleven was, ook na een herstart.