Agent frameworks
Keep your agent framework. Add a real inbox, live email tools, signed inbound events, and thread continuity.
You do not have to rebuild your agent inside CarlyEmail. Keep its model, prompt, memory, tools, and hosting. CarlyEmail adds the email channel around it:
real inbox → signed incoming-mail event → your agent → MCP or SDK → threaded reply
Start with Add email to any agent for the framework-neutral version. Each page below applies that same four-part loop to one runtime.
The portable contract
| Your runtime needs | CarlyEmail gives it |
|---|---|
| A callable tool surface | Hosted MCP or generated TypeScript/Python SDKs |
| A way to receive an event | Signed webhook or authenticated WebSocket |
| A conversation key | Stable thread_id on every message and event |
| A real email identity | A CarlyEmail inbox or verified custom domain |
MCP is the shortest default because the server publishes the live schemas and tool annotations. Use an SDK when you want to expose only a few operations or keep the email calls outside the model's tool loop.
The richer langchain-carlyemail package in the repository adds typed tools, a
loader, a retriever, and a verified inbound router. Until its first PyPI release,
the LangChain page leads with hosted MCP and labels the Git install separately.
What is framework-specific
Only two pieces vary: how a runtime registers MCP tools, and how it resumes an
agent when the webhook arrives. The business logic should not. In every
framework, key memory by CarlyEmail thread_id, reply with the message or thread
tool instead of constructing new email headers, and deduplicate webhook work by
event_id.
The security boundary
An email is untrusted model input. A verified webhook proves CarlyEmail delivered
the payload; it does not make the sender's instructions safe. Give each agent an
inbox-scoped key with the minimum permissions it needs. For early deployments,
allow reads and draft_create but omit message_send; sending then returns
403 regardless of the model's reasoning. See
human in the loop.
Generating a typed client
The spec is published, and a test fails if it drifts from what the API serves.
npx @hey-api/openapi-ts -i https://docs.carlyemail.com/openapi.json -o ./carlyemail
openapi-generator-cli generate -i https://docs.carlyemail.com/openapi.json -g python -o ./carlyemail