Gmail Pub/Sub -> OpenClaw

Mục tiêu: Gmail watch -> Pub/Sub push -> gog gmail watch serve -> OpenClaw webhook.

Yêu cầu trước khi bắt đầu

  • gcloud đã cài đặt và đăng nhập (hướng dẫn cài đặt).
  • gog (gogcli) đã cài đặt và được ủy quyền cho tài khoản Gmail (gogcli.sh).
  • OpenClaw hooks đã bật (xem Webhooks).
  • tailscale đã đăng nhập (tailscale.com). Cấu hình được hỗ trợ sử dụng Tailscale Funnel cho public HTTPS endpoint. Các dịch vụ tunnel khác có thể hoạt động, nhưng không được hỗ trợ chính thức và cần tự config thủ công. Hiện tại, Tailscale là dịch vụ mình hỗ trợ.

Ví dụ config hook (bật Gmail preset mapping):

{
  hooks: {
    enabled: true,
    token: "OPENCLAW_HOOK_TOKEN",
    path: "/hooks",
    presets: ["gmail"],
  },
}

Để gửi tóm tắt Gmail đến giao diện chat, các bạn override preset với mapping có thiết lập deliver + tùy chọn channel/to:

{
  hooks: {
    enabled: true,
    token: "OPENCLAW_HOOK_TOKEN",
    presets: ["gmail"],
    mappings: [
      {
        match: { path: "gmail" },
        action: "agent",
        wakeMode: "now",
        name: "Gmail",
        sessionKey: "hook:gmail:{{messages[0].id}}",
        messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
        model: "openai/gpt-5.2-mini",
        deliver: true,
        channel: "last",
        // to: "+15551234567"
      },
    ],
  },
}

Nếu muốn dùng channel cố định, set channel + to. Còn không thì channel: "last" sẽ dùng route gửi gần nhất (fallback về WhatsApp).

Để bắt buộc dùng model rẻ hơn cho Gmail runs, set model trong mapping (provider/model hoặc alias). Nếu các bạn enforce agents.defaults.models, nhớ thêm vào đó nhé.

Để set model mặc định và thinking level riêng cho Gmail hooks, thêm hooks.gmail.model / hooks.gmail.thinking vào config:

{
  hooks: {
    gmail: {
      model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
      thinking: "off",
    },
  },
}

Lưu ý:

  • model/thinking trong từng hook mapping vẫn sẽ override các giá trị mặc định này.
  • Thứ tự fallback: hooks.gmail.modelagents.defaults.model.fallbacks → primary (auth/rate-limit/timeouts).
  • Nếu agents.defaults.models được set, Gmail model phải nằm trong allowlist.
  • Nội dung Gmail hook được bọc với external-content safety boundaries mặc định. Để tắt (nguy hiểm), set hooks.gmail.allowUnsafeExternalContent: true.

Để tùy chỉnh xử lý payload thêm, các bạn thêm hooks.mappings hoặc module transform JS/TS trong hooks.transformsDir (xem Webhooks).

Wizard (khuyên dùng)

Dùng OpenClaw helper để kết nối mọi thứ lại với nhau (tự động cài deps trên macOS qua brew):

openclaw webhooks gmail setup \
  --account [email protected]

Mặc định:

  • Dùng Tailscale Funnel cho public push endpoint.
  • Ghi config hooks.gmail cho openclaw webhooks gmail run.
  • Bật Gmail hook preset (hooks.presets: ["gmail"]).

Lưu ý về path: khi tailscale.mode được bật, OpenClaw tự động set hooks.gmail.serve.path thành / và giữ public path ở hooks.gmail.tailscale.path (mặc định /gmail-pubsub) vì Tailscale bỏ prefix path trước khi proxy. Nếu cần backend nhận path có prefix, set hooks.gmail.tailscale.target (hoặc --tailscale-target) thành URL đầy đủ như http://127.0.0.1:8788/gmail-pubsub và match với hooks.gmail.serve.path.

