Skip to content

feat: add tool call execution, stop streaming, and redesign tool call UI - #3837

Merged
Pratham-Mishra04 merged 1 commit into
devfrom
05-28-feat_enable_tool_execution_in_the_prompt_playground
May 28, 2026
Merged

feat: add tool call execution, stop streaming, and redesign tool call UI#3837
Pratham-Mishra04 merged 1 commit into
devfrom
05-28-feat_enable_tool_execution_in_the_prompt_playground

Conversation

@impoiler

@impoiler impoiler commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the ability to directly execute MCP tool calls from the prompt playground, and introduces a Stop button to cancel in-flight streaming requests. Previously, users could only submit tool results manually; now they can execute a tool call against the backend and have the result automatically submitted, or fall back to manual entry.

Changes

  • Added executeToolCall in executor.ts that POSTs to /v1/mcp/tool/execute and returns the tool result as a string. Header-building logic was extracted into a shared buildHeaders helper to avoid duplication between executePrompt and executeToolCall.
  • Added AbortController support to executePrompt so streaming requests can be cancelled. AbortError exceptions are silently swallowed since they represent intentional user cancellation.
  • Added handleExecuteToolCall to the prompt context, which calls executeToolCall and then pipes the result into the existing handleSubmitToolResult flow.
  • Added handleStopStreaming to the prompt context, which aborts the active AbortController and resets streaming state.
  • Replaced the spinner-disabled Run button with a dedicated Stop button (destructive styling) that appears while streaming is active.
  • Redesigned ToolCallMessageView to show an "Awaiting tool result" state with two actions: Execute (runs the tool call automatically, showing a spinner while in progress) and Add manually (opens the existing textarea flow). The card layout, animations, and status badges were also refreshed.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

  1. Open the prompt playground and configure a model that supports tool/function calling.
  2. Add a system prompt and user message that triggers a tool call, then click Run.
  3. Once the assistant responds with a tool call, verify the card shows Execute and Add manually buttons.
  4. Click Execute — confirm the spinner appears, the call is sent to /v1/mcp/tool/execute, and the result is automatically submitted and the conversation continues.
  5. On a separate tool call, click Add manually, paste a result, and click Submit result — confirm the existing flow still works.
  6. Start a streaming run and click Stop — confirm streaming halts immediately with no error toast.
cd ui
pnpm i
pnpm build

Screenshots/Recordings

Before/after screenshots of the tool call card and the Stop button should be attached.

Breaking changes

  • Yes
  • No

Related issues

Security considerations

buildHeaders preserves the existing guard that prevents custom headers from overwriting Content-Type, Authorization, or x-bf-api-key-id, so API key handling is unchanged. The new executeToolCall endpoint uses the same auth headers as the rest of the playground.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b9fbc940-caeb-47be-b3c0-75d2aeb0bdcf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 05-28-feat_enable_tool_execution_in_the_prompt_playground

Comment @coderabbitai help to get the list of available commands and usage tips.

impoiler commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

@impoiler
impoiler force-pushed the 05-28-feat_enable_tool_execution_in_the_prompt_playground branch from 9bbc50a to 6160745 Compare May 28, 2026 11:44
@impoiler
impoiler force-pushed the 05-28-feat_enable_tool_execution_in_the_prompt_playground branch from 6160745 to dc6ef37 Compare May 28, 2026 11:59
@impoiler impoiler self-assigned this May 28, 2026
@impoiler impoiler changed the title feat: enable tool execution in the prompt playground feat: add tool call execution, stop streaming, and redesign tool call UI May 28, 2026
@impoiler
impoiler marked this pull request as ready for review May 28, 2026 12:09

Pratham-Mishra04 commented May 28, 2026

Copy link
Copy Markdown
Collaborator

Merge activity

  • May 28, 12:09 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 28, 12:10 PM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 merged commit a2b6cee into dev May 28, 2026
14 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 05-28-feat_enable_tool_execution_in_the_prompt_playground branch May 28, 2026 12:10
@greptile-apps

greptile-apps Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 3/5

The Stop button reliably aborts streaming but leaves a stale placeholder message in the conversation on every use.

