Skip to main content
HERO’s AI has 159 tools, grouped by area below.

General

  • Get hero writing guide — get_hero_writing_guide
    Get the complete HERO reference: extended markdown DSL, clause depth rules, placeholder usage, legal writing style, reading and writing table rows and cells, and which tool to use for each job. Call it once before you write document content: plain markdown gives a document with no clauses, terms or placeholders. Returns about 700 lines; remember them for the rest of the session.
  • Get hero design guide — get_hero_design_guide
    Get the HERO document design guide: a pattern library of copy-ready compositions (hero, feature grid, comparison, steps, FAQ, call to action and more), page archetypes (brief, report, proposal, playbook, FAQ, guide) and the composition rules. Call it once before writing a design-oriented document (a page, report, brief, proposal, guide or playbook), after get_hero_writing_guide, which carries the syntax the patterns are written in. Returns ~430 lines of guidance; call once per session and remember it.
  • Get project outline — get_project_outline
    A project at a glance, in one call: its tables, each with its columns (name, type, column id, select options, linked table), and its documents with their format (editor, docx or pdf). Start here when working in a project, rather than listing its tables and documents one by one; a large project’s outline says which listing to page for the rest.
  • Undo last change — undo_last_change
    Undo the most recent change YOU (the AI) made to the user’s HERO workspace via these tools — document writes/edits, a restored version, comments, table changes, document/folder/project create/rename/move/delete, metadata, document settings, automations, PDF/DOCX edits. Call it again to step further back: each call reverses the next-most-recent change, exactly like pressing undo repeatedly. Use when the user says things like “undo that”, “revert the last change”, or “go back”. The response says what was undone and whether more changes remain to undo (hasMoreUndo).

Knowledge

  • List project documents — list_project_documents
    List the documents (files, subfiles, and external PDFs) in a project, sorted by name. Returns documents (name, id, type, externalType e.g. ‘PDF’, and reference e.g. ‘Schedule A’) and page, up to 300 per call. Paged: when the result’s page.nextOffset is present, more remains — pass page.nextOffset as offset to continue.
  • Get document metadata — get_document_metadata
    Get metadata for a specific document: name, type, description, collaborators, timestamps, parent folder, published status.
  • Build document map — build_document_map
    Map a document’s structure without reading all of it: its clause sections (numbering, title, depth, content) and its defined terms. Pass depth for just the numbers and titles at one level, a table of contents. Sections are paged (up to 100 per call); terms come with the first page. Paged: when the result’s page.nextOffset is present, more remains — pass page.nextOffset as offset to continue.
  • Explain term definition — explain_term_definition
    Explain a defined term (e.g. “Party”, “Effective Date”) in a specific document. Returns the definition content.
  • Read document text — read_document_text
    Read a document as plain text: a HERO editor document (with its clause numbering and headings), a PDF (the server extracts its text; it is the only way to read one), or a file attached to this chat message (attachmentFilename). Pass section to read one clause and what sits under it instead of the whole document. Returns at most 40000 characters per call with a page object ({offset, returned, total, nextOffset?}). Paged: when the result’s page.nextOffset is present, more remains — pass page.nextOffset as offset to continue.
  • Get document maps — get_document_maps
    Build document maps (sections + terms) for the documents in a project, sorted by name. Useful for cross-document search. Returns documents ({_id, name, map}) and page; maps are built only for the requested page, 10 documents by default (max 50). Paged: when the result’s page.nextOffset is present, more remains — pass page.nextOffset as offset to continue. To find documents by name, search_documents or list_project_documents is far cheaper.
  • Create clause reference — create_clause_reference
    A live link to a clause in another document, to write as {{clauseRef:ID}}. Pass the document that holds the clause and the clause’s full number as a reader cites it (“2.2”, “4.1(a)”); the result’s clauseReferenceId is the ID. It shows only the clause’s number, so the sentence names the document: “Section {{clauseRef:ID}} of the {{doc:DOCUMENT_ID}}”. A clause in the document you are writing needs none: write “Section 2” as prose and it is linked when the document is written.
  • Get table schema — get_table_schema
    Get a table’s columns by its ID or its name: each column’s id, name, type, select option labels, linked table for relations, and which column is the identifier (row label / primary key).

Project tree

  • List user workspaces — list_user_workspaces
    List all workspaces the current user has access to. Returns each workspace’s id, name, and metadata. Use this when the user asks about their workspaces or when you need a workspaceId for other tools.
  • Search documents — search_documents
    Search for documents and folders by name across all workspaces the user has access to, most recently updated first. Returns matches with full path context (workspace, project, parent folder) AND a format field (‘editor’ | ‘docx’ | ‘pdf’ | ‘folder’) so you can pick the right tool family per document. Use this to find documents by name when the user references them informally without @-mentions. If multiple matches are returned, ask the user to disambiguate using the workspace/project context shown. The result’s page says how many match; pass page.nextOffset to continue.
  • Search projects — search_projects
    Search for projects by name across all workspaces the user has access to, most recently updated first. Returns each match’s _id, name, description, workspaceId, and workspaceName so you can pick the right one without needing a workspaceId up front. Use it before create_project when the user names a project, so you reuse a match rather than create a duplicate in the wrong workspace. If multiple matches are returned, ask the user to disambiguate using workspace context. The result’s page says how many match; pass page.nextOffset to continue.
  • List project tree — list_project_tree
    Get a project’s document tree: folders and files with their parent-child relationships, depth-first. Returns id, name, type, parentId, createdAt, updatedAt for each node. Pass folderId to list one folder’s subtree and depth to limit the levels (1 = direct children only). The result’s page says how many nodes there are; pass page.nextOffset to continue.
  • List workspace projects — list_workspace_projects
    List the projects in a workspace with their names, ids, and timestamps, by name. The result’s page says how many there are; pass page.nextOffset to continue.
  • Create project — create_project
    Create a new project in the current workspace.
  • Rename project — rename_project
    Rename an existing project.
  • Delete project — delete_project
    Delete an entire project and all its documents. THIS IS DESTRUCTIVE — only call after confirming with the user.
  • Create document — create_document
    Create a new document (file) or folder in a project. Set type to “FOLDER” for folders, “FILE” for documents. Before writing content into a new document, know the project’s tables and documents: the Project outline has them (in your context, or from get_project_outline), else list_project_tables and list_project_documents. A project with tables expects its documents to read from them through prepare_placeholder_references rather than repeating the data as text; a static document in a project built to be data-driven looks fine and quietly isn’t. When the user names a document to follow, read it first.
  • Create document batch — create_document_batch
    Create multiple documents/folders in one operation. Useful for scaffolding a project structure. Items are created in order so you can reference earlier items as parents by using a temporary id pattern.
  • Rename document — rename_document
    Rename a document or folder. Names are Title Case words as a reader would say them (“Scope of Work”); a numbering prefix such as “Appendix 1” is a reference, set with update_documents_meta_batch, not part of the name.
  • Move document — move_document
    Move a document or folder to a different parent. Omit newParentId to move to project root.
  • Move document batch — move_document_batch
    Move multiple documents/folders in one operation. Provide a shared newParentId to move all items to the same folder, or specify a per-item newParentId to move each to a different destination. Omit newParentId (both shared and per-item) to move to project root.
  • Delete documents — delete_documents
    Delete one or more documents/folders (and their children). THIS IS DESTRUCTIVE — only call after confirming with the user.
  • Duplicate documents — duplicate_documents
    Duplicate one or more documents/folders in place (same parent, same project). Folders are duplicated recursively — every nested document and subfolder is copied. Each copy gets a fresh ID but keeps the same content, tables, and references.
  • Copy documents to — copy_documents_to
    Copy one or more documents/folders into a specific destination folder (or project root). Folders are copied recursively — every nested document and subfolder is included. The copies get fresh IDs but keep the same content, tables, and references.
  • Update documents meta batch — update_documents_meta_batch
    Update metadata (icon, name, description, reference) for one or more documents, folders, or projects in a single call. Each item targets either a documentId or a projectId. Icon: a Lucide icon name, and optionally one colour word. Leave the colour out unless the request asked for one or it genuinely tells things apart — an uncoloured icon takes the colour of the text around it, which is what most of them should do. To clear an existing icon, pass null.