Muốn dùng endpoint tùy chỉnh? Dùng --push-endpoint <url> hoặc --tailscale off.

Lưu ý về platform: trên macOS wizard sẽ cài gcloud, gogcli, và tailscale qua Homebrew; trên Linux các bạn cài thủ công trước nhé.

Gateway auto-start (khuyên dùng):

  • Khi hooks.enabled=truehooks.gmail.account được set, Gateway sẽ khởi động gog gmail watch serve khi boot và tự động renew watch.
  • Set OPENCLAW_SKIP_GMAIL_WATCHER=1 để opt out (hữu ích nếu các bạn tự chạy daemon).
  • Đừng chạy manual daemon cùng lúc, không thì sẽ gặp lỗi listen tcp 127.0.0.1:8788: bind: address already in use.

Manual daemon (khởi động gog gmail watch serve + auto-renew):

openclaw webhooks gmail run

Thiết lập một lần

  1. Chọn GCP project sở hữu OAuth client được dùng bởi gog.
gcloud auth login
gcloud config set project <project-id>

Lưu ý: Gmail watch yêu cầu Pub/Sub topic phải nằm trong cùng project với OAuth client.

  1. Bật APIs:
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
  1. Tạo topic:
gcloud pubsub topics create gog-gmail-watch
  1. Cho phép Gmail push publish:
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
  --member=serviceAccount:[email protected] \
  --role=roles/pubsub.publisher

Khởi động watch

gog gmail watch start \
  --account [email protected] \
  --label INBOX \
  --topic projects/<project-id>/topics/gog-gmail-watch

Lưu lại history_id từ output (để debug).

Chạy push handler

Ví dụ local (shared token auth):

gog gmail watch serve \
  --account [email protected] \
  --bind 127.0.0.1 \
  --port 8788 \
  --path /gmail-pubsub \
  --token <shared> \
  --hook-url http://127.0.0.1:18789/hooks/gmail \
  --hook-token OPENCLAW_HOOK_TOKEN \
  --include-body \
  --max-bytes 20000

Lưu ý:

  • --token bảo vệ push endpoint (x-gog-token hoặc ?token=).
  • --hook-url trỏ đến OpenClaw /hooks/gmail (mapped; isolated run + summary to main).
  • --include-body--max-bytes kiểm soát body snippet gửi đến OpenClaw.

Khuyên dùng: openclaw webhooks gmail run bọc cùng flow và tự động renew watch.

Expose handler (nâng cao, không được hỗ trợ)

Nếu cần dùng tunnel không phải Tailscale, tự config thủ công và dùng public URL trong push subscription (không được hỗ trợ chính thức, không có guardrails):

cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate

Dùng URL được tạo làm push endpoint:

gcloud pubsub subscriptions create gog-gmail-watch-push \
  --topic gog-gmail-watch \
  --push-endpoint "https://<public-url>/gmail-pubsub?token=<shared>"

Production: dùng HTTPS endpoint ổn định và config Pub/Sub OIDC JWT, sau đó chạy:

gog gmail watch serve --verify-oidc --oidc-email <svc@...>

Test

Gửi tin nhắn đến inbox đang được watch:

gog gmail send \
  --account [email protected] \
  --to [email protected] \
  --subject "watch test" \
  --body "ping"

Kiểm tra watch state và history:

gog gmail watch status --account [email protected]
gog gmail history --account [email protected] --since <historyId>

Troubleshooting

  • Invalid topicName: project không khớp (topic không nằm trong project của OAuth client).
  • User not authorized: thiếu roles/pubsub.publisher trên topic.
  • Tin nhắn rỗng: Gmail push chỉ cung cấp historyId; fetch qua gog gmail history.

Dọn dẹp

gog gmail watch stop --account [email protected]
gcloud pubsub subscriptions delete gog-gmail-watch-push
gcloud pubsub topics delete gog-gmail-watch