Join our Discord Community

React AI Tool

Collapsible tool execution display with status tracking. Build transparent AI tool calls with React, Next.js, and TypeScript, featuring expandable parameters, results, and error states for shadcn/ui applications.

Trying to implement AI Elements?

Join our Discord community for help from other developers.


Collapsible tool execution display with status tracking for AI function calls using React, Next.js, and TypeScript. Tool calls without visibility are sketchy. Users want to see what APIs the AI is hitting and with what parameters, especially when things go wrong. This free open source shadcn/ui component provides transparent AI tool calls for your conversational AI applications using Vercel AI SDK in JavaScript frameworks.

Tool execution with status

Collapsible tool call with parameters and results:

Loading component...

The React component provides expandable tool containers, status badges (pending, running, completed, error), parameter display with JSON formatting, and result/error handling. Built with TypeScript for type safety and designed for seamless integration in your JavaScript projects.

Installation

npx shadcn@latest add https://www.shadcn.io/registry/ai.json
npx shadcn@latest add https://www.shadcn.io/registry/ai.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/ai.json
bunx shadcn@latest add https://www.shadcn.io/registry/ai.json

Usage

import {
  Tool,
  ToolHeader,
  ToolContent,
  ToolInput,
  ToolOutput,
} from "@/components/ai/tool";

<Tool>
  <ToolHeader type="web_search" state="output-available" />
  <ToolContent>
    <ToolInput input={{ query: "Latest AI news", limit: 10 }} />
    <ToolOutput output="Search results..." />
  </ToolContent>
</Tool>;

Why not just log tool calls to console?

Console logging is for developers, not users in React applications. Plus users can't see console output in production. When your AI calls 5 different APIs to answer one question in Next.js projects, users deserve to know what's happening.

Status indicators prevent panic in TypeScript components. "Searching web..." tells users the 10-second delay is normal, not a crash. Failed tools need clear error messages so users understand what broke in JavaScript implementations.

Usage with AI SDK

Display tool calls from AI models in React applications:

"use client";

import {
  Tool,
  ToolHeader,
  ToolContent,
  ToolInput,
  ToolOutput,
} from "@/components/ai/tool";
import { Response } from "@/components/ai/response";
import { useChat } from "@ai-sdk/react";
import { Button } from "@/components/ui/button";
import { useState } from "react";

export default function ToolDemo() {
  const [input, setInput] = useState("");
  const { messages, append, status } = useChat({
    api: "/api/tools",
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (input.trim()) {
      append({ role: "user", content: input });
      setInput("");
    }
  };

  // Find tool calls in messages
  const toolCalls = messages.flatMap(
    (msg) => msg.parts?.filter((part) => part.type?.startsWith("tool-")) || []
  );

  return (
    <div className="space-y-4 max-w-3xl mx-auto p-6">
      <form onSubmit={handleSubmit} className="flex gap-2">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Ask me to search, calculate, or fetch data..."
          className="flex-1 px-3 py-2 border rounded-lg"
        />
        <Button type="submit" disabled={status === "streaming"}>
          Send
        </Button>
      </form>

      <div className="space-y-3">
        {toolCalls.map((tool, index) => (
          <Tool key={index} defaultOpen={tool.state === "output-available"}>
            <ToolHeader type={tool.type} state={tool.state} />
            <ToolContent>
              <ToolInput input={tool.input} />
              {tool.state === "output-available" && (
                <ToolOutput
                  output={<Response>{tool.output}</Response>}
                  errorText={tool.errorText}
                />
              )}
            </ToolContent>
          </Tool>
        ))}
      </div>
    </div>
  );
}

Backend route with tool definitions:

// app/api/tools/route.ts
import { streamText, convertToModelMessages } from "ai";
import { z } from "zod";

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: "openai/gpt-4o",
    messages: convertToModelMessages(messages),
    tools: {
      calculate: {
        description: "Perform mathematical calculations",
        parameters: z.object({
          expression: z.string().describe("Math expression to evaluate"),
        }),
        execute: async ({ expression }) => {
          // Simulate calculation
          const result = eval(expression); // Use a safe math parser in production
          return { expression, result };
        },
      },
      web_search: {
        description: "Search the web for information",
        parameters: z.object({
          query: z.string().describe("Search query"),
          limit: z.number().default(5).describe("Number of results"),
        }),
        execute: async ({ query, limit }) => {
          // Simulate web search
          await new Promise((resolve) => setTimeout(resolve, 1000));
          return {
            query,
            results: `Found ${limit} results for "${query}"`,
          };
        },
      },
    },
  });

  return result.toUIMessageStreamResponse();
}