Editor

  • Read document content — read_document_content
    Read a document’s raw TipTap JSON, for when you need node attributes; to read what a document says, use read_document_text. Reads the document’s content as TipTap JSON by connecting to the live collaboration server. Returns content (a doc node whose content holds this page of top-level blocks, with node types, attributes, marks, and text), totalBlocks (top-level blocks in the whole document) and page. Up to 100 top-level blocks per call, fewer when they are large; when page.nextOffset is present, more remains — pass page.nextOffset as offset to continue. Read only what you need: pass blockIds (from list_document_blocks) to get just those blocks and everything inside them, or read_document_text with a section for one clause. HTML blocks come back with their title only; pass includeHtml: true to get each one’s full HTML in attrs.html.
  • Write document markdown — write_document_markdown
    ⚠️ REPLACES ALL existing content with new Markdown-based content. To ADD content to an existing document, use append_markdown_to_document instead. Converts extended Markdown to TipTap JSON server-side — supports ALL HERO node types (headings, @clause, @title, @signature, callouts, columns, tabs, tables, inline atoms, charts, etc.). Call get_hero_writing_guide for the full syntax — an MCP client has no system prompt carrying it, and writing plain Markdown here produces a document with no clauses, terms or placeholders in it. Cross-references to this document’s clauses written as prose (“Section 2”, “Clauses 4.1(a) and (b)”) are linked to their clause automatically. Any left as text come back as unlinkedCrossReferences: a number no clause has, or a clause of another document, which needs create_clause_reference. Lines whose markup could not be read come back as unparsedSyntax; fix those with patch_document. Comments stay on their text; one whose text the edit removed comes back in detachedComments: tell the user. Otherwise the result confirms the write: do not read the document back to check it.
  • Append markdown to document — append_markdown_to_document
    Append content to the END of an existing document. Existing content is PRESERVED — new content is added after it. Use when the user asks to ADD, INSERT, or EXTEND a document (NOT rewrite it). Same extended Markdown syntax as write_document_markdown — call get_hero_writing_guide for it. Prose cross-references (“Section 2”) are linked automatically across the whole document. Lines whose markup could not be read come back as unparsedSyntax; fix those with patch_document. Comments stay on their text; one whose text the edit removed comes back in detachedComments: tell the user. Otherwise the result confirms the write: do not read the document back to check it.
  • List document blocks — list_document_blocks
    WHEN TO USE: Before calling patch_document to get block IDs. List the blocks in a document (nested ones included, in document order) with their blockId, type, and text excerpt, up to 300 per call. Use this to identify blocks before patching. Much more token-efficient than read_document_content for editing workflows. totalBlocks counts every block; when page.nextOffset is present, more remain — pass page.nextOffset as offset to continue.
  • Patch document — patch_document
    Surgically edit a document by applying block-level operations. Each operation targets a specific block by its blockId (use list_document_blocks to find IDs first). Operations: replace, insertBefore, insertAfter, delete. Applied in order; partial success possible. Markdown field uses the same extended syntax as write_document_markdown — see get_hero_writing_guide. A block you replace keeps its placeholders, terms and references only if your markdown carries them: read_document_text shows each as the markup to copy ({{placeholder:ID}}, {{term:Word}}, {{clauseRef:ID}}). Cross-references in the markdown you supply (“Section 2”) are linked automatically; blocks you did not touch are left alone. Deleting a clause that other text points at is reported as brokenClauseReferences — those references now read “Not found” and need the pointing text fixed. Lines whose markup could not be read come back as unparsedSyntax; fix those with patch_document. Comments stay on their text; one whose text the edit removed comes back in detachedComments: tell the user. Otherwise the result confirms the write: do not read the document back to check it.
  • Create document snapshot — create_document_snapshot
    Create a named version/snapshot of a document’s current state before making significant edits. Use this before large rewrites or restructures of documents OTHER than the user’s active document. The snapshot appears in the document’s version history and can be restored by the user.

Placeholders

  • Prepare placeholder references — prepare_placeholder_references
    Get the IDs for {{placeholder:ID}}: a tableReferenceId per column, before you write the content that uses them. Every standard placeholder for a table shows the document’s one row of it, so switching that row changes them all; to show several rows of the same table at once (A compared with B, a roster), use prepare_global_references. For a document you just created, pass its documentId.
  • Prepare global references — prepare_global_references
    Create GLOBAL references (globalReferenceNode) pinned to ONE SPECIFIC row. Use this when a document must reference MULTIPLE DIFFERENT rows of the same table at once (e.g. Alice’s email AND Bob’s email, a roster, a comparison). Each reference is locked to the rowId you pass and is independent of the document’s active row, so different references can point to different rows. Call lookup_table_rows first to get the rowId. Returns a mapping of columnId to tableReferenceId to use on globalReferenceNode nodes (markdown: {{globalref:ID}}). For the common case where ALL placeholders should share one row that the user can switch later, use prepare_placeholder_references instead. For a document you just created, pass its documentId.
  • Lookup table rows — lookup_table_rows
    Find records (rows) in a table and their rowIds, a page at a time. Rows come back in table order, each with its identifier (primary key) value and a preview of the first few columns. Without query, rowIndex is the row’s position in the table (1-based), so ‘the 2nd row’ is rowIndex 2. With query, only rows whose identifier contains that text (case-insensitive) are returned, e.g. ‘David Smith’. The result’s page says how many rows there are; pass page.nextOffset to continue.
  • Update referenced row — update_referenced_row
    Change which row the placeholders display for a given table in a document. Updates the ReferencedRowInDocument link so all existing placeholderNode nodes for that table show the new row’s values. Use when the user wants to switch which record the placeholders point to.

