Skip to content

[Chat] Show tool call parameters#11552

Draft
wanglam wants to merge 2 commits intoopensearch-project:mainfrom
wanglam:show-tool-call-arguments
Draft

[Chat] Show tool call parameters#11552
wanglam wants to merge 2 commits intoopensearch-project:mainfrom
wanglam:show-tool-call-arguments

Conversation

@wanglam
Copy link
Collaborator

@wanglam wanglam commented Mar 19, 2026

Description

This PR adds the display of tool call parameters in the tool call row component for non-custom tools. When users expand a tool call accordion, they can now see both the parameters that were passed to the tool and the result returned.

Changes:

  • Added a "Parameters:" section in the tool call accordion that displays the tool's arguments
  • Parameters are displayed as formatted JSON when valid JSON, or as plain text otherwise
  • Added "Result:" label to clearly distinguish between parameters and results
  • Added comprehensive unit tests for the ToolCallRow component

Issues Resolved

image

Testing the changes

  1. Start the OpenSearch Dashboards application
  2. Open the chat interface
  3. Trigger a tool call by asking a question that invokes a non-custom tool
  4. Once the tool completes, click on the tool call row to expand it
  5. Verify that both "Parameters:" and "Result:" sections are displayed
  6. Verify that JSON parameters are formatted and displayed in a code block
  7. Run unit tests: yarn test:jest --testPathPattern="tool_call_row.test"

Changelog

  • feat: [Chat] Display tool call parameters in chat tool call row

Check List

  • All tests pass
    • yarn test:jest
    • yarn test:jest_integration
  • New functionality includes testing.
  • New functionality has been documented.
  • Update CHANGELOG.md
  • Commits are signed per the DCO using --signoff

Signed-off-by: Lin Wang <wonglam@amazon.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

PR Reviewer Guide 🔍

(Review updated until commit a667f5e)

Here are some key observations to aid the review process:

🧪 PR contains tests
🔒 No security concerns identified
✅ No TODO sections
🔀 Multiple PR themes

Sub-PR theme: Add tool call parameters display in ToolCallRow component

Relevant files:

  • src/plugins/chat/public/components/tool_call_row.tsx
  • changelogs/fragments/11552.yml

Sub-PR theme: Add unit tests for ToolCallRow component

Relevant files:

  • src/plugins/chat/public/components/tool_call_row.test.tsx

⚡ Recommended focus areas for review

Unconditional Result Label

The "Result:" label is always rendered even when there is no result to display (i.e., when toolCall.result is undefined or empty). This could result in a dangling label with no content beneath it. Consider conditionally rendering the "Result:" label only when a result exists.

<EuiText size="xs" color="subdued">
  <strong>
    {i18n.translate('chat.toolCall.resultLabel', {
      defaultMessage: 'Result:',
    })}
  </strong>
</EuiText>
Inline Style

The marginBottom: 8 inline style on the parameters EuiPanel uses a raw pixel value rather than an EUI spacing token or a CSS class. This is inconsistent with EUI design conventions and may cause styling issues across themes. Consider using EuiSpacer or an EUI spacing utility instead.

<EuiPanel hasBorder paddingSize="s" style={{ wordBreak: 'break-all', marginBottom: 8 }}>
  {isValidJSON(toolCall.arguments) ? (
    <EuiCodeBlock
      language="json"
      paddingSize="none"
      fontSize="s"
      transparentBackground
      overflowHeight={150}
      isCopyable
    >
      {JSON.stringify(JSON.parse(toolCall.arguments), null, 2)}
    </EuiCodeBlock>
  ) : (
    <EuiText size="s">{toolCall.arguments}</EuiText>
  )}
</EuiPanel>
Weak Accordion Test

The test "should be initially closed by default" only checks that .euiAccordion__childWrapper panels exist, but does not actually verify that the accordion content is hidden/collapsed. This test may pass even if the accordion is open, making it unreliable as a behavioral assertion.

it('should be initially closed by default', () => {
  const toolCall = createToolCall({
    status: 'completed',
    result: 'result',
  });

  render(<ToolCallRow toolCall={toolCall} />);

  // The accordion content should not be visible by default
  // We check that the result text is not immediately visible
  const panels = document.querySelectorAll('.euiAccordion__childWrapper');
  expect(panels.length).toBeGreaterThan(0);
});

@github-actions
Copy link
Contributor

Persistent review updated to latest commit a667f5e

@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

PR Code Suggestions ✨

Latest suggestions up to a667f5e
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Guard result section with conditional rendering

The "Result:" label and its panel are always rendered unconditionally, even when
there is no result to display. This could show an empty panel with a "Result:" label
when toolCall.result is undefined or empty. Wrap the result section in a conditional
check similar to how the parameters section is handled.

src/plugins/chat/public/components/tool_call_row.tsx [481-488]

