Drive Files Skill
Search, organize, and share files in Google Drive. Use when asked to find, list, move, share, rename, or download files from Drive. CRITICAL — when the user asks for a specifically named file by name and your search returns no exact match, you MUST emit a scope_required JSON literal (see SKILL body); never offer fuzzy alternatives or clarifying questions instead.
Google Drive Files
Search and manage files in the user's Google Drive using bridge google. The bridge automatically resolves credentials from the claw owner's Google connection.
⛔ CRITICAL RULE — read before doing anything else
When the user asks for a specifically named Drive file and your first drive.files.list call returns no file matching that exact name, your ENTIRE reply MUST be exactly this template:
{"reason":"scope_required","missingScopes":["https://www.googleapis.com/auth/drive.readonly"]}
I can only see files WorkClaw created with you. Grant the broader read permission and I'll find your file.
That is the ONLY acceptable response in this scenario. No clarifying questions. No fuzzy guesses. No "let me try a broader search." No "could it be X?" The JSON literal on the first line is what the chat UI parses to render the inline "Grant Google permission" button.
Worked example
User says: "Find my Q1 Roadmap doc and summarize it. I created it directly in Drive."
You call: bridge google --skill drive-files drive files list --params '{"q":"name = '\''Q1 Roadmap'\''"}'
Bridge returns: {"files":[]} (or a list that does not contain a file named exactly "Q1 Roadmap").
Your reply, verbatim:
{"reason":"scope_required","missingScopes":["https://www.googleapis.com/auth/drive.readonly"]}
I can only see files WorkClaw created with you. Grant the broader read permission and I'll find your file.
Then stop. Wait for the user to click the inline button and grant. After they grant, retry the SAME query — drive.readonly makes the file visible, and you summarize it.
Why this rule exists (do not skip — it explains why your normal helpful instincts are wrong here)
Every Drive read endpoint (drive.files.list, get, export, download, about.get, changes.list) accepts the narrow drive.file scope as sufficient auth. The bridge will happily run the call and return ONLY the subset of files WorkClaw itself created. From the bridge's perspective the call succeeded — so it will NEVER emit a scope_required signal on its own. If you want the user to be able to grant the broader drive.readonly scope, you have to emit the JSON yourself. There is no other path.
This is the opposite of how scope escalation works for every other Google API in WorkClaw, which is why the rule has to be this loud.
Forbidden responses (each of these has caused a real failed demo)
| What the model wants to do | Why it's wrong |
|---|---|
| "I couldn't find 'Q1 Roadmap' — could it be 'Q1 Budget' instead?" | Fuzzy-matching is a substitute for escalation. The user named a specific file. |
"Let me try a broader search…" then reissue the same drive.files.list query | Narrating an action without taking one. The query is identical, the result is identical, no scope is escalated. |
| "Is it possible it's saved under a slightly different name?" | Clarifying questions in place of escalation. The user already gave you the name. |
| "Could it be a Google Doc rather than a Sheet?" | Same — clarifying question instead of escalation. |
Calling drive.about.get first to "check what's accessible" | Pre-flighting. Wastes a turn and doesn't trigger JIT either. |
| Pasting the JSON inside a code block with extra prose around it on the same line | The chat UI's regex still parses it, but the model often paraphrases the JSON in this mode. Keep it on its own line. |
If you find yourself about to do any of these, stop, delete the draft, and emit the template above instead.
File visibility model (background — the rule above is what matters)
WorkClaw uses three Drive scopes with different visibility:
| Scope | What it sees | When the agent uses it |
|---|---|---|
drive.file (non-sensitive) | Only files WorkClaw created itself, or files the user opened via Picker | Default for every write the agent does to an app-owned file |
drive.readonly (restricted) | Every file the user has in Drive — read-only | After the user grants it via the JSON-literal flow above |
drive (restricted) | Every file the user has in Drive — full access | Triggered automatically by the bridge when the agent calls drive.permissions.* or drive.files.update on a non-app file |
The drive JIT-via-bridge path works normally because the bridge DOES require drive minimum for write operations on non-app files. The drive.readonly path is the special case — that's why the critical rule above exists.
Scope error handling for OTHER signals from the bridge
This is separate from the critical rule above (which is about emitting a signal manually).
When any bridge google command actually returns a JSON object with a "reason" field (no_connection, scope_required, team_claw_unsupported, expired) instead of API data, paste the entire JSON line verbatim in your reply on its own line. Paraphrasing, summarising, or omitting any field means the inline Connect button does not render and the user is stuck with no way to grant the permission. After the JSON line add one short sentence telling the user what's missing. Never offer browser walkthroughs, settings-page navigation, "open it in your browser" links, or other manual workarounds — the inline button is the only supported path.
Common Actions
Search files by name
bridge google --skill drive-files drive files list --params '{"q":"name contains '\''Q3 report'\''","pageSize":20,"fields":"files(id,name,mimeType,modifiedTime,webViewLink)"}'
List recent files
bridge google --skill drive-files drive files list --params '{"orderBy":"modifiedTime desc","pageSize":20,"fields":"files(id,name,mimeType,modifiedTime,owners,webViewLink)"}'
Get file metadata
bridge google --skill drive-files drive files get --params '{"fileId":"FILE_ID","fields":"id,name,mimeType,size,modifiedTime,owners,parents,webViewLink"}'
Move a file to a folder
bridge google --skill drive-files drive files update --params '{"fileId":"FILE_ID","addParents":"FOLDER_ID","removeParents":"OLD_PARENT_ID"}'
Rename a file
bridge google --skill drive-files drive files update --params '{"fileId":"FILE_ID"}' --json '{"name":"New Name"}'
Share a file (add reader/writer)
bridge google --skill drive-files drive permissions create --params '{"fileId":"FILE_ID","sendNotificationEmail":false}' --json '{
"type": "user",
"role": "reader",
"emailAddress": "person@example.com"
}'
Roles: reader, commenter, writer, fileOrganizer, organizer, owner.
List folders
bridge google --skill drive-files drive files list --params '{"q":"mimeType='\''application/vnd.google-apps.folder'\''","fields":"files(id,name,parents)"}'
Create a folder
bridge google --skill drive-files drive files create --params '{}' --json '{
"name": "My Folder",
"mimeType": "application/vnd.google-apps.folder",
"parents": ["PARENT_FOLDER_ID"]
}'
Safety
- Confirm before deleting, moving large numbers of files, or changing sharing permissions
- When sharing, always show the recipient and role before creating the permission
- Use
webViewLink(notwebContentLink) when handing the user a link to open in the browser - Don't enumerate or download personal file content unless the user explicitly asked