Skip to main content
Email is an Integration, not a backend object. A new email is an inbound event that can fire the scheduler; the agent reads and drafts through the integration’s MCP tool.

Why this one is different: untrusted input

Email is attacker-controllable and prompt-injectable, so triage runs propose-only: the agent gets the mailbox ro and cannot write or send directly. It emits proposal cards — record (a task/note), draft, send (external) — a human approves, and trusted code applies. A send stays gated until you approve it.

Fire a triage on a new email

An integration delivers the email as an event.v1 event carrying a plan:
curl -X POST "$API_BASE/agent/events" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name":"email.received",
    "source":{"uri":"mailbox://u_jane/INBOX/AB12CD"},
    "plan":{"prompt":"Triage this email into tasks. Propose a record for each action item and a draft reply if one is warranted."}
  }'
# → 202 {"workload_id":"agent-...","trigger":"event"}
The event must carry a planPOST /events returns 422 if plan is absent. See the error reference.

Approve the proposals

The dispatch emits proactive-card.v1 frames on its Stream. Approving a record commits it to the workspace (a trusted applier does the write); approving a send executes it through the integration. Nothing leaves your control without that approval.

Make it standing

To triage automatically for every inbound message, bind a triage routine to the email integration so each email.received event dispatches the agent — the inbound trigger replaces the manual POST /events call above. See Integrations and AI routines.