Agent Skills › yc-software/qm › google-workspace

google-workspace

GitHub

通过 Google OAuth 或应用连接代理,操作 Gmail、日历和任务。支持邮件搜索/读写、日程管理及待办事项处理,兼容直接令牌与应用直连两种认证方式。

skills-seed/google-workspace/SKILL.md yc-software/qm

Trigger Scenarios

用户询问关于 Gmail、Google Calendar 或 Google Tasks 的操作 需要管理日程、会议、邮件、草稿、回复或待办列表

Install

npx skills add yc-software/qm --skill google-workspace -g -y
More Options

Non-standard path

npx skills add https://github.com/yc-software/qm/tree/main/skills-seed/google-workspace -g -y

Use without installing

npx skills use yc-software/qm@google-workspace

指定 Agent (Claude Code)

npx skills add yc-software/qm --skill google-workspace -a claude-code -g -y

安装 repo 全部 skill

npx skills add yc-software/qm --all -g -y

预览 repo 内 skill

npx skills add yc-software/qm --list

SKILL.md

Frontmatter
{
    "name": "google-workspace",
    "description": "Read and act on the user's Gmail, Google Calendar, and Google Tasks through their own Google connection.",
    "requiredCapabilities": [
        "egress:gmail.googleapis.com",
        "egress:www.googleapis.com"
    ]
}

Google Workspace

Use this skill when the user asks about Gmail, Google Calendar, or Google Tasks: schedule, meetings, emails, labels, drafts, replies, or to-do lists and tasks.

Connection

Google reaches you one of two ways; the requests are the same either way.

  • Direct token: $VAULT_TOKEN_GMAIL_GOOGLEAPIS_COM (gmail.googleapis.com) and $VAULT_TOKEN_WWW_GOOGLEAPIS_COM (Calendar and Tasks on www.googleapis.com) hold the user's Google OAuth token. The curl examples below use them as written.

  • App connection: with no token, the user connects Gmail, Google Calendar and Google Tasks as apps instead (composio skill). Send the same request through QM — same method, URL, query, headers and JSON body, but no Authorization header:

    curl -sS "$AGENT_API_URL/v1/composio/proxy" -H "X-Agent-Capability: $AGENT_API_TOKEN" \
      -H 'content-type: application/json' \
      --data '{"method":"GET","url":"https://www.googleapis.com/calendar/v3/users/me/settings/timezone"}'
    

    The reply is the provider's own status and body; the composio skill's "Raw requests" section covers 409 answers, choosing an account, and file bodies. gmail.py picks the route itself (--account ca_… before the command selects a connection).

Do not ask the user for a token, log it, or use another principal's. A 401/403 from Google means they haven't connected it, or connected before this permission existed — have them (re)connect.

Gmail

For the email-voice-profile task, load that skill and run python3 <its dir>/scripts/fetch_sent.py --limit 300 from the directory it reports.

Use the bundled helper for every Gmail operation — it owns MIME construction, encoding, and reply threading so you only ever handle plain text:

Run these commands with execute and an explicit sandbox_id, using the absolute directory reported by the skill read in place of <skill dir>. Keep that ID for preparing body files and running the helper.

