---
title: "useRenderTool"
description: "Register typed renderers for tool calls, by tool name or wildcard"
---

## Overview

`useRenderTool` registers a chat renderer for tool calls.
You can target a specific tool name (with a typed Zod `parameters` schema) or use a wildcard (`"*"`) fallback renderer.

This is part of the v2 tool rendering hook set with [`useComponent`](/reference/hooks/useComponent), [`useDefaultRenderTool`](/reference/hooks/useDefaultRenderTool), and [`useRenderToolCall`](/reference/hooks/useRenderToolCall).

This hook only handles rendering. It does not register a frontend handler.

## Signature

### Wildcard overload

```tsx
import { useRenderTool } from "@copilotkit/react-core/v2";

useRenderTool(
  {
    name: "*",
    render: (props) => React.ReactElement,
    agentId?: string,
  },
  deps?: ReadonlyArray<unknown>,
);
```

### Named overload

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

useRenderTool(
  {
    name: string,
    parameters: z.ZodTypeAny,
    render: (props) => React.ReactElement,
    agentId?: string,
  },
  deps?: ReadonlyArray<unknown>,
);
```

## Render Props

`render` receives one of these states:

- `{ status: "inProgress", parameters: Partial<T>, result: undefined }`
- `{ status: "executing", parameters: T, result: undefined }`
- `{ status: "complete", parameters: T, result: string }`

`name` is always present in all states.

## Behavior

- Builds a renderer entry with `defineToolCallRenderer`.
- Deduplicates by `agentId:name` key (latest registration wins).
- Intentionally does not remove the renderer on cleanup so previous chat history can still render.
- Tracks updates by `config.name` plus values in `deps` (include changing captures in `deps`).

## Usage

### Named tool renderer

```tsx
function App() {
  useRenderTool(
    {
      name: "searchDocs",
      parameters: z.object({ query: z.string() }),
      render: ({ name, parameters, status, result }) => {
        if (status === "inProgress") return <div>Preparing {name}…</div>;
        if (status === "executing")
          return <div>Searching for: {parameters.query}</div>;
        return <div>Done: {result}</div>;
      },
    },
    [],
  );

  return null;
}
```

### Wildcard fallback renderer

```tsx
function App() {
  useRenderTool(
    {
      name: "*",
      render: ({ name, status }) => (
        <div>
          {status === "complete" ? "✓" : "⏳"} {name}
        </div>
      ),
    },
    [],
  );

  return null;
}
```

## Related

- [`useDefaultRenderTool`](/reference/hooks/useDefaultRenderTool)
- [`useRenderToolCall`](/reference/hooks/useRenderToolCall)
- [`useFrontendTool`](/reference/hooks/useFrontendTool)
