Skip to content

improvement(tools): state every pinned param, not just the credential - #7170

Open
waleedlatif1 wants to merge 5 commits into
stagingfrom
feat/discriminate-prefilled-params
Open

improvement(tools): state every pinned param, not just the credential#7170
waleedlatif1 wants to merge 5 commits into
stagingfrom
feat/discriminate-prefilled-params

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Reported case: an agent with two Gmail read tools on the same account but different labels couldn't route between them. Every param a user fills is stripped from the schema the model sees (createLLMToolSchema), and improvement(tools): tell the model which duplicate tool instance is which #7079 only ever named the credential — so the two tools arrived byte-identical, and the shared credential was correctly suppressed as non-discriminating, leaving nothing at all.
  • Each tool now states the values the workflow pinned on it. Opaque resource ids (credential, knowledge base, workflow) still resolve to a display name; plain values like a label, a row limit or a toggle need no lookup and are stated directly.
  • Now runs for every tool with pinned params, not only duplicates. A lone tool pinned to INBOX can otherwise promise a caller it will search SENT — the model has no way to know the field is fixed. Duplicates additionally get a sentence saying the copies differ.
  • Secrets are never stated: a subblock marked password, a hidden subblock, a secret-named param, and — for a tool whose params resolved an environment variable — every literal value. Resource names are still stated there, since a looked-up name cannot carry the secret.

Renamed tool-binding-labels.ts to tool-pinned-params.ts to match what it now does.

Type of Change

  • Improvement

Testing

31 unit tests, including the exact reported case (same credential, different folder). Verified the guards fail when removed: deleting the password/hidden skip, and deleting the secret-withholding branch, each turn the relevant tests red. Full suite green: 3,953 tests, tsc clean, all 36 audits pass, lint clean.

Behaviour change worth noting for review: descriptions now change for every existing agent that pins any param, not just ones with duplicate tools, and credential lookups now run for every OAuth tool rather than only duplicates. Lookups are deduped per request and memoized for the run, so a credential shared across tools costs one read.

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)

@vercel

vercel Bot commented Aug 27, 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 Aug 28, 2026 12:12am

Request Review

@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR expands model-visible tool annotations from duplicate resource bindings to all safely stateable pinned parameters.

  • Collects pinned fields for block and MCP tools while excluding hidden, password-like, inactive, and unsupported values.
  • Resolves opaque resource identifiers to workspace-scoped display names and caches those lookups.
  • Suppresses literal annotations when tool parameters contain resolved environment secrets.
  • Adds duplicate-tool guidance when otherwise identical tools are pinned to different values.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/sim/providers/tool-binding.ts Introduces pinned-field collection, resource metadata, scalar sanitization, and guards for sensitive or inapplicable parameters.
apps/sim/executor/utils/tool-pinned-params.ts Resolves resource names and appends bounded pinned-parameter statements and duplicate-selection guidance to tool descriptions.
apps/sim/executor/handlers/agent/agent-handler.ts Registers MCP pinned fields and applies secret-aware annotations to provider tools.
apps/sim/executor/handlers/pi/local/sim-tools.ts Adds per-tool secret-provenance checks before annotating Pi tool descriptions.
apps/sim/providers/utils.ts Registers collected pinned fields during standard block-tool transformation.
apps/sim/executor/utils/tool-pinned-params.test.ts Covers resource resolution, duplicate discrimination, annotation limits, caching, and secret withholding.
apps/sim/providers/tool-binding.test.ts Extensively tests pinned-field selection, canonical parameters, sanitization, and sensitive-field exclusions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Workflow tool parameters] --> B[Collect pinned fields]
  B --> C{Sensitive or unsupported?}
  C -->|Yes| D[Exclude literal]
  C -->|No| E[Sanitize scalar value]
  B --> F[Resolve resource IDs to names]
  D --> G[Build provider tool]
  E --> G
  F --> G
  G --> H[Annotate model-visible description]
  H --> I{Duplicate values differ?}
  I -->|Yes| J[Add copy-selection guidance]
  I -->|No| K[Keep pinned-value statement only]
Loading

Reviews (6): Last reviewed commit: "improvement(tools): decide pinned fields..." | Re-trigger Greptile

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 9 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/sim/providers/tool-binding.ts Outdated
Comment thread apps/sim/executor/handlers/agent/agent-handler.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

1 similar comment
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

Two agent tools bound to the same Gmail account but different labels reached the
model byte-identical: every param a user fills is stripped from the schema, and
only the credential was ever named in the description. The model could not tell
Inbox from Sent, and with a single tool it could promise a caller it would search
a folder that tool can never reach.

Each tool now states the values the workflow pinned on it, whether or not it has
a duplicate sibling. Opaque resource ids still resolve to a display name; plain
values like a label, a row limit or a toggle need no lookup and are stated
directly. Secrets never are: a field marked `password`, a hidden field, a
secret-named param, and every literal on a tool whose params resolved an
environment variable are all withheld.
… the prose

Follow-ups from review of the pinned-param descriptions.

A block's subblocks span every operation it supports, so a Gmail block switched
from Send to Read still holds `to`, `subject` and `body` — and the tool stated
them as constraints on a read tool, leaking stale draft content into the prompt.
Literals are now filtered to the selected tool's declared params. Resources are
exempt: an OAuth credential is a block input that never appears in a tool's
param map.

MCP tools carry configured params but have no subblocks, so they registered
nothing and their pinned values went unstated. They now collect from their
configured params directly.

The duplicate hint claimed the copies differ whenever a tool had a sibling, even
when both rendered identical text. It now compares the rendered statements, so
the model is never told to pick between indistinguishable copies.

Also: reuse `isPasswordParameter` instead of a second secret regex, applied only
to literals since it matches `oauthCredential`; make the field type a real union
so a field cannot be both a literal and a resource; and cut the stated-field cap
from six to three, since every field costs tokens on every request in the loop.
…tween copies

Two copies pinned to identical values, where only one of them resolved an
environment variable, rendered different text — one withheld its literal — and
both were then told "other copies are pinned to different values". That is the
exact assertion the comparison exists to prevent. The duplicate check now
compares the un-withheld render, so disclosure differences no longer read as
configuration differences.

Also drops a redundant copy of the resolved-name cache, returns undefined rather
than an empty-string sentinel for an unresolved resource, unexports two
internal-only interfaces, and corrects six comments: five overstated or
referenced the module this branch renamed, and one described the wrong failure
mode for a credential entered in advanced mode.

Adds the uncovered branches the review named: canonical-id grouping (the shape
production actually sees once wire ids are aliased), a sibling that states
nothing, negative-cache reuse, both resource kinds in one pass, an omitted tool
param map, empty and oversized titles, and a non-finite number.
The MCP discovery path stripped only `toolName` from a tool entry's stored
params, so `serverId` and `serverName` stayed in the values treated as pinned
and were stated to the model — an internal server id reaching a provider, and
two of the three field slots consumed before any real param. The cached path
already stripped all three; the split now lives in one helper so the two cannot
drift again.

Pi withheld literal values for every tool whenever ANY input in the whole run
resolved a secret, which is true of almost any real workflow — the feature was
effectively off there. It now asks the registry the same per-input-path question
the Agent block asks, so only the tool that actually carries a secret is
withheld.

A canonical group blocked by one half no longer leaks through the other: a
`file-upload` basic half skipped without claiming its param, letting a
`short-input` twin state a raw file reference. 78 groups have that shape.

Widens the secret-name backstop for params named by a remote MCP schema rather
than by Sim — `authorization`, `cookie`, `signature`, `connectionString`, `otp`
and friends are not in the Sim-tuned `isPasswordParameter` list.
@waleedlatif1
waleedlatif1 force-pushed the feat/discriminate-prefilled-params branch from ca5e742 to 31a8f8e Compare August 27, 2026 23:37
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

…aram name

The membership check asked a proxy question — "does this subblock's id match a
declared tool param?" — when the real one is "is this field part of the
operation the tool was selected for". 41 blocks rename a field on its way to the
tool inside `tools.config.params`, so their pinned values failed the name match
and were never stated. Datadog's `listMonitorName` feeds the tool param `name`;
it is now stated as Filter by Name "CPU" instead of dropped.

`evaluateSubBlockCondition` answers the real question directly and survives a
rename, because it never looks at tool param names. It also still excludes the
stale-field case the name match was introduced for: Gmail's to/subject/body are
gated to the send operations, so a block switched to Read drops them.

The operation selector and trigger-mode subblocks are excluded explicitly — they
carry values but do not constrain the call.

Trigger mode is skipped per subblock rather than blocking its canonical group.
Gmail puts `triggerCredentials` in the same group as `credential`, and blocking
the group dropped the account from every Gmail tool. Only value-level
disqualifiers — password, hidden, unstateable type — block a whole group, since
a canonical group shares one value.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

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.

1 participant