Install
openclaw skills install @atom00blue/drin-agent-inboxRun an autonomous email inbox with Drin — receive inbound email on a domain, read conversation threads, and reply in-thread. Use when building or operating an agent that must read and respond to email (support triage, scheduling, an "email me to do X" interface), set up inbound receiving, test the receive pipeline, or process new inbound messages and act on them.
openclaw skills install @atom00blue/drin-agent-inboxDrin is bidirectional: besides sending, a domain can receive email, which Drin parses into conversation threads your agent can read and reply to. This is the foundation for an agent you can email.
set_domain_receiving with enabled: true (or
PATCH /v1/domains/:id/receiving). Drin returns the MX record(s) to
publish.get_domain_receiving / GET /v1/domains/:id/receiving.The domain must already be verified for sending (see drin-email-best-practices)
so the agent can also reply.
create_inbox with { address: "support@acme.com", domainId: "<id>" }
(or POST /v1/inboxes). This is the address people email to reach the agent.list_inboxes.Inbound and outbound messages are joined into threads.
list_threads (optionally inboxId) — most-recent-first feed. Each thread has
a lastMessageAt and subject.get_thread with the thread id — the full conversation, oldest→newest, both
directions, including each message's direction, from, to, subject, and
status.get_email (detail/lifecycle),
get_email_body (the archived { html, text }), and
list_email_attachments (download bytes via the authenticated url).Two ways to know when new mail arrives:
list_threads and diff against the last id/timestamp
you processed.create_webhook
(drin webhooks create --url <url> --event inbound_received / POST /v1/webhooks);
Drin POSTs a signed payload when mail is received, and returns a signingSecret
ONCE on creation. Verify the signature (drin.webhooks.verify in the SDK)
before trusting it.For each new inbound message:
get_email_body) and any attachments.reply_email with { messageId: "<inbound id>", text: "...", html: "..." }
(or POST /v1/emails/:id/reply). Drin sets In-Reply-To/References and the
Re: subject automatically; from defaults to the inbox address and to to
the original sender.Keep a record of which message ids you've already handled so you never reply
twice (idempotency). When replying to action requests, pass an idempotencyKey.
Use the simulator to exercise the whole receive → thread → (webhook) path safely:
simulate_inbound with { to: "support@acme.com", from: "Customer <c@example.com>", subject: "Help", text: "..." }
(or POST /v1/inbound/simulate). The synthesized message is flagged
test_mode (excluded from metrics/billing) but flows through ingest, threads,
and any webhooks exactly like a real one — so you can build and verify the
agent loop before pointing real DNS at it.seen = load_processed_ids()
for thread in list_threads(inboxId):
convo = get_thread(thread.id)
for msg in convo.messages where msg.direction == "inbound" and msg.id not in seen:
body = get_email_body(msg.id)
action = decide(convo, body) # your agent's reasoning
reply_email(messageId=msg.id, text=action.reply, idempotencyKey=msg.id)
seen.add(msg.id)
save_processed_ids(seen)
Always honor suppressions and never reply to mail you can't authenticate as genuinely inbound (verify webhook signatures).