Skip to main content

Google Drive Activities

Six activities read and write files in Google Drive: gdrive.download, gdrive.upload, gdrive.list, gdrive.get_metadata, gdrive.create_folder and gdrive.delete. Together they cover picking up a file someone dropped in a shared folder, and publishing a generated report back to one.

Setup

All six authenticate as a service account, whose key JSON lives in the secret store. Define the auth block once in context and reference it everywhere:

context:
gdrive_auth:
credentials_secret_key: "GDRIVE_SERVICE_ACCOUNT" # the whole key JSON, in the secret store
# impersonate_user: "ops@example.com" # optional: act as a user via domain-wide delegation
# scopes: ["https://www.googleapis.com/auth/drive.readonly"] # optional: narrow the access

DriveAuthInfo

FieldTypeRequiredDefaultDescription
credentials_secret_keystryesSecret name holding the service-account key JSON
impersonate_userstrnonullAct as this user via domain-wide delegation
scopeslist[str]nofull Drive accessNarrow the granted scopes
A service account has its own empty Drive

It can only see files and folders explicitly shared with its email address — so share the target folder with the service account before the first run, or set impersonate_user and configure domain-wide delegation. This is the most common cause of "file not found".

Environment

VariableEffect
MOCO_GDRIVE_FILE_DIRRoot directory for the file content format (default /tmp/moco/gdrive)
MOCO_GDRIVE_MAX_FILE_SIZE_MBPer-transfer ceiling (default 256)

Content moves in one of two formats

Every download and upload picks a format:

FormatWhere the bytes liveUse it when
base64 (default)Inline in workflow context, as a base64 stringThe file is small and a later step needs its content
fileOn the worker's filesystem, under MOCO_GDRIVE_FILE_DIRThe file is large, or a later shell.run needs it on disk

base64 copies the payload into workflow history, so keep it to small files. file paths are always relative to MOCO_GDRIVE_FILE_DIR; paths that escape that directory are rejected.

Defaults

ActivityTimeoutMax attempts
gdrive.download300 s3
gdrive.upload300 s1
gdrive.list, gdrive.get_metadata60 s3
gdrive.create_folder60 s1
gdrive.delete60 s1
The three write activities are not retried