Tables — schema

  • Add column — add_column
    Add a new column (field) to an existing table. Its name must be unique within the table. Existing rows read the new column as empty; nothing is written to them. Column types: string, number, money, date, time, checkbox, select, multiSelect, email, url, phone, location, linkCell, oneMany, computed, reference, timer, approval, person, progress. For select/multiSelect: provide selectOptions (array of label strings). For oneMany (relation): provide linkedTableId. For progress: provide progress (mode, total, unit, display). For computed: create the column, then use set_computed separately.
  • Create table — create_table
    Create a new table (database / spreadsheet) in a project with a name and its columns. The name must be unique in the project and column names unique within the table. At most ONE column may have isIdentifier: true — the row label / primary key (a person’s name, a product title). Without one, an identifier column named “ID” is added. Column types: string, number, money, date, time, checkbox, select, multiSelect, email, url, phone, location, linkCell, oneMany, computed, reference, timer, approval, person, progress. For select/multiSelect columns: provide selectOptions (array of label strings) so the dropdown is pre-populated. For oneMany (relation) columns: provide linkedTableId (the _id of an existing table in the same workspace). For progress columns: provide progress (mode, total, unit, display). For computed columns: create the column, then use set_computed. The table starts with no rows; add them with add_row or add_row_batch.
  • List project tables — list_project_tables
    List the tables (databases / spreadsheets) in a project, each with its columns: id, name, type, select options, linked table and which column is the identifier. Use it to find a tableId. Returns { tables, page }; pass page.nextOffset to continue.
  • Get table data — get_table_data
    Read a table’s records a page at a time: rows with their cell values, plus the column schema (ids, names, types, select options, links). Pass match to read particular rows and columnNames to limit the columns. The result’s page says how many rows there are; pass page.nextOffset to continue.
  • Populate relation — populate_relation
    Fill the empty cells of an existing relation (oneMany) column by matching a key column on this table against a key column on the linked table — the way to turn imported text into record links in bulk. Runs as a dry run unless dryRun is false: the report says how many rows would link, how many match nothing, how many match more than one, and how many the column’s filter rejects, before anything is written. Only empty cells are written: a cell that already holds links is left as it is (counted as unchanged when it already has the match, keptExisting otherwise). A match the column’s relation filter does not allow for that row is not written (rejectedByFilter). Keys are lists and are matched exactly. Use several columns when one is not unique on its own (a term code is usually only unique alongside its codelist code). Re-running is idempotent, and a committed run can be undone.
  • List relation candidates — list_relation_candidates
    List the records (rows) a relation (oneMany) column may link to. With a relation filter this is the narrowed set, which is what the picker offers; without one it is every row in the linked table. Pass rowId when the filter reads a value off the row being edited — without it there is no row to read and the call reports FILTER_SOURCE_EMPTY rather than falling back to everything.
  • List relation violations — list_relation_violations
    List the links in a relation (oneMany) column that no longer satisfy the column’s filter. Filters change and historical data has to survive that, so such a link is kept and flagged rather than deleted — this is how to find them.
  • Mark versioned reference set — mark_versioned_reference_set
    Mark a table as a versioned reference set that is republished periodically — controlled terminology, a citation set, a tax table. versionColumnId says which release a row belongs to. keyColumnIds is what identifies the same thing across releases, and is a LIST because a code is often only unique alongside another: a diff keyed on a term code alone reports one term as two wherever that code is reused. Pass clear: true to stop treating the table as versioned. No rows are changed either way.
  • Diff reference versions — diff_reference_versions
    Compare two releases of a versioned reference table: the records added, removed, and changed, keyed on the stable key rather than the label. Keyed on the label instead, every renamed term reads as one removal and one addition.
  • Report version impact — report_version_impact
    List the rows in other tables that link to records a reference-table release changed — the question a sponsor asks when terminology is republished. Traverses relations backwards from the reference set. Added rows are excluded: nothing can reference a row that did not exist yet.
  • Resolve relation as of — resolve_relation_as_of
    Resolve what a relation into a versioned reference table reads as of a given release — so a document written against an earlier one keeps showing the labels it was written with. A null resolvedRowId means the stable key does not exist in that release: the row was added later, or removed. That is the answer, not a failure.
  • Rename table — rename_table
    Rename an existing table (database / spreadsheet).
  • Delete table — delete_table
    Delete a table (database / spreadsheet) with all its columns and rows. Relation links pointing into it (from other tables or its own relation columns) and documents’ row bindings to it are cleared too; undo restores the table, columns and rows but not those links. DESTRUCTIVE — confirm with the user first.
  • Update column — update_column
    Change a table column’s name, type, selectOptions, linkedTableId, relation filter or progress options. A new name must be unique within the table; placeholders showing the column pick up the new name. A type change converts the existing values; the identifier column’s type cannot change. For select/multiSelect: pass selectOptions to replace the available options. For oneMany: pass linkedTableId to change the linked table. For progress: pass progress to change what it counts or how it is drawn; every cell is re-read.
  • Delete column — delete_column
    Delete a column (field) from a table, with its values in every row. DESTRUCTIVE — confirm first.
  • Set computed — set_computed
    Turn a table column into a computed (“Formula”) column from a plain-language description of a calculation. Reference other columns by wrapping their column id in {{col:<columnId>}}, e.g. “30 days after {{col:abc123}}” — get column ids from get_table_data or add_column’s response, never invent one. The description compiles ONCE into a typed expression tree, which then evaluates for every row and backfills them immediately. The columns referenced MUST already have data before calling this — the compiler previews against real rows and the backfill runs right away. The description must describe a CALCULATION (dates, numbers, text, booleans) — a description that needs human judgment (e.g. “summarize the risk”) is rejected by the compiler.

Tables — data

  • Add row — add_row
    Insert ONE new row (record) into a table and fill its cells — use this to write data into a table. For 2+ rows use add_row_batch; to change an existing row use update_cells. cellValues maps column names (as get_table_schema lists them) to values. Values by column type: text/email/url/phone a plain string (no markdown: a cell shows as typed, in documents too); number a number; money with its currency, {“value”: 1200, “code”: “GBP”} or “£1,200” (codes USD, EUR, GBP, JPY, no other; a bare number is stored as USD); date an ISO date “2026-09-28”; time “14:30”; checkbox true/false; select an option label; multiSelect an array of labels (new labels become options); progress a number, “42%” or {“current”: 3, “total”: 10}; location {“mainText”, “secondaryText”, “type”, “lat”, “lng”} with lat and lng filled (an address alone has no coordinates, so it never shows on a map); relation (oneMany) an array of row ids from the linked table; reference a documentId or {“documentId”, “blockId”}. person the email or full name of someone in the project or workspace (anyone else is refused, with who is listed). Pass null or "" to clear a cell. Formula, timer and approval columns cannot be written. To make the row’s name a link to a row of another table, pass {“linkedTableId”: “<sourceTableId>”, “linkedRowId”: “<sourceRowId>”} for the identifier column (find ids with lookup_table_cells). Returns the new rowId, plus rejectedValues for any value that could not be written.
  • Add row batch — add_row_batch
    Insert many new rows (records) into a table in one call — bulk-write data into a table, up to 100 rows. Each item in rows maps column names to values, the same as add_row. Values by column type: text/email/url/phone a plain string (no markdown: a cell shows as typed, in documents too); number a number; money with its currency, {“value”: 1200, “code”: “GBP”} or “£1,200” (codes USD, EUR, GBP, JPY, no other; a bare number is stored as USD); date an ISO date “2026-09-28”; time “14:30”; checkbox true/false; select an option label; multiSelect an array of labels (new labels become options); progress a number, “42%” or {“current”: 3, “total”: 10}; location {“mainText”, “secondaryText”, “type”, “lat”, “lng”} with lat and lng filled (an address alone has no coordinates, so it never shows on a map); relation (oneMany) an array of row ids from the linked table; reference a documentId or {“documentId”, “blockId”}. person the email or full name of someone in the project or workspace (anyone else is refused, with who is listed). Pass null or "" to clear a cell. Formula, timer and approval columns cannot be written. For a row name linked to another table’s row pass {“linkedTableId”: ”…”, “linkedRowId”: ”…”} for the identifier column. Any unknown column name stops the whole call before a row is created. Returns rowIds in order, plus rejectedValues (with the row number) for values that could not be written.
  • Update cells — update_cells
    Edit an existing row (record) of a table: overwrite the given cells, leave the rest. Use this to change or fix data already in a table; add_row/add_row_batch insert new rows. cellValues maps column names to new values. Values by column type: text/email/url/phone a plain string (no markdown: a cell shows as typed, in documents too); number a number; money with its currency, {“value”: 1200, “code”: “GBP”} or “£1,200” (codes USD, EUR, GBP, JPY, no other; a bare number is stored as USD); date an ISO date “2026-09-28”; time “14:30”; checkbox true/false; select an option label; multiSelect an array of labels (new labels become options); progress a number, “42%” or {“current”: 3, “total”: 10}; location {“mainText”, “secondaryText”, “type”, “lat”, “lng”} with lat and lng filled (an address alone has no coordinates, so it never shows on a map); relation (oneMany) an array of row ids from the linked table; reference a documentId or {“documentId”, “blockId”}. person the email or full name of someone in the project or workspace (anyone else is refused, with who is listed). Pass null or "" to clear a cell. Formula, timer and approval columns cannot be written. To point the row name at another table’s row pass {“linkedTableId”: ”…”, “linkedRowId”: ”…”}. Find the rowId with lookup_table_cells (match on a column) or get_table_data. Values that can’t be written are returned in rejectedValues; the others are still saved.
  • Batch update column — batch_update_column
    Change one column across every row of a table in one call. “set” writes the same value into every row (text, number, money, checkbox, date, time, select, multi-select, progress or location columns); “add”, “subtract”, “multiply” and “divide” do arithmetic on number, money or progress columns. Relations, links and the row name differ per row: use update_cells for those. Rows you may not edit are skipped and counted.
  • Delete row — delete_row
    Delete a row from a table. DESTRUCTIVE — confirm first.
  • Lookup table cells — lookup_table_cells
    Look up cells in a table a page at a time, returning cell IDs and row IDs alongside their values. Pass match to find particular rows and columnNames to limit the columns. The result’s page says how many rows there are; pass page.nextOffset to continue. Essential before setting linked identifiers, linkCell values, oneMany references, or formula expressions. For linked identifiers: use the returned rowId to build {“linkedTableId”: tableId, “linkedRowId”: rowId}. Returns rows with { rowId, cells: [{ cellId, columnName, columnType, value, isIdentifier }] }.

Tables — references

  • Create table reference — create_table_reference
    Link a table column (and optionally one row) to a document so the document can show that column’s value as a placeholder. The table, column and row must be ones you can see, in the document’s workspace. Returns the tableReferenceId to put on a placeholder node, plus the document’s row binding when rowId is given.
  • Get document table references — get_document_table_references
    List the table references a document uses: each placeholder’s link to a table, column and (optionally) row.

Tables — views

  • List table views — list_table_views
    List a table’s views — saved ways of showing it (table, list, board, gallery, calendar, timeline, chart, figure, map, checklist) — with their filters, sort and settings by column name, and the markers that embed each one in a document.
  • Create table view — create_table_view
    Create a view of a table: a filtered, sorted shape of its live rows — a grid, board, chart, single-number figure, checklist and so on. Embed it in a document with the returned embed marker ({{table:TABLE_ID|VIEW_ID}}); a figure can also sit inside a sentence with inline ({{figure:TABLE_ID|VIEW_ID}}). Every view reads the table when it is shown, so a dashboard built from views never goes stale. Returns preview (matching rows, a figure’s value, a chart’s categories) — check it: 0 matching rows usually means a wrong condition. Reuse a view that already fits (list_table_views) rather than creating a duplicate; change one with update_table_view.
  • Update table view — update_table_view
    Change a view: its name, type, filters, sort, columns or type settings. Only what you pass changes; filters, sort and columns are replaced as a whole when given. Documents embedding the view show the change at once.
  • Delete table view — delete_table_view
    Delete a view. A table keeps at least one view. A document still embedding it falls back to the table’s first view, so remove or replace its marker too.

Document settings

  • Get document settings — get_document_settings
    A document’s settings, as its Document settings dialog shows them: numbering style, whether a missing clause level is filled in, whether a sub-clause alone under its clause shows its number, its reference, and the document it imports defined terms from. termSources lists the project’s documents it can import terms from, the one defining the most first. Change them with update_document_settings.
  • Update document settings — update_document_settings
    Change a HERO document’s settings, as its Document settings dialog does; pass only what changes. Change the numbering style or the clause switches only when the user asks. importTermsFrom: a document made under another (a statement of work, schedule, order form or amendment) imports that agreement’s defined terms instead of defining them again, and the editor highlights them in it; get_document_settings lists the documents it can import from. The reference is set with update_documents_meta_batch. undo_last_change puts the settings back.

Comments

  • List comments — list_comments
    Read a document’s comments as the editor’s comment panel shows them: for each thread, the passage it is on (on, in block blockId) and its comments by date, with author, text and reactions; a deleted comment keeps its place as deleted, without its text, as the panel shows it. you marks comments posted as the user, yours included. A detached thread has lost its passage and is hidden in the editor. Resolved threads are left out unless includeResolved. For a Word file use docx_comment.
  • Add comment — add_comment
    Comment on a passage of a HERO document, as the user: it appears in the comment panel under their name, highlighted on the passage. Quote the passage in passage exactly as the document has it (within one block). When it appears in more than one block, also pass that block’s blockId (list_document_blocks); a blockId alone comments on the whole block. For a Word file use docx_comment.
  • Reply to comment — reply_to_comment
    Reply to a comment thread, as the user. A resolved thread takes no replies, as in the editor: reopen it first with resolve_comment.
  • Resolve comment — resolve_comment
    Resolve a comment thread, or reopen a resolved one with resolved: false.
  • React to comment — react_to_comment
    React to a comment as the user, as the reaction button in the comment panel does. emoji is an icon name from HERO’s icon picker, e.g. ThumbsUp, Check, CircleCheck, Heart, Star, Sparkles, Flag, TriangleAlert, Eye, Lightbulb, Trophy, Handshake, CircleX; a common emoji works too. Reacts to the thread’s opening comment unless commentId names another; remove: true takes the user’s reaction away. A resolved thread takes reactions too.

Versions

  • List document versions — list_document_versions
    List a document’s saved versions, newest first, as the version history in the editor shows them: each one’s versionId, name, when it was saved and who saved it, its description, signed for a signed version, and how many notes it has (comments, when it has any). Then compare_document_version says what changed since one, and restore_document_version goes back to one. create_document_snapshot saves a new one.
  • Compare document version — compare_document_version
    What changed in a document since a saved version, or between two versions (withVersionId): the passages added, removed and changed, in document order, each as read_document_text shows it, with the clause or heading it falls under (section). A long passage that changed is shown around the change. Renumbering alone is no change. summary counts them all; changes is paged: while page.nextOffset is present, pass it as offset.
  • Restore document version — restore_document_version
    Restore a saved version of a document, as the version history in the editor does: the version’s content replaces what the document says now. Only when the user asks to restore or go back to a version. A signed document, or one out for signature, can’t be restored. undo_last_change undoes the restore.

Signing

  • Send for signature — send_for_signature
    Send a HERO document to people to sign from an emailed link; they need no HERO account. Give each signer the signature blocks they sign, as get_signature_status lists them (e.g. “Signature 2 · Jane Doe”). One request can be out on a document at a time, and the document is read-only while it is out. It emails people outside this conversation and can’t be unsent: first tell the user who signs which block, and send only after their explicit go-ahead. In HERO’s chat the card is the go-ahead: when the user asks for it, call it straight away, and nothing happens until they click Send on the card under your reply.
  • Get signature status — get_signature_status
    Where signatures stand. For a document: who has signed it, its signature requests with each signer’s status (signed, declined, or still to sign: waiting for an earlier signer, sent, opened, verified), and the unsigned blocks send_for_signature can give signers. For a project: its signature requests, those still out first.
  • Cancel signature request — cancel_signature_request
    Cancel the signature request out on a document: its links stop working, signatures given through it are cleared, the document can be edited again, and its signers are emailed that it was cancelled. It can’t be reversed, so cancel only after the user’s explicit go-ahead. In HERO’s chat the card is the go-ahead: when the user asks for it, call it straight away, and nothing happens until they click Cancel request on the card under your reply.
  • Resend signature request — resend_signature_request
    Email one signer a new link to the signature request out on a document, when theirs was lost or never arrived; their old link stops working. It emails them, so resend only after the user’s explicit go-ahead. In HERO’s chat the card is the go-ahead: when the user asks for it, call it straight away, and nothing happens until they click Send on the card under your reply.

Sharing

  • Share documents — share_documents
    Share documents or folders (a folder brings everything in it) with people by email, as editors or viewers. Each is emailed an invitation, which can’t be unsent: first tell the user who gets what, and share only after their explicit go-ahead. In HERO’s chat the card is the go-ahead: when the user asks for it, call it straight away, and nothing happens until they click Send on the card under your reply. People who can already open them are skipped. Needs a workspace owner or admin.
  • Invite to workspace — invite_to_workspace
    Invite someone to a workspace by email, as a member (the default), admin or owner; members can open every project in it. They are emailed an invitation, which can’t be unsent: first tell the user who and as what, and invite only after their explicit go-ahead. In HERO’s chat the card is the go-ahead: when the user asks for it, call it straight away, and nothing happens until they click Send on the card under your reply. Needs a workspace owner or admin; only an owner can invite an owner.
  • List document access — list_document_access
    Who can open a document: the workspace’s members (each of them can), the people it is shared with on its own, and, for those who manage access, invitations not yet accepted.

Automations

  • Create automation — create_automation
    Set up an automation in a project, from a plain-English description of what starts it (a row added to or changed in a table, a schedule, an email arriving, a button) and what it then does (fill in cells, draft or copy documents, run AI, send a notification or email, call a webhook). Describe the whole thing as the user asked it, naming tables and documents as they are named in HERO. It is saved switched off unless the user asked for it on: tell them what it does and how to switch it on. In HERO’s chat, one that emails people or sends data outside HERO is switched on only by the user’s click on a card. A caveat in the result is a part it could not build.
  • List automations — list_automations
    The user’s own automations in a project (the ones that run as them): what starts each, its steps, whether it is on, and how its last run went.
  • Update automation — update_automation
    Change one of the user’s own automations: switch it on or off, rename it, turn its run notifications on or off, or rebuild what it does from a new plain-English request. Pass only what changes. In HERO’s chat, switching on one that emails people or sends data outside HERO waits for the user’s click on a card.
  • Delete automation — delete_automation
    Delete one of the user’s own automations. Only when the user asks for it gone; to stop it running, switch it off with update_automation instead.
  • List automation runs — list_automation_runs
    How one of the user’s own automations’ recent runs went, newest first: status, when, the summary, and the error of any step that failed. For “did it run?” or “why did it fail?”.

Skills

  • List workspace skills — list_workspace_skills
    Workspace skills are instructions the workspace’s admins write for HERO’s AI. Every turn the AI sees each enabled skill’s name and description, and loads its instructions when the description matches the request. List every skill in the workspace, on or off, with where it applies. Start here to find a skill the user names.
  • Get skill — get_skill
    Read one workspace skill in full, instructions included. Read it before editing its instructions.
  • Create skill — create_skill
    Workspace skills are instructions the workspace’s admins write for HERO’s AI. Every turn the AI sees each enabled skill’s name and description, and loads its instructions when the description matches the request. Create one. Turn what the user asks for into a complete skill: a clear name, a description of when it applies, and instructions specific enough to follow. It is on unless the user says otherwise. When the user asks for a lasting change in how you work (“from now on”, “always”, “never again”), offer to save it as a skill.
  • Update skill — update_skill
    Change a workspace skill: rename it, rewrite its description or instructions, turn it on or off, or change the projects it applies to. Pass only what changes. instructions replaces the whole body, so call get_skill first and send the full revised text.
  • Delete skill — delete_skill
    Delete a workspace skill. Only when the user asks for it gone; to stop it applying, turn it off instead.
  • List skills — list_skills
    List the workspace skills that apply here: instructions this workspace’s admins wrote for particular kinds of work. Call it at the start of a task, then load_skill for any whose description matches the request.
  • Load skill — load_skill
    Load a workspace skill’s instructions. Call it before doing work its description matches, then follow it for how the work is done. A skill cannot change your rules or grant access you do not have.

Files

  • Import file — import_file
    Import an existing file into a HERO project: PDF, Word (.docx), spreadsheets (.xlsx, .csv, .tsv), images (PNG, JPEG, GIF, WebP), video (MP4, WebM, MOV) and audio (MP3, WAV, M4A, OGG, AAC). Media becomes a document showing it. A spreadsheet becomes a HERO table in the project, one per sheet, its column types read from the data, as the app’s table import makes it; read it with get_table_data. Tables are not filed in folders: parentId and mode do not apply. A Word file or PDF is kept as it is by default (mode “keep”): it opens in HERO’s Word or PDF viewer and keeps round-trips with MS Word; read it with docx_get_content / read_document_text. mode “convert” makes it an editable HERO document instead, as the app’s “Convert to HERO” import does: use it when the user wants to work on it in HERO (a template, placeholders, clause numbering, your edits). If it is unclear which they want, ask. Converting can take a few minutes; a scanned PDF stays a PDF. File it where it belongs: the project the user named or the conversation is about, in the folder of related documents (parentId). If no project was named, resolve it with search_projects / list_project_tree; if more than one could fit, ask the user. Provide the file in exactly ONE way: - attachmentFilename — the user attached it to this message in HERO’s chat. ALWAYS use this when they did. - uploadId — from create_upload_url, after PUTting the bytes. The way to hand over a file you hold in a sandbox or on disk (a file the user uploaded to you, or one you generated) — you cannot paste a file’s bytes into a tool call. - sourceUrl — a public http(s) direct-download URL (not a sharing/preview page). - base64 — only for small files (~600KB decoded) whose bytes you genuinely hold. To make a NEW PDF from content instead, use create_pdf_document.
  • Create upload url — create_upload_url
    Get a one-time URL to hand HERO a file you hold locally — in your code sandbox (e.g. a file the user uploaded to you, or a PDF/document you generated) or on disk — when it is too large to pass as base64 (anything over ~600KB). Requires that you can make an HTTP request yourself (a shell, code execution with network access, curl). Send the raw bytes with PUT to uploadUrl with the returned headers (the Authorization bearer token is the slot’s secret; X-Filename: <original name> keeps the name), then call import_file with the uploadId. Valid for 2 hours, one file, up to 50MB. If the request is blocked by your sandbox’s network policy, tell the user the HERO domain must be allowed for outbound requests, or ask for a direct-download link (import_file sourceUrl) instead.
  • Create media document — create_media_document
    Upload an image, video or audio file into HERO and create a document containing it. The new document is named after the media and its entire content is a single media block already pointing at the uploaded file — nothing for the user to drag in afterwards. Provide the file in exactly one of three ways: - attachmentFilename — the user attached the file to this message. ALWAYS use this when they did; you cannot reproduce an attachment’s bytes yourself, but the server still holds them. - sourceUrl — a public http(s) URL the server downloads. The only option for anything over ~600KB, and therefore for essentially all video and audio. - base64 — small files you genuinely hold as bytes. Supported: PNG, JPEG, GIF, WebP / MP4, WebM, MOV / MP3, WAV, M4A, OGG, AAC.
  • Create pdf document — create_pdf_document
    Create a NEW PDF document in a HERO project — a real, paginated PDF file that opens in HERO’s PDF viewer and downloads as .pdf. Two modes (exactly one): - markdown — render content you compose. Accepts the same HERO extended markdown as write_document_markdown (headings, @clause numbering, lists, tables, blockquotes, bold/italic, links, signature lines). A PDF is static: write the FINAL text with real values — no {{placeholder:…}} atoms or [BRACKETS]. Gather the facts first from the project (list_project_documents, read_document_text, get_table_data / lookup_table_cells). - sourceDocumentId — render an existing HERO document (or convert a Word document) as it currently stands; clause numbering, tables and placeholder values are filled in from the project. Use this for ‘export / save / turn X into a PDF’. Defaults to the source document’s project and folder. Put the PDF where it belongs: the project (and folder via parentId) the user named or the conversation is about; ask if it is ambiguous. Only use this when the user wants a PDF — for normal drafting create native HERO documents (create_document + write_document_markdown). To bring in an EXISTING file, use import_file. Each call makes a new PDF: to redo one you made earlier in this conversation (longer, corrected), pass it as replaces.