The abort plumbing is correct end-to-end except for one concrete gap: onStreamingStart appends a placeholder before fetch is called, but when the user clicks Stop the abort clears activeRunRef before onFinally fires, so no cleanup callback ever removes that placeholder. Every Stop click therefore silently contaminates the messages list with an empty or partially-streamed assistant bubble. The rest of the changes — header extraction, executeToolCall, the new UI states — look correct.

context.tsx (handleStopStreaming) needs the placeholder cleanup fix before this ships; executor.ts (executeToolCall) warrants a second look at the hardcoded index: 0 field.

Important Files Changed

Filename Overview
ui/components/prompts/utils/executor.ts Extracts buildHeaders helper and adds executeToolCall + AbortSignal support to executePrompt. The AbortError swallowing is correct; hardcoded index: 0 in executeToolCall payload could misidentify non-first tool calls on the backend.
ui/components/prompts/context.tsx Adds handleStopStreaming and handleExecuteToolCall to the prompt context. handleStopStreaming correctly aborts in-flight requests but does not remove the dangling placeholder message that onStreamingStart already appended to the messages list, leaving a stale bubble in the conversation after every Stop click.
ui/components/prompts/components/messagesView/toolCallView.tsx Redesigned tool call card with Execute/Add-manually flow and per-tool-call executing state. All existing data-testid attributes are preserved in-code but tool-call-response-textarea and tool-call-response-submit are now hidden behind the "Add manually" toggle, requiring test scaffolds to be updated.
ui/components/prompts/components/newMessageInputView.tsx Replaces the spinner-disabled Run button with a dedicated Stop button during streaming. handleRun still guards against isStreaming and the textarea is disabled during streaming, so the keyboard shortcut is safe.
ui/components/prompts/components/messagesView/rootMessageView.tsx Wires handleExecuteToolCall from context down to ToolCallMessageView — straightforward prop threading, no issues.

Reviews (1): Last reviewed commit: "feat: enable tool execution in the promp..." | Re-trigger Greptile

Comment on lines +622 to +627
const handleStopStreaming = useCallback(() => {
abortRef.current?.abort();
abortRef.current = null;
activeRunRef.current = null;
setIsStreaming(false);
}, []);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Dangling placeholder message after Stop

handleStopStreaming sets activeRunRef.current = null before the AbortError propagates. When executePrompt later runs its finally block, callbacks.onFinally() calls isActive()null === Symbol(…)false, so setIsStreaming(false) is a no-op there — but more importantly, neither onError nor onEmptyResponse is ever invoked for an abort. The placeholder message added by onStreamingStart before the fetch is therefore never removed from the messages array, leaving a stale empty (or partially-streamed) assistant bubble in the conversation every time the user clicks Stop.

To fix, handleStopStreaming should also remove the trailing placeholder, e.g. setMessages(prev => { const last = prev[prev.length - 1]; return (last?.type === MessageType.Response && last.content === '') ? prev.slice(0, -1) : prev; });

