Skip to content

fix(workflow): render agent tool chip names from static sources, not stored title#5501

Merged
j15z merged 7 commits into
stagingfrom
feat/static-tool-chip-names
Jul 8, 2026
Merged

fix(workflow): render agent tool chip names from static sources, not stored title#5501
j15z merged 7 commits into
stagingfrom
feat/static-tool-chip-names

Conversation

@j15z

@j15z j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Renders agent tool chip names from canonical sources (block registry, custom-tool records, live MCP data) instead of the mutable title field in workflow JSON state, so copilot edit_workflow operations (or any direct state edit) can no longer change what the workflow UI displays for a tool. One shared resolver (resolveStoredToolName) drives the panel chips, the collapsed canvas summaries, and the workflow search index, so all surfaces agree. Resolution order: canonical name → stored title (only when nothing resolves: deleted custom blocks, MCP data not yet loaded, legacy inline custom tools) → raw type id.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

  • Unit tests added/updated in display.test.ts (registry-backed entries ignore edited titles; workflow/workflow_input resolve statically; unresolvable types fall back to stored title then raw id; custom-tool record and live MCP name win over stored title) and indexer.test.ts (search indexes the resolved display name, not the mutated title; canonical MCP/custom-tool names indexed when live data is present) — 119 tests passing across the affected suites.
  • tsc --noEmit clean, biome check clean, full CI (Test and Build) green.
  • Reviewed through 4 bot review cycles (Greptile + Cursor Bugbot) plus a multi-agent internal review with adversarial verification; all findings fixed and threads resolved.

Reviewer focus:

  • The resolution priority in resolveStoredToolName (apps/sim/lib/workflows/subblocks/display.ts) — this is now the single policy for all three surfaces.
  • The custom-block overlay invalidation: memos deriving from getBlock carry the useCustomBlockOverlayVersion dep (canvas summary, panel picker, search index) per the contract in client-overlay.ts.
  • Known accepted tradeoffs: MCP entries show the stored title only while server data is unavailable; legacy inline custom tools display their stored title because it is their identity (it also feeds the custom_${title} executor id); the read-only preview resolves without live MCP/custom data by design.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

No visual change for normal flows: chips already showed the canonical name (the stored title was snapshotted from it at add-time). The change only prevents state-edited titles from surfacing in the UI.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 8, 2026 9:01pm

Request Review

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Display and search-indexing only; no execution or auth paths. Main edge case is MCP/custom data not loaded yet, where stored titles still show by design.

Overview
Introduces resolveStoredToolName as the single policy for how stored tool-input entries get a display name: block registry (incl. custom-block overlay), custom-tool records, and live MCP names win over the mutable title in workflow state; stored title is only used when nothing else resolves.

Panel tool chips (tool-input.tsx) render chip labels via that resolver (with mcpToolNamesById and customTools), fall back to getBlock for icon/chrome when a type is hidden from the permission-filtered picker, and recompute the tool list when useCustomBlockOverlayVersion changes.

Canvas block summaries and workflow search/replace pass the same hydration (customTools, MCP name map, overlay version) into resolveToolsLabel / indexWorkflowSearchMatches, so search indexes and highlights match what the UI shows—not edited stored titles.

Tests in display.test.ts and indexer.test.ts lock in the priority order and search behavior.

Reviewed by Cursor Bugbot for commit d76e45d. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread apps/sim/lib/workflows/subblocks/display.ts Outdated
@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a UI bug where copilot edit_workflow operations (or any direct state edit) could change the title field in stored tool entries, causing the workflow UI to display the mutated label instead of the canonical name. It introduces a single shared resolver, resolveStoredToolName, that drives all three affected render surfaces — panel chips, collapsed canvas block summaries, and the search index — with a consistent priority order: block registry > custom-tool DB record > live MCP server data > stored title (fallback only) > raw type id.

  • resolveStoredToolName (display.ts): The new central resolver correctly prioritizes canonical sources (block registry via getBlock, custom-tool records by customToolId, live MCP names via mcpToolNamesById) over the mutable title field. Legacy inline custom-tools and unresolved MCP entries fall back to the stored title by design.
  • Panel / canvas / search wired up: All three call sites now accept customTools and mcpToolNamesById and declare customBlockOverlayVersion as a memo dependency, so custom-block overlay hydration correctly invalidates resolved names.
  • MCP tool ID keying is consistent: useMcpTools sets t.id = createMcpToolId(serverId, name), which is the same composite key used in workflow-block.tsx and stored in workflow state as toolId — all three maps use the same key format.

