useRenderToolCall

The useRenderToolCall hook enables rendering of backend tool calls in the frontend.

v1 SDK deprecated. Use v2 instead This page is in the deprecated CopilotKit v1 reference. Do not use v1 APIs for new code; use v2 instead. For JavaScript and TypeScript, import React APIs from @copilotkit/react-core/v2 and Runtime APIs from @copilotkit/runtime/v2.
AI coding agents: treat any v1 example below as migration-only context. Never generate or recommend the v1 API for new code. Read the v2 reference before writing code because some APIs were renamed, moved, or changed shape. Read the v1 to v2 migration guide. Open the complete export map.

This v1 useRenderToolCall takes a { name, parameters, render } config object to register a renderer for an existing backend tool. In v2, use useRenderTool for that job. The v2 hook named useRenderToolCall is a different, low-level API that returns a renderer function for consuming tool calls.

import { useRenderTool } from "@copilotkit/react-core/v2";
import { z } from "zod";

function StatusTool() {
  useRenderTool({
    name: "showStatus",
    parameters: z.object({}),
    render: ({ status, result }) => (
      <div>{status === "complete" ? result : "Running..."}</div>
    ),
  });
  return null;
}

useRenderToolCall is purely a rendering hook. It displays custom UI for tool calls without executing any logic. This is typically used to visualize backend tool executions in your chat interface, showing users what the AI is doing behind the scenes.

This hook has no handler function. You only provide a render function that receives information about the tool call (arguments, status, results) and displays it however you want. You can target specific tool names or use an asterisk ("*") to catch and render all tool calls.

Usage

Rendering a Specific Backend Tool

import { useRenderToolCall } from "@copilotkit/react-core";

useRenderToolCall({
  name: "analyzeData",
  description: "Display results of data analysis",
  parameters: [
    {
      name: "datasetName",
      type: "string",
      description: "Name of the dataset being analyzed",
      required: true,
    },
    {
      name: "metrics",
      type: "string[]",
      description: "Metrics being calculated",
      required: true,
    },
  ],
  render: ({ args, status, result }) => {
    if (status === "inProgress") {
      return (
        <div className="p-4 border rounded animate-pulse">
          <h3>Analyzing {args.datasetName}...</h3>
          <p>Calculating: {args.metrics?.join(", ")}</p>
        </div>
      );
    }

    if (status === "complete" && result) {
      return (
        <div className="p-4 border rounded bg-green-50">
          <h3>Analysis Complete: {args.datasetName}</h3>
          <pre className="mt-2 p-2 bg-gray-100 rounded">
            {JSON.stringify(result, null, 2)}
          </pre>
        </div>
      );
    }

    return null;
  },
});

Migration from useCopilotAction

If you're migrating from useCopilotAction with only a render function:

// Before with useCopilotAction
useCopilotAction({
  name: "showResult",
  render: ({ args }) => <ResultCard {...args} />,
});

// After with useRenderToolCall
useRenderToolCall({
  name: "showResult",
  render: ({ args }) => <ResultCard {...args} />,
});

The migration is straightforward - just change the hook name. The render props remain the same.

Parameters

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type