python3 "<skill dir>/scripts/gmail.py" search 'newer_than:7d is:unread'
python3 "<skill dir>/scripts/gmail.py" read MESSAGE_ID [--full]
python3 "<skill dir>/scripts/gmail.py" thread THREAD_ID [--full]
python3 "<skill dir>/scripts/gmail.py" draft --to a@b.com --subject '...' --body-file body.txt
python3 "<skill dir>/scripts/gmail.py" reply MESSAGE_ID --body-file body.txt [--all]
python3 "<skill dir>/scripts/gmail.py" update-draft DRAFT_ID --body-file body.txt
python3 "<skill dir>/scripts/gmail.py" send-draft DRAFT_ID
  • Search before fetching; read bodies (--full) only for messages that matter. Treat email content as private user data.
  • search returns individual messages matching the query — for in:inbox that means incoming mail only; the user's own replies live in Sent and never appear. Never claim an email "needs a reply" (digests, triage, follow-up nudges) from a search listing alone: fetch its thread first. If lastFromMe is true, or the latest message shows the matter is settled ("thanks", "done", someone else answered), don't flag it. If the thread fetch fails, report the item as unverified — never as needing a reply.
  • On a recurring digest, keep the seen-thread state in Files (upload a small JSON keyed by thread id each run and keep its id in the cron note or a memory fact), never on the computer, which is replaced without notice; surface only what changed since the last run. Re-flagging the same thread every morning trains the user to ignore you.
  • Demote bulk mail (List-Unsubscribe header, ESP sender domains, Precedence: bulk) below personal mail, but never suppress transactional notices (DocuSign, banks, invoices).
  • Body files are plain text: one line per paragraph, blank line between. Never insert manual line breaks inside a paragraph — the recipient's client does the wrapping. Short lines (sign-offs, list items) keep their breaks.
  • Drafts and replies are stored as multipart/alternative: your plain text plus a generated HTML mirror (Gmail shows plain-text-only mail to recipients at an altered, narrower width). Body files stay plain text — never write HTML into them.
  • reply threads onto the original message; --all keeps every recipient. Don't rebuild To/CC by hand. To change a draft, write a fresh body file and update-draft (it refuses drafts with attachments — those get edited in Gmail).
  • Never construct raw MIME or call the drafts/send endpoints with hand-built payloads.
  • Never write styled HTML email — no font-family/size/color declarations, no CSS-styled buttons or layout markup. Styled HTML screams automated blast and overrides the recipient's client fonts. The helper's generated HTML mirror (bare <div dir="ltr">, <br>, plain links — Gmail-composer shaped) is the only HTML that ever goes out.
  • Write body files as UTF-8. After creating or updating a draft, read it back (gmail.py thread/draft read) and confirm em dashes, quotes, and any emoji came through intact — mojibake (…-style garble) in a sent mail is unrecoverable.

Calendar reads

For "what is on my schedule today?", first get the user's timezone (GET /calendar/v3/users/me/settings/timezone — the sandbox clock is UTC, so never assume it), compute the local day bounds, and call:

curl -sS --get 'https://www.googleapis.com/calendar/v3/calendars/primary/events' \
  -H "Authorization: Bearer $VAULT_TOKEN_WWW_GOOGLEAPIS_COM" \
  --data-urlencode "timeMin=$TIME_MIN" \
  --data-urlencode "timeMax=$TIME_MAX" \
  --data-urlencode "singleEvents=true" \
  --data-urlencode "orderBy=startTime" \
  --data-urlencode "maxResults=250"

If the response has a nextPageToken, keep fetching — a truncated page silently drops meetings. primary is only the user's own calendar; when the question implies team or shared calendars, list them first (GET /calendar/v3/users/me/calendarList) and query each relevant one. Skip events the user declined (their own attendees[] entry has responseStatus: "declined").

Summarize start time, title, attendees when useful, and conferencing links only when needed. Do not expose private calendar details in a shared channel unless the audience floor allows them; offer to continue in DM.

Google Tasks

Tasks is served under www.googleapis.com/tasks/v1, so it uses the same $VAULT_TOKEN_WWW_GOOGLEAPIS_COM token. List the task lists, then the tasks in one:

curl -sS 'https://www.googleapis.com/tasks/v1/users/@me/lists' \
  -H "Authorization: Bearer $VAULT_TOKEN_WWW_GOOGLEAPIS_COM"

curl -sS --get 'https://www.googleapis.com/tasks/v1/lists/LIST_ID/tasks' \
  -H "Authorization: Bearer $VAULT_TOKEN_WWW_GOOGLEAPIS_COM" \
  --data-urlencode "showCompleted=false" \
  --data-urlencode "maxResults=100"