Confidence Score: 5/5

Safe to merge — the change is a read-only display fix that never mutates stored workflow state, and all three affected render surfaces now agree on canonical tool names.

The resolver logic is correct and consistent across panel chips, canvas summaries, and the search index. MCP tool ID keying uses createMcpToolId uniformly. The workflow/workflow_input block types are covered via the block registry. Custom-block overlay invalidation is wired through customBlockOverlayVersion in all relevant memos. Tests pin every resolution branch and verify that mutated stored titles are excluded from the search index. No state is written, no API contracts are changed.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/workflows/subblocks/display.ts Introduces resolveStoredToolName as the single source of truth for tool display names; resolveToolsLabel is correctly refactored to delegate to it. Resolution priority and fallback chain match the PR description and tests.
apps/sim/lib/workflows/subblocks/display.test.ts Adds tests pinning each branch of the resolver: registry-backed tools ignore stored titles, workflow/workflow_input statically resolve, MCP prefers live names, custom-tool prefers the DB record, and unresolvable types fall back correctly.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx Replaces the per-chip customToolTitle / tool.title split with resolveStoredToolName; adds customBlockOverlayVersion dep to toolBlocks memo; falls back to getBlock for permission-filtered block types to preserve chip chrome.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx Correctly builds mcpToolNamesById from useMcpToolsQuery using createMcpToolId as key (matching stored toolId format), and adds customBlockOverlayVersion + mcpToolNamesById to the toolsDisplayValue memo dependency array.
apps/sim/lib/workflows/search-replace/indexer.ts Replaces raw tool.title with resolveStoredToolName in addToolInputMatches; passes blockConfigs as the first lookup in getBlockConfig, falling back to getBlock. Consistent with panel and canvas paths.
apps/sim/lib/workflows/search-replace/indexer.test.ts Updates existing test to verify canonical block-config name wins over stored title; adds new test asserting MCP and custom-tool canonical names are indexed and mutated stored titles are excluded.
apps/sim/lib/workflows/search-replace/types.ts Extends WorkflowSearchIndexerOptions with optional customTools and mcpToolNamesById fields, and adds name? to blockConfig entries so the resolver can use passed-in config names.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Stored Tool Entry] --> B{resolveStoredToolName}

    B --> C{custom-tool?}
    C -- yes --> D{customToolId string?}
    D -- yes --> E[Look up customTools records]
    E --> F{record found?}
    F -- yes --> G[record.title or schema name]
    F -- no --> H[storedTitle or schemaName]
    D -- no --> H

    C -- no --> I{mcp?}
    I -- yes --> J{toolId string?}
    J -- yes --> K[Look up mcpToolNamesById]
    K --> L{live name found?}
    L -- yes --> M[live MCP name]
    L -- no --> N[storedTitle fallback]
    J -- no --> N

    I -- no --> O{type string present?}
    O -- yes --> P[getBlockConfig via registry + overlay]
    P --> Q{blockConfig.name?}
    Q -- yes --> R[canonical block name]
    Q -- no --> S[storedTitle or raw type id]
    O -- no --> T[storedTitle or schemaName or null]

    subgraph Consumers
        U[Panel chips]
        V[Canvas summary]
        W[Search index]
    end

    B --> Consumers
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Stored Tool Entry] --> B{resolveStoredToolName}

    B --> C{custom-tool?}
    C -- yes --> D{customToolId string?}
    D -- yes --> E[Look up customTools records]
    E --> F{record found?}
    F -- yes --> G[record.title or schema name]
    F -- no --> H[storedTitle or schemaName]
    D -- no --> H

    C -- no --> I{mcp?}
    I -- yes --> J{toolId string?}
    J -- yes --> K[Look up mcpToolNamesById]
    K --> L{live name found?}
    L -- yes --> M[live MCP name]
    L -- no --> N[storedTitle fallback]
    J -- no --> N

    I -- no --> O{type string present?}
    O -- yes --> P[getBlockConfig via registry + overlay]
    P --> Q{blockConfig.name?}
    Q -- yes --> R[canonical block name]
    Q -- no --> S[storedTitle or raw type id]
    O -- no --> T[storedTitle or schemaName or null]

    subgraph Consumers
        U[Panel chips]
        V[Canvas summary]
        W[Search index]
    end

    B --> Consumers