Examples

Tool with streaming input

Tool receiving parameters in real-time:

Loading component...

Tool with error state

Failed tool execution with error display:

Loading component...

Multiple tool calls

Sequential tool executions in a workflow:

Loading component...

Features

  • Collapsible containers with smooth Radix UI animations in React applications
  • Visual status badges (pending, running, completed, error) for TypeScript components
  • JSON-formatted parameter display with syntax highlighting in JavaScript frameworks
  • Flexible output rendering supporting markdown and custom components for Next.js projects
  • Error state handling with clear error messages
  • Auto-open for completed/errored tools for immediate visibility
  • Keyboard navigation with proper focus management
  • Screen reader accessible with semantic HTML
  • Perfect for AI agents, AI chat applications, and conversational AI function calling
  • Free open source component built for Next.js with shadcn/ui design system and AI Elements
  • Optimized for Vercel AI SDK streaming and function calling

API Reference

Tool

Container component managing collapsible state.

PropTypeDefaultDescription
defaultOpenbooleanfalseInitial expanded state
classNamestring-Additional CSS classes
...propsComponentProps<typeof Collapsible>-Collapsible component props

ToolHeader

Header showing tool name and status badge.

PropTypeDescription
typestringRequired - Tool name/type
state"input-streaming" | "input-available" | "output-available" | "output-error"Required - Execution state
classNamestringAdditional CSS classes
...propsComponentProps<typeof CollapsibleTrigger>Trigger props

ToolContent

Container for tool parameters and results.

PropTypeDescription
classNamestringAdditional CSS classes
...propsComponentProps<typeof CollapsibleContent>Content props

ToolInput

Display for tool input parameters.

PropTypeDescription
inputanyRequired - Tool parameters (displayed as JSON)
classNamestringAdditional CSS classes
...propsComponentProps<'div'>Standard div attributes

ToolOutput

Display for tool results or errors.

PropTypeDescription
outputReactNodeTool execution result
errorTextstringError message if failed
classNamestringAdditional CSS classes
...propsComponentProps<'div'>Standard div attributes

Keyboard interactions

KeyDescription
Space / EnterToggle tool expansion
TabNavigate between tools
EscapeClose expanded tool

Tool execution gotchas that will bite you

Long-running tools freeze the UI: Weather APIs take 3+ seconds, database queries even longer in React applications. Show progress or users think it crashed. "Searching..." beats dead silence in TypeScript components.

JSON parameter formatting breaks: Complex objects get mangled in display in JavaScript implementations. Use proper JSON.stringify with 2-space indentation or your parameters look like garbage in Next.js projects.

Error messages are useless: "Something went wrong" tells users nothing in React applications. Show the actual API error: "Rate limit exceeded, try again in 60 seconds."

Tool result size crashes browsers: Some APIs return 50KB responses in TypeScript components. Truncate after 1000 characters or add pagination. Don't let a Wikipedia API call freeze the page in JavaScript frameworks.

Tool dependencies create confusion: When one tool's output feeds into another, users lose track in React applications. Number them or show the flow visually.

Failed tools disappear: Keep failed tools visible with retry buttons in Next.js projects. Users want to debug what broke, not guess why their query vanished in TypeScript implementations.

Integration with other components

Tool works seamlessly with Response for formatted output in React applications. Use alongside CodeBlock for JSON results in Next.js projects. Combine with Task for multi-step workflows. This free open source component integrates seamlessly with modern JavaScript frameworks.

Questions developers actually ask