> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pome.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Gmail

> A digital twin of the Gmail REST API. Deterministic, resettable, no network.

A deterministic, resettable, in-process simulation of the Gmail REST API v1. It
reproduces the same response shapes and error semantics as Gmail without sending
real email or touching Google. Each instance starts from a scenario seed and
resets between runs, so the same scenario produces the same state every time.

## What it covers

* Gmail REST v1 mounted at `/gmail/v1/users/:userId/...` (uploads at
  `/upload/gmail/v1/users/:userId/...`)
* Messages: list, get, send, insert, import, modify, batchModify, batchDelete,
  trash, untrash, delete, and attachments.get
* Drafts: list, get, create, update, send, delete
* Threads: list, get, modify, trash, untrash, delete
* Labels: list, get, create, update, patch, delete
* History: list
* Settings: filters (list/get/create/delete), forwardingAddresses (list/get),
  sendAs (list/get)
* 13 MCP tools (`create_draft`, `list_drafts`, `get_thread`, `get_message`,
  `search_threads`, `label_thread`, `unlabel_thread`,
  `apply_sensitive_thread_label`, `list_labels`, `label_message`,
  `unlabel_message`, `apply_sensitive_message_label`, `create_label`)

## What it does not cover

`users.watch` and `users.stop` return 501 — there's no Pub/Sub push. Resumable
upload returns 501. Filter `action.forward` returns 501. `processForCalendar=true`
and `deleted=true` on insert/import return 501.

Non-goals: real SMTP/network delivery (send is a mailbox-state transition — no
mail ever leaves), Pub/Sub, Google OAuth/OIDC, and the Calendar, Drive, Contacts,
and admin surfaces. The bearer token is the Pome session JWT, not a Google OAuth
token — no consent screens, refresh tokens, or scopes.

## Quickstart

```bash theme={null}
pome run scenarios/22-gmail-inbox-triage.md \
  --agent "<your agent command>"
```

That scenario boots the twin in-process, seeds a mailbox, and scores the run
once the agent exits.

## Point your agent at it

For interactive development without a full scenario run, start the standalone
twin:

```bash theme={null}
pome twin start gmail
```

The command prints env-var lines you can paste into your agent's environment:

```text theme={null}
POME_GMAIL_REST_URL=http://127.0.0.1:3336/s/standalone
POME_GMAIL_MCP_URL=http://127.0.0.1:3336/s/standalone/mcp
POME_AUTH_TOKEN=<jwt>
POME_GMAIL_TOKEN=<jwt>
```

`POME_GMAIL_REST_URL` is the REST root. `POME_GMAIL_MCP_URL` is the MCP transport
endpoint. `POME_AUTH_TOKEN` is a short-lived JWT that authenticates every request
on the session. `POME_GMAIL_TOKEN` is an alias of `POME_AUTH_TOKEN`.

The default mailbox is `pome-agent@pome-twin.test`. Mailbox resolution accepts
only `me` or the exact seeded `gmail_email` — anything else is rejected.

To check whether the twin is alive, use the unauthenticated root health endpoint:

```bash theme={null}
curl http://127.0.0.1:3336/healthz
```

The session path `/s/standalone/healthz` requires the JWT and returns 401 without
it.

### Reset between runs

```bash theme={null}
pome twin reset
```

Clears the local twin state. The next `pome twin start gmail` reseeds from the
fixture.

## Scenario seed shape

Gmail scenarios use a seed block with a required `primaryMailbox`, an optional
`mailboxes` array, a `deliveryMode`, and a `clock`:

```json theme={null}
{
  "primaryMailbox": "pome-agent@pome-twin.test",
  "deliveryMode": "sender-only",
  "clock": "2026-07-22T09:00:00Z",
  "mailboxes": [
    {
      "email": "pome-agent@pome-twin.test",
      "displayName": "Pome Agent",
      "labels": [{ "id": "Label_1", "name": "follow-up" }],
      "messages": [
        {
          "id": "msg_1",
          "threadId": "thread_1",
          "from": "support@acme.test",
          "to": ["pome-agent@pome-twin.test"],
          "subject": "Order #4821 not delivered",
          "text": "Customer is asking for a refund status update.",
          "date": "2026-07-22T08:45:00Z",
          "labels": ["UNREAD", "INBOX"],
          "attachments": []
        }
      ],
      "drafts": [],
      "filters": [],
      "forwardingAddresses": [],
      "sendAs": []
    }
  ]
}
```

`deliveryMode` defaults to `"sender-only"`; set it to `"seeded-mailboxes"` to
route sends between mailboxes that are both present in `mailboxes[]`. Set
`twins: ["gmail"]` in the scenario's `## Config` block.

## Example scenarios

Ready-made examples you can run or copy to see the twin in action:

```bash theme={null}
pome scenarios gmail
pome scenarios gmail --copy
```

### Catalog

| #  | Scenario                                                                        | What it exercises                                                                                                |
| -- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 22 | **Inbox triage** (`22-gmail-inbox-triage.md`)                                   | Find an unread support thread, label it for follow-up, and prepare a draft reply.                                |
| 23 | **First-party parity** (`23-gmail-first-party-parity.md`)                       | Exercise the full 13-tool Gmail MCP workflow over one deterministic mailbox.                                     |
| 27 | **Gmail → GitHub support escalation** (`27-gmail-github-support-escalation.md`) | Label a Gmail support thread, then open a labeled GitHub bug for the same incident (cross-twin: gmail + github). |

### Run one

```bash theme={null}
pome run scenarios/22-gmail-inbox-triage.md --agent "<your agent command>"
```

Or let `/pome-test` pick matching scenarios automatically. See [/test-with-pome](/docs/skills/test-with-pome).