Drive allows several files to share a name in one folder, so a retried create leaves a duplicate behind. The idempotent paths are upload with an explicit file_id (which replaces that file's contents in place) and create_folder with skip_if_exists: true; with either of those set it is safe to raise max_attempts via the activity's retry_policy. delete is destructive, so a retry after an ambiguous failure could remove a file recreated in between.

DriveFile

Returned by get_metadata, list and create_folder.

FieldTypeDescription
file_idstrDrive file id
namestrFile name
mime_typestrMIME type
size_bytesint | nullSize; absent for Google-native documents
created_timestr | nullCreation timestamp
modified_timestr | nullLast modification timestamp
web_view_linkstr | nullLink to open the file in Drive
parentslist[str]Parent folder ids
trashedbool | nullWhether the file is in the trash

gdrive.list

Lists files, filtered by parent folder and/or name, or by a raw Drive query string. Use it to resolve a name to a file_id.

Returns one page; pass the returned next_page_token back as page_token for the next.

Input

FieldTypeRequiredDefaultDescription
authDriveAuthInfoyesService-account credentials
querystrnonullRaw Drive query string; overrides the filters below
parent_folder_idstrnonullOnly files in this folder
name_containsstrnonullOnly files whose name contains this
include_trashedboolnofalseInclude trashed files
page_sizeintno100Files per page
page_tokenstrnonullToken from a previous call
order_bystrnonullSort order, e.g. modifiedTime desc
drive_idstrnonullShared drive to search within

Output

FieldTypeDescription
fileslist[DriveFile]The page of results
file_countintNumber of files in this page
next_page_tokenstr | nullToken for the next page, or null when this is the last

Example

- activity:
type: gdrive.list
name: find-latest-report
input_data:
auth: "{{ gdrive_auth }}"
parent_folder_id: "{{ inbox_folder_id }}"
name_contains: "monthly-report"
order_by: "modifiedTime desc"
page_size: 10
output_name: found # -> files[{file_id, name, mime_type, size_bytes, ...}], file_count,
# next_page_token

gdrive.download

Downloads a file's content, either inline as base64 or onto the worker's disk.

Input

FieldTypeRequiredDefaultDescription
file_idstryesFile to download
authDriveAuthInfoyesService-account credentials
output_formatenumno"base64"base64 or file
file_pathstrnonullDestination path under MOCO_GDRIVE_FILE_DIR, for output_format: file
export_mime_typestrnoformat-specificOverride the export format for a Google-native document
acknowledge_abuseboolnofalseDownload a file Drive has flagged as abusive

Output

FieldTypeDescription
file_idstrThe file downloaded
namestrFile name
mime_typestrMIME type of the returned content
size_bytesintSize of the content
formatenumbase64 or file — which of the two data holds
datastrThe base64 content, or the absolute path it was written to
exportedboolWhether a Google-native document was exported to get these bytes

Example

- activity:
type: gdrive.download
name: fetch-report
input_data:
file_id: "{{ found.files[0].file_id }}"
auth: "{{ gdrive_auth }}"
output_format: base64 # or 'file' plus a file_path
output_name: report # -> file_id, name, mime_type, size_bytes, format, data, exported
- activity:
type: gdrive.download
name: download-to-disk
input_data:
file_id: "{{ uploaded_file_id }}"
auth: "{{ gdrive_auth }}"
output_format: file
file_path: "gdrive-demo/{{ file_name }}"
output_name: downloaded_file

format echoes which of the two data holds, so a downstream step can branch on it.

Google-native documents are exported

Docs, Sheets, Slides and Drawings have no stored bytes and cannot be downloaded directly; they are exported automatically to .docx, .xlsx, .pptx and .pdf respectively, and exported: true says so. Set export_mime_type: application/pdf to get a PDF of any of them instead.


gdrive.upload

Creates a file from base64 content or from a file on the worker's disk — or replaces an existing file's content when file_id is given.

Input

FieldTypeRequiredDefaultDescription
namestryesFile name in Drive
authDriveAuthInfoyesService-account credentials
source_formatenumno"base64"base64 (use data) or file (use file_path)
datastrnonullBase64 content, for source_format: base64
file_pathstrnonullPath under MOCO_GDRIVE_FILE_DIR, for source_format: file
parent_folder_idstrnoDrive rootFolder to create the file in
mime_typestrnoguessed from nameTarget MIME type. A Google-native type converts the upload
source_mime_typestrnoguessed from nameWhat the bytes actually are, needed for conversion
file_idstrnonullReplace this file's content instead of creating a new one
descriptionstrnonullFile description
propertiesdict[str, str]nonullCustom file properties

Output

FieldTypeDescription
file_idstrThe created or updated file
namestrFile name
mime_typestrMIME type in Drive
size_bytesint | nullSize
web_view_linkstr | nullLink to open the file
parentslist[str]Parent folder ids

Examples

- activity:
type: gdrive.upload
name: publish-summary
input_data:
name: "summary-{{ run_date }}.csv"
auth: "{{ gdrive_auth }}"
data: "{{ base64.b64encode(summary_csv.encode()).decode() }}"
parent_folder_id: "{{ output_folder_id }}"
mime_type: "text/csv" # optional; guessed from the file name when omitted
output_name: published # -> file_id, name, mime_type, size_bytes, web_view_link, parents
- activity:
type: gdrive.upload
name: publish-large-export
input_data:
name: "export.parquet"
auth: "{{ gdrive_auth }}"
source_format: file
file_path: "exports/export.parquet" # relative to MOCO_GDRIVE_FILE_DIR
parent_folder_id: "{{ output_folder_id }}"
output_name: published

Set mime_type to a Google-native type (e.g. application/vnd.google-apps.spreadsheet) to have Drive convert the upload into a native document as it lands. Conversion needs to know the format to convert from, which is taken from the file name — add source_mime_type when the name has no useful extension:

- activity:
type: gdrive.upload
input_data:
name: "Q3 numbers" # no extension, so the source format can't be guessed
auth: "{{ gdrive_auth }}"
data: "{{ base64.b64encode(csv_text.encode()).decode() }}"
mime_type: "application/vnd.google-apps.spreadsheet" # target: a real Google Sheet
source_mime_type: "text/csv" # what the bytes actually are

gdrive.get_metadata

Returns one file's metadata without downloading its content.

Input

FieldTypeRequiredDefaultDescription
file_idstryesFile to describe
authDriveAuthInfoyesService-account credentials

Output

A DriveFile.

Example

- activity:
type: gdrive.get_metadata
name: describe-report
input_data:
file_id: "{{ uploaded_file_id }}"
auth: "{{ gdrive_auth }}"
output_name: metadata # -> file_id, name, mime_type, size_bytes, parents, ...

gdrive.create_folder

Creates a folder. With skip_if_exists: true it reuses an existing folder of the same name under the same parent instead of creating a second one — which also makes the activity safe to retry.

Input

FieldTypeRequiredDefaultDescription
namestryesFolder name
authDriveAuthInfoyesService-account credentials
parent_folder_idstrnoDrive rootParent folder
skip_if_existsboolnofalseReuse a same-named folder under the same parent

Output

FieldTypeDescription
folderDriveFileThe folder, created or reused
createdbooltrue when it was created, false when an existing one was reused

Example

- activity:
type: gdrive.create_folder
input_data:
name: "{{ run_date }}"
auth: "{{ gdrive_auth }}"
parent_folder_id: "{{ archive_folder_id }}"
skip_if_exists: true # reuse a folder of this name instead of creating a second one
output_name: run_folder # -> folder{file_id, name, ...}, created

gdrive.delete

Moves a file or folder to the trash, or deletes it outright.

Input

FieldTypeRequiredDefaultDescription
file_idstryesFile or folder to delete
authDriveAuthInfoyesService-account credentials
permanentboolnofalseDelete outright instead of trashing

Output

FieldTypeDescription
file_idstrThe file deleted
permanentboolWhether it was deleted outright

Example

- activity:
type: gdrive.delete
input_data:
file_id: "{{ stale_file_id }}"
auth: "{{ gdrive_auth }}"
permanent: false # move to trash (default); true deletes outright
output_name: deleted # -> file_id, permanent
Deleting a folder deletes its contents

And permanent: true cannot be undone. Prefer the default trash behaviour unless you are certain.


A complete runnable example — create a folder, upload a report, list it, download it back and clean up — lives in moco-examples/gdrive-demo/.

To index Drive documents for retrieval, see llama_index.index_gdrive, which reuses the same auth block.