diff --git a/docs/automation/cron-jobs.md b/docs/automation/cron-jobs.md
index 1d76cbfbcee8..f2d483cb83f2 100644
--- a/docs/automation/cron-jobs.md
+++ b/docs/automation/cron-jobs.md
@@ -325,7 +325,7 @@ Keep hook endpoints behind loopback, tailnet, or trusted reverse proxy.
Wire Gmail inbox triggers to OpenClaw via Google PubSub.
-**Prerequisites:** `gcloud` CLI, `gog` (gogcli), OpenClaw hooks enabled, Tailscale for the public HTTPS endpoint.
+**Prerequisites:** `gcloud` CLI, `gog` (gogcli), and OpenClaw hooks enabled. The `openclaw webhooks gmail setup` helper still configures the Pub/Sub push flow, which also needs Tailscale or another HTTPS push endpoint.
### Wizard setup (recommended)
@@ -338,7 +338,7 @@ This writes `hooks.gmail` config, enables the Gmail preset, and uses Tailscale F
### Gateway auto-start
-When `hooks.enabled=true` and `hooks.gmail.account` is set, the Gateway starts `gog gmail watch serve` on boot and auto-renews the watch. Set `OPENCLAW_SKIP_GMAIL_WATCHER=1` to opt out.
+When `hooks.enabled=true` and `hooks.gmail.account` is set, the Gateway starts the configured `gog gmail watch` delivery runner on boot and auto-renews the watch. Push configs start `gog gmail watch serve`; pull configs start `gog gmail watch pull`. Set `OPENCLAW_SKIP_GMAIL_WATCHER=1` to opt out.
### Manual one-time setup
diff --git a/docs/cli/webhooks.md b/docs/cli/webhooks.md
index c5dafe6e584b..f72639b12e76 100644
--- a/docs/cli/webhooks.md
+++ b/docs/cli/webhooks.md
@@ -17,14 +17,14 @@ openclaw webhooks gmail setup --account [...]
openclaw webhooks gmail run [--account ] [...]
```
-| Subcommand | Description |
-| ------------- | -------------------------------------------------------------------------------------------- |
-| `gmail setup` | Configure Gmail watch, Pub/Sub topic/subscription, and the OpenClaw webhook delivery target. |
-| `gmail run` | Run `gog watch serve` plus the watch auto-renew loop. |
+| Subcommand | Description |
+| ------------- | ---------------------------------------------------------------------------------------- |
+| `gmail setup` | Configure the existing Gmail Pub/Sub push flow and the OpenClaw webhook delivery target. |
+| `gmail run` | Run the configured `gog gmail watch` delivery process plus the watch auto-renew loop. |
## `webhooks gmail setup`
-Configure Gmail watch, Pub/Sub, and OpenClaw webhook delivery.
+Configure Gmail watch, Pub/Sub push, and OpenClaw webhook delivery.
```bash
openclaw webhooks gmail setup --account you@example.com
@@ -83,17 +83,18 @@ openclaw webhooks gmail setup --account you@example.com --hook-url https://gatew
## `webhooks gmail run`
-Run `gog watch serve` plus the watch auto-renew loop in the foreground.
+Run the configured `gog gmail watch` delivery process plus the watch auto-renew loop in the foreground. Push configs start `gog gmail watch serve`; pull configs start `gog gmail watch pull`.
```bash
openclaw webhooks gmail run --account you@example.com
```
-`run` accepts the same `gog watch serve`, OpenClaw delivery, Pub/Sub, and Tailscale flags as `setup`, except:
+`run` accepts the same push-oriented `gog watch serve`, OpenClaw delivery, Pub/Sub, and Tailscale flags as `setup`, except:
- `--account` is **optional** on `run` (it falls back to the configured account).
- `run` does **not** accept `--project`, `--push-endpoint`, or `--json`.
- `run` flags have no built-in defaults; missing values fall back to the values written by `setup`.
+- Pull mode is selected from `hooks.gmail.delivery.mode` in config. Use `hooks.gmail.delivery.subscription` for the full pull subscription path.
| Category | Flags |
| ----------------- | -------------------------------------------------------------------------------- |
diff --git a/docs/gateway/configuration-reference.md b/docs/gateway/configuration-reference.md
index cb3c14404a4c..4e9085be3ff3 100644
--- a/docs/gateway/configuration-reference.md
+++ b/docs/gateway/configuration-reference.md
@@ -771,14 +771,14 @@ Validation and safety notes:
gmail: {
account: "openclaw@gmail.com",
topic: "projects//topics/gog-gmail-watch",
- subscription: "gog-gmail-watch-push",
- pushToken: "shared-push-token",
+ delivery: {
+ mode: "pull",
+ subscription: "projects//subscriptions/gog-gmail-watch",
+ },
hookUrl: "http://127.0.0.1:18789/hooks/gmail",
includeBody: true,
maxBytes: 20000,
renewEveryMinutes: 720,
- serve: { bind: "127.0.0.1", port: 8788, path: "/" },
- tailscale: { mode: "funnel", path: "/gmail-pubsub" },
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
thinking: "off",
},
@@ -786,8 +786,34 @@ Validation and safety notes:
}
```
-- Gateway auto-starts `gog gmail watch serve` on boot when configured. Set `OPENCLAW_SKIP_GMAIL_WATCHER=1` to disable.
-- Don't run a separate `gog gmail watch serve` alongside the Gateway.
+- Pull delivery starts `gog gmail watch pull` on boot. It consumes a Pub/Sub pull subscription from the gateway host and posts processed Gmail notifications into the local OpenClaw hook endpoint. It does not need `pushToken`, `serve`, `tailscale`, or a public HTTP callback URL.
+- Pull delivery requires `delivery.subscription` to be a full Pub/Sub subscription resource path: `projects//subscriptions/`.
+- Do not run a separate `gog gmail watch pull` against the same subscription alongside the Gateway.
+- Set `OPENCLAW_SKIP_GMAIL_WATCHER=1` to disable the Gateway-managed Gmail watcher.
+
+Push delivery is still supported for existing deployments and explicit HTTP ingress setups. Omit `delivery.mode` to preserve existing push behavior, or set it explicitly:
+
+```json5
+{
+ hooks: {
+ gmail: {
+ account: "openclaw@gmail.com",
+ topic: "projects//topics/gog-gmail-watch",
+ delivery: {
+ mode: "push",
+ subscription: "gog-gmail-watch-push",
+ },
+ pushToken: "shared-push-token",
+ hookUrl: "http://127.0.0.1:18789/hooks/gmail",
+ serve: { bind: "127.0.0.1", port: 8788, path: "/" },
+ tailscale: { mode: "funnel", path: "/gmail-pubsub" },
+ },
+ },
+}
+```
+
+- Push delivery starts `gog gmail watch serve` and requires a Pub/Sub push subscription to reach the callback endpoint.
+- `openclaw webhooks gmail setup` remains push-oriented in this release. Pull-mode cloud setup is a later slice after pull delivery is dogfooded.
---
diff --git a/src/cli/webhooks-cli.ts b/src/cli/webhooks-cli.ts
index dbd576f50528..b7207ed91872 100644
--- a/src/cli/webhooks-cli.ts
+++ b/src/cli/webhooks-cli.ts
@@ -39,7 +39,7 @@ export function registerWebhooksCli(program: Command) {
gmail
.command("setup")
- .description("Configure Gmail watch + Pub/Sub + OpenClaw hooks")
+ .description("Configure Gmail watch + Pub/Sub push + OpenClaw hooks")
.requiredOption("--account ", "Gmail account to watch")
.option("--project ", "GCP project id (OAuth client owner)")
.option("--topic ", "Pub/Sub topic name", DEFAULT_GMAIL_TOPIC)
@@ -78,10 +78,10 @@ export function registerWebhooksCli(program: Command) {
gmail
.command("run")
- .description("Run gog watch serve + auto-renew loop")
+ .description("Run configured gog gmail watch delivery + auto-renew loop")
.option("--account ", "Gmail account to watch")
.option("--topic ", "Pub/Sub topic path (projects/.../topics/..)")
- .option("--subscription ", "Pub/Sub subscription name")
+ .option("--subscription ", "Pub/Sub subscription name or full path for pull configs")
.option("--label