Comment on lines +219 to +226
body: JSON.stringify({
id: toolCall.id,
type: toolCall.type,
index: 0,
function: {
name: toolCall.function.name,
arguments: toolCall.function.arguments,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Hardcoded index: 0 may misidentify the tool call

index: 0 is hardcoded regardless of which tool call is being executed. If the backend uses the index field to correlate the request to a specific call in a multi-tool-call assistant turn, this will always point to the first tool call, silently executing the wrong one when the user clicks Execute on the second or third entry in the list. Even if id is the authoritative identifier on the backend today, the intent of index here should be clarified or set to the actual position of this tool call.

Comment on lines +249 to +290
<div className="animate-in fade-in-0 duration-150 motion-reduce:animate-none space-y-2">
<div className="flex items-center gap-2">
<div>
<div className="text-xs font-medium text-foreground">Tool result</div>
<div className="text-[10px] text-muted-foreground">
Paste the result returned by this tool call.
</div>
</div>

<Button
variant="ghost"
size="sm"
className="ml-auto h-7 px-2 text-xs text-muted-foreground"
data-testid="tool-call-response-cancel"
onClick={() => hideManualEntry(tc.id)}
disabled={isExecuting}
>
Cancel
</Button>
</div>

<Textarea
autoFocus
placeholder="Paste tool result..."
value={responses[tc.id] ?? ""}
onChange={(e) => handleResponseChange(tc.id, e.target.value)}
data-testid="tool-call-response-textarea"
className="min-h-[84px] resize-none rounded-md bg-background font-mono text-xs"
rows={4}
disabled={isExecuting}
/>

<div className="flex justify-end">
<Button
variant="secondary"
size="sm"
className="h-8 active:scale-[0.97] transition-transform"
data-testid="tool-call-response-submit"
disabled={!responses[tc.id]?.trim() || isExecuting}
onClick={() => handleSubmitResponse(tc.id)}
>
<Send className="size-3.5" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 data-testid elements now gated behind a UI interaction

tool-call-response-textarea and its sibling tool-call-response-submit are now conditionally rendered inside isManualEntryOpen, meaning any test that previously expected to find and interact with those elements directly will now need to first click tool-call-response-add-manually. No Playwright tests in tests/e2e/ currently reference these IDs, so there is no immediate breakage, but the change contracts against the preserve-e2e-testid rule — adding a comment or updating any future test scaffold would prevent silent regressions.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

akshaydeo pushed a commit that referenced this pull request May 29, 2026
… UI (#3837)

## Summary

Adds the ability to directly execute MCP tool calls from the prompt playground, and introduces a **Stop** button to cancel in-flight streaming requests. Previously, users could only submit tool results manually; now they can execute a tool call against the backend and have the result automatically submitted, or fall back to manual entry.

## Changes

- Added `executeToolCall` in `executor.ts` that POSTs to `/v1/mcp/tool/execute` and returns the tool result as a string. Header-building logic was extracted into a shared `buildHeaders` helper to avoid duplication between `executePrompt` and `executeToolCall`.
- Added `AbortController` support to `executePrompt` so streaming requests can be cancelled. `AbortError` exceptions are silently swallowed since they represent intentional user cancellation.
- Added `handleExecuteToolCall` to the prompt context, which calls `executeToolCall` and then pipes the result into the existing `handleSubmitToolResult` flow.
- Added `handleStopStreaming` to the prompt context, which aborts the active `AbortController` and resets streaming state.
- Replaced the spinner-disabled Run button with a dedicated **Stop** button (destructive styling) that appears while streaming is active.
- Redesigned `ToolCallMessageView` to show an "Awaiting tool result" state with two actions: **Execute** (runs the tool call automatically, showing a spinner while in progress) and **Add manually** (opens the existing textarea flow). The card layout, animations, and status badges were also refreshed.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

1. Open the prompt playground and configure a model that supports tool/function calling.
2. Add a system prompt and user message that triggers a tool call, then click **Run**.
3. Once the assistant responds with a tool call, verify the card shows **Execute** and **Add manually** buttons.
4. Click **Execute** — confirm the spinner appears, the call is sent to `/v1/mcp/tool/execute`, and the result is automatically submitted and the conversation continues.
5. On a separate tool call, click **Add manually**, paste a result, and click **Submit result** — confirm the existing flow still works.
6. Start a streaming run and click **Stop** — confirm streaming halts immediately with no error toast.

```sh
cd ui
pnpm i
pnpm build
```

## Screenshots/Recordings

_Before/after screenshots of the tool call card and the Stop button should be attached._

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

`buildHeaders` preserves the existing guard that prevents custom headers from overwriting `Content-Type`, `Authorization`, or `x-bf-api-key-id`, so API key handling is unchanged. The new `executeToolCall` endpoint uses the same auth headers as the rest of the playground.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
@akshaydeo akshaydeo mentioned this pull request May 29, 2026
18 tasks
akshaydeo added a commit that referenced this pull request May 29, 2026
## Summary

This PR releases **core v1.5.14**, **framework v1.3.14**, **transports v1.5.6**, and bumps all dependent plugins to their respective `.14` patch versions. It delivers a broad set of new capabilities across MCP authentication, key rotation, OTel metrics, Bedrock/Anthropic compatibility, and UI improvements, alongside a number of targeted bug fixes and refactors.

## Changes

- **Direct API Key Header** — Providers can now receive an API key passed directly via a request header (#3817)
- **MCP Per-User Auth** — Introduced `MCPCredentialStore` abstraction, per-user MCP credential reconciliation, and a new per-user header auth type with lazy-auth submission flow (#3656, #3702, #3703, #3704, #3705)
- **MCP TLS Configuration** — Added configurable TLS (`insecureSkipVerify`, `caCertPem`) for HTTP/SSE MCP client connections (#3779, #3783)
- **MCP Sessions Management** — Filter, search, and pagination on the MCP sessions list API and table, plus a `can_reauth` identity gate (#3823, #3824, #3825)
- **Key Rotation** — Keys now rotate on 401/402/403 responses; returns `502 upstream_credentials_exhausted` when all keys are permanently exhausted. Added `triggered_rotation` to `KeyAttemptRecord` and tightened `bifrost_key_rotation_events_total` semantics (#3430, #3491)
- **OTel Metrics** — Added OTel spec-compatible metrics (backward compatible) with provider cache and semantic cache attributes in metrics export (#3865, #3816)
- **Opus 4.8 Support** — System message handling and general compatibility for Opus 4.8 (#3868, #3878)
- **Dimension Rankings** — New `GetDimensionRankings` API and dashboard tabs for team, customer, BU, and user rankings (#3766)
- **Model Pricing Attributes** — `additional_attributes` field on model pricing rows with management API and UI editor (#3829)
- **Prompt Cache Retention** — Added prompt cache retention parameter on responses requests (#3810)
- **Tool Call Execution UI** — Inline tool-call execution, stop streaming, bulk execute/submit, and a redesigned tool-call UI (#3837, #3843)
- **Sheet Navigation** — Prev/next keyboard navigation and URL state across virtual key, MCP client, and routing rule sheets (#3739, #3740, #3744, #3745)
- **Bedrock Tool Name Truncation** — Truncate Bedrock function/tool names to the provider length limit
- **Bedrock Guardrails** — Set guardrail config in Bedrock requests built from responses (#3862)
- **Anthropic Tool Use** — Default `tool_use` input to `{}` when arguments are absent (#3880)
- **Responses Streaming** — Fixed responses stream events (#3838)
- **Compat Flow** — Fixed missing parameter parsing on the compat flow (#3881)
- **Passthrough API Version** — Set a default API version in passthrough requests as a fallback (#3853)
- **Virtual Key Updates** — Avoid overriding optional fields during virtual key update (#3855)
- **User-Mode Flows** — Gate user-mode flows on caller `user_id`, skip temp token mint, and unify flow/credential kind filtering for pending flows (#3841, #3859)
- **Partial Tool Calls** — Handle partial tool call execution failures and return successful results (#3849)
- **URL Query Escaping** — Support escaped characters in URL query parameters (#3826)
- **MCP Auth Errors** — Inline banner and retry support for MCP auth-required errors (#3856)
- **Renamed Resolvers** — `staticHeadersResolver`/`serverOAuthResolver` renamed to `sharedHeadersResolver`/`sharedOAuthResolver` (#3840)
- **Starlark Nested Tool Calls** — Exposed `RunWithPluginPipeline` on `ClientManager` and routed Starlark nested tool calls through the canonical plugin gate (#3794)
- **Deferred-Fill OAuth Removed** — Removed deferred-fill user-mode OAuth flow support (#3839)
- **Go 1.26.3** — Upgraded toolchain to Go 1.26.3 (#3782)

## Type of change

- [x] Bug fix
- [x] Feature
- [x] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [x] Providers/Integrations
- [x] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go version  # should report go1.26.3
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

- Validate MCP per-user auth by configuring a per-user header auth type and confirming credentials are stored and reconciled on virtual key and MCP client changes.
- Validate key rotation by triggering a 401/402/403 from an upstream provider and confirming rotation occurs; exhaust all keys and confirm a `502 upstream_credentials_exhausted` is returned.
- Validate OTel metrics output includes `provider_cache` and `semantic_cache` attributes.
- Validate Bedrock requests with tool names exceeding the provider limit are truncated correctly.
- Validate Opus 4.8 system message handling by sending a request with a system message to an Opus 4.8 endpoint.

## Breaking changes

- [x] Yes
- [ ] No

The deferred-fill user-mode OAuth flow has been removed (#3839). Any integrations relying on that flow must migrate to the new per-user credential store approach. The `staticHeadersResolver` and `serverOAuthResolver` identifiers have been renamed to `sharedHeadersResolver` and `sharedOAuthResolver` respectively (#3840); any direct references must be updated.

## Related issues

#3817, #3656, #3702, #3703, #3704, #3705, #3779, #3783, #3823, #3824, #3825, #3430, #3491, #3865, #3816, #3868, #3878, #3766, #3829, #3810, #3837, #3843, #3739, #3740, #3744, #3745, #3862, #3880, #3838, #3881, #3853, #3855, #3841, #3859, #3849, #3826, #3856, #3840, #3794, #3839, #3782, #3724, #3814, #3836, #3869, #3886

## Security considerations

- MCP per-user credentials are stored via the new `MCPCredentialStore` abstraction; ensure the backing store is appropriately access-controlled and that credential values are encrypted at rest.
- The direct API key header feature passes provider secrets via HTTP headers; ensure TLS is enforced on all ingress paths and that headers are not logged in plaintext.
- User-mode flows are now gated on `caller user_id` and temp token minting is skipped where appropriate, reducing the surface for privilege escalation.
- TLS configuration for MCP HTTP/SSE connections supports `insecureSkipVerify`; this should only be enabled in controlled environments.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
@akshaydeo akshaydeo mentioned this pull request May 29, 2026
akshaydeo added a commit that referenced this pull request May 29, 2026
## ✨ Features

- **Direct API Key Header** - Pass a provider API key directly via
request header (#3817)
- **MCP Per-User Authentication** - New per-user header auth type with
credential storage
  and lazy-auth submission flow (#3703, #3704, #3705)
- **MCP TLS Configuration** - Configurable TLS (insecureSkipVerify,
caCertPem) for HTTP/SSE
  MCP client connections (#3779, #3783)
- **MCP Sessions Management** - Filter, search, and pagination on the
MCP sessions list API
  and table, plus a can_reauth identity gate (#3823, #3824, #3825)
- **Tool Call Execution UI** - Inline tool-call execution, stop
streaming, bulk
  execute/submit, and a redesigned tool-call UI (#3837, #3843)
- **Dimension Rankings Dashboard** - New dashboard tabs for team,
customer, BU, and user
  rankings, backed by a GetDimensionRankings API (#3766)
- **Model Pricing Attributes** - additional_attributes on model pricing
rows with management
  API and UI editor (#3829)
- **Prompt Cache Retention** - Prompt cache retention parameter on
responses requests
  (#3810)
- **Opus 4.8 Support** - System message handling and compatibility for
Opus 4.8 (#3878,
  #3868)
  - **Key Rotation** - Rotate keys on 401/402/403 and return 502
upstream_credentials_exhausted when all keys are permanently dead
(#3491)
- **OTel Metrics** - OTel spec compatible metrics plus provider and
semantic cache
  attributes in metrics export (#3865, #3816)
- **Sheet Navigation** - Prev/next keyboard navigation and URL state
across virtual key, MCP
  client, and routing rule sheets (#3739, #3740, #3744, #3745)
  - **Go 1.26.3** - Upgraded toolchain to Go 1.26.3 (#3782)

  ## 🐞 Fixed

- **Bedrock Tool Names** - Truncate Bedrock function/tool names to the
provider length limit
- **Bedrock Guardrails** - Set guardrail config in Bedrock request built
from responses
  (#3862)
- **Anthropic Tool Use** - Default Anthropic tool_use input to {} when
arguments are absent
  (#3880)
  - **Responses Streaming** - Fixed responses stream events (#3838)
- **Compat Flow** - Fixed missing parameter parsing on the compat flow
(#3881)
- **Passthrough API Version** - Set a default API version in passthrough
requests as a
  fallback (#3853)
- **Virtual Key Updates** - Avoid overriding optional fields during
virtual key update
  (#3855)
- **User-Mode Flows** - Gate user-mode flows on caller user_id, skip
temp token mint, and
  unify flow/credential kind filtering for pending flows (#3841, #3859)
- **Partial Tool Calls** - Handle partial tool call execution failures
and return successful
  results (#3849)
- **URL Query Escaping** - Support escaped characters in URL query
parameters (#3826)
- **MCP Auth Errors** - Inline banner and retry support for MCP
auth-required errors (#3856)
- **JSON Editor Height** - Cap JSON editor max height at 400px in
message views (#3842)
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