# Tool Rendering
URL: /docs/api-reference/tools/rendering

Register React renderers for assistant-ui tool calls, tool results, and model data parts.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

## API Reference

### DataRenderers

- `length`: `0`
- `toString`: `() => string`
- `toLocaleString`: `{ (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; }`
- `pop`: `() => undefined`
- `push`: `(...items: never[]) => number`
- `concat`: `{ (...items: ConcatArray<never>[]): never[]; (...items: ConcatArray<never>[]): never[]; }`
- `join`: `(separator?: string) => string`
- `reverse`: `() => never[]`
- `shift`: `() => undefined`
- `slice`: `(start?: number, end?: number) => never[]`
- `sort`: `(compareFn?: ((a: never, b: never) => number) | undefined) => []`
- `splice`: `{ (start: number, deleteCount?: number): never[]; (start: number, deleteCount: number, ...items: never[]): never[]; }`
- `unshift`: `(...items: never[]) => number`
- `indexOf`: `(searchElement: never, fromIndex?: number) => number`
- `lastIndexOf`: `(searchElement: never, fromIndex?: number) => number`
- `every`: `{ <S>(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): boolean; }`
- `some`: `(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any) => boolean`
- `forEach`: `(callbackfn: (value: never, index: number, array: never[]) => void, thisArg?: any) => void`
- `map`: `<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[]`
- `filter`: `{ <S>(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): S[]; (predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): never[]; }`
- `reduce`: `{ (callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never): never; (callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never, initialValue: never): never; <U>(callbackfn: (previousValue: U, currentValue: never, currentIndex: number, array: never[]) => U, initialValue: U): U; }`
- `reduceRight`: `{ (callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never): never; (callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never, initialValue: never): never; <U>(callbackfn: (previousValue: U, currentValue: never, currentIndex: number, array: never[]) => U, initialValue: U): U; }`
- `find`: `{ <S>(predicate: (value: never, index: number, obj: never[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: never, index: number, obj: never[]) => unknown, thisArg?: any): undefined; }`
- `findIndex`: `(predicate: (value: never, index: number, obj: never[]) => unknown, thisArg?: any) => number`
- `fill`: `(value: never, start?: number, end?: number) => []`
- `copyWithin`: `(target: number, start: number, end?: number) => []`
- `entries`: `() => ArrayIterator<[number, never]>`
- `keys`: `() => ArrayIterator<number>`
- `values`: `() => ArrayIterator<never>`
- `includes`: `(searchElement: never, fromIndex?: number) => boolean`
- `flatMap`: `<U, This>(callback: (this: This, value: never, index: number, array: never[]) => U | readonly U[], thisArg?: This | undefined) => U[]`
- `flat`: `<A, D>(this: A, depth?: D | undefined) => FlatArray<A, D>[]`
- `at`: `(index: number) => undefined`
- `findLast`: `{ <S>(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): undefined; }`
- `findLastIndex`: `(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any) => number`
- `toReversed`: `() => never[]`
- `toSorted`: `(compareFn?: ((a: never, b: never) => number) | undefined) => never[]`
- `toSpliced`: `{ (start: number, deleteCount: number, ...items: never[]): never[]; (start: number, deleteCount?: number): never[]; }`
- `with`: `(index: number, value: never) => never[]`

### getMcpAppFromToolPart

Returns MCP app metadata for a tool-call part that points at a `ui://` resource.

Returns `undefined` when the part has no MCP app metadata or the metadata does not reference an assistant-ui MCP app resource.

- `part`: `ToolPartLike`

  - `mcp?`: `ToolCallMessagePartMcpMetadata` — MCP app metadata associated with this tool call, when present.

    - `app?`: `McpAppMetadata`

      - `resourceUri`: `string`
      - `mimeType?`: `string`
      - `visibility?`: `readonly ("model" | "app")[]`
      - `serverId?`: `string` — Routable server identity emitted by the agent stack when multiple MCP servers back one agent; for

### makeAssistantDataUI

Creates a React component that registers a named data-part renderer when rendered.

```
type AssistantDataUIProps = {
  /** Data part name this renderer handles. */
  name: string;
  /** Component rendered for matching data message parts. */
  render: DataMessagePartComponent<T>;
};

const makeAssistantDataUI: <T = any>(dataUI: AssistantDataUIProps<T>) => AssistantDataUI;
```

### McpAppRenderer

- `0`: `McpAppRendererOptions`

  - `sandbox?`: `McpAppSandboxConfig` — Sandbox + container styling. Passes through to SafeContentFrame.

    - `sandbox?`: `SandboxOption[]`
    - `useShadowDom?`: `boolean`
    - `enableBrowserCaching?`: `boolean`
    - `salt?`: `string`
    - `product?`: `string`
    - `className?`: `string`
    - `style?`: `CSSProperties`
    - `unsafeDocumentWrite?`: `boolean`

  - `maxHeight?`: `number` — Upper bound (in pixels) applied to the widget-driven auto-resize height. Defaults to 800.

  - `hostInfo?`: `McpAppHostInfo` — Identifies the host to the widget in the \`ui/initialize\` response.

    - `name`: `string`
    - `version`: `string`

  - `hostContext?`: `McpAppHostContext` — Delivered to the widget on initialize and pushed via \`notifications/host_context/changed\` on change.

    - `theme?`: `"light" | "dark"`
    - `displayMode?`: `McpAppDisplayMode`
    - `availableDisplayModes?`: `McpAppDisplayMode[]`

  - `handlers?`: `Omit< McpAppBridgeHandlers, "callTool" | "readResource" | "listResources" >` — Optional widget interaction and lifecycle handlers. Data-plane handlers (\`callTool\`, \`readResource\`, \`listResources\`) always use \`host\`. Which handlers a widget may call is captured when its frame mounts, so a \`forPart\` resolver returns the same handler keys for a part on every render even when the implementations change.

    - `onError?`: `(error: Error) => void`
    - `allowedTools?`: `readonly string[]`
    - `openLink?`: `(params: { url: string }) => Promise<unknown> | unknown`
    - `sendMessage?`: `(params: unknown) => Promise<unknown> | unknown`
    - `updateModelContext?`: `(params: unknown) => Promise<unknown> | unknown`
    - `requestDisplayMode?`: `(params: { mode: McpAppDisplayMode; }) => Promise<{ mode: McpAppDisplayMode }> | { mode: McpAppDisplayMode }`
    - `onSizeChange?`: `(params: { width?: number; height?: number }) => void`
    - `onInitialized?`: `() => void`
    - `onRequestTeardown?`: `(params: unknown) => void`
    - `onLog?`: `(params: unknown) => void`

  - `fallback?`: `ReactNode` — Rendered when no MCP app is on the part, or while load is in flight / failed (unless overridden).

  - `loadingFallback?`: `ReactNode` — Rendered while the resource is loading. Defaults to \`fallback\`.

  - `errorFallback?`: `ReactNode | ((error: Error) => ReactNode)` — Rendered when the resource load rejects. Defaults to \`fallback\`.

  - `host`: `ResourceElement<McpAppsHost>` — Provides the data-plane operations the widget can request (\`loadResource\`, \`callTool\`, \`readResource\`, \`listResources\`). Use \`McpAppsRemoteHost({ url })\` for the default HTTP-route convention.

    - `hook`: `(...args: any[]) => V`
    - `args`: `readonly unknown[]`
    - `key?`: `string | number`
    - `deps?`: `readonly unknown[]`

  - `forPart?`: `(part: ToolCallMessagePart) => McpAppPartOptions` — Resolves the options for one part. Each returned value replaces the thread-wide option of the same name, so a host can give every MCP app its own display mode and answer \`requestDisplayMode\` for the part that asked. \`handlers\` is the exception and merges per key. Its keys are capabilities negotiated with the widget rather than data, so replacing the whole bag to add one handler would withdraw the others from that part's widget with nothing to observe it by.

- `length`: `1`

- `toString`: `() => string`

- `toLocaleString`: `{ (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; }`

- `pop`: `() => McpAppRendererOptions`

- `push`: `(...items: McpAppRendererOptions[]) => number`

- `concat`: `{ (...items: ConcatArray<McpAppRendererOptions>[]): McpAppRendererOptions[]; (...items: (McpAppRendererOptions | ConcatArray<McpAppRendererOptions>)[]): McpAppRendererOptions[]; }`

- `join`: `(separator?: string) => string`

- `reverse`: `() => McpAppRendererOptions[]`

- `shift`: `() => McpAppRendererOptions`

- `slice`: `(start?: number, end?: number) => McpAppRendererOptions[]`

- `sort`: `(compareFn?: ((a: McpAppRendererOptions, b: McpAppRendererOptions) => number) | undefined) => [options: McpAppRendererOptions]`

- `splice`: `{ (start: number, deleteCount?: number): McpAppRendererOptions[]; (start: number, deleteCount: number, ...items: McpAppRendererOptions[]): McpAppRendererOptions[]; }`

- `unshift`: `(...items: McpAppRendererOptions[]) => number`

- `indexOf`: `(searchElement: McpAppRendererOptions, fromIndex?: number) => number`

- `lastIndexOf`: `(searchElement: McpAppRendererOptions, fromIndex?: number) => number`

- `every`: `{ <S>(predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => unknown, thisArg?: any): boolean; }`

- `some`: `(predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => unknown, thisArg?: any) => boolean`

- `forEach`: `(callbackfn: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => void, thisArg?: any) => void`

- `map`: `<U>(callbackfn: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => U, thisArg?: any) => U[]`

- `filter`: `{ <S>(predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => value is S, thisArg?: any): S[]; (predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => unknown, thisArg?: any): McpAppRendererOptions[]; }`

- `reduce`: `{ (callbackfn: (previousValue: McpAppRendererOptions, currentValue: McpAppRendererOptions, currentIndex: number, array: McpAppRendererOptions[]) => McpAppRendererOptions): McpAppRendererOptions; (callbackfn: (previousValue: McpAppRendererOptions, currentValue: McpAppRendererOptions, currentIndex: number, array: McpAppRendererOptions[]) => McpAppRendererOptions, initialValue: McpAppRendererOptions): McpAppRendererOptions; <U>(callbackfn: (previousValue: U, currentValue: McpAppRendererOptions, currentIndex: number, array: McpAppRendererOptions[]) => U, initialValue: U): U; }`

- `reduceRight`: `{ (callbackfn: (previousValue: McpAppRendererOptions, currentValue: McpAppRendererOptions, currentIndex: number, array: McpAppRendererOptions[]) => McpAppRendererOptions): McpAppRendererOptions; (callbackfn: (previousValue: McpAppRendererOptions, currentValue: McpAppRendererOptions, currentIndex: number, array: McpAppRendererOptions[]) => McpAppRendererOptions, initialValue: McpAppRendererOptions): McpAppRendererOptions; <U>(callbackfn: (previousValue: U, currentValue: McpAppRendererOptions, currentIndex: number, array: McpAppRendererOptions[]) => U, initialValue: U): U; }`

- `find`: `{ <S>(predicate: (value: McpAppRendererOptions, index: number, obj: McpAppRendererOptions[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: McpAppRendererOptions, index: number, obj: McpAppRendererOptions[]) => unknown, thisArg?: any): McpAppRendererOptions | undefined; }`

- `findIndex`: `(predicate: (value: McpAppRendererOptions, index: number, obj: McpAppRendererOptions[]) => unknown, thisArg?: any) => number`

- `fill`: `(value: McpAppRendererOptions, start?: number, end?: number) => [options: McpAppRendererOptions]`

- `copyWithin`: `(target: number, start: number, end?: number) => [options: McpAppRendererOptions]`

- `entries`: `() => ArrayIterator<[number, McpAppRendererOptions]>`

- `keys`: `() => ArrayIterator<number>`

- `values`: `() => ArrayIterator<McpAppRendererOptions>`

- `includes`: `(searchElement: McpAppRendererOptions, fromIndex?: number) => boolean`

- `flatMap`: `<U, This>(callback: (this: This, value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => U | readonly U[], thisArg?: This | undefined) => U[]`

- `flat`: `<A, D>(this: A, depth?: D | undefined) => FlatArray<A, D>[]`

- `at`: `(index: number) => McpAppRendererOptions`

- `findLast`: `{ <S>(predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => unknown, thisArg?: any): McpAppRendererOptions | undefined; }`

- `findLastIndex`: `(predicate: (value: McpAppRendererOptions, index: number, array: McpAppRendererOptions[]) => unknown, thisArg?: any) => number`

- `toReversed`: `() => McpAppRendererOptions[]`

- `toSorted`: `(compareFn?: ((a: McpAppRendererOptions, b: McpAppRendererOptions) => number) | undefined) => McpAppRendererOptions[]`

- `toSpliced`: `{ (start: number, deleteCount: number, ...items: McpAppRendererOptions[]): McpAppRendererOptions[]; (start: number, deleteCount?: number): McpAppRendererOptions[]; }`

- `with`: `(index: number, value: McpAppRendererOptions) => McpAppRendererOptions[]`

### McpAppsRemoteHost

- `0`: `McpAppsRemoteHostOptions`

  - `url`: `string`
  - `fetch?`: `typeof fetch`
  - `headers?`: `Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>)`

- `length`: `1`

- `toString`: `() => string`

- `toLocaleString`: `{ (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; }`

- `pop`: `() => McpAppsRemoteHostOptions`

- `push`: `(...items: McpAppsRemoteHostOptions[]) => number`

- `concat`: `{ (...items: ConcatArray<McpAppsRemoteHostOptions>[]): McpAppsRemoteHostOptions[]; (...items: (McpAppsRemoteHostOptions | ConcatArray<McpAppsRemoteHostOptions>)[]): McpAppsRemoteHostOptions[]; }`

- `join`: `(separator?: string) => string`

- `reverse`: `() => McpAppsRemoteHostOptions[]`

- `shift`: `() => McpAppsRemoteHostOptions`

- `slice`: `(start?: number, end?: number) => McpAppsRemoteHostOptions[]`

- `sort`: `(compareFn?: ((a: McpAppsRemoteHostOptions, b: McpAppsRemoteHostOptions) => number) | undefined) => [options: McpAppsRemoteHostOptions]`

- `splice`: `{ (start: number, deleteCount?: number): McpAppsRemoteHostOptions[]; (start: number, deleteCount: number, ...items: McpAppsRemoteHostOptions[]): McpAppsRemoteHostOptions[]; }`

- `unshift`: `(...items: McpAppsRemoteHostOptions[]) => number`

- `indexOf`: `(searchElement: McpAppsRemoteHostOptions, fromIndex?: number) => number`

- `lastIndexOf`: `(searchElement: McpAppsRemoteHostOptions, fromIndex?: number) => number`

- `every`: `{ <S>(predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any): boolean; }`

- `some`: `(predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any) => boolean`

- `forEach`: `(callbackfn: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => void, thisArg?: any) => void`

- `map`: `<U>(callbackfn: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => U, thisArg?: any) => U[]`

- `filter`: `{ <S>(predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => value is S, thisArg?: any): S[]; (predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any): McpAppsRemoteHostOptions[]; }`

- `reduce`: `{ (callbackfn: (previousValue: McpAppsRemoteHostOptions, currentValue: McpAppsRemoteHostOptions, currentIndex: number, array: McpAppsRemoteHostOptions[]) => McpAppsRemoteHostOptions): McpAppsRemoteHostOptions; (callbackfn: (previousValue: McpAppsRemoteHostOptions, currentValue: McpAppsRemoteHostOptions, currentIndex: number, array: McpAppsRemoteHostOptions[]) => McpAppsRemoteHostOptions, initialValue: McpAppsRemoteHostOptions): McpAppsRemoteHostOptions; <U>(callbackfn: (previousValue: U, currentValue: McpAppsRemoteHostOptions, currentIndex: number, array: McpAppsRemoteHostOptions[]) => U, initialValue: U): U; }`

- `reduceRight`: `{ (callbackfn: (previousValue: McpAppsRemoteHostOptions, currentValue: McpAppsRemoteHostOptions, currentIndex: number, array: McpAppsRemoteHostOptions[]) => McpAppsRemoteHostOptions): McpAppsRemoteHostOptions; (callbackfn: (previousValue: McpAppsRemoteHostOptions, currentValue: McpAppsRemoteHostOptions, currentIndex: number, array: McpAppsRemoteHostOptions[]) => McpAppsRemoteHostOptions, initialValue: McpAppsRemoteHostOptions): McpAppsRemoteHostOptions; <U>(callbackfn: (previousValue: U, currentValue: McpAppsRemoteHostOptions, currentIndex: number, array: McpAppsRemoteHostOptions[]) => U, initialValue: U): U; }`

- `find`: `{ <S>(predicate: (value: McpAppsRemoteHostOptions, index: number, obj: McpAppsRemoteHostOptions[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: McpAppsRemoteHostOptions, index: number, obj: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any): McpAppsRemoteHostOptions | undefined; }`

- `findIndex`: `(predicate: (value: McpAppsRemoteHostOptions, index: number, obj: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any) => number`

- `fill`: `(value: McpAppsRemoteHostOptions, start?: number, end?: number) => [options: McpAppsRemoteHostOptions]`

- `copyWithin`: `(target: number, start: number, end?: number) => [options: McpAppsRemoteHostOptions]`

- `entries`: `() => ArrayIterator<[number, McpAppsRemoteHostOptions]>`

- `keys`: `() => ArrayIterator<number>`

- `values`: `() => ArrayIterator<McpAppsRemoteHostOptions>`

- `includes`: `(searchElement: McpAppsRemoteHostOptions, fromIndex?: number) => boolean`

- `flatMap`: `<U, This>(callback: (this: This, value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => U | readonly U[], thisArg?: This | undefined) => U[]`

- `flat`: `<A, D>(this: A, depth?: D | undefined) => FlatArray<A, D>[]`

- `at`: `(index: number) => McpAppsRemoteHostOptions`

- `findLast`: `{ <S>(predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any): McpAppsRemoteHostOptions | undefined; }`

- `findLastIndex`: `(predicate: (value: McpAppsRemoteHostOptions, index: number, array: McpAppsRemoteHostOptions[]) => unknown, thisArg?: any) => number`

- `toReversed`: `() => McpAppsRemoteHostOptions[]`

- `toSorted`: `(compareFn?: ((a: McpAppsRemoteHostOptions, b: McpAppsRemoteHostOptions) => number) | undefined) => McpAppsRemoteHostOptions[]`

- `toSpliced`: `{ (start: number, deleteCount: number, ...items: McpAppsRemoteHostOptions[]): McpAppsRemoteHostOptions[]; (start: number, deleteCount?: number): McpAppsRemoteHostOptions[]; }`

- `with`: `(index: number, value: McpAppsRemoteHostOptions) => McpAppsRemoteHostOptions[]`

### useAssistantDataUI

Registers a renderer for named `data` message parts while the component is mounted.

- `dataUI`: `AssistantDataUIProps<any> | null`

  - `name`: `string` — Data part name this renderer handles.
  - `render`: `DataMessagePartComponent<T>` — Component rendered for matching data message parts.

### toolApprovalAcceptsText

Whether the request asks for a free-form answer, on its own or alongside its options. Renderers read this to decide whether to offer a text affordance, and the runtime reads it to reject a `text` response the host cannot record. A `display: "questions"` request takes its answers per question instead.

```
const toolApprovalAcceptsText: (approval: { readonly display?: ToolApprovalDisplay; readonly allowFreeform?: boolean; }) => boolean;
```

### makeAssistantToolUI

> [!warn]
>
> **Deprecated.** Put `render`/`renderText` on the matching toolkit entry, or use `MessagePrimitive.Parts` inline tool render overrides for per-message UI. See <https://assistant-ui.com/docs/migrations/toolkit-tools>.

Creates a React component that registers a tool-call renderer when rendered.

Use this to package reusable display components for tools whose definitions are registered elsewhere.

```
type AssistantToolUIProps = {
  /** Name of the tool whose calls should use this renderer. */
  toolName: string;
  /** Component rendered for matching tool-call message parts. */
  render: ToolCallMessagePartComponent<TArgs, TResult>;
  /**
   * How the UI is presented relative to the chain-of-thought trace. Set
   * `"standalone"` to surface it on its own (e.g. human-in-the-loop or
   * generative UI for a backend/MCP tool). Defaults to `"inline"`.
   */
  display?: "standalone" | "inline";
};

const makeAssistantToolUI: <TArgs, TResult>(tool: AssistantToolUIProps<TArgs, TResult>) => AssistantToolUI;
```

### useAssistantToolUI

> [!warn]
>
> **Deprecated.** Put `render`/`renderText` on the matching toolkit entry, or use `MessagePrimitive.Parts` inline tool render overrides for per-message UI. See <https://assistant-ui.com/docs/migrations/toolkit-tools>.

Registers a tool-call renderer while the component is mounted.

This only affects rendering. Pair it with [Tools](/docs/api-reference/tools/toolkits#tools) or a backend tool registry to expose the actual tool definition to the model.

- `tool`: `AssistantToolUIProps<any, any> | null`

  - `toolName`: `string` — Name of the tool whose calls should use this renderer.
  - `render`: `ToolCallMessagePartComponent<TArgs, TResult>` — Component rendered for matching tool-call message parts.
  - `display?`: `"standalone" | "inline"` — How the UI is presented relative to the chain-of-thought trace. Set \`"standalone"\` to surface it on its own (e.g. human-in-the-loop or generative UI for a backend/MCP tool). Defaults to \`"inline"\`.