| title | useRenderToolCall |
|---|---|
| description | useRenderToolCall Hook API Reference |
useRenderToolCall is a React hook that provides a function to render visual representations of tool calls in the chat
interface. It manages the rendering of tool execution states (InProgress, Executing, Complete) based on configured
render functions.
The useRenderToolCall hook:
- Returns a render function for tool calls
- Automatically determines the appropriate status (InProgress, Executing, or Complete)
- Manages tool execution state transitions
- Supports agent-specific and wildcard renderers
- Integrates with CopilotKit's tool rendering system
import { useRenderToolCall } from "@copilotkit/react-core";
import { ToolCall } from "@ag-ui/core";
function ToolCallDisplay({ toolCall, toolMessage }) {
const renderToolCall = useRenderToolCall();
return (
<div className="tool-call-container">
{renderToolCall({ toolCall, toolMessage })}
</div>
);
}The hook returns a function with the following signature:
(props: UseRenderToolCallProps) => React.ReactElement | null;interface UseRenderToolCallProps {
toolCall: ToolCall; // The tool call to render
toolMessage?: ToolMessage; // Optional result message
}The render function automatically determines the tool's status:
- Complete: When a
toolMessageis provided - Executing: When the tool is currently running (tracked internally)
- InProgress: Default state when neither complete nor executing
The function selects renderers based on priority:
- Exact match with matching agentId
- Exact match without agentId (global)
- Exact match (any agentId)
- Wildcard renderer (
*) - No render (returns null)
import { useRenderToolCall } from "@copilotkit/react-core";
import { AssistantMessage } from "@ag-ui/core";
function ChatMessage({ message }: { message: AssistantMessage }) {
const renderToolCall = useRenderToolCall();
if (!message.toolCalls) {
return <div>{message.content}</div>;
}
return (
<div>
{message.content}
{message.toolCalls.map((toolCall) => (
<div key={toolCall.id} className="tool-call">
{renderToolCall({ toolCall })}
</div>
))}
</div>
);
}import { useRenderToolCall } from "@copilotkit/react-core";
import { Message, ToolMessage } from "@ag-ui/core";
function ChatWithResults({
message,
allMessages,
}: {
message: AssistantMessage;
allMessages: Message[];
}) {
const renderToolCall = useRenderToolCall();
return (
<>
{message.toolCalls?.map((toolCall) => {
// Find the corresponding result message
const toolMessage = allMessages.find(
(m): m is ToolMessage =>
m.role === "tool" && m.toolCallId === toolCall.id,
);
return (
<div key={toolCall.id}>
{renderToolCall({
toolCall,
toolMessage, // Pass result if available
})}
</div>
);
})}
</>
);
}The hook works with tool renderers defined at various levels:
Renderers defined in CopilotKitProvider:
import {
CopilotKitProvider,
defineToolCallRenderer,
} from "@copilotkit/react-core";
const searchRenderer = defineToolCallRenderer({
name: "search",
render: ({ args, status }) => <SearchDisplay {...args} status={status} />,
});
function App() {
return (
<CopilotKitProvider renderToolCalls={[searchRenderer]}>
{/* Components using useRenderToolCall will use this renderer */}
</CopilotKitProvider>
);
}Renderers registered via useFrontendTool:
function DynamicTool() {
useFrontendTool({
name: "dynamicAction",
handler: async (args) => {
/* ... */
},
render: ({ args, status }) => <div>Dynamic tool: {status}</div>,
});
// This renderer is automatically available to useRenderToolCall
return null;
}A fallback renderer for unmatched tools:
const wildcardRenderer = defineToolCallRenderer({
name: "*",
render: ({ name, args, status }) => (
<div className="unknown-tool">
<span>Unknown tool: {name}</span>
<span>Status: {status}</span>
</div>
),
});The hook manages three status states automatically:
Initial state when tool is called but not executing:
// Renderer receives:
{
name: string;
args: Partial<T>; // May be incomplete during streaming
status: ToolCallStatus.InProgress;
result: undefined;
}Active execution state:
// Renderer receives:
{
name: string;
args: T; // Complete arguments
status: ToolCallStatus.Executing;
result: undefined;
}Final state with results:
// Renderer receives:
{
name: string;
args: T; // Complete arguments
status: ToolCallStatus.Complete;
result: string; // Tool execution result
}The hook supports agent-specific renderers:
import { useCopilotChatConfiguration } from "@copilotkit/react-core";
function AgentAwareRendering() {
const renderToolCall = useRenderToolCall();
const config = useCopilotChatConfiguration();
// The hook automatically selects renderers based on the current agent
// Priority: agent-specific > global > wildcard
return (
<div>
<h3>Agent: {config?.agentId || "default"}</h3>
{/* Renders will use agent-appropriate renderers */}
{toolCalls.map((tc) => renderToolCall({ toolCall: tc }))}
</div>
);
}