feat: add AtomicMail toolkit for autonomous agent inboxes - #9130
Open
dom-dalty wants to merge 1 commit into
Open
feat: add AtomicMail toolkit for autonomous agent inboxes#9130dom-dalty wants to merge 1 commit into
dom-dalty wants to merge 1 commit into
Conversation
Add AtomicMailTools exposing register_inbox / send_email / list_inbox (sync and async) over AtomicMail's proof-of-work signup and JMAP API, so an agent can provision its own inbox and send/receive mail with no human signup. Includes a deterministic no-LLM workflow cookbook (register -> read -> send) and unit tests. Fixes a send-path bug found in live testing: the From header used the bare inboxId local-part, which JMAP rejects as forbiddenFrom. The full <inboxId>@<allowedFromDomain> address is now derived from the capability JWT and the required identityId is set on EmailSubmission. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
PR TriageMissing issue link: Please link the issue this PR addresses using |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an AtomicMail toolkit (
AtomicMailTools) that gives an Agno agent its own email inbox. AtomicMail issues inboxes through an autonomous, proof-of-work signup flow — no domain setup or human verification step — and exposes them over JMAP, which makes it a natural fit for agents that need to send and receive mail without a human in the loop.The toolkit exposes three tools, each with sync and async variants:
register_inbox— provision (or idempotently reuse) an inbox via the proof-of-work signup handshake. The resulting API key is cached to~/.atomicmail/credentials.json(override withcredentials_dirorATOMIC_MAIL_CREDENTIALS_DIR) so the same inbox is reused across runs.send_email— send a plain-text email from the registered inbox.list_inbox— list the most recent messages in the inbox.A cookbook example (
cookbook/91_tools/atomic_mail_tools.py) drives the toolkit end to end from a deterministic, no-LLM Agno Workflow (register → read inbox → send), with the inbox username and recipient supplied viaadditional_data/env so no address is hardcoded.Type of change
Checklist
./scripts/format.shand./scripts/validate.sh) — both pass cleanDuplicate and AI-Generated PR Check
main)Additional Notes
Testing.
pytest libs/agno/tests/unit/tools/test_atomic_mail.py— 18 passing (sync + async, network mocked). Verified end to end against the live AtomicMail API in a freshly rebuilt dev environment: an inbox was registered, listed, and used to send an email that was confirmed received.A real send-path bug was found and fixed during live testing.
send_emailbuilt theFromheader from the capability JWT'sinboxIdclaim, assuming it was a full address. In practiceinboxIdis only the local-part, so JMAP rejected the message withforbiddenFrom("From address is malformed"). The fix:<inboxId>@<allowedFromDomain>address from the capability JWT (both values are present as claims),identityIdtoEmailSubmission/set.A regression test was added that asserts the wire-level
Fromaddress andidentityId, so the mocked-response tests can no longer mask this class of bug.Protocol note. The proof-of-work handshake runs on every authentication and its solve time is server-dictated (dynamic difficulty; observed anywhere from ~4s to ~160s). This is inherent to AtomicMail's anti-abuse design, not a defect, but callers should expect
register_inbox/send_email/list_inboxlatency to vary.Security. No credentials, tokens, or personal addresses are committed. The
POW_SCRYPT_SALTconstant is a public protocol parameter (identical for every client), not a secret. Credentials are written only at runtime to the user's home directory with0o600permissions.AI disclosure. This PR was developed with AI assistance (Claude Code): the assistant reviewed the initial toolkit, found and fixed the send-path bug, added the workflow cookbook and the regression test, and ran the live end-to-end validation. All changes were human-reviewed and human-tested before submission.