0.0 / 30
What changed in the harness
Selection accuracy 96→93, token cost up 1%, 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.3 / 30
03Economics
11.1 / 20
04Discoverability
18.8 / 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.
31 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 |
|---|---|---|
photopea_create_document |
no_return_description |
Create a new blank document and make it the active document. This is typically the first step in a workflow. The document opens with a Background layer. Use open_file instead to edit an existing image. Returns the new document's metadata (name, width, height, resolution, mode). |
photopea_open_file |
no_return_description |
Open an existing image file in Photopea as a new document. Supports PSD, PNG, JPG, WebP, SVG, and other common formats. The opened file becomes the active document. Use create_document instead to start with a blank canvas. Returns metadata about the opened document (name, width, height, layer count). |
photopea_resize_document |
no_return_description |
Resize the active document canvas to new pixel dimensions, resampling all layer content to fit. This is a destructive operation — all layers are scaled proportionally. Use undo to revert if needed. Returns the document's updated width and height. |
photopea_close_document |
no_return_description |
Close the active document. Set save to true to save changes before closing. Unsaved changes are discarded if save is false. The next open document becomes active, if any. Returns a confirmation that the document was closed. |
photopea_add_layer |
no_return_description |
Add a new empty layer to the active document. The new layer becomes the active layer. Use this before operations that draw onto a layer, such as fill_selection or add_gradient. Returns the new layer's name and index. |
photopea_add_fill_layer |
no_return_description |
Add a non-destructive solid color fill layer that covers the entire canvas. Unlike fill_selection, this creates a separate adjustment-style layer that can be toggled, recolored, or deleted without affecting other layers. Use set_layer_properties to change its opacity or blend mode. Returns the new fill layer's name and index. |
photopea_delete_layer |
no_return_description |
Permanently remove a layer from the active document by name or index. The next layer in the stack becomes active after deletion. Use get_layers to see available layers before deleting. Returns a confirmation that the layer was deleted. |
photopea_select_layer |
no_return_description |
Set a layer as the active layer by name or index. Many tools (apply_filter, apply_adjustment, fill_selection) operate on the active layer — use this to target a specific layer first. Use get_layers to find layer names and indices. Returns the name and index of the newly active layer. |
photopea_set_layer_properties |
no_return_description |
Update one or more properties on a layer. Only specified properties are changed; others remain at their current values. Use get_layers to inspect current property values before modifying. Returns the layer's updated properties. |
photopea_move_layer |
no_return_description |
Translate a layer by a relative x/y offset in pixels from its current position. Positive x moves right, positive y moves down. Use get_layers to check current layer bounds, or transform_layer for scaling and rotation. Returns the layer's new position. |
photopea_duplicate_layer |
no_return_description |
Create a copy of a layer in the active document. The duplicate becomes the active layer and is placed above the original. Use newName to distinguish the copy from the original. Returns the name and index of the duplicated layer. |
photopea_reorder_layer |
no_return_description |
Move a layer to a new position in the layer stack. Use 'top' or 'bottom' to move to the ends of the stack, or 'above'/'below' to shift one position relative to the current index. Use get_layers to see the current layer order. Returns the layer's new index in the stack. |
photopea_group_layers |
no_return_description |
Group multiple layers into a layer group (folder). Layers are specified by name — use get_layers to find layer names. Grouped layers can be ungrouped later with ungroup_layers. Returns the new group's name and the list of layers it contains. |
photopea_ungroup_layers |
no_return_description |
Dissolve a layer group, moving all child layers to the document root. The group folder is removed but its contents are preserved. Use get_layers to find group names. Returns the names of the layers that were moved to the root. |
photopea_add_text |
no_return_description |
Add a new text layer to the active document at the specified position. The text layer becomes the active layer. Use paragraphBounds to create a text box with word wrapping, or omit for point text. Use load_font to add custom fonts, and list_fonts to find available font names. Returns the new text layer's name and index. |
photopea_edit_text |
no_return_description |
Modify the content or style of an existing text layer. Only specified properties are changed — omit parameters to keep their current values. Use get_layers to find text layer names if needed. Returns the updated text layer's properties. |
photopea_add_shape |
no_return_description |
Add a vector shape layer (rectangle or ellipse) to the active document. The shape layer becomes the active layer. Shapes are non-destructive and can be resized with transform_layer without quality loss. Returns the new shape layer's name and index. |
photopea_place_image |
no_return_description |
Place an image into the active document from a URL or local file path. Creates a new layer with the placed image as the active layer. Use width/height to resize while preserving aspect ratio, or x/y to position the layer. Returns the new layer's name and index. |
photopea_apply_adjustment |
no_return_description |
Apply a destructive image adjustment to the active layer's pixel data. Use select_layer to target a specific layer first. Modifies pixels directly — use undo to revert if needed. Returns a confirmation that the adjustment was applied. |
photopea_apply_filter |
no_return_description |
Apply a destructive filter effect to the active layer's pixel data. Use select_layer to target a specific layer first. Modifies pixels directly — use undo to revert if needed. Returns a confirmation that the filter was applied. |
photopea_transform_layer |
no_return_description |
Scale, rotate, or flip a layer in-place. Modifies the layer's pixel data destructively. Use get_layers to check current layer bounds before transforming, and undo to revert if needed. Returns the layer's updated bounds. |
photopea_add_gradient |
no_return_description |
Apply a linear gradient fill to a layer, replacing its current pixel content. The target layer must already exist — use add_layer to create one first. Colors are distributed evenly across the gradient. Returns a confirmation that the gradient was applied. |
photopea_make_selection |
no_return_description |
Create a pixel selection region in the active document. After creating a selection, use fill_selection to fill it with color, or clear_selection to deselect. Use type 'all' to select the entire canvas, or 'rect'/'ellipse' with bounds for a specific region. Returns the bounds of the created selection. |
photopea_modify_selection |
no_return_description |
Modify the current active selection. Requires an existing selection created by make_selection. For expand, contract, and feather, the amount parameter specifies pixels. Invert swaps selected and unselected areas. Returns the bounds of the modified selection. |
photopea_fill_selection |
no_return_description |
Fill the current selection with a solid color on the active layer. Requires an active selection — use make_selection to create one first. Modifies pixel data on the active layer directly. Use clear_selection afterward to deselect. Returns a confirmation that the fill was applied. |
photopea_clear_selection |
no_return_description |
Deselect the current selection in the active document, removing the marching ants. Does not modify any pixel data. Use after fill_selection or other selection-based operations are complete. Returns a confirmation that the selection was cleared. |
photopea_export_image |
no_return_description |
Export the active document to a file and save it to the local filesystem. The entire document is flattened and exported in the chosen format. Use create_document or open_file to set up the document before exporting. Returns a confirmation of the export, including the saved output path. |
photopea_load_font |
no_return_description |
Load a custom font from a URL (TTF, OTF, or WOFF2) into Photopea. The font becomes available for add_text and edit_text. Use list_fonts to find the PostScript name after loading. Returns the loaded font's PostScript name. |
photopea_run_script |
no_return_description |
Execute arbitrary Photopea/ExtendScript JavaScript in the Photopea environment. Use this for advanced operations not covered by other tools. Has full access to the Photopea DOM (app, activeDocument, layers). Use with caution — scripts can modify or delete any document data. Returns the value the script passes to app.echoToOE(). |
photopea_undo |
no_return_description |
Undo one or more recent actions in the active document. Each step reverses one operation from the history. Use after destructive operations (apply_filter, apply_adjustment, fill_selection) to revert changes. Returns the number of steps actually undone. |
photopea_redo |
no_return_description |
Redo one or more previously undone actions in the active document. Only available after using undo — the redo history is cleared when new actions are performed. Returns the number of steps actually redone. |
Selection evidence
Confusable tool pairs.
8 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
photopea_move_layer |
photopea_reorder_layer |
high | A task like 'move this layer to the top' or 'move the layer above the others' is ambiguous between move_layer (pixel x/y translation) and reorder_layer (z-order stacking position) — both are literally 'moving' a layer but operate on entirely different axes. |
photopea_add_fill_layer |
photopea_fill_selection |
high | A request like 'fill the background with blue' or 'fill the layer with red' could map to either the non-destructive whole-canvas add_fill_layer or the destructive fill_selection on the active layer/selection — the phrase 'fill layer with color' matches both tool descriptions closely. |
photopea_add_layer |
photopea_add_fill_layer |
medium | 'Add a new layer filled with color X' plausibly triggers either add_layer (empty layer, then needs a separate fill step) or add_fill_layer (a color-filled layer directly), since both create a new layer as the immediate next active layer. |
photopea_add_fill_layer |
photopea_add_gradient |
medium | A task like 'add a gradient fill layer' could be misrouted to add_fill_layer (which only supports solid color despite the 'fill layer' naming) instead of add_gradient, since both are described in terms of filling a layer with color(s). |
photopea_add_text |
photopea_edit_text |
medium | An instruction like 'set the text to Hello World' is ambiguous about whether a new text layer should be created (add_text) or an existing one modified (edit_text), especially if the document already has a text layer the user forgot to mention. |
photopea_load_font |
photopea_list_fonts |
medium | The near-identical names ('load' vs 'list') plus overlapping font-related descriptions make it plausible an agent calls list_fonts (search) when the user meant load_font (import from URL), or vice versa, e.g. for 'get the Arial font available'. |
photopea_make_selection |
photopea_modify_selection |
medium | A task like 'select everything except the center rectangle' could be attempted via make_selection with an unsupported inverse shape, or via modify_selection's invert action after a base selection — the boundary between creating vs. adjusting a selection is not always obvious to a task description. |
photopea_apply_adjustment |
photopea_apply_filter |
low | Both are generic 'apply X to active layer pixels' destructive operations with a similar description template; a vague instruction like 'enhance the image' could theoretically route to either, though the concrete adjustment/filter type lists (brightness/hue vs blur/sharpen) are usually distinguishing enough. |
Compare the field