Skip to Content
FeaturesTool Result Rendering

Tool Result Rendering

Frontend tools can include a render method that displays custom React components for their results. This creates rich, interactive content directly in the chat interface, going beyond simple text responses.

AI with Custom Tool Rendering

Tools that render React components

Send a message to get started

Custom Rendering with React Components

The render method receives the tool’s return value and renders a React component:

useAIFrontendTool({ name: "create_chart", description: "Create a data visualization chart", parameters: z.object({ title: z.string().describe("Title for the chart"), type: z.enum(["bar", "pie", "line"]).describe("Type of chart"), data: z.array(z.object({ label: z.string().describe("Label for data point"), value: z.number().describe("Value for data point"), })).describe("Data points for the chart"), }), execute: async (params) => { return { chartId: `chart-${Date.now()}`, title: params.title, type: params.type, data: params.data, createdAt: new Date().toISOString(), }; }, render: (result) => ( <ChartComponent title={result.title} type={result.type} data={result.data} /> ), });

Complete Implementation Example

Here’s a full example showing tools with custom rendering:

"use client"; import React from "react"; import { ChatContainer, useAIFrontendTool } from "ai-chat-bootstrap"; import { z } from "zod"; // Custom Chart Component function ChartComponent({ data, type, title }: { data: Array<{ label: string; value: number }>; type: "bar" | "pie" | "line"; title: string; }) { const maxValue = Math.max(...data.map(d => d.value)); return ( <div className="p-4 bg-card rounded-lg border"> <h3 className="text-lg font-semibold mb-4">{title}</h3> <div className="space-y-3"> {data.map((item, index) => ( <div key={index} className="flex items-center gap-3"> <div className="w-16 text-sm text-muted-foreground"> {item.label} </div> <div className="flex-1 bg-muted rounded-full h-6 relative"> <div className="h-full bg-primary rounded-full transition-all duration-500" style={{ width: `${(item.value / maxValue) * 100}%` }} /> <div className="absolute inset-0 flex items-center justify-center text-xs font-medium"> {item.value} </div> </div> </div> ))} </div> </div> ); } export function ToolRenderingDemo() { // Chart creation tool with custom rendering useAIFrontendTool({ name: "create_chart", description: "Create a data visualization chart", parameters: z.object({ title: z.string().describe("Title for the chart"), type: z.enum(["bar", "pie", "line"]).describe("Type of chart"), data: z.array(z.object({ label: z.string().describe("Label for data point"), value: z.number().describe("Value for data point"), })).describe("Data points for the chart"), }), execute: async (params) => { return { chartId: `chart-${Date.now()}`, title: params.title, type: params.type, data: params.data, createdAt: new Date().toISOString(), }; }, render: (result) => ( <ChartComponent title={result.title} type={result.type} data={result.data} /> ), }); return ( <ChatContainer transport={{ api: "/api/chat" }} messages={{ systemPrompt: "You can create charts using the create_chart tool when users request data visualizations.", }} header={{ title: "AI with Custom Rendering" }} ui={{ placeholder: "Ask me to create a chart!" }} /> ); }

Backend Integration

The backend API route works the same way - tools with render methods are handled automatically:

import { createAzure } from "@ai-sdk/azure"; import { createAIChatHandler } from "ai-chat-bootstrap/server"; const azure = createAzure({ resourceName: process.env.AZURE_RESOURCE_NAME!, apiKey: process.env.AZURE_API_KEY!, apiVersion: process.env.AZURE_API_VERSION ?? "preview", }); const model = azure(process.env.AZURE_DEPLOYMENT_ID!); export const POST = createAIChatHandler({ model, });

Advanced Features

Conditional Rendering

Render different components based on the result:

render: (result) => { if (result.type === 'success') { return <SuccessCard message={result.message} />; } if (result.type === 'error') { return <ErrorCard error={result.error} retry={result.retry} />; } return <DefaultCard data={result} />; }

State Management

Tools can interact with external state:

render: (result) => ( <div onClick={() => setSelectedItem(result.id)}> <ItemCard item={result} isSelected={selectedItem === result.id} /> </div> )

Event Handling

Components can trigger additional actions:

render: (result) => ( <div className="p-4 bg-card rounded-lg border"> <h3>{result.title}</h3> <button onClick={() => { // Trigger another tool or action executeAnotherTool(result.id); }} className="mt-2 bg-primary text-primary-foreground px-4 py-2 rounded" > Process Result </button> </div> )

How It Works

  1. Tool Execution: Tool runs and returns structured data
  2. Render Invocation: The render method receives the result
  3. Component Creation: A React component is created and rendered
  4. Chat Integration: The component appears in the chat message
  5. Interactivity: Users can interact with the rendered component
  6. State Updates: Components can trigger further tool executions

MCP Tool Rendering

Custom rendering also works with MCP (Model Context Protocol) tools!

While this page focuses on frontend tools registered with useAIFrontendTool, you can apply the same rendering patterns to tools provided by MCP servers. MCP tools are external services that expose tool capabilities via the Model Context Protocol.

Key Differences for MCP Tools

  1. Response Format: MCP tools return results in a standardized format with content array
  2. Registration: Use toolRenderers array in the mcp prop instead of useAIFrontendTool
  3. Identification: Match tools using serverUrl + toolName for uniqueness

Quick Example

<ChatContainer transport={{ api: "/api/chat" }} mcp={{ enabled: true, servers: [ { id: "weather-server", transport: { type: "streamable-http", url: "http://localhost:3030/mcp", }, }, ], toolRenderers: [ { serverUrl: "http://localhost:3030/mcp", toolName: "get_weather", render: (result) => { // Parse MCP response format const data = JSON.parse(result.content[0].text); return <WeatherCard {...data} />; }, }, ], }} />

Learn More

For complete details on MCP tool rendering including:

  • MCP response format parsing
  • Multiple server configurations
  • Tool uniqueness guarantees
  • Debugging tips

See the MCP Servers - Custom Tool Rendering section.

API Reference

Next

Continue to Sharing Context →

Last updated on