Skip to content

Tool Calls ​

Visualize AI tool calls in your chat UI.

New in 0.4.0

A tool call that the turn paused on (an open approval or question) shows a clock instead of the tick of a finished call, also after a reload. Approving or answering is covered in Approvals and Questions.

Overview ​

When an agent uses tools, Chat UI shows what it is doing, step by step:

  • the latest step prominently, with a spinner while the tool runs, a tick when it finished and a clock when it waits for you;
  • the earlier steps of the turn folded behind "N previous steps" (with the turn's duration), which expands to a compact list;
  • the label of a step is the model's reasoning if the server sends one, else the tool's displayName, else the tool's name prettified (get_weather becomes "Get Weather").

Arguments and results are not drawn in the transcript; they reach your code through the callbacks below, and approval cards show the arguments of a call that needs a decision (under "Details").

Default Tool Call Display ​

Tool calls are displayed automatically, live while the turn runs and from the stored message afterwards:

tsx
<Chat
  baseUrl="/api/agents"
  agentId="assistant"
/>

A finished message carries its calls in metadata.toolCallDetails ({ id, name, args, result?, reasoning?, displayName? }[]) and, optionally, metadata.toolCallDurationSeconds:

tsx
<ChatMessage
  message={{
    ...message,
    metadata: {
      toolCallDetails: [{ id: "call_1", name: "get_weather", args: { location: "New York" }, result: { temperature: 72 } }],
      toolCallDurationSeconds: 2,
    },
  }}
/>

Tool Call Callbacks ​

Track tool calls programmatically:

tsx
<Chat
  baseUrl="/api/agents"
  agentId="assistant"
  onToolCall={(toolName, args) => {
    console.log("Tool called:", toolName);
    console.log("Arguments:", args);

    // Analytics, logging, etc.
    analytics.track("tool_call", { tool: toolName });
  }}
  onToolResult={(toolName, result) => {
    console.log("Tool result:", toolName);
    console.log("Result:", result);
  }}
/>

ToolCall Component ​

Use the built-in components directly:

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

// A single call
<ToolCall
  toolName="get_weather"
  toolCallId="call_123"
  args={{ location: "NYC" }}
  result={{ temperature: 72 }}
/>

// Several calls: the last is the latest step, the rest fold
<ToolCalls
  toolCalls={[
    { id: "1", name: "search", args: { query: "..." }, result: { results: [] } },
    { id: "2", name: "calculate", args: { expression: "..." } },
  ]}
  isExecuting={false}
  durationSeconds={3}
/>

See ToolCall for every prop.

Tools that wait for you ​

When a call is paused on an approval or a question, its row shows a clock labelled "Waiting for your answer". The row is marked as long as the card is open; once the card has an outcome (answered, cancelled, expired) it goes back to a normal step. A conversation opened again after a reload keeps the cards but not the calls, so a row is made for each open card (callsWithOpenActions) and marked the same way. In your own layout: ToolCalls takes waitingIds (waitingToolCallIds(message, calls) computes it).

Active Tool Calls ​

Track in-progress tool calls in a custom layout:

tsx
import { useChat } from "@cognipeer/chat-ui";

function CustomChat() {
  const { activeToolCalls } = useChat({
    baseUrl: "/api/agents",
    agentId: "assistant",
  });

  // activeToolCalls is a Map<string, { name, args, result?, reasoning?, displayName? }>

  return (
    <div>
      {activeToolCalls.size > 0 && (
        <div className="active-tools">
          Running: {Array.from(activeToolCalls.values()).map((t) => t.name).join(", ")}
        </div>
      )}
    </div>
  );
}

ChatMessageList draws activeToolCalls for you while the turn runs and no text has streamed yet; once text arrives the steps move to the message when it is stored.

Styling Tool Calls ​

Tool rows use the theme variables (--chat-accent-primary for the spinner and tick, --chat-warning for the waiting clock, --chat-text-secondary / --chat-text-tertiary for labels), so changing colours through themeColors restyles them. See Theming.

Next Steps ​

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