Tool call

Free · MIT

Collapsible 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.

MarkdownOpen in v0
Open in v0

Installation

$ npx shadcn@latest add https://goodui.dev/r/tool-call.json

The 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

Use it for
  • 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.
Reach for something else
  • 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 needUse
Standalone cardvariant="card" (default)
Quiet row inside a chat messagevariant="inline"
Known duration from the APIduration (ms); otherwise it is measured while status is running
Start expandeddefaultOpen, 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

PropTypeDefault
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—
openboolean—
defaultOpenbooleanfalse
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 / SpaceToggles the body on the header button.
TabMoves 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