Xzero UI
Pro library

Tool callPro

A tool call row for agent transcripts: the tool's mark and the call in plain words, a live state while it runs, and the input and output a click away, with approval and retry when needed.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/tool-call
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/tool-call

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { ToolCall, ToolCallGroup } from "@/components/xzero/tool-call/tool-call";

// One call on its own
<ToolCall
  tool="github"
  title="Searched issues in xzero-ui/web"
  titles={{ running: "Searching issues in xzero-ui/web" }}
  status="success"
  input={{ repo: "xzero-ui/web", query: "is:open label:release-blocker" }}
  output={{ type: "list", items: [{ lead: "#1284", title: "Checkout button stays disabled after a coupon is removed", tag: "checkout" }] }}
  durationMs={1180}
/>

// Every call from one assistant turn, wired to your agent loop
export function ToolCalls({ calls, working, agent }) {
  return (
    <ToolCallGroup
      calls={calls}
      active={working}
      onApprove={call => agent.approve(call.id)}
      onDeny={call => agent.deny(call.id)}
      onRetry={call => agent.retry(call.id)}
    />
  );
}

API reference

ToolCall

One inline tool call for an agent or chat transcript: the tool's mark, a verb phrase, quiet meta and a status icon. Clicking the row springs it open into Input (the arguments) and Output (a readable result), each with a copy button. Awaiting approval it shows inline Allow and Deny; on an error it shows the reason and Retry. With no props it renders a sample GitHub search.

PropTypeDefaultDescription
idstring–Stable id for the call. A group uses it as the React key, so a call that changes status keeps its row and its open state.
tool"github" | "linear" | "postgres" | "slack" | "gmail" | "web" | { name: string; mark: ReactNode }–Which tool ran. The built in ids draw the real brand mark (web draws a globe for web search); a custom tool passes its own name and a 16px mark.
titlestring–The settled verb phrase, such as "Searched issues in xzero-ui/web". Keep it to one line; it truncates.
titlesPartial<Record<ToolCallStatus, string>>–Phrasing per status, such as { running: "Searching issues in xzero-ui/web", approval: "Post a summary to #release" }. Falls back to title.
status"running" | "success" | "error" | "approval" | "denied"–Running shimmers the title with a spinner; success shows a check, the summary and the duration; error shows the reason and Retry; approval shows Allow and Deny on an accent outline; denied shows that the call never ran.
inputRecord<string, ToolCallValue>–The arguments the model passed, shown as a mono key and value list with a copy button.
output{ type: "list"; items } | { type: "table"; columns; rows } | { type: "json"; value } | { type: "text"; text }–What came back. Lists show a number, a title and a tag per row; tables and JSON (with a syntax tint) fold after five rows or ten lines behind "Show 18 more lines". Copy gives JSON, lines or tab separated rows.
summarystring–Quiet meta before the duration, such as "4 results". Derived from the output when left out (results, rows, fields).
messagestring–One line under the title: the error reason, or what allowing the call will do.
durationMsnumber–How long the call took, shown as 640ms or 1.2s with tabular numerals. The group header shows the total.
defaultOpenbooleanfalseOpens the Input and Output panel on first render.
openboolean–Controls the panel. Pair with onOpenChange.
onOpenChange(open: boolean) => void–Called when the row is opened or closed.
onApprove() => void–Allow on a call awaiting approval. Update status yourself (usually to running, then success). Without it the preview simulates the call and says so to assistive technology.
onDeny() => void–Deny on a call awaiting approval. Without it the call is marked denied locally.
onRetry() => void–Retry on a failed call. Without it the preview simulates a successful retry.
renderOutput(call: ToolCallData) => ReactNode | undefined–Draws a custom result for a successful call inside the Output well, such as a chart or a file preview. Return undefined to fall back to the built in view.
classNamestring–Class on the call's outer element.

ToolCallGroup

Several calls from one assistant turn under a quiet header, "Used 4 tools", with an overlapping stack of the tools' marks and the total duration. Opening it staggers the rows in; while the agent works the header reads "Using 3 tools" with a shimmer. A call that needs a decision opens a closed group, and the group folds itself away once every call has finished unless the person has opened or closed anything.

PropTypeDefaultDescription
callsToolCallData[]four settled sample callsThe calls in order, each with id, tool, title, status and optional titles, input, output, summary, message and durationMs. Append to the array as the agent starts new calls; each new row grows in.
activebooleanany call runningThe agent is still working in this turn, so the header keeps saying "Using" between calls instead of flickering to "Used".
defaultOpenbooleanopen while any call is running, waiting or failedWhether the list is open on first render. A finished transcript starts folded.
openboolean–Controls the list. Pair with onOpenChange. Calls that need a decision only open the group on their own when it is uncontrolled.
onOpenChange(open: boolean) => void–Called when the header is toggled or the group folds itself.
autoCollapsebooleantrueFolds the list 450ms after every call has finished, so the answer reads right under "Used 4 tools". Skipped once the person has opened or closed the group or any row.
onApprove(call: ToolCallData) => void–Allow on a call awaiting approval.
onDeny(call: ToolCallData) => void–Deny on a call awaiting approval.
onRetry(call: ToolCallData) => void–Retry on a failed call.
renderOutput(call: ToolCallData) => ReactNode | undefined–Custom result renderer applied to every successful call in the group.
classNamestring–Class on the group's outer element.

ToolCallData

The shape of one call, shared by ToolCall props and ToolCallGroup calls.

PropTypeDefaultDescription
id (required)string–Stable id for the call. A group uses it as the React key, so a call that changes status keeps its row and its open state.
tool (required)"github" | "linear" | "postgres" | "slack" | "gmail" | "web" | { name: string; mark: ReactNode }–Which tool ran. The built in ids draw the real brand mark (web draws a globe for web search); a custom tool passes its own name and a 16px mark.
title (required)string–The settled verb phrase, such as "Searched issues in xzero-ui/web". Keep it to one line; it truncates.
titlesPartial<Record<ToolCallStatus, string>>–Phrasing per status, such as { running: "Searching issues in xzero-ui/web", approval: "Post a summary to #release" }. Falls back to title.
status (required)"running" | "success" | "error" | "approval" | "denied"–Running shimmers the title with a spinner; success shows a check, the summary and the duration; error shows the reason and Retry; approval shows Allow and Deny on an accent outline; denied shows that the call never ran.
inputRecord<string, ToolCallValue>–The arguments the model passed, shown as a mono key and value list with a copy button.
output{ type: "list"; items } | { type: "table"; columns; rows } | { type: "json"; value } | { type: "text"; text }–What came back. Lists show a number, a title and a tag per row; tables and JSON (with a syntax tint) fold after five rows or ten lines behind "Show 18 more lines". Copy gives JSON, lines or tab separated rows.
summarystring–Quiet meta before the duration, such as "4 results". Derived from the output when left out (results, rows, fields).
messagestring–One line under the title: the error reason, or what allowing the call will do.
durationMsnumber–How long the call took, shown as 640ms or 1.2s with tabular numerals. The group header shows the total.

Keyboard interactions

KeysAction
TabMoves through the group header, each call row, a row's Allow, Deny or Retry buttons, and inside an open row its copy buttons and the show more control.
Enter, SpaceOn the group header, opens or closes the list. On a call row, opens or closes Input and Output. On Allow, Deny, Retry, copy and show more, activates them.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in ai

Guidance for AI tools

Tool call: A tool call row for agent transcripts: the tool's mark and the call in plain words, a live state while it runs, and the input and output a click away, with approval and retry when needed. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components