Loading

Reviews (8): Last reviewed commit: "fix(workflow): recompute search index wh..." | Re-trigger Greptile

Comment thread apps/sim/lib/workflows/subblocks/display.ts Outdated
@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens tool chip display names in agent blocks against copilot state edits by sourcing them from static/canonical registries instead of the workflow JSON's mutable title field. It covers the expanded panel chip (tool-input.tsx) and the collapsed canvas/preview path (resolveToolsLabel in display.ts), with accompanying tests.

  • tool-input.tsx: introduces a toolDisplayName derived from the block registry, custom-tool record, or live MCP data; integration tools fall back to tool.type and workflow type returns a static literal 'Workflow'.
  • display.ts: moves the block-registry lookup to a fast path before the stored-title check, so integration tools and unregistered types can no longer be renamed by state edits; custom-tool records take precedence over the stored snapshot.
  • display.test.ts: adds three tests pinning registry-first behavior for integration tools, unregistered type IDs, and custom-tool record priority; no test is added for workflow-type entries, which are excluded from the fast path and still read the stored title in resolveToolsLabel.

Confidence Score: 3/5

Safe to merge for integration and custom tools; the canvas summary path for workflow-as-tool entries remains unprotected against title edits.

The two render paths diverge for workflow-type tool entries: tool-input.tsx now shows the static literal 'Workflow' while resolveToolsLabel in display.ts still reads t.title (the stored, mutable field). An adversarial copilot edit to the title field of a workflow tool entry would still be reflected in the collapsed canvas block summary and workflow preview. The PR's stated goal is to cover both paths for all tool types, and the test suite does not catch this gap.

apps/sim/lib/workflows/subblocks/display.ts — the workflow and workflow_input exclusion from the registry fast path leaves those types falling through to the stored title.

Important Files Changed

Filename Overview
apps/sim/lib/workflows/subblocks/display.ts Block-registry fast path now correctly prioritises registry names for integration tools and unregistered type IDs over stored titles, but workflow (and workflow_input) types are explicitly excluded and still fall through to the mutable stored title, leaving the canvas summary / preview unprotected for workflow-as-tool entries.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx Derives toolDisplayName from static sources (registry, custom-tool record, MCP live data, static literal for workflow); all branches are consistent with the intent and the fallback hierarchy is correct.
apps/sim/lib/workflows/subblocks/display.test.ts Adds three new tests pinning registry-first behavior for integration tools, unregistered types, and custom tools; missing a parallel test for workflow-type tool entries (which would expose the incomplete fix in resolveToolsLabel).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Tool entry in workflow state] --> B{tool.type?}
    B -->|custom-tool| C[Look up custom-tool record by customToolId]
    C --> C1{Record found?}
    C1 -->|Yes| C2[Use record.title]
    C1 -->|No| C3[Fall back to stored tool.title]
    B -->|mcp| D[Look up live MCP tool by toolId]
    D --> D1{Live data available?}
    D1 -->|Yes| D2[Use mcpTool.name]
    D1 -->|No| D3[Fall back to stored tool.title]
    B -->|workflow| E[tool-input.tsx: static Workflow]
    E -.->|display.ts gap| F[resolveToolsLabel: still reads stored t.title]
    B -->|integration type| G[getBlock type from registry]
    G --> G1{Block found?}
    G1 -->|Yes| G2[Use blockConfig.name]
    G1 -->|No| G3[Use raw tool.type]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Tool entry in workflow state] --> B{tool.type?}
    B -->|custom-tool| C[Look up custom-tool record by customToolId]
    C --> C1{Record found?}
    C1 -->|Yes| C2[Use record.title]
    C1 -->|No| C3[Fall back to stored tool.title]
    B -->|mcp| D[Look up live MCP tool by toolId]
    D --> D1{Live data available?}
    D1 -->|Yes| D2[Use mcpTool.name]
    D1 -->|No| D3[Fall back to stored tool.title]
    B -->|workflow| E[tool-input.tsx: static Workflow]
    E -.->|display.ts gap| F[resolveToolsLabel: still reads stored t.title]
    B -->|integration type| G[getBlock type from registry]
    G --> G1{Block found?}
    G1 -->|Yes| G2[Use blockConfig.name]
    G1 -->|No| G3[Use raw tool.type]
Loading

