You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## What
Updates the v2 `useRenderToolCall` reference page and makes opting a
tool out of the default rendering a single, schema-free call.
## Why
The reference page had drifted out of sync with the hook implementation
(`packages/react-core/src/v2/hooks/use-render-tool-call.tsx`) — most
notably `toolCallId` in the render props, added after the doc was last
touched. While documenting how to opt out of rendering, the natural
example (`useRenderTool({ name: "...", render: () => <></> })`) only
type-checked for the wildcard `"*"`; a named tool required a
`parameters` schema, forcing a throwaway `z.any()`. This PR re-aligns
the doc and removes that rough edge.
## Changes
### Docs (`showcase/shell-docs`)
- `useRenderToolCall.mdx`:
- Document `toolCallId` in the render-prop shape (previously
undocumented).
- Describe agentId-scoped lookup priority: agent-specific → unscoped →
wildcard `"*"` → built-in `DefaultToolCallRenderer`.
- Note args are parsed with `partialJSONParse` (streaming), not strict
`JSON.parse`.
- Correct `toolCall` prop to `toolCall.function.name` /
`toolCall.function.arguments`.
- Rewrite the Status Resolution table to match real logic (`toolMessage`
presence + provider executing set).
- New **"Disable default tool rendering"** section, ordered least→most
specific: wildcard first (all tools), then a **"For specific tools"**
subsection. Both use a schema-free `useRenderTool` call; dropped the old
`useFrontendTool` handler/schema boilerplate.
- `useRenderTool.mdx`: document the render-only (no-schema) named
overload.
### react-core
- Make `parameters` optional on the named `useRenderTool` overload,
mirroring the existing wildcard path; `defineToolCallRenderer` defaults
the args schema to `z.any()` when none is given.
- This lets `useRenderTool({ name: "myTool", render: () => <></> }, [])`
type-check with no Zod schema. Typed `parameters` behavior is unchanged.
- Added a test for the named render-only registration.
## Verification
- `@copilotkit/react-core` tests pass (1280) including the new case;
`build` (tsc) passes.
- Opt-out snippets type-checked in-package (`tsc`): wildcard,
specific-name (no schema), and named-with-schema all compile.
- `oxlint` (shell-docs) passes — 0 errors.
- Previewed locally at `/reference/hooks/useRenderToolCall`.
Copy file name to clipboardExpand all lines: showcase/shell-docs/src/content/reference/hooks/useRenderToolCall.mdx
+46-10Lines changed: 46 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ description: "React hook that returns a renderer function for tool calls in the
9
9
The v2 `useRenderToolCall` (this page, from `@copilotkit/react-core/v2`) is a **no-argument hook** that *returns* a renderer function for consuming tool calls. It is **not** the v1 [`useRenderToolCall`](/reference/v1/hooks/useRenderToolCall), which takes a `{ name, parameters, render }` config object to *register* a renderer. To register renderers in v2, use [`useFrontendTool`](/reference/hooks/useFrontendTool) or [`useHumanInTheLoop`](/reference/hooks/useHumanInTheLoop).
10
10
</Callout>
11
11
12
-
`useRenderToolCall` returns a renderer function that maps tool calls to React elements. The returned function looks up the first matching render configuration by tool name (falling back to a wildcard `"*"` renderer if no exact match is found), parses the JSON arguments, determines the current `ToolCallStatus`, and returns the appropriate React element. When neither a per-tool nor a wildcard renderer is registered, it falls back to the framework's built-in `DefaultToolCallRenderer`, so the returned element is effectively always non-null (the signature keeps `ReactElement | null` for type compatibility).
12
+
`useRenderToolCall` returns a renderer function that maps tool calls to React elements. The returned function looks up the matching render configuration by tool name (preferring a renderer scoped to the active `agentId`, then an unscoped one, then a wildcard `"*"` renderer if no exact match is found), partially parses the JSON arguments, determines the current `ToolCallStatus`, and returns the appropriate React element. When neither a per-tool nor a wildcard renderer is registered, it falls back to the framework's built-in `DefaultToolCallRenderer`, so the returned element is effectively always non-null (the signature keeps `ReactElement | null` for type compatibility).
13
13
14
14
This hook is primarily used by chat UI components to display visual feedback for tool calls. In most applications you will not call it directly; instead, you register render components via `useFrontendTool` or `useHumanInTheLoop`, and the chat components use `useRenderToolCall` internally to resolve them.
15
15
@@ -32,7 +32,7 @@ function useRenderToolCall(): (
32
32
The input object describing the tool call to render.
| No `toolMessage`, tool call id **not** in the executing set|`ToolCallStatus.InProgress`|`undefined`|
52
+
|No `toolMessage`, tool call id **is** in the provider executing set|`ToolCallStatus.Executing`|`undefined`|
53
+
| A `toolMessage`is present |`ToolCallStatus.Complete`| The result string from the tool message |
54
54
55
55
## ToolCallStatus
56
56
@@ -168,14 +168,50 @@ function App() {
168
168
169
169
## Behavior
170
170
171
-
-**Name-based lookup**: The renderer searches registered render configurations for an exact tool name match first, then falls back to a wildcard (`"*"`) renderer, and finally to the framework's built-in `DefaultToolCallRenderer`.
172
-
-**JSON parsing**: The tool call's `args` string is parsed from JSON before being passed to the render component. If parsing fails, args default to an empty object.
173
-
-**Status inference**: Status is determined from the presence and state of the `toolMessage` prop. The render component always receives a consistent shape with `name`, `args`, `status`, and `result`.
171
+
-**Name-based lookup with agent scoping**: The renderer searches registered render configurations for an exact tool name match first. When multiple match the same name, it prefers the one scoped to the active `agentId`, then an unscoped renderer, then the first match. If no exact match exists, it falls back to a wildcard (`"*"`) renderer, and finally to the framework's built-in `DefaultToolCallRenderer`.
172
+
-**Partial JSON parsing**: The tool call's `arguments` string is parsed with `partialJSONParse` before being passed to the render component, so partially-streamed arguments can render incrementally while the tool call is still `InProgress`.
173
+
-**Status inference**: Status is determined from the presence of the `toolMessage` prop and whether the tool call id is in the provider's executing set. The render component always receives a consistent shape with `name`, `toolCallId`, `args`, `status`, and `result`.
174
174
-**Default renderer for unmatched tools**: If no renderer is registered for the tool name and no wildcard renderer exists, the function falls back to the built-in `DefaultToolCallRenderer` rather than returning `null`, so unhandled tool calls still paint out-of-the-box.
175
175
-**Used internally by chat components**: The built-in `CopilotChat`, `CopilotPopup`, and `CopilotSidebar` components use this hook to render tool calls. You only need to call it directly when building custom chat UIs.
176
176
177
+
### Disable default tool rendering
178
+
179
+
Because the hook falls back to the built-in `DefaultToolCallRenderer` when no renderer matches, tool calls paint UI out-of-the-box. To turn that off, register a renderer that produces no UI (an empty fragment, `() => <></>`). A registered renderer takes priority over the default, so no fallback UI is shown.
180
+
181
+
Register a wildcard (`"*"`) renderer with [`useRenderTool`](/reference/hooks/useRenderTool) to disable the default for **all** tool calls. The wildcard overload takes no `parameters` schema, so no Zod is required. Any tool with its own named renderer still paints.
182
+
183
+
```tsx
184
+
function App() {
185
+
// Suppress the built-in DefaultToolCallRenderer for every tool call
To disable rendering for a single tool, register a renderer under that tool's name. Named renderers take a `parameters` schema; when you only want to suppress UI, pass a pass-through schema (`z.any()`):
You can also opt out conditionally — render nothing for some statuses and real UI for others (for example, hide while `InProgress` but show a result on `Complete`), since the `render` function receives the current `status`.
211
+
177
212
## Related
178
213
214
+
-[`useRenderTool`](/reference/hooks/useRenderTool) -- register a renderer by tool name or wildcard (no schema needed for `"*"`)
179
215
-[`useFrontendTool`](/reference/hooks/useFrontendTool) -- register tools with render components
180
216
-[`useHumanInTheLoop`](/reference/hooks/useHumanInTheLoop) -- register interactive tools with render components
181
217
-[`CopilotKit`](/reference/v2) -- configure static render tool calls at the provider level
0 commit comments