Every identity comes with a real email inbox it fully controls. Your agent can send mail from it, read what arrives, reply in-thread, and block until a verification email lands — the same inbox works over the CLI, the Python SDK, and the TypeScript SDK.
Every example below runs against one identity. Grab it once (or set it as the active identity in the CLI) and the rest follow. Need one first? See Identities.
ravi identity use <identity-uuid> from ravi import Ravi
ravi = Ravi(api_key="ravi_id_...")
identity = ravi.identities.get("<identity-uuid>") import { Ravi } from "@ravi-hq/sdk";
const ravi = new Ravi({ apiKey: process.env.RAVI_API_KEY! });
const identity = await ravi.identities.get("<identity-uuid>"); Send an email
Compose and send from the identity’s address. Plain text or HTML, with optional cc, bcc, and attachments.
ravi email compose \
--to user@example.com \
--subject "Hello" \
--body "Hi from my agent" msg = identity.email.send(
to="user@example.com",
subject="Hello",
body="Hi from my agent",
) const msg = await identity.email.send(
"user@example.com",
"Hello",
"Hi from my agent",
); Attach files
Pass local file paths — Ravi uploads each one (up to 10 MB) and attaches it for you. Works the same on send, reply, and forward.
ravi email compose \
--to user@example.com \
--subject "Invoice" \
--body "Invoice attached." \
--attach ./invoice.pdf msg = identity.email.send(
to="user@example.com",
subject="Invoice",
body="Invoice attached.",
attachments=["./invoice.pdf"],
) const msg = await identity.email.send(
"user@example.com",
"Invoice",
"Invoice attached.",
{ attachments: ["./invoice.pdf"] },
); Read the inbox
List messages as a flat feed — filter to unread to see only what needs attention.
ravi message email --unread inbox = identity.email.inbox(unread=True)
for msg in inbox:
print(msg.subject, msg.from_email) const inbox = await identity.email.inbox({ unread: true });
for (const msg of inbox) {
console.log(msg.subject, msg.from_email);
} Prefer conversations grouped by subject? List threads instead.
ravi inbox email threads = identity.email.threads() const threads = await identity.email.threads(); Read one message
Fetch a single message by id to see its full body and metadata.
ravi message email <message-id> msg = identity.email.get("<message-id>")
print(msg.subject)
print(msg.body) const msg = await identity.email.get("<message-id>");
console.log(msg.subject);
console.log(msg.body); Reply and forward
Messages carry their own actions — reply to the sender, reply to everyone, or forward. Threading is handled for you.
ravi email reply <message-id> --body "Thanks — got it!" msg = identity.email.get("<message-id>")
msg.reply(body="Thanks — got it!") const msg = await identity.email.get("<message-id>");
await msg.reply("Thanks — got it!"); ravi email reply-all <message-id> --body "Thanks, all!" msg.reply_all(body="Thanks, all!") await msg.replyAll("Thanks, all!"); ravi email forward <message-id> --to ops@acme.com --body "FYI" msg.forward(to="ops@acme.com") await msg.forward("ops@acme.com"); Wait for a verification email
The move that makes agents work: trigger a signup somewhere, then block until the
confirmation email arrives. wait_for polls the inbox and returns the first
message that matches.
# Kick off a signup elsewhere, then wait for the email to land.
msg = identity.email.wait_for(
lambda m: "verify" in m.subject.lower(),
timeout=120,
)
print(msg.body) // Kick off a signup elsewhere, then wait for the email to land.
const msg = await identity.email.waitFor(
(m) => m.subject.toLowerCase().includes("verify"),
{ timeoutMs: 120_000 },
);
console.log(msg.body); Mark as read
msg = identity.email.get("<message-id>")
msg.mark_read() const msg = await identity.email.get("<message-id>");
await msg.markRead(); Looking for exact request and response fields? See the full API reference.