0.0 / 30
What changed in the harness
Selection accuracy 98→100, token cost up 13%, unconfirmed writes 0%→0%.
Category breakdown
Where the score comes from.
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
01Safety
02Legibility
19.7 / 30
03Economics
16.3 / 20
04Discoverability
13.1 / 20
Highest-impact fix
Estimated gain +30 pointsAdd explicit identity and permission preflight tools
Expose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
Defects and rewrites.
37 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.
| Tool | Defect types | Suggested rewrite |
|---|---|---|
drive_files_list |
no_return_description |
List files in Google Drive, optionally filtered by a search query in the 'q' parameter and sorted per orderBy; shared drive files are included automatically. Returns the matching files as file-metadata records, with fields selected by the fields parameter and the page limited by pageSize. |
drive_files_get |
name_restates_behavior params_unexplained no_return_description |
Retrieve metadata for a single file using its unique Google Drive file ID (obtainable from drive_files_list); shared drive files are supported automatically. Returns the file's metadata with only the fields requested in the fields parameter. |
drive_files_create |
no_return_description |
Create a new file in Google Drive with the given name, mimeType, and parent folders; optionally upload local content by supplying its path in uploadPath. Returns the new file's metadata with the fields requested in the fields parameter (e.g. id, webViewLink). |
drive_files_copy |
no_return_description |
Copy an existing source file (fileId), optionally renaming the copy, placing it in different parent folders, or converting it to another format via mimeType (e.g. markdown to Google Doc). Returns the copy's metadata with only the fields requested. |
drive_files_update |
no_return_description |
Update an existing file's metadata (name, mimeType) or replace its content by providing a local path in uploadPath. Returns the updated file's metadata with the fields requested in the fields parameter. |
drive_files_delete |
no_return_description |
Permanently delete the file identified by fileId from Google Drive; deletions are irreversible. Returns confirmation once the file has been deleted. |
drive_permissions_create |
no_return_description |
Share a file by granting a permission to a user, group, domain, or anyone, with the given role (e.g. reader, writer, owner); supply emailAddress when the grantee type is user or group. Returns the permission that was created. |
sheets_get |
params_unexplained no_return_description |
Fetch metadata for the spreadsheet identified by spreadsheetId; set includeGridData to true to also include raw cell values in the response. Returns the spreadsheet metadata, including grid data when requested. |
sheets_values_get |
params_unexplained no_return_description |
Read cell values from a range of the spreadsheet identified by spreadsheetId, using A1 notation such as 'Sheet1!A1:D10'; majorDimension and valueRenderOption control the shape and formatting of returned values. Returns the values found in the requested range. |
sheets_values_update |
params_unexplained no_return_description |
Write a 2D array of values (JSON string) into a range of the spreadsheet identified by spreadsheetId; valueInputOption determines whether input is parsed as RAW or USER_ENTERED. Returns a result describing the applied update. |
sheets_values_append |
params_unexplained no_return_description |
Append a 2D array of values (JSON string) after the last row of a range in the spreadsheet identified by spreadsheetId; valueInputOption determines RAW vs USER_ENTERED parsing. Returns a result describing the range into which values were appended. |
calendar_events_list |
name_restates_behavior no_return_description |
List events for the calendar identified by calendarId (use 'primary' for the main calendar), optionally filtered by time window, free-text search q, and limited by maxResults; set singleEvents to expand recurring events and orderBy to choose startTime or updated ordering. Returns the matching calendar events. |
calendar_events_get |
name_restates_behavior params_unexplained no_return_description |
Retrieve full details of a single event in the calendar identified by calendarId, looked up by its eventId. Returns the event with its title, start/end times, description, and location. |
calendar_events_insert |
params_unexplained no_return_description |
Create a new event in the calendar identified by calendarId with a required title (summary) and start/end times supplied as JSON strings (e.g. '{"dateTime":"2026-03-10T10:00:00-07:00"}'), plus optional description and location. Returns the created event with its assigned ID. |
calendar_events_update |
name_restates_behavior params_unexplained no_return_description |
Update an existing event (eventId) in the calendar identified by calendarId using patch semantics, so only supplied fields (summary, start, end, description) are changed while others remain. Returns the updated event. |
calendar_events_delete |
name_restates_behavior params_unexplained no_return_description |
Permanently delete the event identified by eventId from the calendar identified by calendarId. Returns confirmation that the event was removed. |
docs_get |
params_unexplained no_return_description |
Retrieve the content and metadata of the Google Doc identified by documentId. Returns the document's text and structural content (paragraphs, lists, inline objects) along with its metadata. |
docs_create |
no_return_description |
Create a new empty Google Doc with the given title. Returns the new document's metadata, including its document ID for use in subsequent calls. |
docs_batchUpdate |
params_unexplained no_return_description |
Apply one or more update requests (supplied as a JSON-array string, e.g. insert text or formatting) to the Google Doc identified by documentId, applied as a single batch. Returns the results of each applied request. |
gmail_messages_list |
no_return_description |
List Gmail messages for the account identified by userId (use 'me'), optionally filtered by a Gmail search query q and label IDs, and limited by maxResults. Returns metadata for the matching messages. |
gmail_messages_get |
name_restates_behavior no_return_description |
Retrieve a single Gmail message for the account identified by userId (use 'me'), looked up by its message id; the format parameter controls verbosity (full, metadata, minimal, raw). Returns the message's content, headers, or raw payload depending on the chosen format. |
gmail_threads_list |
no_return_description |
List Gmail conversation threads for the account identified by userId (use 'me'), optionally filtered by query q and limited by maxResults. Returns metadata for the matching threads. |
gmail_threads_get |
name_restates_behavior no_return_description |
Retrieve a Gmail conversation thread for the account identified by userId (use 'me'), looked up by its thread id, including all messages in the conversation; format controls response verbosity. Returns the full thread with its message history. |
gmail_threads_modify |
no_return_description |
Add and/or remove labels on a Gmail thread identified by id for the account userId, e.g. remove INBOX to archive, remove UNREAD to mark read, or add STARRED to star. Returns the thread's updated label state. |
tasks_tasklists_list |
no_return_description |
List the authenticated user's task lists. Returns a paginated set of task list objects; use maxResults to control page size (1-100) and pageToken to fetch the next page. |
tasks_tasklists_get |
no_return_description |
Get a task list by ID; pass "@default" as tasklist to fetch the user's default list. Returns the TaskList object with its title and ID. |
tasks_tasklists_insert |
no_return_description |
Create a new task list with the given title. Returns the created TaskList object, including its assigned ID. |
tasks_tasklists_update |
no_return_description |
Update a task list; only supplied fields change. Returns the updated TaskList object. |
tasks_tasklists_delete |
no_return_description |
Delete a task list by ID. If it contains assigned tasks, the originals in Docs/Chat Spaces are also removed. Returns an empty success response. |
tasks_tasks_list |
no_return_description |
List tasks in a task list. Hidden and assigned tasks are excluded by default; set showHidden/showAssigned to include them, and showCompleted/showDeleted to include those states. Filter by completion, due, and last-modified date ranges. Returns a paginated set of task objects. |
tasks_tasks_get |
name_restates_behavior params_unexplained no_return_description |
Get a single task within a task list by passing tasklist (the list containing the task, e.g. as returned by tasks_tasks_list) and task (the task's ID from that list). Returns the full Task object, including title, notes, status, due date, and ID. |
tasks_tasks_insert |
no_return_description |
Create a new task in a task list with optional notes, status, and due date. Pass parent to nest it as a subtask, or previous to position it immediately after a sibling task. Returns the created Task object, including its ID. |
tasks_tasks_update |
no_return_description |
Update an existing task; only supplied fields change. Common use: set status to "completed" to finish a task. Returns the updated Task object. |
tasks_tasks_move |
no_return_description |
Move a task within its current list or into another list. Set parent/previous to reposition it, and destinationTasklist to move to a different list. Returns the moved Task object. |
tasks_tasks_delete |
no_return_description |
Delete a task from a task list. If the task was assigned from Docs/Chat Spaces, the original there is also removed. Returns an empty success response. |
tasks_tasks_clear |
no_return_description |
Hide all completed tasks in a task list. Cleared tasks are not deleted but stop appearing in default list responses. Returns an empty success response. |
gmail_drafts_create |
no_return_description |
Create a Gmail draft that is NOT sent; the user opens Gmail to review and send. Pass threadId to attach it to an existing conversation (subject should match the thread), and both body and htmlBody to produce a multipart/alternative draft. Returns the created draft resource, including its ID. |
Selection evidence
Confusable tool pairs.
10 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
tasks_tasklists_update |
tasks_tasks_update |
medium | A user saying 'update my task list' can mean renaming the list container (tasklists_update) or editing tasks inside the list (tasks_update); both tools share the token 'task' and an update action. |
tasks_tasklists_get |
tasks_tasks_get |
medium | 'Get the task' versus 'get the task list' is ambiguous because users often call a task list simply 'tasks'; both require an ID-shaped argument and differ only by the container/item distinction. |
tasks_tasklists_insert |
tasks_tasks_insert |
low | 'Add a new task' usually means tasks_insert, but 'create a new task list' could be phrased as 'add a task' if the user is vague about containers. |
tasks_tasklists_delete |
tasks_tasks_delete |
low | 'Delete the task' vs 'delete a task list' is mostly distinguishable, but ambiguous phrasing like 'remove my shopping tasks' could target either the list or its items. |
tasks_tasklists_list |
tasks_tasks_list |
medium | 'Show me my tasks' maps to tasks_list, while 'list my task lists' maps to tasklists_list; users frequently use the word 'tasks' for both the container and the items, and both tools share list/task tokens. |
sheets_get |
sheets_values_get |
medium | A request to 'get the spreadsheet' or 'read the sheet' could mean retrieving metadata (sheets_get) or the actual cell values (sheets_values_get); both operate on the same spreadsheetId and share get/sheet tokens. |
gmail_messages_list |
gmail_threads_list |
medium | 'List emails matching X' could target messages or threads; both take the same userId/q/maxResults parameters and share gmail/list/query tokens, with users rarely distinguishing a thread from its messages. |
drive_files_export |
drive_files_download |
high | Both already reference each other in their descriptions (export says to use download for automatic export; download says it exports Docs/Sheets/Slides), so a task like 'export this Google Doc to PDF' is genuinely ambiguous between the two. |
gmail_messages_get |
gmail_threads_get |
medium | 'Get the email conversation' could select gmail_threads_get, while 'get the email' selects gmail_messages_get; they share get/gmail/id/message tokens and a thread contains multiple messages. |
sheets_values_update |
sheets_values_append |
low | 'Add these values to the sheet' could mean overwriting a range (update) or appending after the last row (append); both share range/sheet/spreadsheet/value tokens, though the append-description clarifies placement. |
Compare the field