Integrations
Curated integrations let Robin reach into Google (Gmail + Calendar), GitHub, and Discord without you ever pasting raw OAuth tokens. The catalog is small on purpose — every provider is reviewed before it lands.
How the broker works
1. You click "Connect Google" in the cloud-shell sidebar.
2. Control plane mints a state JWT and redirects you to Google consent.
3. You approve. Google redirects back to /auth/cb/google.
4. Control plane exchanges the code for tokens, then HMAC-relays them
to YOUR VM's /oauth/inbound endpoint. Tokens never persist on the
control plane.
5. Your VM writes them to user-data/secrets/google.json and kicks off
`robin run sync-gmail && robin run sync-calendar` to bootstrap.
The same pattern works for any provider in the catalog (packages/catalog/src/index.ts). provider.account = "default" is the common case; if you connect the same provider twice (e.g. work + personal Google), the second one lands as google.work.json.
Connected providers
Google (Gmail + Calendar)
Read-only scopes: gmail.metadata, calendar.readonly. We never see message bodies — just headers, recipients, calendar event titles + times. The sync-gmail and sync-calendar jobs in user-data/jobs/ poll on the schedule you set.
GitHub
Scopes: notifications, read:user, public_repo. The sync-github job pulls authored events, notifications, and releases from starred repos into user-data/memory/knowledge/github/.
Discord
Scopes: bot, identify, applications.commands. Allowlisted to a single user + guild — DMs come in via webhook, posted into your dispatcher queue, surfaced on your primary pane.
Token refresh
OAuth tokens expire. We chose a split-trust model so neither side holds everything:
- The VM keeps the
refresh_token(underuser-data/secrets/). - The control plane keeps the broker
client_id+client_secretenv vars.
Every 30 minutes, your VM scans user-data/secrets/*.json for tokens within 5 min of expiry and POSTs the refresh request to /api/oauth/refresh on the control plane, signed with your per-VM INBOUND_KEY. The control plane hits the provider, returns the new tokens, and drops both from memory. Result lands back in secrets/<provider>.json. Source.
Self-hosted integrations
Anything you can write a user-data/scripts/sync-foo.js and user-data/jobs/sync-foo.md for runs as a regular Robin job. The catalog is for things that need an OAuth broker; everything else is just a script under user-data/.
Webhooks
Each provider has a public webhook URL at https://<handle>.askrobin.io/webhook/<provider> (or /webhook/<provider>/<account> for multi-account). shell-mux on :8080 reverse-proxies these to the integrations server, which enqueues them into your dispatcher's SQLite queue. Provider-specific signature verification happens in your per-provider script.