ViteHub is still experimental. Expect bugs and breaking changes.

Gmail

Let an Agent search Gmail and create unsent drafts through structured tools.

gmail() gives an Agent structured Gmail search and authorization tools. Draft mode adds draft creation, but the Capability never exposes a send tool or the underlying gog executable.

Use email() for application-owned transactional email through the Email primitive. Use gmail() for an operator-owned Gmail account and structured Gmail tools.

Configure the Agent

Install gog on the Workspace Session host, configure its Google OAuth client, and keep its authentication state under the service account. The application owns this setup; the Capability never accepts OAuth client secrets or keyring passwords as tool input.

server/agents/inbox.ts
import { defineAgent } from 'vite-hub/agent'
import { gmail } from 'vite-hub/agent/capabilities'

export default defineAgent({
  capabilities: [
    gmail({ mode: 'draft' }),
  ],
  driver: 'codex',
  workspace: {
    mode: 'write',
  },
})

Current gog path conventions keep configuration in .config/gogcli and OAuth metadata plus file-keyring entries in .local/share/gogcli on Linux, so persist both directories for the service account. Supply GOG_KEYRING_PASSWORD through Server Env or the deployment secret store. Follow the gog OAuth client setup before the first authorization attempt.

Choose a mode

Read mode is the default and exposes two tools:

ToolBehavior
gmail_authStarts or completes remote authorization for one Gmail address.
gmail_searchSearches or lists Gmail threads. It does not retrieve full message bodies.

Draft mode exposes the same tools plus gmail_draft, which creates an unsent draft with to, optional cc and bcc, a subject, and a plain-text body.

gmail()
gmail({ mode: 'draft' })

gmail() has no send mode. Search commands run with read-only and no-send controls. Draft creation runs with --gmail-no-send, and no Capability-owned tool can send the resulting draft.

This limits the tools exposed to the Agent, not the credential itself. If sending must be impossible, isolate the credential behind a runtime or provider policy that cannot send. gmail() does not provide that isolation.

Complete authorization

Gmail tools return authorization as structured states instead of asking the user to run shell commands:

StatusNext action
account_requiredAsk which Gmail address to use, then retry the original tool with account.
authorization_requiredSend authorizationUrl to the user. Google may redirect to a localhost page that does not load; collect the full browser address-bar URL.
connectedRetry the original Gmail tool.
configuration_requiredThe operator must configure the OAuth client using setupUrl. Do not request secrets in chat.

Complete a pending redirect through gmail_auth:

Agent tool call
await gmail_auth({
  action: 'complete',
  account: 'owner@example.com',
  redirectUrl: 'http://localhost:8080/?code=...&state=...',
})

The Capability accepts only an HTTP loopback URL with both code and state. It exchanges the URL on the Workspace Session host and does not return it in the result.

Runtime requirements

gmail() requires all of the following:

  • An explicit Workspace with workspace.mode: 'write', because each structured Gmail call opens a writable Workspace Session.
  • A Workspace Session host with command execution and gog available.
  • Operator-owned OAuth client configuration and persistent service-account state.

Each underlying gog command opens its own Workspace Session and closes the Session on success or failure. Gmail search results remain untrusted external content and the contributed skills/gmail/SKILL.md tells the Agent to treat them as data, not instructions.

Draft authorization may grant the Gmail account scope that gog needs to create drafts. The no-send contract applies only to the Capability-owned tools and their command flags.

Verify Gmail access

Run vitehub agent info --agent <name> --json and inspect the resolved tools. Read mode lists only gmail_auth and gmail_search. Draft mode also lists gmail_draft.

Start with a test Gmail account. Search for in:inbox, create a draft in draft mode, and verify in Gmail that the message remains in Drafts and was not sent.

Options

OptionTypeDefaultDescription
mode"read" | "draft""read"Exposes search and authorization tools, with draft creation added only in draft mode.