Draft Queue
The draft queue is for teammate-requested emails that need the owner to review before sending. It is durable SQL data in queued_email_drafts, not compose application state.
Rules
- Use
queue-email-draftwhen a teammate asks the agent to prepare an email for an organization member. - The requester and reviewer must both be members of the active organization.
requireQueueContextthrows if there's no active org, or if the caller isn't a member — both surface as plain errors, not empty results. - Slack requests should queue drafts, not send raw emails.
queue-email-draftreturnsreviewUrl; include that URL when replying to Slack so the owner can open the exact draft.- Slack intake verifies the sender email via Slack
users.infowhen the app hasusers:read.email, and passes verified sender name/email into the agent context. If that scope is missing, Slack intake cannot resolve a real email and will not queue anything — tell the requester to ask an admin to grantusers:read.emailrather than guessing their address from their Slack display name. - Managed Slack installs request
users:read.emailthrough the generated OAuth manifest; an existing install must be reconnected after the scope is granted. Legacy bot-token installs must add the scope in Slack manually. ownerEmailaccepts more than an exact email:resolveOrgMemberEmailalso matches an unambiguous local-part prefix (e.g."jane"matchesjane@co.comif she's the onlyjane*member). If more than one member matches the prefix, the action throws listing all org member emails instead of guessing — pass the full email in that case.- Use
send-queued-draftsonly when the queued draft owner explicitly asks to send. - Use
open-queued-draftwhen the user wants to manually tweak a queued draft in the compose panel.
Status Lifecycle And Access
A queued draft moves through queued -> in_review -> sent, or -> dismissed
at any point before sent. Rules enforced in server/lib/queued-drafts.ts:
- Ownership is strict. Only the
ownerEmail(or an orgowner/adminrole) can callupdate-queued-draft,open-queued-draft, orsend-queued-draftsfor a given draft —requireQueuedDraft(id, {ownerOnly: true})rejects the original requester from editing or sending it, even though they created it. - Sent drafts are frozen.
updateQueuedDraftthrows"Sent queued drafts cannot be edited."ifstatusis alreadysentand the caller isn't also setting it tosentagain. Don't retry an edit on a sent draft — create a newqueue-email-draftinstead. open-queued-drafttransitions status toin_reviewand copies the draft into a realcompose-{id}application-state entry (auto-appending the owner's configured signature, not the requester's). It also blocks opening a draft that is alreadysentordismissed.send-queued-drafts --all=truesends everyqueuedorin_reviewdraft assigned to the caller (default limit 50, capped 50) by delegating to the realsend-emailaction per draft — each send still requires the standard approval gate. Partial failures are reported per-draft in{ sent, failed }rather than aborting the whole batch; report both lists back to the user.- Queueing a draft for someone else fires a best-effort in-app notification to the owner (skipped when self-queuing); a failed notify does not fail the queue action itself.
Actions
| Action | Purpose |
|---|---|
list-org-members |
Resolve valid organization members for ownerEmail |
queue-email-draft |
Create a queued draft for a member to review |
list-queued-drafts |
List active, sent, dismissed, review, or requested drafts |
update-queued-draft |
Edit queued draft fields or set status |
open-queued-draft |
Open a queued draft as compose-{id} |
send-queued-drafts |
Send one queued draft or all active drafts assigned to the current user |
navigate --view=draft-queue |
Open the queue UI |
Typical Flow
- Resolve the target reviewer with
list-org-membersif the user gave a name. - Call
queue-email-draftwithownerEmail, recipients, subject, body, and context. - Tell the requester it was queued and include the returned
reviewUrl.
For review:
- Call
list-queued-drafts --scope=review --status=active. - Use
update-queued-draftfor tone/content changes. - Use
open-queued-draftfor manual compose edits, orsend-queued-draftswhen the owner asks to send.