01Safety
0.0 / 30
What changed in the harness
Selection accuracy 100→100, token cost down 49%, unconfirmed writes 0%→0%.
Category breakdown
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
0.0 / 30
18.8 / 30
7.8 / 20
12.0 / 20
Highest-impact fix
Estimated gain +30 pointsExpose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
24 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 |
|---|---|---|
API-get-user |
params_unexplained no_return_description |
Retrieves a Notion user by user_id (the user's UUID). Returns the user object, including id, name, avatar_url, type (person or bot), and email for person users. |
API-get-users |
no_return_description |
Lists all users in the Notion workspace, paginated with start_cursor and page_size (max 100). Returns a paginated list of user objects plus a next_cursor and has_more flag. |
API-get-self |
no_return_description |
Returns the bot user object for the integration's access token, including its id, name, and owner/workspace information. |
API-post-search |
no_return_description |
Searches all pages and data sources visible to the integration whose title matches the query text, optionally filtered to only pages or only data sources and sorted by last_edited_time; paginated via start_cursor and page_size. Returns a paginated list of matching page and data source objects. |
API-get-block-children |
no_return_description |
Retrieves the children of the block or page identified by block_id, paginated via start_cursor and page_size (max 100). Returns a paginated list of child block objects. |
API-patch-block-children |
no_return_description |
Appends the given children (an array of block objects) to the container block or page identified by block_id, inserting after the block given by after if specified. Returns the parent block along with the newly created child block objects. |
API-retrieve-a-block |
no_return_description |
Retrieves a single block by its block_id. Returns the block object, including its type-specific content. |
API-update-a-block |
no_return_description |
Updates a block's content or archived state, identified by block_id: type carries the type-specific fields to change (e.g. rich_text, checked), and archived set to true trashes the block or false restores it. Returns the updated block object. |
API-delete-a-block |
no_return_description |
Archives (moves to trash) the block identified by block_id. Returns the updated block object with archived set to true. |
API-retrieve-a-page |
no_return_description |
Retrieves a page by its page_id, optionally limited to specific property values via filter_properties. Returns the page object with its properties and metadata. |
API-patch-page |
params_unexplained no_return_description |
Updates a page's properties, icon, cover, or trash state, identified by page_id: properties are the property values to change, icon/cover set the page icon and cover image, archived and in_trash toggle whether the page is trashed or restored. Returns the updated page object. |
API-post-page |
params_unexplained no_return_description |
Creates a new page under the given parent — a page, database, or the workspace — with the specified properties and optional child blocks, icon, and cover. Returns the newly created page object. |
API-retrieve-a-page-property |
name_restates_behavior no_return_description |
Fetches the value of one property (given by property_id) on the page identified by page_id, paginating with page_size and start_cursor when the property holds a list of items (e.g. relations, people). Returns a property item object or a paginated list of property items. |
API-retrieve-a-comment |
no_return_description |
Retrieves the comments on the block or page identified by block_id, paginated via start_cursor and page_size (max 100). Returns a paginated list of comment objects. |
API-create-a-comment |
params_unexplained no_return_description |
Adds a new comment to the page given by parent, with the comment text supplied as rich_text (an array of text objects making up the comment body). Returns the newly created comment object. |
API-query-data-source |
name_restates_behavior params_unexplained no_return_description |
Queries the rows (pages) of the data source identified by data_source_id, with optional filter conditions, sorts (an array of {property, direction} objects), and inclusion of archived/trashed rows via the archived and in_trash flags; paginated via start_cursor and page_size (max 100). Returns a paginated list of matching page objects. |
API-retrieve-a-data-source |
name_restates_behavior no_return_description |
Fetches the schema and metadata of the data source identified by data_source_id. Returns the data source object, including its title, properties schema, and parent. |
API-update-a-data-source |
name_restates_behavior params_unexplained no_return_description |
Updates the data source identified by data_source_id: title and description are arrays of rich text objects, and properties updates the column schema. Returns the updated data source object. |
API-create-a-data-source |
name_restates_behavior params_unexplained no_return_description |
Creates a new data source as a child of the page given by parent, with the given properties (column schema) and title (an array of rich text objects). Returns the newly created data source object. |
API-list-data-source-templates |
name_restates_behavior params_unexplained no_return_description |
Lists the page templates defined for the data source identified by data_source_id, used when creating new entries, paginated via start_cursor and page_size (max 100). Returns a paginated list of template objects. |
API-retrieve-a-database |
no_return_description |
Retrieves the legacy database object identified by database_id. Returns the database's title, parent, and properties schema. |
API-move-page |
params_unexplained no_return_description |
Moves the page identified by page_id to a new parent, given by parent (a page, database, or the workspace). Returns the updated page object. |
API-retrieve-page-markdown |
no_return_description |
Reads the content of the page or block identified by page_id and converts it to Markdown; include_transcript controls whether full meeting note transcripts are inlined versus shown as a placeholder link. Returns the page content as a Markdown string. |
API-update-page-markdown |
no_return_description |
Edits the content of the page or block identified by page_id as Markdown, using the strategy given by type: replace_content overwrites the whole page, update_content applies find-and-replace edits via content_updates, and the deprecated insert_content/replace_content_range insert or replace a specific range. Returns the updated page object. |
Selection evidence
11 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
API-retrieve-a-page |
API-retrieve-page-markdown |
high | Both retrieve a Notion page by page_id; a task like 'show me the content of this page' could plausibly be routed to either the raw page-object endpoint or the markdown-content endpoint, since neither name signals which representation (properties vs. body content) is returned. |
API-update-a-block |
API-delete-a-block |
high | API-update-a-block explicitly supports 'archived: true to archive (delete) a block', duplicating the purpose of API-delete-a-block. A task like 'delete this block' could be satisfied by either tool since the update tool's own description uses the word 'delete'. |
API-query-data-source |
API-retrieve-a-data-source |
high | 'Get the database' is ambiguous between retrieving the data source's schema/metadata (retrieve-a-data-source) and querying its rows (query-data-source) — Notion's own API has this exact naming confusion, and a task phrased generically as 'get me the data source' could select either. |
API-patch-page |
API-update-page-markdown |
high | Both are described as updating a page; a generic task like 'update this page' is ambiguous between changing page properties/icon/cover/trash-state (patch-page) and rewriting the page body content (update-page-markdown), since neither name clarifies which aspect of the page is mutated. |
API-patch-page |
API-move-page |
medium | A task like 'move this page to the trash' maps to patch-page's in_trash flag, while 'move this page under a different parent' maps to move-page — the shared verb 'move' in natural language could cause the agent to pick the wrong tool despite their differing parameters. |
API-get-user |
API-get-users |
medium | A vague task like 'get user info' without a clear single ID could be routed to either the single-user lookup (needs user_id) or the list-all-users endpoint, especially if the agent hasn't yet resolved a specific user_id. |
API-get-user |
API-get-self |
medium | A task like 'who is this integration/bot user' or 'get my user info' is ambiguous between retrieving a specific user by ID (get-user) and retrieving the token's own bot user (get-self), especially if the agent conflates 'the current user' with 'a named user'. |
API-retrieve-a-block |
API-retrieve-a-page |
medium | In Notion's data model a page is itself a block and shares the same ID format, so a task like 'retrieve this item by its ID' without explicit type context could plausibly be routed to either the block or page retrieval endpoint. |
API-patch-block-children |
API-update-a-block |
medium | Both modify block content; a task like 'edit this block to add a new bullet point' is ambiguous between appending new child blocks (patch-block-children) and updating an existing block's own content (update-a-block). |
API-update-a-block |
API-update-page-markdown |
medium | Both are 'update content' style tools where the target ID could be a block or a page (the markdown tool explicitly accepts either); a task like 'update the text on this page/block' could plausibly select either depending on how the agent interprets the target. |
API-retrieve-a-page |
API-retrieve-a-page-property |
medium | A task like 'get the status of this page' could be satisfied by retrieving the whole page object and reading a property from it, or by directly retrieving that specific property item — the boundary between 'retrieve the page' and 'retrieve a page property' is not obvious from the names alone. |
Compare the field