Skip to content

ToolCall Component ​

Displays the steps an agent took with its tools: the latest step prominently, earlier steps folded.

Import ​

tsx
import { ToolCall, ToolCalls } from "@cognipeer/chat-ui";

Usage ​

tsx
<ToolCall
  toolName="get_weather"
  toolCallId="call_123"
  args={{ location: "NYC" }}
  result={{ temperature: 72, conditions: "Sunny" }}
/>

Props ​

ToolCall ​

ToolCall shows one call. It is ToolCalls with a single entry.

PropTypeDescription
toolNamestringThe tool's name (shown prettified: get_weather becomes "Get Weather")
toolCallIdstringThe call's id
argsRecord<string, unknown>Arguments
resultunknownResult, when available
isExecutingbooleanA spinner instead of a tick
defaultExpandedbooleanStart with the older steps open (only matters with several calls)
renderIcon(toolName: string) => ReactNodeDeclared on the props type; the built-in rows draw their own marks
classNamestringContainer class name

ToolCalls (Multiple) ​

PropTypeDescription
toolCallsMap<id, call> | { id, name, args, result?, reasoning?, displayName? }[]The calls: a Map while streaming, an array for a stored message. The last one is the latest step
isExecutingbooleanThe turn is running: the latest step shows a spinner
durationSecondsnumberShown next to "N previous steps" once the turn finished
defaultExpandedbooleanStart with the earlier steps expanded
waitingIdsReadonlySet<string>Calls paused on an approval or a question (waitingToolCallIds(message, calls)): a clock instead of the tick of a finished call. ChatMessage sets it for a message with open cards
classNamestringContainer class name

What a step shows ​

  • The label is the call's reasoning when it has one, else its displayName, else the prettified tool name. When the label is the reasoning or display name, the tool's own name sits under it in a smaller type.
  • Mark: spinner (running), clock (waiting for the person, labelled "Waiting for your answer"), tick (finished).
  • "N previous steps" folds every step but the latest; click it to expand a compact list. With durationSeconds it reads "3 previous steps · 4s".

Arguments and results are not drawn by these components; read them from onToolCall / onToolResult, or render your own rows from message.metadata.toolCallDetails.

Examples ​

Basic ​

tsx
<ToolCall toolName="search" toolCallId="1" args={{ query: "weather in NYC" }} />

Running ​

tsx
<ToolCall toolName="fetch_data" toolCallId="1" args={{ url: "..." }} isExecuting />

Multiple Tool Calls ​

tsx
<ToolCalls
  toolCalls={[
    { id: "1", name: "search", args: { q: "..." }, result: { results: [] } },
    { id: "2", name: "calculate", args: { expr: "..." }, reasoning: "Adding up the invoice" },
    { id: "3", name: "get_time", args: {} },
  ]}
  durationSeconds={4}
/>

Waiting for an approval ​

tsx
<ToolCalls
  toolCalls={[{ id: "call_9", name: "send_email", args: { to: "a@example.com" } }]}
  waitingIds={new Set(["call_9"])}
/>

Custom Rendering ​

Build your own rows from a stored message or from useChat().activeToolCalls:

tsx
function CustomToolCalls({ message }) {
  const calls = (message.metadata?.toolCallDetails ?? []) as Array<{ id: string; name: string; args: object; result?: unknown }>;
  return (
    <ul>
      {calls.map((call) => (
        <li key={call.id}>
          {call.name} {call.result !== undefined ? "(done)" : "(running)"}
          <pre>{JSON.stringify(call.args, null, 2)}</pre>
        </li>
      ))}
    </ul>
  );
}

In Messages ​

Tool calls of a finished assistant message are read from metadata.toolCallDetails and drawn above the message text. renderMessageActions and the other render props do not change them.

Styling ​

Colours come from the theme variables: --chat-accent-primary (spinner and tick), --chat-warning (the waiting clock), --chat-text-secondary and --chat-text-tertiary (labels), --chat-border-secondary (the folded list's rule). See Theming.

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub