Skip to content

fix(web): don't fetch plugin-auth routes for non-builtin tool providers (#39169)#39206

Open
Taranum01 wants to merge 1 commit into
langgenius:mainfrom
Taranum01:fix/39169-agents-configure-api-tool-builtin-route
Open

fix(web): don't fetch plugin-auth routes for non-builtin tool providers (#39169)#39206
Taranum01 wants to merge 1 commit into
langgenius:mainfrom
Taranum01:fix/39169-agents-configure-api-tool-builtin-route

Conversation

@Taranum01

Copy link
Copy Markdown

Summary

Fixes #39169 — Agents configure page (/agents/<id>/configure) was firing
GET /workspaces/current/tool-provider/builtin/<id>/credential/... for every tool in the
agent, including custom (api) tool providers. Because custom (api) providers have their
credentials stored on the tool_api_providers row and do not go through the plugin daemon,
passing an api-provider row id to the builtin route raised PluginNotFoundError and surfaced
as a 500 toast on every configure page load.

Repro (per the issue)

  1. Create a custom API tool provider (Tools → Custom → import OpenAPI schema) with API Key
    header auth.
  2. On the new Agents platform, add several tools from this provider to an agent.
  3. Open /agents/<agent_id>/configure — the configure page requests
    GET /console/api/workspaces/current/tool-provider/builtin/<api-row-uuid>/credential/schema/api-key
    → 500 with PluginNotFoundError. Chat and runtime are unaffected; this is a console-only
    cosmetic regression that also adds a permanent warning badge on the Configuration menu item.

Fix

Two layers of defense:

  1. useGetApi short-circuits to an empty URL set for non-builtin providerType.
    All plugin-auth useQuery hooks key off enabled: !!url, so handing back empty strings
    opts the call out cleanly. Legacy callers that pre-date the providerType field (pass
    undefined) keep their original builtin URL behavior — no risk of regressing unrelated
    call sites.
  2. CredentialStatus short-circuits to null for non-builtin providerType in both the
    unauthorized and authorized branches, mirroring the existing canSwitchCredential gate.
    This avoids rendering a "Not authorized" button that has no meaningful action for custom
    (api) tools and prevents the matching AuthorizedInNode flow from firing either.

The useGetApi change is the minimal defense-in-depth: if any other call site ever forgets
to gate on providerType, the underlying hook will still hand back empty URLs and the
useQuery will stay disabled.

Tests

  • Extended use-get-api.spec.ts with a providerType gating (#39169) block pinning the
    contract for builtin, api, mcp, and undefined providerType.
  • New provider-tool/__tests__/item.spec.tsx covers the render-level guard: usePluginAuth
    is never called for an api-type tool (unauthorized or authorized), but is still called for
    a builtin one.

All 4 useGetApi + AgentProviderToolItem tests + the 12 pre-existing
tools/__tests__/index.spec.tsx tests pass. tsc and tsslint are clean on the changed
files (5875 checks). The pre-commit hook ran and passed.

Files

 web/app/components/plugins/plugin-auth/hooks/use-get-api.ts                       | 71 +++++--
 web/app/components/plugins/plugin-auth/hooks/__tests__/use-get-api.spec.ts        | 70 ++++++++
 web/features/agent-v2/.../tools/provider-tool/item.tsx                            | 16 +-
 web/features/agent-v2/.../tools/provider-tool/__tests__/item.spec.tsx             | 186 ++++++++++++++++++++

Refs #39169

Made with Cursor

…rs (langgenius#39169)

The Agents configure page (/agents/<id>/configure) was firing a
`GET /workspaces/current/tool-provider/builtin/<id>/credential/...`
request for every tool in the agent, including custom (api) tool
providers. Custom API tools have their credentials stored on the
`tool_api_providers` row — they do not go through the plugin daemon —
so passing an api-provider row id to the builtin route raised
`PluginNotFoundError` in the plugin daemon and surfaced as a 500 toast
on every configure page load.

Two fixes:

1. `useGetApi` now short-circuits to an empty URL set when called with
   an explicitly-set non-builtin `providerType`. All plugin-auth
   `useQuery` hooks key off `enabled: !!url`, so handing back empty
   strings opts the call out cleanly. Legacy callers that pre-date the
   `providerType` field (i.e. pass `undefined`) keep their original
   builtin URL behavior.

2. `CredentialStatus` short-circuits to `null` for non-builtin
   `providerType` in both the unauthorized and authorized branches,
   mirroring the existing `canSwitchCredential` gate. This avoids
   rendering a "Not authorized" button that has no meaningful action
   for custom (api) tools and prevents the matching
   `AuthorizedInNode` flow from firing either.

Regression tests:

- Extended `use-get-api.spec.ts` with a `providerType gating (langgenius#39169)`
  block pinning the contract for builtin, api, mcp, and undefined
  `providerType`.
- New `provider-tool/__tests__/item.spec.tsx` covers the render-level
  guard: `usePluginAuth` is never called for an api-type tool
  (unauthorized or authorized), but is still called for a builtin one.

Refs langgenius#39169

Signed-off-by: Taranum Wasu <taranumwasu@Taranums-MacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 17, 2026
@github-actions github-actions Bot added the web This relates to changes on the web. label Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agents configure page throws 500: credential schema of a custom API tool provider is requested via the builtin tool-provider route (PluginNotFoundError)

1 participant