Skip to content

Files

Markdown

The owner’s files, read live from every Drive or OneDrive account they connected. A file’s id carries the account it’s in, so pass ids exactly as a tool gave them. A Drive link the owner pastes works as an id too.

Reading covers files, folders, Google Docs and Sheets, PDFs and pictures. Writing covers Google Drive: copy a template, make folders, move and rename, write Google Docs and Sheets, change cells and text, and save workspace files and email attachments into Drive. Each write is listed on Home with Undo.

Writing needs the owner’s Drive connection to allow it. Until it does, a write returns error reauth, and a card asks the owner to connect again.

Office files (.xlsx, .docx, .pptx) are edited in the workspace: workspace.open copies them in, code changes them, and files.save with over puts a new version back.

Where search is on, search and read here cover only what search’s copy doesn’t hold yet.

What find_tools sends with these tools, word for word:

The owner’s files, such as Google Drive, searched live across every account they connected. Read a folder to work through it. A Drive link the owner pastes opens directly. Spreadsheets read tab by tab, pictures as images; a scanned PDF has no text, so search for its words instead. Google Drive: Drive matches words in names and file text, by relevance, not meaning: try other words when a search misses. OneDrive: OneDrive searches the files the owner can open in OneDrive and SharePoint with Microsoft Search: words, “exact phrases”, filetype:xlsx, author:“Name”. Older Office files such as .doc and .ppt are read from a PDF copy.

Tool What it does Owner’s yes
files.search Files whose name or text match, across the owner’s accounts, and which accounts failed. nextPage, passed as page, gives more. No
files.read A file’s text by id or Drive link, 30,000 characters at a time (nextOffset gives the rest), or a folder’s items (nextPage gives more). A picture comes back as an image. No
files.copy A copy of a file, such as a template, under a new name, in a folder (an id from search or folder) when given No
files.folder A new folder, inside another when parentId is given No
files.move Move files or folders into a folder, up to 50 at once Checked
files.rename Rename a file or folder Checked
files.create_doc A new Google Doc written from Markdown: headings, lists, tables, bold and links No
files.append_text Add text as a new paragraph at the end of a Google Doc Checked
files.create_sheet A new Google Sheet from rows, the first row its headings No
files.save Put a workspace file in Drive: a new file, or with over, a new version of the Drive file it was opened from Depends
files.save_attachment Save an email’s attachment into Drive: attachment is its id from search (gmail:…:a:…). For mail not in search, email is the thread’s id from mail search and attachment the id mail read listed No
files.sheet_rows A sheet’s cells, such as “Projects!A1:H50” No
files.append_rows Add rows after a sheet’s table, such as range “Leads!A:F” Checked
files.update_cells Write over cells, such as a date in “Projects!F12”; their old values are kept for Undo Checked
files.replace_text Replace every match of some text in a Google Doc Checked

files.search · Files whose name or text match, across the owner’s accounts, and which accounts failed. nextPage, passed as page, gives more.

Owner’s yes: No. Nothing of the owner’s changes.

Input Type Required What it is Limits
query text yes 1–500 characters
source text no Only accounts whose name contains this, e.g. an email address up to 120 characters
modifiedAfter text no up to 40 characters
limit whole number no 1–20, default 10
page text no up to 4,000 characters

Returns:

{
nextPage?: string;
hits: (Hit & {
source: string;
})[];
searched: string[];
failed: Failure[];
}

files.read · A file’s text by id or Drive link, 30,000 characters at a time (nextOffset gives the rest), or a folder’s items (nextPage gives more). A picture comes back as an image.

Owner’s yes: No. Nothing of the owner’s changes.

Input Type Required Limits
id text yes 3–500 characters
offset whole number no 0 or more
page text no up to 4,000 characters

Returns:

Content & {
id: string;
source: string;
nextOffset?: number;
}

files.copy · A copy of a file, such as a template, under a new name, in a folder (an id from search or folder) when given.

Owner’s yes: No. It makes something new.
Your work: listed on Home, with Undo.

Input Type Required Limits
id text yes 3–500 characters
name text yes 1–200 characters
folderId text no 3–500 characters

Returns:

{
id: string;
name: string;
url: string;
}

files.folder · A new folder, inside another when parentId is given.

Owner’s yes: No. It makes something new.
Your work: listed on Home, with Undo.

Input Type Required Limits
name text yes 1–200 characters
parentId text no 3–500 characters

Returns:

{
id: string;
name: string;
url: string;
}

files.move · Move files or folders into a folder, up to 50 at once.

Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.

Input Type Required Limits
ids list of text yes 1–50 items, each 3–500 characters
folderId text yes 3–500 characters

Returns:

{
moved: {
id: string;
name: string;
from: string[];
}[];
}

files.rename · Rename a file or folder.

Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.

Input Type Required Limits
id text yes 3–500 characters
name text yes 1–200 characters

Returns:

{
before: string;
id: string;
}

files.create_doc · A new Google Doc written from Markdown: headings, lists, tables, bold and links.

Owner’s yes: No. It makes something new.
Your work: listed on Home, with Undo.

Input Type Required Limits
name text yes 1–200 characters
markdown text yes 1–200,000 characters
folderId text no 3–500 characters

Returns:

{
id: string;
name: string;
url: string;
}

files.append_text · Add text as a new paragraph at the end of a Google Doc.

Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.

Input Type Required Limits
id text yes 3–500 characters
text text yes 1–50,000 characters

Returns:

{
start: number;
end: number;
id: string;
}

files.create_sheet · A new Google Sheet from rows, the first row its headings.

Owner’s yes: No. It makes something new.
Your work: listed on Home, with Undo.

Input Type Required Limits
name text yes 1–200 characters
rows list of list of text or number yes 1–200 items
folderId text no 3–500 characters

Returns:

{
id: string;
name: string;
url: string;
}

files.save · Put a workspace file in Drive: a new file, or with over, a new version of the Drive file it was opened from.

Owner’s yes: Depends on the input: checked when it changes what’s there, not when it makes something new.
Your work: listed on Home, with Undo.

Input Type Required What it is Limits
workspace text yes Its path, such as shared/report.xlsx 1–500 characters
folderId text no Where a new file goes 3–500 characters
name text no 1–200 characters
asGoogle true or false no Makes an .xlsx, .docx or .pptx a Google file
over text no The Drive file it was opened from: open’s from. Never a Google file 3–500 characters

Returns:

{
id: string;
name: string;
url: string;
}

files.save_attachment · Save an email’s attachment into Drive: attachment is its id from search (gmail:…:a:…). For mail not in search, email is the thread’s id from mail search and attachment the id mail read listed.

Owner’s yes: No. It makes something new.
Your work: listed on Home, with Undo.

Input Type Required Limits
email text no 3–500 characters
attachment text yes 3–300 characters
folderId text no 3–500 characters
name text no 1–200 characters

Returns:

{
id: string;
name: string;
url: string;
}

files.sheet_rows · A sheet’s cells, such as “Projects!A1:H50”.

Owner’s yes: No. Nothing of the owner’s changes.

Input Type Required Limits
id text yes 3–500 characters
range text yes up to 200 characters

Returns:

{
values: Values;
}

files.append_rows · Add rows after a sheet’s table, such as range “Leads!A:F”.

Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.

Input Type Required Limits
id text yes 3–500 characters
range text yes up to 200 characters
values list of list of text or number yes 1–200 items

Returns:

{
id: string;
updatedRange: string;
}

files.update_cells · Write over cells, such as a date in “Projects!F12”; their old values are kept for Undo.

Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.

Input Type Required Limits
id text yes 3–500 characters
range text yes up to 200 characters
values list of list of text or number yes 1–200 items

Returns:

{
id: string;
range: string;
before: string[][];
}

files.replace_text · Replace every match of some text in a Google Doc.

Owner’s yes: Checked. It changes what’s there.
Your work: listed on Home, with Undo.

Input Type Required Limits
id text yes 3–500 characters
find text yes 1–2,000 characters
replace text yes up to 5,000 characters

Returns:

{
id: string;
find: string;
replace: string;
changed: number;
}

Named types in the results above.

