email.read
Schema
Input = { query?: string, // Gmail-style search, e.g. "is:unread newer_than:2d from:alice" limit?: number, // 1-50, default 10 unreadOnly?: boolean, // default false}
Output = { messages: Array<{ id, from, to: string[], subject, date, snippet, body?, unread? }>, provider: string, // 'twin' | 'gmail'}requiresConnection: 'gmail' on this skill means the registry can answer “not connected” before
run is even called — see Connecting Gmail. It prefers
ctx.integrations.email (the Twin’s own Gmail wiring, provider: 'twin') when available; otherwise
it reads directly against the Gmail REST API with the connection’s own decrypted access token
(provider: 'gmail'), refreshing is handled one layer up by the Twin, so this skill just surfaces a
clear “reconnect Gmail” error if the token is invalid. Body text is decoded from the message’s
text/plain MIME part and capped at 8,000 characters.
Example
curl -s -X POST http://localhost:4000/api/studio/skills/invoke \ -H 'content-type: application/json' -b cookies.txt \ -d '{"name":"email.read","input":{"query":"is:unread","limit":5}}'{ "ok": true, "output": { "provider": "gmail", "messages": [{ "id": "18d2a...", "from": "Jordan Alvarez <jordan@nimbus.co>", "to": ["you@example.com"], "subject": "Q3 numbers", "date": "2026-09-05T18:02:00.000Z", "snippet": "Does Friday still work for the review?", "unread": true }] }}