agentmail-python

The official Python SDK for AgentMail, giving AI agents a full email inbox API to send, receive, and manage threaded conversations.

SDK
PyPI
v0.5.10
66stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
60/100Good
Development Activity68
Maintenance72
Community40
Maturity40
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
68/100Good
Architecture78
Code Quality62
Innovation58
Learning Curve75

AgentMail is the Python client library for the AgentMail API, a hosted email inbox service purpose-built for AI agents. It wraps the full AgentMail REST surface (inboxes, messages, threads, drafts, attachments, webhooks, API keys, organizations) behind a single AgentMail client, plus an AsyncAgentMail variant built on the same httpx-based transport for non-blocking workloads. Every request and response model is defined with Pydantic, so agent code gets validated, typed objects instead of raw JSON dictionaries.

Beyond simple request/response calls, the SDK exposes a websockets-backed real-time channel for streaming inbox events (new mail, replies, delivery status) without polling, along with built-in retry-with-backoff for transient 408/429/5xx errors, configurable timeouts, and a .with_raw_response escape hatch for inspecting raw headers and status codes. The client is entirely auto-generated by Fern from AgentMail’s API definition, so it tracks the live API surface closely and stays current with new endpoints as they ship.

What You Get

  • Sync (AgentMail) and async (AsyncAgentMail) clients sharing one httpx-based transport
  • Typed Pydantic models for every request and response object
  • Real-time websocket streaming for inbox events alongside standard REST calls
  • Built-in retry-with-backoff, configurable timeouts, and raw-response access via .with_raw_response

Common Use Cases

  • Provisioning a dedicated inbox for an AI agent to send and receive email autonomously
  • Building a support or reply bot that watches threads over the websocket channel and drafts responses
  • Managing organization-wide API keys, domains, and webhooks for a multi-agent email deployment

Under The Hood

Architecture The SDK is a Fern-generated, layered client: a top-level AgentMail/AsyncAgentMail class (src/agentmail/client.py) lazily instantiates per-resource sub-clients (inboxes, threads, messages, drafts, webhooks, websockets, organizations, metrics, api_keys, auth, domains, lists, pods, agent) as properties, each backed by a paired client.py/raw_client.py pair sharing one SyncClientWrapper/AsyncClientWrapper. Cross-cutting concerns (HTTP transport, retries, JSON encoding, error mapping, logging) live in core/ and are shared by every resource module, so behavior changes to retry policy or serialization propagate everywhere without touching business logic. It is a mechanically regular, generated architecture rather than a hand-designed one, consistent and easy to trace, but changes come from regenerating off Fern’s API definition rather than hand-editing.

Tech Stack Python >=3.8, packaged with Poetry. Core runtime dependencies are httpx for HTTP transport, pydantic and pydantic-core for request/response models, websockets for the realtime channel, and typing_extensions for backported typing. Dev tooling includes pytest with pytest-asyncio and pytest-xdist for parallel async-aware tests, mypy with the pydantic mypy plugin for type-checking, and ruff for linting and import sorting. CI runs a poetry install, mypy compile step, and pytest suite on every push, with a tag-gated PyPI publish job.

Code Quality The tests/utils/ directory carries real Fern-generated coverage for the shared runtime pieces, including a substantial HTTP client test file and dedicated serialization and query-encoding tests. However tests/custom/test_client.py, the slot meant for hand-written project-specific tests, contains a single test marked skipped as unimplemented, so there is no test coverage of actual API-call behavior beyond the generated transport layer. Naming and typing are consistent throughout, a py.typed marker is present, mypy is enforced in CI, and errors are centralized through a typed ApiError hierarchy (ConflictError, NotFoundError, UnprocessableError, ValidationError) rather than bare excepts.

API Design The SDK’s ergonomics come from Fern’s generation conventions: lazy per-resource properties keep import cost low, .with_raw_response gives an escape hatch without duplicating every method signature, and the sync/async split is achieved by generating twin classes off one API definition. Getting started requires one import and one constructor call, and every resource follows the same client.<resource>.<verb>() shape, so once a caller learns inboxes.create() the rest of the surface is guessable. This is competent, consistent, boilerplate-light API design rather than a technically novel pattern.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search