Tool Call
betaOne tool invocation: name and icon, queued/running/done/failed/awaiting-approval status, live elapsed time and collapsible JSON args and result.
Finished call
minimal
read_file Completed
Arguments
Result
Live lifecycle
pending → running (shimmer + timer) → success with a JSON result; controlled open state.
full
search_web Queued
Arguments
All states
Queued, running, done and failed.
state
list_files Queued
Arguments
run_tests Running
Arguments
read_file Completed
Arguments
Result
deploy_preview Failed
Arguments
Error: build failed — Type error in message.tsx:295
Inline
A compact row inside answer text.
variant
I checked the docs before answering:
fetch_url Completed
Arguments
Result
The hook drops the optimistic value automatically when the action throws.
Awaiting approval
Approve/Deny Buttons in the actions footer resolve the call.
composition
run_command Waiting for approval
Arguments
Installation
npx shadcn@latest add https://kuro.abstergo.fyi/r/tool-call.jsonCopies the source into components/kura/tool-call with its dependencies (kura-theme, code-block, shimmer-text, use-controllable-state, utils). Tokens come from the kura-theme item.
When to use it
Use it for
- Show a function/tool call an LLM made (AI SDK tool parts, MCP calls, OpenAI/Anthropic tool_use blocks) inside an assistant message.
- Show a tool's progress with a live timer, then its result or error.
- A tool that needs the user's go-ahead: status="awaiting-approval" with Approve/Deny buttons in `actions`.
- Compact inline mentions of tool use within answer text (variant="inline").
Reach for something else when
- A multi-step plan with many steps and progress — use agent-timeline (put ToolCalls inside steps if needed).
- A dedicated, prominent permission request with risk level and keyboard shortcuts — use approval-prompt.
- Plain code output — use code-block.
- Model thinking — use reasoning.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| name* | string | — | Tool identifier, e.g. "search_web". Rendered in mono when no `title` is given; also used in the status announcement. |
| title | React.ReactNode | — | Human label, e.g. "Searching the web" → "Searched the web". Replaces `name` visually. |
| icon | React.ReactNode | — | Tool icon (lucide), e.g. <Globe />. Default a wrench. |
| status | "pending" | "running" | "success" | "error" | "awaiting-approval" | "running" | Lifecycle. pending = hollow ring; running = jade pulse + shimmering title + ticking timer; success = check; error = cross (details open by default); awaiting-approval = jade hand. |
| args | unknown | — | Arguments. Objects are pretty-printed JSON with syntax tint (CodeBlock); strings render as-is. |
| result | unknown | — | Output. Objects are pretty-printed JSON; strings render as-is. Long values collapse at 220px with “Show N more lines”. |
| error | React.ReactNode | — | Error message for status="error", shown in a danger panel in the details. |
| summary | React.ReactNode | — | One-line summary next to the title (truncated). Default: the first primitive value in `args`. Pass null to hide. |
| startedAt | Date | number | — | Start time for the live timer (e.g. from the server). Default: when status became running. |
| duration | number | — | Final duration in ms (persisted calls). Default: measured from running → success/error. |
| variant | "card" | "inline" | "card" | card = bordered card; inline = compact borderless row for use inside message text. |
| open | boolean | — | Details expanded (controlled). |
| defaultOpen | boolean | — | Initial expanded state when uncontrolled. Default true for "error" and "awaiting-approval". |
| onOpenChange | (open: boolean) => void | — | Called when details are toggled. |
| actions | React.ReactNode | — | Always-visible footer row (right-aligned), e.g. Deny / Approve buttons. |
All native attributes of the root element, className and ref pass through.
Anatomy
- ToolCall`data-status`, `data-variant`, `data-state="open" | "closed"` (when it has details).
data-slot="tool-call" - TriggerHeader row; a button with aria-expanded when there are details.
data-slot="tool-call-trigger" - Status20px status glyph (aria-hidden).
data-slot="tool-call-status" - IconTool icon (aria-hidden).
data-slot="tool-call-icon" - TitleTitle or mono name; shimmers while running.
data-slot="tool-call-title" - SummaryTruncated one-line summary.
data-slot="tool-call-summary" - ElapsedMono tabular duration: 180ms, 1.5s, 1m 5s.
data-slot="tool-call-elapsed" - DetailsCollapsible args/error/result (grid-rows transition, inert when closed).
data-slot="tool-call-details" - Section“Arguments” / “Result” label + headerless CodeBlock.
data-slot="tool-call-section" - ErrorDanger panel with the error message.
data-slot="tool-call-error" - ActionsFooter for `actions`.
data-slot="tool-call-actions"
Accessibility
- The header is a button (aria-expanded/aria-controls) only when there is something to expand.
- Each call has a polite status region (“search_web Running” → “search_web Completed”); the ticking timer is not announced.
- Status is conveyed by text for screen readers, not only by colour/icon.
- Collapsed details are inert; JSON panes are keyboard-scrollable regions named “Arguments code” / “Result code”.
- Reduced motion: The running pulse and title shimmer stop; the chevron and details change without travel (fade only).
| Keys | Action |
|---|---|
| Enter / Space | Expand or collapse the details |
| Tab | Into the JSON panes and footer actions |
Notes for agents
- Map AI SDK tool part states: input-streaming → pending, input-available → running, output-available → success, output-error → error.
- Keep the same ToolCall mounted across states so the measured timer works; for history, pass `duration` (ms).
- Swap `title` between present and past tense (“Searching…” → “Searched the web”) as the status changes.
- args/result accept any JSON-serializable value; circular objects fall back to String().