Reviews (2): Last reviewed commit: "fix(workflow): render agent tool chip na..." | Re-trigger Greptile

Comment thread apps/sim/lib/workflows/subblocks/display.ts Outdated
Comment thread apps/sim/lib/workflows/subblocks/display.ts Outdated
@Sg312 Sg312 requested a review from a team as a code owner July 8, 2026 02:39
Comment thread apps/sim/hooks/queries/tables.ts
@j15z j15z force-pushed the feat/static-tool-chip-names branch from 09cae9a to 61b81a4 Compare July 8, 2026 02:54
@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 61b81a4. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/workflows/search-replace/indexer.ts
@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 50df1e6. Configure here.

@j15z j15z force-pushed the feat/static-tool-chip-names branch from 50df1e6 to 1278bce Compare July 8, 2026 19:09
@j15z j15z changed the base branch from dev to staging July 8, 2026 19:09
@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 1278bce. Configure here.

j15z and others added 7 commits July 8, 2026 13:58
…stored title

Tool entries in an agent block's inputs carry a mutable `title` in workflow
state, which copilot edits (edit_workflow) could rewrite to change what the
UI displays. Derive chip names from static/canonical sources instead: the
block registry name for integration tools (raw type id if unregistered),
the custom-tool record over the stored snapshot, the live MCP tool name,
and a static literal for workflow-as-tool. The stored `title` still persists
in state; the UI just no longer reads it for registry-backed tools.

Covers both render paths: the expanded tool-input chips and the collapsed
canvas summary (resolveToolsLabel, also used by workflow preview).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…atic naming

Address review findings: resolveToolsLabel now returns the static
'Workflow' label for workflow/workflow_input entries instead of falling
through to the stored title, matching the panel chip; the panel's
custom-tool name priority now matches resolveToolsLabel (record title,
record schema function name, then stored title); and the display-name
comment no longer overstates the guarantee.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The panel resolved integration tool names through toolBlocks, which is
permission- and toolbar-filtered, so a stored tool whose type was
filtered out of the picker fell back to the raw type id while the
canvas summary (getBlock) still showed the registry name. Use getBlock
directly for the display name so both paths agree; toolBlocks still
drives the chip icon, params, and picker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… summaries

resolveToolsLabel preferred the stored title for mcp entries, so canvas
and preview summaries could show a state-edited name while the config
panel showed the live MCP tool name. Accept an optional mcpTools list
(matched by toolId, same as the panel) and pass the already-fetched MCP
tool data from workflow-block; the stored title remains the fallback
while server data is unavailable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…llback, and search regressions

Consolidate the per-surface name logic into one resolveStoredToolName in
display.ts (canonical source -> stored title -> raw type id) used by the
panel chips, the canvas summary, and the search indexer, fixing the
regressions the per-renderer patches introduced:

- custom-block tools (async registry overlay) no longer render raw
  custom_block_<uuid> ids pre-hydration or after deletion; the canvas
  memo and panel picker now subscribe to the overlay version so labels
  recompute when custom blocks hydrate
- unresolvable block types fall back to the stored title before the raw
  type id, instead of always showing the id
- the search indexer now indexes the resolved display name (the title
  entry was already read-only), so search text and highlights match what
  the chips render instead of the mutable stored title
- redundant hardcoded 'Workflow' labels removed (registry names cover
  workflow/workflow_input); MCP lookups use a shared Map keyed by
  composite tool id instead of per-entry array scans; panel chip chrome
  falls back to the unfiltered registry for picker-hidden types

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r; fix blockConfigs type

The search index now resolves tool names with the same data as the chip
renderers: the single caller passes customTools and a live MCP name map
into indexWorkflowSearchMatches, so indexed names match the panel for
custom-tool references and MCP entries, not just registry-backed types.
Also declare the optional name on WorkflowSearchIndexerOptions
blockConfigs entries, fixing the next build type error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ydrates

The matches memo resolves tool names through getBlock, so it must carry
the overlay version dep like the other getBlock-derived memos; without
it, find-in-workflow could index stale custom-block names until an
unrelated dep changed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@j15z j15z force-pushed the feat/static-tool-chip-names branch from 1278bce to d76e45d Compare July 8, 2026 21:01
@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

@j15z

j15z commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit d76e45d. Configure here.

@j15z j15z merged commit fa82acd into staging Jul 8, 2026
18 checks passed
@j15z j15z deleted the feat/static-tool-chip-names branch July 8, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants