Email workflows use eight canonical actions. Provider parity is explicit, never assumed.

Canonical tools

ActionUse it for
list_emailsBrowse a mailbox, folder, or label
search_emailsUse a provider-supported query expression
get_emailFetch a known message and normalized body
list_threadsBrowse conversation-grouped mail
create_draftStage an unsent message
send_emailStart a new external conversation
reply_to_emailPreserve reply/thread context
add_email_labelAdd a label or move a message

Provider matrix

ToolkitRead/searchDraft/reply/sendOrganize
GmailFullFullYes
Microsoft OutlookFullFullYes
MailgunList onlySend onlyNo
SMTPNoSend onlyNo
ResendNoSend onlyNo
SendGridNoSend onlyNo

Worked example

ts
import { Eyeball } from "@eyeball/sdk";

const eyeball = new Eyeball({
  apiKey: process.env.EYEBALL_API_KEY!,
  baseUrl: process.env.EYEBALL_EXECUTOR_URL!,
});

const sent = await eyeball.tools.run(
  "gmail.send_email",
  {
    to: ["guest@example.com"],
    subject: "Your table is confirmed",
    body: "Friday at 7 PM for four guests.",
  },
  {
    userId: "demo_user",
    idempotencyKey: "reservation:res_42:email",
  },
);
console.log(sent);

This mutation runs deterministically against Gmail mocks with zero Gmail accounts. Verify recipients and preserve the idempotency key before moving live.

See the generated Gmail reference.