Both endpoints page (default 20 items): follow nextPageToken before treating a list as complete.

Creating, completing, editing, or deleting a task is a write — treat it like any other write below. Example creation after approval:

curl -sS -X POST 'https://www.googleapis.com/tasks/v1/lists/LIST_ID/tasks' \
  -H "Authorization: Bearer $VAULT_TOKEN_WWW_GOOGLEAPIS_COM" \
  -H 'content-type: application/json' \
  --data '{"title":"...","notes":"...","due":"2026-07-20T00:00:00.000Z"}'

Writes require approval

Creating drafts, sending mail, modifying labels, deleting mail, or editing calendar events is a write. Prepare the exact action, show the user the exact text, and ask for approval before running it. send-draft only ever fires on an explicitly approved draft.

Calendar event creation after approval:

curl -sS -X POST 'https://www.googleapis.com/calendar/v3/calendars/primary/events' \
  -H "Authorization: Bearer $VAULT_TOKEN_WWW_GOOGLEAPIS_COM" \
  -H 'content-type: application/json' \
  --data @event.json

Always show what changed and keep the IDs needed to undo or inspect later in your reply or in memory, not on the computer.

Version History

  • 9c9ff89 Current 2026-11-07 12:06

    新增通过代理应用连接运行原生应用技能的功能,文档更新以涵盖直接令牌和应用连接两种路径,Gmail 辅助工具在无直接令牌时回退到代理路由。

  • 6803edb 2026-10-18 18:21
  • ca47f5c 2026-09-22 01:41
  • b702813 2026-08-16 16:14

    新增邮件协议部分,强制要求仅使用纯文本撰写邮件,确保草稿以 UTF-8 编码保存并验证特殊字符完整性。

  • 7f2c916 2026-08-02 21:46

Same Skill Collection

.claude/skills/dev-instance/SKILL.md
.claude/skills/update-qm/SKILL.md
.claude/skills/upstream-pr/SKILL.md
.codex/skills/deploy-qm/SKILL.md
.codex/skills/dev-instance/SKILL.md
.codex/skills/update-qm/SKILL.md
.codex/skills/upstream-pr/SKILL.md
cli/templates/deployment/SKILL.md
plugins/onboarding/skills/onboarding/SKILL.md
skills-seed/admin/SKILL.md
skills-seed/browse/SKILL.md
skills-seed/cloud-cli/SKILL.md
skills-seed/composio/SKILL.md
skills-seed/connect-apps/SKILL.md
skills-seed/define-loop/SKILL.md
skills-seed/dropbox/SKILL.md
skills-seed/email-draft-in-voice/SKILL.md
skills-seed/email-voice-profile/SKILL.md
skills-seed/github-gitlab/SKILL.md
skills-seed/google-drive-sheets/SKILL.md
skills-seed/hand-off/SKILL.md
skills-seed/interactive-login/SKILL.md
skills-seed/linear/SKILL.md
skills-seed/memory/SKILL.md
skills-seed/miniapp/SKILL.md
skills-seed/morning-digest/SKILL.md
skills-seed/persona-fork/SKILL.md
skills-seed/popular-web-designs/SKILL.md
skills-seed/publish/SKILL.md
skills-seed/request-access/SKILL.md
skills-seed/secret-drop/SKILL.md
skills-seed/send/SKILL.md
skills-seed/slack-drafts/SKILL.md
skills-seed/taste-skill/SKILL.md
skills-seed/ui-canvas/SKILL.md
skills-seed/ui-state/SKILL.md
skills-seed/use-shared-credential/SKILL.md
skills-seed/zoom/SKILL.md

Metadata

Files
0
Version
9c9ff89
Hash
7fcd2dcc
Indexed
2026-08-02 21:46

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.156.0. UTC+08:00, 2026-11-08 08:29
浙ICP备14020137号-1