lupin.Open console
Email

Build an email draft lifecycle with explicit state transitions

Create, update and retire drafts while preserving source messages and separating drafting from sending.

Treat a draft as a reviewable resource

A draft gives an agent somewhere to put proposed email content without sending it. That boundary is especially useful for autonomous registration, whose initial key can create drafts while outgoing email remains disabled. Store the returned draft_id with the work item and source message IDs so the operator can locate the proposal after a worker restart. A draft existing in the inbox is not evidence of human approval. Keep your application’s review status explicit rather than treating an empty send_at field or a particular subject prefix as consent.

Create once with a stable client identity

Create through POST /v0/emails/inboxes/:inbox_id/emails/drafts and supply a stable client_id when you need creation deduplication. A normal draft can include recipients, subject, text and attachments. Set in_reply_to for a reply draft or forward_of for a forward draft; those fields are mutually exclusive. Reply drafts derive conversation details from their source, while reply_all cannot be combined with explicit to, cc or bcc fields. Choose the intended operation at creation instead of relying on the model to repair contradictory fields after a validation failure.

Illustrative draft-create body; it does not send the message.
{"to":["reviewer@example.com"],"subject":"Proposed response","text":"Please review this draft.","client_id":"case-104-proposal-1"}

Update only the intended fields

PATCH on the draft resource supports field changes, nullable clears, attachment additions/removals, label changes and send_at updates. Build patches from deliberate edits rather than serializing an entire partially populated form, which can accidentally clear fields. Keep a local content revision or digest for review: if a model rewrites recipients or attaches a new file after approval, the old approval no longer describes the current proposal. Read the current draft again before showing a final review when more than one worker or human can edit it. Scheduling through a non-null send_at requires draft_send authority; a less-privileged worker must cancel an existing schedule before editing that scheduled draft.

Interpret sending as a transition

POST /v0/emails/inboxes/:inbox_id/emails/drafts/:draft_id/send returns the sent email and deletes the draft on successful delivery submission. Forwarded content and attachments merge at send time, so review needs to account for the source resource as well as the editable body. A missing draft after an uncertain send is not enough evidence to claim delivery; preserve the send operation identity and inspect the resulting message or recorded outcome. A draft that still exists may also have a failed or scheduled state requiring explicit inspection.

Retire stale proposals deliberately

Delete abandoned drafts when the underlying request is withdrawn or superseded, after recording the local reason if your workflow needs an audit trail. Avoid silently overwriting an older human-edited draft with a fresh model response. Scheduled drafts add another lifecycle boundary because the cron can attempt them later without an interactive worker waiting. Your next step is a state diagram in your own application covering proposed, under-review, approved, scheduled, sent, failed and abandoned. Tie every transition to a real returned resource state or authorized human decision rather than an optimistic model summary.

Handle duplicate creation carefully

A repeated client_id can recover an existing draft rather than create a revised proposal. If the task genuinely changes, read and update the saved draft deliberately or create a new proposal identity after retiring the old one. Do not assume replaying draft creation with changed text is the same as editing that resource; keep creation recovery and content revision separate.

Sources & verification

Reviewed against checked-in Lupin API handlers and documentation. Example requests were not executed against live providers.

Prepared with AI assistance by Lupin editorial. How we research and maintain these guides.

Put it into practice

Give your agent the right tools.

Review the API, workspace requirements and permissions before enabling a workflow.

Explore email Register an agent