google-loops
garrytan/gbrain/skills/google-loops/SKILL.md
Set up and operate the Gmail/Calendar/Contacts connector and the open-loop engine: who is waiting on the user, what they promised, and the context needed to respond. Covers painless BYO OAuth setup (exactly two user interactions), the daily `gbrain waiting` digest, loop closing/muting, and troubleshooting via the typed error catalog.
Skill31k starsChanged 2 months ago
What's in it
- Google Loops — Setup and Daily Operation
- Contract for the harness (read first)
- Setup (the one command)
- Daily operation
- Continuous ingestion
- Troubleshooting
- Cost honesty
- Output Format
- When it fails
- Anti-Patterns
---
name: google-loops
version: 1.0.0
description: |
Set up and operate the Gmail/Calendar/Contacts connector and the open-loop
engine: who is waiting on the user, what they promised, and the context
needed to respond. Covers painless BYO OAuth setup (exactly two user
interactions), the daily `gbrain waiting` digest, loop closing/muting, and
troubleshooting via the typed error catalog.
triggers:
- "connect gmail"
- "connect google"
- "connect calendar"
- "connect contacts"
- "who is waiting on me"
- "what do I owe people"
- "open loops"
- "unanswered email"
- "set up email ingestion"
- "gbrain waiting"
tools:
- open_loops
- loops_close
- loops_mute
- entity
- context_pack
mutating: true
writes_pages: false
---
# Google Loops — Setup and Daily Operation
The connector ingests Gmail threads, calendar events, and contacts into the
brain and maintains the open-loop record behind `gbrain waiting`. Full
references: `docs/guides/google-connect.md` (setup + every error and its
fix) and `docs/guides/open-loops.md` (how detection works).
## Contract for the harness (read first)
1. **Relay `[SHOW USER]` blocks verbatim.** Setup commands print fenced
`[SHOW USER] ... [/SHOW USER]` blocks — numbered steps with deep links.
Pass them to the user unchanged (paraphrasing loses load-bearing detail
like "Desktop app, NOT Web application"). Batch everything into ONE
message per block.
2. **The whole setup is exactly two user interactions.** (1) The Google
Cloud checklist + the user hands back the downloaded client JSON.
(2) The user clicks one consent URL. If you find yourself asking a third
question, re-read the block you skipped.
3. **Never put secrets in argv or chat when avoidable.** When the user drops
`client_secret_*.json` into chat, save it to a file (mode 0600) and pass
the path: `gbrain google connect --client-json <path>`. Env
(`GOOGLE_CLIENT_ID`/`GOOGLE_CLIENT_SECRET`) also works. Raw
`--client-id/--client-secret` flags are the last resort.
4. **Every command speaks JSON.** Add `--json` and read
`{ ok, status, next_action: { command, user_message }, error }`. When
`next_action.user_message` is present, that IS the message to show the
user; when `next_action.command` is present, that is your next call.
Errors carry `{ code, problem, cause, fix, doc_url }` — show the user
`problem` + `fix`, nothing else.
5. **Re-running is always safe.** `gbrain google connect` and
`gbrain google setup` are idempotent state machines — the documented fix
for most errors is "run it again."
## Setup (the one command)
```bash
gbrain google setup --json
```
Handles: credential intake (prints the GCP checklist when nothing is on
file) → consent (loopback locally; auto paste-back over SSH/headless —
non-TTY flows complete via a second call:
`gbrain google connect --code "<pasted-redirect-url>"`) → source
registration → a budgeted first sync (newest mail first; the deep backfill
resumes on later syncs automatically) → the first `gbrain waiting` digest.
Multiple accounts: repeat with `--account work@example.com`.
Already holding Google access another way (a Google CLI with its own auth,
`gcloud`, a credential gateway that mints tokens)? Skip OAuth and point the
source at it — no credential enters gbrain:
```bash
gbrain sources add gmail-work --kind google --account you@example.com \
--access command --token-command "<command that prints an access token>"
```
(`--access env --token-env <VAR>` reads an externally-refreshed token from
the environment instead.) Then `gbrain sync --source gmail-work` and
`gbrain waiting` work identically.
Verify health afterwards: `gbrain google status --json` (per-account
refresh probe) — and `gbrain doctor` carries a `google_oauth` check that
warns once a Testing-mode account goes 5+ days without a successful
refresh. An actively-syncing account gets no pre-warning before the 7-day
Testing-mode expiry — publishing to Production is the real fix.
## Daily operation
```bash
gbrain waiting --json # the killer output: ranked people waiting
gbrain loops done <id> # user handled it
gbrain loops drop <id> # user is not going to do it
gbrain loops mute sender <email> # never track this sender again (closes its open reply-owed loops)
gbrain loops unmute sender <email> # undo; the loops it closed are re-checked on the next sync
gbrain loops drop sender <email> --dry-run # preview closing one sender's reply-owed loops
```
- `waiting` may end with `withheld_noise`: open reply-owed loops from senders
whose mail is automated (bank or shipping alerts). Show the user each
`preview_command`, run it (`--dry-run` changes nothing), and drop only after
the user agrees: a drop cannot be undone. Offer `loops mute sender` when the
user wants a stop they can reverse.
- `waiting` REFUSES on stale data (no successful sync in 24h) and names the
exact fix (`gbrain sync --source <id>`). Run the sync, then retry. Only
use `--stale-ok` when the user explicitly accepts stale results.
- `completeness: "partial"` means some mail in the last 14 days is held after
repeated import failures (listed in `held`). Present the answer as partial:
name each held item (sender, and subject when shown) and its retry command
(`gbrain sources retry-held <id>`). Never say "you are clean" on a partial
answer.
- When presenting loops, show: the counterparty, what's owed (summary), the
evidence quote, the deep link (opens the exact Gmail thread in the right
account), and the due date when present. The trusted-local result already
carries a paste-ready `text` digest — reuse it.
- For "context to respond": each group carries the counterparty's entity
card (summary, recent history, other open threads). Need more, call
`context_pack` with the counterparty slug.
- After the user says they replied/handled something, close the loop
(`loops done`) — thread loops also self-close on the next sync when the
reply is visible in Gmail.
## Continuous ingestion
Google sources sync like any source: autopilot and `gbrain sync --all` pick
them up automatically. No cron of its own. A bare un-targeted `gbrain sync`
does NOT reach them — use `--source <id>` or `--all`.
## Troubleshooting
Every failure has a typed code with the fix attached —
`docs/guides/google-connect.md#troubleshooting` is the canonical table. The
three the user will actually hit:
- **"Google hasn't verified this app"** during consent → expected; it's the
user's own app: Advanced → Continue. Warn them BEFORE they click the URL.
- **`access_denied_test_user`** → they forgot to add themselves as a test
user (the error carries the deep link).
- **`invalid_grant_testing_expiry`** (everything silently stopped ~day 7) →
their consent screen is still in Testing; publish to Production, then
`gbrain google connect --reauth <email>`.
## Cost honesty
Commitment extraction sends recent email text (≤30 days, ≤50 threads/sweep)
to the configured chat provider. Tell the user once during setup; the off
switch is `gbrain config set loops.extraction_enabled false`. The
unanswered-thread detector is free and unaffected.
## Output Format
When relaying `gbrain waiting`, present per counterparty, most urgent first, then the `## No counterparty` section (loops that name no person) last:
```
## <Counterparty> (<N> open)
- [<loop_type>] <what's owed> (<age>) — due <date if any>
> "<evidence quote>"
<Gmail deep link>
```
The trusted-local `--json` result already carries this as a paste-ready
`text` field — prefer relaying it over re-rendering. For setup commands,
relay `[SHOW USER]` blocks verbatim and `error.problem` + `error.fix` on
failures; never dump raw JSON envelopes at the user.
## When it fails
Follow the [agent operator protocol](../conventions/agent-operator-protocol.md) for any gbrain error `code`, exit code, `[AGENT]` block or notice block. Specific to this skill:
- Setup prints `[SHOW USER]` blocks: relay them verbatim, one message per block. `gbrain mcp expose` and `gbrain google` still exit 2 when they need the user's confirmation (documented legacy), so read the block, not just the exit code.
- A Google credential error (`invalid_grant_revoked`, `consent_timeout`, `wrong_account_consented`, …) carries `{ code, problem, cause, fix }`: show the user the problem and fix; most fixes are "run it again" by the user.
- `gbrain waiting` refuses on stale data or reports partial coverage from held items: run the sync it names, or `gbrain sources status <id>` then, after the user agrees, `gbrain sources retry-held <id>`.
## Anti-Patterns
- **Paraphrasing a `[SHOW USER]` block.** The checklists carry load-bearing
detail ("Desktop app, NOT Web application", the test-user step). Relay
verbatim, one message per block.
- **Asking the user for client_id/client_secret as chat text.** Take the
downloaded JSON as a 0600 file (`--client-json <path>`) or env vars;
secrets in argv/chat are the last resort, never the default.
- **Answering "who is waiting on me" from `query`/`search`.** The open-loop
record is `open_loops` / `gbrain waiting` — search results have no
loop-state semantics and will happily surface answered threads.
- **Dropping `completeness: "partial"`.** A partial answer with no loops is
not an empty inbox; say which items are held and how to re-attempt them.
- **Bypassing the staleness refusal with `--stale-ok` silently.** Run the
named `gbrain sync --source <id>` first; only pass `--stale-ok` when the
user explicitly accepts possibly-outdated loops.
- **Marking loops done for the user.** Close (`gbrain loops done <id>`) only
after the user says it's handled; thread loops self-close on the next sync
when the reply is visible in Gmail.
More agent context in garrytan/gbrain
78 other files this repository gives its agents, the first 60 shown.
AGENTS.md
CLAUDE.md
llms.txt
Skill
- academic-verifyskills/academic-verify/SKILL.md
- archive-crawlerskills/archive-crawler/SKILL.md
- article-enrichmentskills/article-enrichment/SKILL.md
- ask-userskills/ask-user/SKILL.md
- blog-ingestskills/blog-ingest/SKILL.md
- book-mirrorskills/book-mirror/SKILL.md
- brain-ingest-gateskills/brain-ingest-gate/SKILL.md
- brain-link-disciplineskills/brain-link-discipline/SKILL.md
- brain-opsskills/brain-ops/SKILL.md
- brain-pdfskills/brain-pdf/SKILL.md
- brain-taxonomistskills/brain-taxonomist/SKILL.md
- briefingskills/briefing/SKILL.md
- bulk-ingestionskills/bulk-ingestion/SKILL.md
- captureskills/capture/SKILL.md
- chat-connectorsskills/chat-connectors/SKILL.md
- citation-fixerskills/citation-fixer/SKILL.md
- citation-graph-ingestskills/citation-graph-ingest/SKILL.md
- cold-startskills/cold-start/SKILL.md
- company-brainifyskills/company-brainify/SKILL.md
- concept-synthesisskills/concept-synthesis/SKILL.md
- context-auditskills/context-audit/SKILL.md
- conversation-archiveskills/conversation-archive/SKILL.md
- correction-pipelineskills/correction-pipeline/SKILL.md
- cron-schedulerskills/cron-scheduler/SKILL.md
- cross-modal-reviewskills/cross-modal-review/SKILL.md
- daily-task-managerskills/daily-task-manager/SKILL.md
- daily-task-prepskills/daily-task-prep/SKILL.md
- data-loss-gateskills/data-loss-gate/SKILL.md
- data-researchskills/data-research/SKILL.md
- db-repairskills/db-repair/SKILL.md
- draft-in-voiceskills/draft-in-voice/SKILL.md
- eiirpskills/eiirp/SKILL.md
- enrichskills/enrich/SKILL.md
- fact-checkskills/fact-check/SKILL.md
- frontmatter-guardskills/frontmatter-guard/SKILL.md
- functional-area-resolverskills/functional-area-resolver/SKILL.md
- gbrain-advisorskills/gbrain-advisor/SKILL.md
- gbrain-upgradeskills/gbrain-upgrade/SKILL.md
- idea-ingestskills/idea-ingest/SKILL.md
- idea-lineageskills/idea-lineage/SKILL.md
- ingestskills/ingest/SKILL.md
- maintainskills/maintain/SKILL.md
- mcp-accessskills/mcp-access/SKILL.md
- measure-before-you-fixskills/measure-before-you-fix/SKILL.md
- media-ingestskills/media-ingest/SKILL.md
- meeting-ingestionskills/meeting-ingestion/SKILL.md
- migrateskills/migrate/SKILL.md
- minion-orchestratorskills/minion-orchestrator/SKILL.md
- perplexity-researchskills/perplexity-research/SKILL.md
- postgres-adoptskills/postgres-adopt/SKILL.md
- publishskills/publish/SKILL.md
- queryskills/query/SKILL.md
- remote-mcpskills/remote-mcp/SKILL.md
- repo-architectureskills/repo-architecture/SKILL.md
- reportsskills/reports/SKILL.md
- research-compendiumskills/research-compendium/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool registry_write, action report. How to connect one.