type Hit = {
id: string;
title: string;
type: string;
who?: string;
people?: string[];
date?: string;
snippet?: string;
url: string;
}
type Failure = {
source: string;
kind: "not_connected" | "reauth" | "forbidden" | "not_found" | "rate_limited" | "unavailable" | "too_large" | "unsupported" | "bad_input" | "vendor" | "changed" | "unknown_outcome";
message: string;
integration: string;
connection: string;
}
type Content = {
title: string;
url: string;
text: string;
attachments?: Attachment[];
items?: Hit[];
nextPage?: string;
image?: {
mimeType: string;
data: string;
};
note?: string;
}
type Values = {
length: number;
toString: () => string;
toLocaleString: {
(): string;
(locales: string | string[], options?: (NumberFormatOptions & DateTimeFormatOptions)): string;
};
pop: () => string[];
push: (...items: string[][]) => number;
concat: {
(...items: ConcatArray<string[]>[]): string[][];
(...items: (string[] | ConcatArray<string[]>)[]): string[][];
};
join: (separator?: string) => string;
reverse: () => string[][];
shift: () => string[];
slice: (start?: number, end?: number) => string[][];
sort: (compareFn?: ((a: string[], b: string[]) => number)) => Values;
splice: {
(start: number, deleteCount?: number): string[][];
(start: number, deleteCount: number, ...items: string[][]): string[][];
};
unshift: (...items: string[][]) => number;
indexOf: (searchElement: string[], fromIndex?: number) => number;
lastIndexOf: (searchElement: string[], fromIndex?: number) => number;
every: {
<S extends string[]>(predicate: (value: string[], index: number, array: string[][]) => value is S, thisArg?: any): this is S[];
(predicate: (value: string[], index: number, array: string[][]) => unknown, thisArg?: any): boolean;
};
some: (predicate: (value: string[], index: number, array: string[][]) => unknown, thisArg?: any) => boolean;
forEach: (callbackfn: (value: string[], index: number, array: string[][]) => void, thisArg?: any) => void;
map: <U>(callbackfn: (value: string[], index: number, array: string[][]) => U, thisArg?: any) => U[];
filter: {
<S extends string[]>(predicate: (value: string[], index: number, array: string[][]) => value is S, thisArg?: any): S[];
(predicate: (value: string[], index: number, array: string[][]) => unknown, thisArg?: any): string[][];
};
reduce: {
(callbackfn: (previousValue: string[], currentValue: string[], currentIndex: number, array: string[][]) => string[]): string[];
(callbackfn: (previousValue: string[], currentValue: string[], currentIndex: number, array: string[][]) => string[], initialValue: string[]): string[];
<U>(callbackfn: (previousValue: U, currentValue: string[], currentIndex: number, array: string[][]) => U, initialValue: U): U;
};
reduceRight: {
(callbackfn: (previousValue: string[], currentValue: string[], currentIndex: number, array: string[][]) => string[]): string[];
(callbackfn: (previousValue: string[], currentValue: string[], currentIndex: number, array: string[][]) => string[], initialValue: string[]): string[];
<U>(callbackfn: (previousValue: U, currentValue: string[], currentIndex: number, array: string[][]) => U, initialValue: U): U;
};
find: {
<S extends string[]>(predicate: (value: string[], index: number, obj: string[][]) => value is S, thisArg?: any): S;
(predicate: (value: string[], index: number, obj: string[][]) => unknown, thisArg?: any): string[];
};
findIndex: (predicate: (value: string[], index: number, obj: string[][]) => unknown, thisArg?: any) => number;
fill: (value: string[], start?: number, end?: number) => Values;
copyWithin: (target: number, start: number, end?: number) => Values;
entries: () => ArrayIterator<[number, string[]]>;
keys: () => ArrayIterator<number>;
values: () => ArrayIterator<string[]>;
includes: (searchElement: string[], fromIndex?: number) => boolean;
flatMap: <U, This = undefined>(callback: (this: This, value: string[], index: number, array: string[][]) => U | readonly U[], thisArg?: This) => U[];
flat: <A, D extends number = 1>(this: A, depth?: D) => FlatArray<A, D>[];
at: (index: number) => string[];
__@iterator@457: () => ArrayIterator<string[]>;
__@unscopables@459: {
[x: number]: boolean;
length?: boolean;
toString?: boolean;
toLocaleString?: boolean;
pop?: boolean;
push?: boolean;
concat?: boolean;
join?: boolean;
reverse?: boolean;
shift?: boolean;
slice?: boolean;
sort?: boolean;
splice?: boolean;
unshift?: boolean;
indexOf?: boolean;
lastIndexOf?: boolean;
every?: boolean;
some?: boolean;
forEach?: boolean;
map?: boolean;
filter?: boolean;
reduce?: boolean;
reduceRight?: boolean;
find?: boolean;
findIndex?: boolean;
fill?: boolean;
copyWithin?: boolean;
entries?: boolean;
keys?: boolean;
values?: boolean;
includes?: boolean;
flatMap?: boolean;
flat?: boolean;
at?: boolean;
[Symbol.iterator]?: boolean;
readonly [Symbol.unscopables]?: boolean;
};
}
type Attachment = {
id: string;
name: string;
size: number;
}