XDSChatToolCalls@xds/core · Chat
Preview coming soon

Usage

ChatToolCalls displays tool or function call invocations from an LLM response. Pass an array of calls and the component handles the rest — a single call renders inline, while multiple calls collapse into a summary with the latest call visible at the surface. Use it anywhere an AI agent shows what actions it took.

Best practices

GuidancePractices
DoInclude a target string on every call so the user can see what the tool acted on — a file path, a shell command, or a search query.
DoShow a duration on completed calls so users can judge which tools are slow and understand why a response took time.
DoProvide resultDetail with a code block for calls that produce output — diffs for edits, terminal output for shell commands — so users can inspect results inline.
DoSet a unique key on each call item when streaming so React can animate additions without re-mounting completed rows.
Don'tDon't omit the status field — without it the call defaults to complete, which is misleading for calls that are still running or have failed.
Don'tDon't display tool calls outside a chat message context — they are designed to sit inside an assistant message, not as standalone UI.
Don'tDon't use custom wrappers around individual calls — the component handles single vs. grouped layout automatically based on the array length.

Anatomy

ElementDescription
Status iconrequiredA colored circle with a check, cross, or spinner indicating whether the call is pending, running, complete, or errored.
Tool namerequiredThe function or tool name displayed in monospace — bash, edit, read, web_search, etc.
Node badgeA neutral pill badge showing which sandbox or environment ran the tool, like cli:remote-server or workspace.
Target labelThe target of the action — a file path, command, or search query — shown after the tool name.
Diff statsGreen additions and red deletions counts for edit operations, displayed inline after the target.
DurationExecution time shown on the trailing edge for completed calls.
Group headerA wrench icon with a call count, shown when multiple calls are present. Clicking toggles between the summary and the full list.

Import

ts
import {XDSChatToolCalls} from '@xds/core/Chat'

Props

PropTypeDescription
callsrequired
XDSChatToolCallItem[]Array of tool call data. Each item has name, status, target, duration, node, additions, deletions, stats, errorMessage, resultDetail, key, and data.
label
stringCustom summary label for groups. Auto-generated from count if omitted.
isExpanded
booleanControlled expanded state for the group.
defaultIsExpanded
boolean (default: false)Default expanded state when uncontrolled.
onExpandedChange
(isExpanded: boolean) => voidCallback fired when the expanded state changes.

Examples

Common configurations, variations, and states.
ChatToolCalls — ExpandableTool calls with expandable result details showing diffs and command output in code blocks. Click a row to reveal its result.
tsx
'use client';
import {XDSChatToolCalls} from '@xds/core/Chat';
import {XDSCodeBlock} from '@xds/core/CodeBlock';
const editDiff = `--- a/src/utils/formatDate.ts
+++ b/src/utils/formatDate.ts
@@ -8,7 +8,11 @@
-export function formatDate(date: Date): string {
- return date.toLocaleDateString();
-}
+export function formatDate(
+ date: Date,
+ locale = 'en-US',
+ options?: Intl.DateTimeFormatOptions,
+): string {
+ return new Intl.DateTimeFormat(locale, options).format(date);
+}`;
const testOutput = `$ yarn test
PASS src/utils/formatDate.test.ts
PASS src/components/DatePicker.test.tsx
Test Suites: 2 passed, 2 total
Tests: 14 passed, 14 total
Time: 1.8s`;
export default function ChatToolCallsInteractiveToolCalls() {
return (
<XDSChatToolCalls
defaultIsExpanded
calls={[
{
name: 'edit',
target: 'src/utils/formatDate.ts',
status: 'complete',
duration: '85ms',
node: 'cli:remote-server',
additions: 6,
deletions: 3,
resultDetail: (
<XDSCodeBlock
code={editDiff}
language="typescript"
maxHeight="50vh"
/>
),
},
{
name: 'bash',
target: 'yarn test',
status: 'complete',
duration: '1.8s',
node: 'cli:remote-server',
resultDetail: (
<XDSCodeBlock code={testOutput} language="bash" maxHeight="50vh" />
),
},
{
name: 'web_search',
target: 'Intl.DateTimeFormat locale options',
status: 'complete',
duration: '1.2s',
},
]}
/>
);
}
ChatToolCalls — SimpleA single inline tool call above a collapsible multi-call group with diff stats. Shows both layouts side by side.
tsx
'use client';
import {XDSChatToolCalls} from '@xds/core/Chat';
import {XDSStack} from '@xds/core/Layout';
export default function ChatToolCallsSimple() {
return (
<XDSStack direction="vertical" gap={4}>
<XDSChatToolCalls
calls={[
{
name: 'bash',
target: 'git status',
status: 'complete',
duration: '1.2s',
},
]}
/>
<XDSChatToolCalls
defaultIsExpanded
calls={[
{
name: 'read',
target: 'src/components/DataGrid.tsx',
status: 'complete',
duration: '30ms',
},
{
name: 'edit',
target: 'src/components/DataGrid.tsx',
status: 'complete',
duration: '85ms',
additions: 24,
deletions: 8,
},
{
name: 'edit',
target: 'src/components/DataGrid.test.tsx',
status: 'complete',
duration: '60ms',
additions: 45,
},
]}
/>
</XDSStack>
);
}
ChatToolCalls — StatusesAll four status states — pending, running, complete, and error — shown together in a single group.
tsx
'use client';
import {XDSChatToolCalls} from '@xds/core/Chat';
export default function ChatToolCallsStatuses() {
return (
<XDSChatToolCalls
defaultIsExpanded
calls={[
{
key: 'pending',
name: 'bash',
target: 'yarn build',
status: 'pending',
},
{
key: 'running',
name: 'bash',
target: 'yarn test',
status: 'running',
},
{
key: 'complete',
name: 'edit',
target: 'src/App.tsx',
status: 'complete',
duration: '120ms',
additions: 8,
deletions: 2,
},
{
key: 'error',
name: 'bash',
target: 'yarn lint',
status: 'error',
duration: '0.8s',
errorMessage: '3 lint errors found',
},
]}
/>
);
}

Showcase source

tsx
'use client';
import {XDSChatToolCalls} from '@xds/core/Chat';
export default function ChatToolCallsShowcase() {
return (
<XDSChatToolCalls
defaultIsExpanded
calls={[
{
name: 'bash',
target: 'git diff --stat',
status: 'complete',
duration: '340ms',
},
{
name: 'read',
target: 'src/utils/formatDate.ts',
status: 'complete',
duration: '45ms',
},
{
name: 'edit',
target: 'src/utils/formatDate.ts',
status: 'complete',
duration: '120ms',
additions: 12,
deletions: 3,
},
]}
/>
);
}