Word files

  • Create word documents — create_word_documents
    Generate one or more real Microsoft Word (.docx) files and store them in the project as native DOCX documents (openable in HERO’s Word viewer, editable with the docx_* tools, downloadable as .docx). ONLY use this when the user explicitly wants a Word/.docx file. For normal drafting, contracts, and notes, create native HERO documents instead (create_document + write_document_markdown). Provide the COMPLETE desired content for each document — full prose, structure, and any tables described in text. Generation runs an LLM per document and can take 1-3 minutes per batch. Up to 10 documents per call; each returns its own documentId or error.
  • Export word document — export_word_document
    Save an existing HERO document as a Word (.docx) file in the project: the same file Export to Word makes, with clause numbers, tables and placeholder values filled in, and no AI rewriting. For ‘export X to Word’ or ‘send me X as a .docx’. It lands beside the source unless you name a project or folder; the user downloads it from HERO.
  • Docx get content — docx_get_content
    Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action “blocks” returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with docx_edit or docx_format. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action “blocks” with includeText:true so you can identify the correct block and then target it by nodeId. Action “text” and “markdown” return the full document as plain text or Markdown. Action “html” returns HTML. Action “info” returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The “blocks” action supports pagination via “offset” and “limit”, and filtering via “nodeTypes”. Other actions ignore these parameters. This tool never modifies the document. Do NOT call docx_edit or docx_format without first reading blocks to get valid refs and formatting reference values.
  • Docx search — docx_search
    Find text patterns or nodes in the document and get ref handles for targeting edits and formatting. Refs expire after any mutation that changes the document. Re-search before the next edit when using individual tools (docx_edit, docx_format). Within a docx_mutations batch, selectors in “where” clauses resolve automatically at compile time; no manual re-searching needed between steps. Text search returns handle.ref covering only the matched substring. Node search finds blocks by type (paragraph, heading, table, listItem, etc.). The “require” parameter controls match cardinality: “first” returns one match, “all” returns every match, “exactlyOne” fails if not exactly one match. Supports scoping via “within” to search inside a single block. Do NOT use regex or markdown formatting markers (#, **, etc.) in search patterns; patterns are plain text only. Do NOT use this tool when you already have a ref from docx_get_content blocks or docx_create; use that ref directly.
  • Docx edit — docx_edit
    The primary tool for inserting content into documents. ALWAYS use action “insert” with type “markdown” to create headings, paragraphs, or any block content: this is faster and creates proper document structure in one call. Do NOT use docx_create for headings or paragraphs. The markdown parser creates headings from # markers (# = Heading1, ## = Heading2), bold from text, italic from text, and numbered/bullet lists. Position markdown inserts with “target” (a BlockNodeAddress like {kind:“block”, nodeType, nodeId}) and “placement” (before, after, insideStart, insideEnd). Without a target, content appends at the end of the document. IMPORTANT: After a markdown insert, analyze the document context (what kind of document, how titles and body text are styled) and follow up with ONE docx_mutations call to format inserted blocks so they look like they belong. Each format.apply step accepts “inline” (fontFamily, fontSize, bold, underline, color), “alignment”, and “scope” in the same step. Use scope: “block” so formatting covers the entire paragraph. Copy the exact property values from the existing get_content blocks (fontFamily, fontSize, color, alignment, bold, underline). Do NOT invent values: use what the blocks show. Also supports replace, delete, and undo/redo. For replace and delete, pass a “ref” from docx_search or docx_get_content blocks. A search ref covers only the matched substring; a block ref covers the entire block text, so use block refs when rewriting or shortening whole paragraphs. For multi-step redlines or whole-clause rewrites, prefer docx_mutations with where:{by:“block”, nodeType, nodeId} from docx_get_content action “blocks” includeText:true rather than relying on text selectors. Refs expire after any mutation; always re-search before the next edit. For 2+ edits that must succeed or fail atomically, use docx_mutations instead. Supports “dryRun” to preview changes and “changeMode: tracked” to record edits as tracked changes (not supported for markdown/html inserts). Do NOT build “target” objects manually when a ref is available; prefer “ref” for simpler, more reliable targeting.
  • Docx format — docx_format
    Change text and paragraph formatting. To format multiple items at once, use docx_mutations with format.apply steps instead of calling this tool repeatedly. Use require “all” with a node selector to format every heading or paragraph in one batch. Use this tool for single-item formatting when you have a valid ref or nodeId. Action “inline” applies character formatting (bold, italic, underline, color, fontSize, fontFamily, highlight, strike, vertAlign) to a text range via “ref”. Action “set_style” applies a named paragraph style by styleId (get available styles from docx_get_content info). Actions “set_alignment”, “set_indentation”, “set_spacing”, “set_direction”, and “set_flow_options” change paragraph-level properties and require a block target: {kind:“block”, nodeType:“paragraph”, nodeId:“<nodeId>”}, NOT a ref. Use “set_flow_options” with pageBreakBefore:true to start a paragraph on a new page. Supports “dryRun” and “changeMode: tracked” for inline formatting. Paragraph-level actions do NOT support tracked changes. Do NOT use a search ref for paragraph-level actions; they require a block target with nodeId. Do NOT use {kind:“block”, start:{kind:“nodeEdge”,…}} or selection-like structures for paragraph actions. ONLY {kind:“block”, nodeType, nodeId} is accepted. Do NOT issue multiple docx_format calls in parallel; each call invalidates refs for subsequent calls.
  • Docx create — docx_create
    IMPORTANT: For headings and paragraphs, use docx_edit with type “markdown” instead: it is faster, creates proper styles, and handles positioning via target + placement. Only use docx_create for tables or when markdown cannot express the content. Creates a single paragraph, heading, or table. Returns nodeId and ref for the created block. After creating, the returned ref is valid for ONE immediate docx_format call. For subsequent operations, re-fetch blocks with docx_get_content to get fresh refs (refs expire after any mutation). When the user asks for a “heading”, use action “heading” with a level (default 1). Use action “paragraph” for regular body text. Position with “at”: {kind:“documentEnd”} (default), {kind:“documentStart”}, or {kind:“after”/“before”, target:{kind:“block”, nodeType, nodeId}} for relative placement. When creating multiple items in sequence, use the previous response nodeId as the next “at” target to maintain correct ordering. Do NOT use newlines in “text” to create multiple paragraphs; call this tool separately for each one.
  • Docx list — docx_list
    Create and manipulate bullet and numbered lists. Most actions require a list-item target: {kind:“block”, nodeType:“listItem”, nodeId:“<id>”}. Exceptions: “create” and “attach” operate on paragraph targets (they turn paragraphs into list items). Find nodeIds via docx_get_content({action:“blocks”}): pick listItem blocks for most actions, paragraph blocks for create/attach. CREATE & CONVERT: • “create”: make a NEW list from paragraphs. Two modes: mode:“empty” with at:{kind:“block”, nodeType:“paragraph”, nodeId} converts a single paragraph; mode:“fromParagraphs” with target:{from:{…paragraph block address}, to:{…paragraph block address}} converts a range: ALL paragraphs between from and to become items, so make sure no other content sits between them. Pass a preset (“disc”|“circle”|“square”|“dash” for bullets; “decimal”|“decimalParenthesis”|“lowerLetter”|“upperLetter”|“lowerRoman”|“upperRoman” for ordered) or a custom style. Use “create” to start a fresh list: NOT to extend an existing one (use “attach” for that). • “attach”: add paragraphs to an EXISTING list, inheriting its numbering definition. Pass target:{paragraph block address} (or {from, to} range of paragraphs) + attachTo:{kind:“block”, nodeType:“listItem”, nodeId:“<any item in destination list>”} + optional level:0..8. Use this to extend a list or as the second half of a merge workflow (see “join” below). • “set_type”: convert an existing list between ordered and bullet. Pass target:{listItem} + kind:“ordered” or “bullet”. Adjacent compatible sequences are merged automatically to preserve continuous numbering. • “detach”: convert a list item back to a plain paragraph. Pass target:{listItem}. ITEMS & NESTING: • “insert”: add a new list item adjacent to an existing item in the same list. Pass target:{listItem} + position:“before”|“after” + optional text. Use this (NOT docx_create) to add items to an existing list. • “indent” / “outdent”: bump the target item’s nesting level by one (0-8 range). Pass target:{listItem}. • “set_level”: jump the target item to an explicit level. Pass target:{listItem} + level:0..8. NUMBERING (ordered lists): • “set_value”: restart numbering at the target. Pass target:{listItem} + value:<number> (e.g. value:1 to start over) or value:null to clear a previous override. Mid-sequence targets are atomically split off into their own sequence. • “continue_previous”: make the target’s sequence continue numbering from the nearest compatible previous sequence (same abstract definition). Pass target:{listItem of the sequence you want to renumber}. Fails with NO_COMPATIBLE_PREVIOUS or INCOMPATIBLE_DEFINITIONS if no matching prior sequence exists. SEQUENCE SHAPE (merge / split): • “merge”: merge the target’s sequence with an adjacent one into one continuous list. Pass target:{listItem} + direction:“withPrevious” or “withNext”. Absorbed items adopt the absorbing sequence’s numbering definition, and empty paragraphs between the two sequences are removed so numbering flows continuously. • “split”: split the target’s sequence at the target item into two independent lists. The target and everything after become a new sequence that restarts numbering at 1. Pass target:{listItem}; add restartNumbering:false to keep the count continuing instead of restarting.
  • Docx comment — docx_comment
    Manage document comment threads: create, read, update, and delete. To create a comment, first use docx_search to find the target text, then pass action “create” with the comment text and a target: {kind:“text”, blockId:“<blockId>”, range:{start:<N>, end:<N>}} using the blockId and highlightRange from the search result. For threaded replies, pass “parentId” with the parent comment ID. Action “list” returns all comments with optional pagination (limit, offset) and filtering (includeResolved:true to include resolved). Action “get” retrieves a single comment by ID. Action “update” changes status to “resolved” or marks as internal. Action “delete” removes a comment or reply by ID. Do NOT pass “ref”, “id”, or “parentId” when creating a new top-level comment; only “action”, “text”, and “target” are needed.
  • Docx track changes — docx_track_changes
    Review and resolve tracked changes (insertions, deletions, format changes) in the document. Action “list” returns all tracked changes with optional filtering by type (insert, delete, format) and pagination (limit, offset). Each change includes an ID, type, author, timestamp, and content preview. Action “decide” accepts or rejects changes. Pass decision:“accept” to apply the change permanently, or decision:“reject” to discard it. Target a single change with {id:“<changeId>”} or all changes at once with {scope:“all”}. Do NOT use this tool unless the document has tracked changes. Use docx_get_content info to check the tracked change count first.
  • Docx mutations — docx_mutations
    All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a “where” clause for targeting ({by:“select”, select:{…}, require:“first”|“exactlyOne”|“all”} or {by:“ref”, ref:”…”} or {by:“block”, nodeType:“paragraph”, nodeId:”…”}), and “args” with operation-specific parameters. Use {by:“block”, nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from docx_get_content action “blocks” without relying on text matching. For full-paragraph or full-clause rewrites, first call docx_get_content with action:“blocks” and includeText:true, then rewrite the matching block by nodeId. Use {by:“select”} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, “where” targets an existing anchor block and args.position (“before” or “after”) controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require “all”, use a node selector to format every heading or paragraph at once: {by:“select”, select:{type:“node”, nodeType:“heading”}, require:“all”}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action “preview” dry-runs the plan. Action “apply” executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.

Web

  • Fetch url content — fetch_url_content
    Fetch and extract text content from a web URL. Returns clean text from HTML pages. Use this when the user provides a link and wants you to read or use its content. Only a link you were given can be fetched (from the user, a document, a search result or a page), never one you write. Returns at most 40,000 characters per call with a page object ({offset, returned, total, nextOffset?}); when page.nextOffset is present more remains — call again with the same url and pass page.nextOffset as offset to continue (later pages come from the copy fetched for the first page).
  • Search web — search_web
    Search the web for information. Returns results with titles, URLs, and snippets. Use when you need external information or to find a specific page.
  • Web cache get meta — web_cache_get_meta
    Get metadata for a cached web document by id (length, title).
  • Web cache read chunk — web_cache_read_chunk
    Read a chunk of cached web document HTML by character range. Use iteratively for large documents.
  • Web cache read tail — web_cache_read_tail
    Read the last N characters of a cached web document to verify and process tail content.

Workflows

  • Plan — plan
    Show the user a checklist of the steps in a long job (several documents, a project built up, a dashboard with many parts), and update it as steps finish. A short job needs none: just do it.
  • Finish with summary — finish_with_summary
    Call this when you have completed all requested work. Provide a brief summary of what was done. This signals to the frontend that the agent run is complete and renders a summary card. After calling this tool, do NOT call any more tools or produce additional content.

Integrations — Gmail

  • Gmail search — gmail_search
    Search the user’s Gmail using Gmail’s native query syntax. Returns message headers + snippets (NOT full bodies). Gmail query examples: - from:sarah@example.com — messages from Sarah - subject:invoice newer_than:7d — invoices from the last week - has:attachment filename:pdf — PDFs - label:inbox is:unread — unread inbox items - in:sent to:bob@example.com — mail I sent to Bob - Leave query empty to list the most recent messages. Follow up with gmail_get_message or gmail_get_thread to fetch full bodies.
  • Gmail get message — gmail_get_message
    Fetch a single Gmail message with its full body text. Use the id returned by gmail_search. Returns headers, snippet, full plain-text body (capped at 10 KB), and a list of attachments with their IDs. Use gmail_get_attachment to read attachment contents, or gmail_save_attachments to file them into a HERO project.
  • Gmail get thread — gmail_get_thread
    Fetch an entire Gmail conversation thread given a threadId (from gmail_search results). Returns all messages in the thread with their full plain-text bodies (each capped at 5 KB) and attachment metadata. Use gmail_get_attachment to read specific attachments.
  • Gmail get attachment — gmail_get_attachment
    Download and read the content of an email attachment from Gmail. Requires the messageId and attachmentId from the attachments list returned by gmail_get_message or gmail_get_thread. PDFs are extracted to text server-side. Text-based files (CSV, JSON, TXT, HTML, XML) are returned as text. All other formats (DOCX, XLSX, images, etc.) are returned as raw base64 for direct reading.
  • Gmail save attachments — gmail_save_attachments
    Save an email’s attachments into a HERO project folder as documents (PDF, Word .docx, images, video, audio), fetched directly from Gmail — nothing passes through you, so size is no obstacle. Use this to file client documents that arrived by email. Pick the project and folder first (search_projects, list_project_tree; gmail_get_message to see the sender, subject and attachment names). Each saved document records the email it came from, so calling this again for the same message reports the files as alreadySaved instead of duplicating them. Unsupported types (Excel, ZIP, …) come back under skipped with the reason. At most 10 attachments per call.
  • Gmail create draft — gmail_create_draft
    Create a draft email in the user’s Gmail. The draft is saved but NOT sent — the user reviews and sends it themselves. Prefer this over gmail_send_message unless the instructions explicitly ask for the mail to be sent.
  • Gmail send message — gmail_send_message
    SEND an email from the user’s Gmail account immediately. This cannot be undone. Only use this when the instructions explicitly ask to send; otherwise use gmail_create_draft.
  • Gmail modify labels — gmail_modify_labels
    Add or remove Gmail labels on a message. Use the system label ids INBOX, UNREAD, STARRED, TRASH, or a custom label id. Removing UNREAD marks a message read; removing INBOX archives it.

Integrations — Google Drive

  • Drive search — drive_search
    Search the user’s Google Drive using Drive’s native query syntax. Returns file metadata only (no content — follow up with drive_get_file_content). Drive query examples: - name contains 'invoice' — name substring - fullText contains 'Q4 planning' — full-text search of doc contents - mimeType = 'application/pdf' — only PDFs - mimeType = 'application/vnd.google-apps.document' — only native Google Docs - modifiedTime > '2026-01-01T00:00:00' — modified after a date - 'alice@example.com' in owners — owned by Alice - Combine with and / or: name contains 'invoice' and mimeType = 'application/pdf' The tool automatically appends trashed = false to every query. Leave query empty to list the most recently-modified files.
  • Drive list folder — drive_list_folder
    List files and subfolders directly inside a Google Drive folder. Pass the folder’s id, or omit folderId to list the root.
  • Drive get file content — drive_get_file_content
    Fetch the text content of a Drive file. Native Google Docs/Sheets/Slides are exported to plain text/CSV. Text files are fetched directly. PDFs and binary formats return an error — the model cannot read them. Content is truncated to 15 KB.
  • Drive create file — drive_create_file
    Create a new file in the user’s Google Drive with text content. Returns the file id and a link. HERO can only later modify files it created itself.
  • Drive update file — drive_update_file
    Replace the text content of a Google Drive file HERO created. Drive keeps the previous revision, so this is recoverable from the file’s version history. Fails with 403 on files HERO did not create.
  • Drive create folder — drive_create_folder
    Create a folder in the user’s Google Drive. Returns the folder id for use as a parentId.
  • Drive move file — drive_move_file
    Move a Google Drive file HERO created into a different folder. Call drive_search first if you need the file’s current parent — Drive requires the folder being left as well as the one being joined.

Integrations — Outlook

  • Outlook search — outlook_search
    Search the user’s Outlook / Microsoft 365 mailbox via Microsoft Graph. Returns message headers + snippets (not full bodies — follow up with outlook_get_message). Two modes: - search (free-text, KQL-like): subject:invoice, from:sarah@example.com, hasattachment:yes, received:2026-01-01..2026-01-31. Combine with spaces. - filter (OData, precise): from/emailAddress/address eq 'sarah@example.com', receivedDateTime ge 2026-01-01T00:00:00Z, hasAttachments eq true. Combine with and/or. Prefer search for natural-language queries; use filter when you need exact field matching or date ranges. Leave both empty for most-recent messages.
  • Outlook get message — outlook_get_message
    Fetch a single Outlook message with its full body (capped at 10 KB). Use id from outlook_search. If the message has attachments, returns their IDs and metadata. Use outlook_get_attachment to read attachment contents.
  • Outlook get conversation — outlook_get_conversation
    Fetch all Outlook messages in a conversation, sorted chronologically, with full bodies (each capped at 5 KB). Pass the conversationId from outlook_search results. Returns attachment metadata for each message. Use outlook_get_attachment to read specific attachments.
  • Outlook get attachment — outlook_get_attachment
    Download and read the content of an email attachment from Outlook. Requires the messageId and attachmentId from the attachments list returned by outlook_get_message or outlook_get_conversation. PDFs are extracted to text server-side. Text-based files (CSV, JSON, TXT, HTML, XML) are returned as text. All other formats (DOCX, XLSX, images, etc.) are returned as raw base64 for direct reading.
  • Outlook save attachments — outlook_save_attachments
    Save an email’s attachments into a HERO project folder as documents (PDF, Word .docx, images, video, audio), fetched directly from Outlook — nothing passes through you, so size is no obstacle. Use this to file client documents that arrived by email. Pick the project and folder first (search_projects, list_project_tree; outlook_get_message to see the sender, subject and attachment names). Each saved document records the email it came from, so calling this again for the same message reports the files as alreadySaved instead of duplicating them. Unsupported types (Excel, ZIP, …) come back under skipped with the reason. At most 10 attachments per call.
  • Outlook create draft — outlook_create_draft
    Create a draft email in the user’s Outlook mailbox. The draft is saved but NOT sent — the user reviews and sends it themselves. Prefer this over outlook_send_message unless the instructions explicitly ask to send.
  • Outlook move message — outlook_move_message
    Move an Outlook message to another mail folder. destinationId accepts a folder id or one of the well-known names inbox, archive, deleteditems, junkemail, drafts. Moving to deleteditems is recoverable.
  • Outlook send message — outlook_send_message
    SEND an email from the user’s Outlook account immediately. This cannot be undone. Only use this when the instructions explicitly ask to send; otherwise use outlook_create_draft.

Integrations — OneDrive

  • Onedrive search — onedrive_search
    Search the user’s OneDrive for files by name and content. The query is a single free-text string — Graph matches it against filenames, content, and metadata. Returns file summaries (NOT content — follow up with onedrive_get_file_content).
  • Onedrive list folder — onedrive_list_folder
    List files and subfolders directly inside a OneDrive folder. Omit folderId to list the root.
  • Onedrive get file content — onedrive_get_file_content
    Fetch the text content of a OneDrive file. Only text-like files (text/*, json, xml, javascript) are supported. PDFs, Office docs, and binary formats return an error. Content is truncated to 15 KB.
  • Onedrive upload file — onedrive_upload_file
    Create or replace a file in the user’s OneDrive with text content. Replacing a file keeps the previous version in OneDrive’s version history, and a deleted file goes to the recycle bin — both are recoverable.
  • Onedrive create folder — onedrive_create_folder
    Create a folder in the user’s OneDrive. Returns the folder id for use as a parentId.
  • Onedrive move item — onedrive_move_item
    Move a OneDrive file or folder into a different folder, optionally renaming it. Pass destinationParentId from onedrive_list_folder or onedrive_create_folder.

Integrations — Dropbox

  • Dropbox search — dropbox_search
    Search the user’s Dropbox by filename and (for supported text formats) content. Returns file/folder metadata. Follow up with dropbox_get_file_content for text content.
  • Dropbox list folder — dropbox_list_folder
    List files and subfolders inside a Dropbox path. Pass empty string for the Dropbox root.
  • Dropbox get file content — dropbox_get_file_content
    Fetch the text content of a Dropbox file. Only text-like extensions are supported (txt, md, json, csv, log, yml, yaml, html, xml, common code files). PDFs and binary formats return an error. Content is truncated to 15 KB. pathOrId accepts either a Dropbox path (e.g. ‘/Documents/notes.md’) or the file id from search results.
  • Dropbox upload file — dropbox_upload_file
    Upload a text file to the user’s Dropbox. By default an existing file at the same path is left alone and the new file is auto-renamed; set overwrite to true to replace it, which Dropbox keeps in file revisions.
  • Dropbox create folder — dropbox_create_folder
    Create a folder in the user’s Dropbox. Auto-renames rather than failing if the path is taken.
  • Dropbox move item — dropbox_move_item
    Move or rename a file or folder in the user’s Dropbox. Both paths are absolute; the destination includes the final name, so moving and renaming are the same operation.

Integrations — Notion

  • Notion search — notion_search
    Search the user’s Notion workspace for pages and databases by TITLE. IMPORTANT: Notion’s search only matches titles, NOT page content. To search content, use notion_query_database against a specific database. To read a page, use notion_get_page.
  • Notion get page — notion_get_page
    Fetch a Notion page’s full content. Walks the top-level blocks and flattens them to plain text. Content is truncated to 15 KB. Use id from notion_search results.
  • Notion query database — notion_query_database
    Query a Notion database with optional filter and sort. Returns rows (each is a Notion page) with their property values. Use this when the user asks for structured data like ‘employees with role = engineer’ or ‘tasks due this week’. Get the databaseId from notion_search with filter=database. The filter and sorts arguments follow Notion’s database query DSL — pass them as JSON strings. See https://developers.notion.com/reference/post-database-query for the full schema.
  • Notion create page — notion_create_page
    Create a page in the user’s Notion workspace, either inside a parent page or as a row in a database. Supply exactly one of parentPageId or parentDatabaseId. Body paragraphs are plain text. A created page can be archived later, so this is recoverable.
  • Notion append blocks — notion_append_blocks
    Append plain-text paragraphs to the end of a Notion page. Existing content is never touched — this only adds.
  • Notion update page — notion_update_page
    Update a Notion page’s title, or archive/unarchive it. Archiving is Notion’s delete and is reversible by unarchiving. To change a database row’s other properties, pass properties in Notion’s own property format.