-<EuiText size="xs" color="subdued">
-    <strong>
-      {i18n.translate('chat.toolCall.resultLabel', {
-        defaultMessage: 'Result:',
-      })}
-    </strong>
-  </EuiText>
-  <EuiPanel hasBorder paddingSize="s" style={{ wordBreak: 'break-all' }}>
+{toolCall.result && (
+  <>
+    <EuiText size="xs" color="subdued">
+      <strong>
+        {i18n.translate('chat.toolCall.resultLabel', {
+          defaultMessage: 'Result:',
+        })}
+      </strong>
+    </EuiText>
+    <EuiPanel hasBorder paddingSize="s" style={{ wordBreak: 'break-all' }}>
Suggestion importance[1-10]: 6

__

Why: The "Result:" label and panel are always rendered unconditionally, which could show an empty section when toolCall.result is undefined or empty. This is a valid improvement for consistency with how the parameters section is handled, though it may be a minor issue if result is always present in practice.

Low
General
Safely handle JSON parsing errors

Although isValidJSON is called before this line, JSON.parse can still throw if
isValidJSON has any edge cases or if the value changes between checks. Wrap the
parse in a try-catch or store the parsed result from isValidJSON to avoid a
potential runtime error.

src/plugins/chat/public/components/tool_call_row.tsx [473]

-{JSON.stringify(JSON.parse(toolCall.arguments), null, 2)}
+{(() => { try { return JSON.stringify(JSON.parse(toolCall.arguments), null, 2); } catch { return toolCall.arguments; } })()}
Suggestion importance[1-10]: 4

__

Why: While isValidJSON is called before JSON.parse, wrapping in a try-catch adds defensive safety. However, if isValidJSON is correctly implemented, this is a low-risk scenario and the improvement is marginal. The inline IIFE pattern also reduces readability.

Low

Previous suggestions

Suggestions up to commit a667f5e
CategorySuggestion                                                                                                                                    Impact
Possible issue
Conditionally render result section

The "Result:" label and its panel are always rendered unconditionally, even when
there is no result to display. This could show an empty panel with just a "Result:"
label. The result section should be conditionally rendered only when toolCall.result
exists, similar to how the parameters section is handled.

src/plugins/chat/public/components/tool_call_row.tsx [481-487]

-<EuiText size="xs" color="subdued">
-    <strong>
-      {i18n.translate('chat.toolCall.resultLabel', {
-        defaultMessage: 'Result:',
-      })}
-    </strong>
-  </EuiText>
+{toolCall.result && (
+  <>
+    <EuiText size="xs" color="subdued">
+      <strong>
+        {i18n.translate('chat.toolCall.resultLabel', {
+          defaultMessage: 'Result:',
+        })}
+      </strong>
+    </EuiText>
+    <EuiPanel hasBorder paddingSize="s" style={{ wordBreak: 'break-all' }}>
+      {isError &&
Suggestion importance[1-10]: 6

__

Why: The "Result:" label is always rendered unconditionally even when toolCall.result is absent, which could show an empty panel. Wrapping it in a conditional check similar to the parameters section would improve correctness and consistency.

Low
General
Guard against JSON parse errors

The JSON.parse(toolCall.arguments) call is not wrapped in a try-catch, but it's
guarded by isValidJSON. However, if isValidJSON has any edge cases or the parse
fails for any reason, this will throw an uncaught error. Consider wrapping this in a
try-catch or ensuring the parsed value is safely handled.

src/plugins/chat/public/components/tool_call_row.tsx [473]

-{JSON.stringify(JSON.parse(toolCall.arguments), null, 2)}
+{(() => {
+  try {
+    return JSON.stringify(JSON.parse(toolCall.arguments), null, 2);
+  } catch {
+    return toolCall.arguments;
+  }
+})()}
Suggestion importance[1-10]: 3

__

Why: While the code is already guarded by isValidJSON, adding a try-catch provides extra safety. However, since isValidJSON should reliably prevent invalid JSON from reaching JSON.parse, this is a low-impact defensive measure.

Low

@codecov
Copy link

codecov bot commented Mar 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.50%. Comparing base (d5e1567) to head (a667f5e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11552      +/-   ##
==========================================
+ Coverage   61.48%   61.50%   +0.01%     
==========================================
  Files        4988     4988              
  Lines      136631   136633       +2     
  Branches    23629    23631       +2     
==========================================
+ Hits        84012    84035      +23     
+ Misses      46568    46538      -30     
- Partials     6051     6060       +9     
Flag Coverage Δ
Linux_1 25.05% <ø> (ø)
Linux_2 39.41% <ø> (ø)
Linux_3 42.67% <100.00%> (+0.02%) ⬆️
Linux_4 33.87% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

✅ All unit tests passing

🔗 Workflow run · commit a667f5e6c44307c97c0baa7f50b9789decfba510

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant