- **Admin GUI for agent tool secrets, e.g. `tool:web_search` (issue #2117).**
  `UpdateToolSecretsMutation`/`DeleteToolSecretsMutation`
  (`config/graphql/pipeline_settings_mutations.py`),
  `PipelineSettingsType.tools_with_secrets`, and
  `WebSearchTool.is_configured()` gating
  (`opencontractserver/llms/tools/web_search_tools.py`) were fully implemented
  backend-side, but the frontend never selected `toolsWithSecrets` and had no
  GraphQL documents or UI for either mutation — the only way to configure the
  web search tool's provider/API key was a raw GraphQL call. Added:
  - `toolsWithSecrets` to `GET_PIPELINE_SETTINGS`, and new
    `UPDATE_TOOL_SECRETS`/`DELETE_TOOL_SECRETS` documents
    (`frontend/src/components/admin/system_settings/graphql.ts`).
  - New standalone `ToolSecretsPanel.tsx`: a "Web Search Tool" card with a
    Configured/Not-configured status indicator, a Provider select (`brave`/
    `tavily`, mirroring `opencontractserver.constants.web_search.SUPPORTED_PROVIDERS`
    — see `WEB_SEARCH_PROVIDERS` in `frontend/src/assets/configurations/constants.ts`),
    a password-type API key input, and a Save / Remove Configuration (with
    inline confirm) action pair — mirroring the existing component-secrets
    modal's input/status-chip conventions. Mounted in `SystemSettings.tsx`
    below the Filetype Defaults / Enrichment Chains sections.
  - Tests: new `frontend/tests/tool-secrets-panel.ct.tsx` covering the
    not-configured empty state, save with correct mutation variables, and
    delete-after-confirm.
