{
  "schemaVersion": "1.0",
  "item": {
    "slug": "google-workspace-byok",
    "name": "Google Workspace BYOK",
    "source": "tencent",
    "type": "skill",
    "category": "效率提升",
    "sourceUrl": "https://clawhub.ai/kyesh/google-workspace-byok",
    "canonicalUrl": "https://clawhub.ai/kyesh/google-workspace-byok",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/google-workspace-byok",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=google-workspace-byok",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "scripts/setup.js",
      "scripts/auth.js",
      "scripts/gmail.js",
      "scripts/shared.js",
      "scripts/package.json"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/google-workspace-byok"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/google-workspace-byok",
    "agentPageUrl": "https://openagent3.xyz/skills/google-workspace-byok/agent",
    "manifestUrl": "https://openagent3.xyz/skills/google-workspace-byok/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/google-workspace-byok/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Google Workspace BYoK (Bring Your Own Key)",
        "body": "Direct Google Calendar and Gmail API access using your own GCP project OAuth2 credentials. Supports multiple Google accounts."
      },
      {
        "title": "Prerequisites",
        "body": "Node.js (v18+)\nA Google Cloud project with Calendar and Gmail APIs enabled\nOAuth2 Desktop app credentials from your GCP project"
      },
      {
        "title": "Step 1: Install Dependencies",
        "body": "cd {baseDir}/scripts && npm install\n\nThis installs googleapis (Google API client) and mupdf (PDF text extraction for email attachments)."
      },
      {
        "title": "Step 2: Create a Google Cloud Project",
        "body": "Go to Google Cloud Console and create a new project (or use an existing one)\nEnable the Google Calendar API and Gmail API:\n\nGo to APIs & Services → Library\nSearch for \"Google Calendar API\" → click Enable\nSearch for \"Gmail API\" → click Enable"
      },
      {
        "title": "Step 3: Configure the OAuth Consent Screen",
        "body": "Go to Google Auth Platform → Audience (direct link)\nIf prompted, configure the consent screen:\n\nApp name: anything (e.g., \"OpenClaw\")\nUser support email: your email\nScopes: skip (the auth script requests scopes at runtime)\n\n\nIf your app is in Testing publishing status (the default), add every Google account you want to authorize as a test user:\n\nUnder Test users, click Add users\nEnter the email addresses of each account you'll connect\nSave\n\n⚠️ Important: Apps in \"Testing\" status have a 7-day token expiry. To get long-lived tokens, publish your app to \"Production\" in the Audience settings. For personal Gmail accounts (External user type), you can skip Google's verification review — you'll just see an \"unverified app\" warning during consent. This is fine for personal use."
      },
      {
        "title": "Step 4: Create OAuth Credentials",
        "body": "Go to Google Auth Platform → Clients (direct link)\nClick Create Client → choose Desktop app as the application type\nName it whatever you like (e.g., \"OpenClaw\")\nClick Create and download the credentials JSON\nRun the setup script:\n\nnode {baseDir}/scripts/setup.js --credentials /path/to/downloaded-credentials.json\n\nThis copies your credentials to ~/.openclaw/google-workspace-byok/credentials.json."
      },
      {
        "title": "Step 5: Authorize Google Accounts",
        "body": "For each Google account you want to connect:\n\nnode {baseDir}/scripts/auth.js --account <label>\n\nThe <label> is a friendly name you'll use to reference this account (e.g., \"personal\", \"work\", \"household\").\n\nAuth flow:\n\nThe script prints an authorization URL\nOpen the URL in your browser and sign in with the Google account\nGrant the requested permissions\nYou'll be redirected to http://localhost/... — the page won't load, and that's expected\nCopy the full URL from your browser's address bar and paste it back into the script\nThe script exchanges the code for tokens and saves them\n\nScopes requested (default — read/write):\n\ncalendar — Full read/write access to Google Calendar\ngmail.readonly — Read-only access to Gmail\n\nPass --readonly to request read-only calendar access instead.\n\nTokens are stored in ~/.openclaw/google-workspace-byok/tokens/<label>.json."
      },
      {
        "title": "Usage",
        "body": "All scripts are in {baseDir}/scripts/. Run them with node."
      },
      {
        "title": "Calendar",
        "body": "# List all calendars\nnode {baseDir}/scripts/calendar.js --account <label> --action list-calendars\n\n# List upcoming events (default: next 7 days, primary calendar)\nnode {baseDir}/scripts/calendar.js --account <label> --action events\n\n# List events with options\nnode {baseDir}/scripts/calendar.js --account <label> --action events --calendar <calendarId> --days <number> --max <number>\n\n# Get a specific event\nnode {baseDir}/scripts/calendar.js --account <label> --action get-event --calendar <calendarId> --event-id <eventId>\n\n# Check free/busy\nnode {baseDir}/scripts/calendar.js --account <label> --action freebusy --days <number>"
      },
      {
        "title": "Gmail",
        "body": "# List recent emails (default: 10)\nnode {baseDir}/scripts/gmail.js --account <label> --action list\n\n# Search emails\nnode {baseDir}/scripts/gmail.js --account <label> --action list --query \"from:someone@example.com\" --max 20\n\n# Read a specific email (includes attachment metadata with IDs)\nnode {baseDir}/scripts/gmail.js --account <label> --action read --message-id <messageId>\n\n# Download all attachments from an email\nnode {baseDir}/scripts/gmail.js --account <label> --action attachment --message-id <messageId> --out-dir /tmp/attachments\n\n# Download a specific attachment\nnode {baseDir}/scripts/gmail.js --account <label> --action attachment --message-id <messageId> --attachment-id <id> --out-dir /tmp\n\n# List labels\nnode {baseDir}/scripts/gmail.js --account <label> --action labels\n\nGmail search uses the same query syntax as the Gmail web search box (e.g., is:unread, from:, newer_than:1d, has:attachment)."
      },
      {
        "title": "Reading PDF Attachments",
        "body": "The skill includes mupdf for extracting text from PDF attachments — useful for newsletters, invoices, school letters, etc. It handles multilingual text (Japanese, Chinese, etc.) well.\n\n# 1. Download the attachment\nmkdir -p /tmp/attachments\nnode {baseDir}/scripts/gmail.js --account <label> --action attachment --message-id <id> --out-dir /tmp/attachments\n\n# 2. Extract text from the PDF\nnode --input-type=module -e \"\nimport * as mupdf from '{baseDir}/scripts/node_modules/mupdf/dist/mupdf.js';\nimport fs from 'fs';\nconst data = fs.readFileSync('/tmp/attachments/filename.pdf');\nconst doc = mupdf.Document.openDocument(data, 'application/pdf');\nfor (let i = 0; i < doc.countPages(); i++) {\n  const page = doc.loadPage(i);\n  console.log(page.toStructuredText('preserve-whitespace').asText());\n}\n\"\n\nNote: mupdf is an ESM module — use node --input-type=module with import syntax, not require()."
      },
      {
        "title": "Account Management",
        "body": "# List configured accounts\nnode {baseDir}/scripts/accounts.js --action list\n\n# Check token status\nnode {baseDir}/scripts/accounts.js --action status --account <label>"
      },
      {
        "title": "File Layout",
        "body": "~/.openclaw/google-workspace-byok/\n├── credentials.json          # Your GCP OAuth credentials\n└── tokens/\n    ├── personal.json          # Token for \"personal\" account\n    └── work.json              # Token for \"work\" account"
      },
      {
        "title": "Error 403: access_denied — \"has not completed the Google verification process\"",
        "body": "Your app is in Testing mode and the Google account isn't listed as a test user. Fix: Google Auth Platform → Audience → Test users → Add the email."
      },
      {
        "title": "Error: invalid_grant",
        "body": "The refresh token expired or was revoked. Re-run node {baseDir}/scripts/auth.js --account <label> to re-authorize."
      },
      {
        "title": "Tokens expire after 7 days",
        "body": "Apps in \"Testing\" publishing status issue tokens that expire after 7 days. Publish your app to \"Production\" for long-lived tokens. For personal Gmail (External user type), you can skip verification and just accept the \"unverified app\" warning."
      },
      {
        "title": "Error: redirect_uri_mismatch",
        "body": "Your credentials.json doesn't include http://localhost as a redirect URI. Edit your OAuth client in GCP Console → Authorized redirect URIs → add http://localhost."
      },
      {
        "title": "npm install fails or mupdf won't install",
        "body": "mupdf requires a C++ build toolchain on some platforms. If it fails, you can still use all other features — PDF text extraction is the only feature that requires it. Try: npm install --ignore-scripts to skip native compilation, then install mupdf separately if needed."
      }
    ],
    "body": "Google Workspace BYoK (Bring Your Own Key)\n\nDirect Google Calendar and Gmail API access using your own GCP project OAuth2 credentials. Supports multiple Google accounts.\n\nPrerequisites\nNode.js (v18+)\nA Google Cloud project with Calendar and Gmail APIs enabled\nOAuth2 Desktop app credentials from your GCP project\nSetup\nStep 1: Install Dependencies\ncd {baseDir}/scripts && npm install\n\n\nThis installs googleapis (Google API client) and mupdf (PDF text extraction for email attachments).\n\nStep 2: Create a Google Cloud Project\nGo to Google Cloud Console and create a new project (or use an existing one)\nEnable the Google Calendar API and Gmail API:\nGo to APIs & Services → Library\nSearch for \"Google Calendar API\" → click Enable\nSearch for \"Gmail API\" → click Enable\nStep 3: Configure the OAuth Consent Screen\nGo to Google Auth Platform → Audience (direct link)\nIf prompted, configure the consent screen:\nApp name: anything (e.g., \"OpenClaw\")\nUser support email: your email\nScopes: skip (the auth script requests scopes at runtime)\nIf your app is in Testing publishing status (the default), add every Google account you want to authorize as a test user:\nUnder Test users, click Add users\nEnter the email addresses of each account you'll connect\nSave\n\n⚠️ Important: Apps in \"Testing\" status have a 7-day token expiry. To get long-lived tokens, publish your app to \"Production\" in the Audience settings. For personal Gmail accounts (External user type), you can skip Google's verification review — you'll just see an \"unverified app\" warning during consent. This is fine for personal use.\n\nStep 4: Create OAuth Credentials\nGo to Google Auth Platform → Clients (direct link)\nClick Create Client → choose Desktop app as the application type\nName it whatever you like (e.g., \"OpenClaw\")\nClick Create and download the credentials JSON\nRun the setup script:\nnode {baseDir}/scripts/setup.js --credentials /path/to/downloaded-credentials.json\n\n\nThis copies your credentials to ~/.openclaw/google-workspace-byok/credentials.json.\n\nStep 5: Authorize Google Accounts\n\nFor each Google account you want to connect:\n\nnode {baseDir}/scripts/auth.js --account <label>\n\n\nThe <label> is a friendly name you'll use to reference this account (e.g., \"personal\", \"work\", \"household\").\n\nAuth flow:\n\nThe script prints an authorization URL\nOpen the URL in your browser and sign in with the Google account\nGrant the requested permissions\nYou'll be redirected to http://localhost/... — the page won't load, and that's expected\nCopy the full URL from your browser's address bar and paste it back into the script\nThe script exchanges the code for tokens and saves them\n\nScopes requested (default — read/write):\n\ncalendar — Full read/write access to Google Calendar\ngmail.readonly — Read-only access to Gmail\n\nPass --readonly to request read-only calendar access instead.\n\nTokens are stored in ~/.openclaw/google-workspace-byok/tokens/<label>.json.\n\nUsage\n\nAll scripts are in {baseDir}/scripts/. Run them with node.\n\nCalendar\n# List all calendars\nnode {baseDir}/scripts/calendar.js --account <label> --action list-calendars\n\n# List upcoming events (default: next 7 days, primary calendar)\nnode {baseDir}/scripts/calendar.js --account <label> --action events\n\n# List events with options\nnode {baseDir}/scripts/calendar.js --account <label> --action events --calendar <calendarId> --days <number> --max <number>\n\n# Get a specific event\nnode {baseDir}/scripts/calendar.js --account <label> --action get-event --calendar <calendarId> --event-id <eventId>\n\n# Check free/busy\nnode {baseDir}/scripts/calendar.js --account <label> --action freebusy --days <number>\n\nGmail\n# List recent emails (default: 10)\nnode {baseDir}/scripts/gmail.js --account <label> --action list\n\n# Search emails\nnode {baseDir}/scripts/gmail.js --account <label> --action list --query \"from:someone@example.com\" --max 20\n\n# Read a specific email (includes attachment metadata with IDs)\nnode {baseDir}/scripts/gmail.js --account <label> --action read --message-id <messageId>\n\n# Download all attachments from an email\nnode {baseDir}/scripts/gmail.js --account <label> --action attachment --message-id <messageId> --out-dir /tmp/attachments\n\n# Download a specific attachment\nnode {baseDir}/scripts/gmail.js --account <label> --action attachment --message-id <messageId> --attachment-id <id> --out-dir /tmp\n\n# List labels\nnode {baseDir}/scripts/gmail.js --account <label> --action labels\n\n\nGmail search uses the same query syntax as the Gmail web search box (e.g., is:unread, from:, newer_than:1d, has:attachment).\n\nReading PDF Attachments\n\nThe skill includes mupdf for extracting text from PDF attachments — useful for newsletters, invoices, school letters, etc. It handles multilingual text (Japanese, Chinese, etc.) well.\n\n# 1. Download the attachment\nmkdir -p /tmp/attachments\nnode {baseDir}/scripts/gmail.js --account <label> --action attachment --message-id <id> --out-dir /tmp/attachments\n\n# 2. Extract text from the PDF\nnode --input-type=module -e \"\nimport * as mupdf from '{baseDir}/scripts/node_modules/mupdf/dist/mupdf.js';\nimport fs from 'fs';\nconst data = fs.readFileSync('/tmp/attachments/filename.pdf');\nconst doc = mupdf.Document.openDocument(data, 'application/pdf');\nfor (let i = 0; i < doc.countPages(); i++) {\n  const page = doc.loadPage(i);\n  console.log(page.toStructuredText('preserve-whitespace').asText());\n}\n\"\n\n\nNote: mupdf is an ESM module — use node --input-type=module with import syntax, not require().\n\nAccount Management\n# List configured accounts\nnode {baseDir}/scripts/accounts.js --action list\n\n# Check token status\nnode {baseDir}/scripts/accounts.js --action status --account <label>\n\nFile Layout\n~/.openclaw/google-workspace-byok/\n├── credentials.json          # Your GCP OAuth credentials\n└── tokens/\n    ├── personal.json          # Token for \"personal\" account\n    └── work.json              # Token for \"work\" account\n\nTroubleshooting\nError 403: access_denied — \"has not completed the Google verification process\"\n\nYour app is in Testing mode and the Google account isn't listed as a test user. Fix: Google Auth Platform → Audience → Test users → Add the email.\n\nError: invalid_grant\n\nThe refresh token expired or was revoked. Re-run node {baseDir}/scripts/auth.js --account <label> to re-authorize.\n\nTokens expire after 7 days\n\nApps in \"Testing\" publishing status issue tokens that expire after 7 days. Publish your app to \"Production\" for long-lived tokens. For personal Gmail (External user type), you can skip verification and just accept the \"unverified app\" warning.\n\nError: redirect_uri_mismatch\n\nYour credentials.json doesn't include http://localhost as a redirect URI. Edit your OAuth client in GCP Console → Authorized redirect URIs → add http://localhost.\n\nnpm install fails or mupdf won't install\n\nmupdf requires a C++ build toolchain on some platforms. If it fails, you can still use all other features — PDF text extraction is the only feature that requires it. Try: npm install --ignore-scripts to skip native compilation, then install mupdf separately if needed."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/kyesh/google-workspace-byok",
    "publisherUrl": "https://clawhub.ai/kyesh/google-workspace-byok",
    "owner": "kyesh",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/google-workspace-byok",
    "downloadUrl": "https://openagent3.xyz/downloads/google-workspace-byok",
    "agentUrl": "https://openagent3.xyz/skills/google-workspace-byok/agent",
    "manifestUrl": "https://openagent3.xyz/skills/google-workspace-byok/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/google-workspace-byok/agent.md"
  }
}