Tool call
Free · MITCollapsible card for an agent's tool call: name and arguments in the header, a status that morphs from spinner to drawn check or error, a live duration while running, and argument and output panes inside.
Installation
$ npx shadcn@latest add https://goodui.dev/r/tool-call.jsonThe file lands in components/goodui/tool-call.tsx and is yours to edit. With the @goodui registry added, npx shadcn@latest add @goodui/tool-call works too.
Usage
import { ToolCall } from "@/components/goodui/tool-call"
<ToolCall
name="search_bookings"
args={{ client: "Maya Chen", range: "last 90 days" }}
status={call.status} // "pending" | "running" | "success" | "error"
output={call.result} // string renders in a monospace pane
error={call.error}
/>When to use
- Showing what an agent did: each function or MCP tool call with its arguments, a live status and the result.
- Long-running calls where the user wants to see progress (duration ticks while running).
- Failures the user should read, with the error message in a rose pane.
- A whole multi-step plan with nesting and overall progress: use agent-plan.
- Model reasoning rather than external calls: use reasoning-block.
- Logs with hundreds of entries: a virtualized list; this card is for a handful of calls per message.
| If you need | Use |
|---|---|
| Standalone card | variant="card" (default) |
| Quiet row inside a chat message | variant="inline" |
| Known duration from the API | duration (ms); otherwise it is measured while status is running |
| Start expanded | defaultOpen, or open/onOpenChange to control it |
Examples
Inline rows under an answer
<ToolCall variant="inline" name="get_client" args={{ id: "cl_2291" }} status="success" duration={312} output={json} />
<ToolCall variant="inline" name="read_policy" title="Reading the cancellation policy" args="deposits.md" status="success" duration={88} />Custom icon and a React node as output
<ToolCall name="find_free_slot" icon={<Calendar />} status="success" output={<SlotCard slot={slot} />} defaultOpen />API reference
| Prop | Type | Default |
|---|---|---|
| name* Tool name, shown in monospace. | string | — |
| title Friendlier text shown instead of the name. | React.ReactNode | — |
| args Arguments as an object (rendered as a key/value grid) or a preformatted string. | Record<string, unknown> | string | — |
| status | "pending" | "running" | "success" | "error" | "pending" |
| output Result; strings render in a scrollable monospace pane, nodes as-is. | React.ReactNode | — |
| error Error message shown in the body when status is "error". | string | — |
| duration Duration in ms. When omitted it is measured from the moment status becomes "running". | number | — |
| open | boolean | — |
| defaultOpen | boolean | false |
| onOpenChange | (open: boolean) => void | — |
| icon Replaces the wrench icon. | React.ReactNode | — |
| variant card: bordered; inline: a quiet row for inside a message. | "card" | "inline" | "card" |
| labels Text for built-in controls and screen readers; pass translations here. | Partial<ToolCallLabels> | — |
Also accepts every <div> attribute.
Accessibility
| Enter / Space | Toggles the body on the header button. |
| Tab | Moves through the header; the body contains no controls unless your output has them. |
- The header is a <button> with aria-expanded and aria-controls pointing at the body.
- The status is announced as text (Waiting, Running, Done, Failed) through a visually hidden span; the icons are decorative.
- The error pane is prefixed with a hidden "Error:" label. Section titles (Arguments, Output) are headings.
- Built-in strings go through the labels prop for translation.
Motion
- Status icons swap on a spring (stiffness 520, damping 26): dashed circle, spinner, a check whose stroke draws in over 0.3 s, or a rose X.
- While running, a thin light sweeps along the bottom edge of the header and the duration ticks every 100 ms.
- The body opens to its real height on a spring (stiffness 420, damping 36).
- Reduced motion: the spinner slows to 2 s per turn, the sweep is removed, the check does not draw and the body toggles instantly.
Notes for AI
Coding agents read these rules through MCP and llms.txt, or paste this page with Copy page.
- Drive status from your agent events: pending → running → success | error. Pass output only once you have it.
- args accepts an object (rendered as key: value rows and previewed in the header) or a preformatted string.
- duration is in milliseconds; omit it to show the measured time from when status became running.
- title replaces the monospace name with friendlier text; name is still used for the preview semantics.
FAQ
Can the output be more than text?
Yes. Strings render in a scrollable monospace pane; any other React node renders as-is.
What if a call has no arguments or output?
The header still works; the chevron and body are omitted when there is nothing to show.
Related
Live checklist of an agent's plan: pending, active with a pulsing halo, drawn check, error and skipped states, nested substeps that fold away when done, and a spring progress bar with a step count.
"Thinking 8.7s" disclosure with a live tenths timer, a shimmering label while the model reasons, the current step previewed under the header and the full step list plus notes folded inside.
User, assistant and system messages with avatars, grouping, a hover actions row (copy, good/bad, retry, edit), markdown-ish rendering of lists, quotes and fenced code into CodeBlocks, and a blinking caret while the answer streams.
Syntax-colored code from a built-in tokenizer or your own tokens, with theme-derived colors, line numbers, highlighted lines, a file tab, copy with a drawn check, a wrap toggle and a staggered line entrance.