# SlexKit ToolHost for LLMs ToolHost is the structured-input path for confirmations, choices, and forms. Do not use it for ordinary display-only UI. ## ToolHost Raw Markdown: /docs/reference/toolhost.md --- title: ToolHost category: Reference status: ready order: 70 summary: "Structured user-input UI for confirmations, choices, forms, and templates." slexkitRenderMode: component --- # ToolHost ToolHost bridges tool calls to interactive UI. When a model asks for confirmation, a choice, or form input, ToolHost renders the structured UI in the browser and returns the user's response as a `ToolResult`. ## Concepts When a model emits a tool call such as `confirm-action` or `fill-form`, ToolHost compiles it into a standard `SlexExpression` and mounts it using the core runtime. The mounted UI uses `submit:actions` to submit the user's input and settle a Promise. ToolHost is **separate from display-oriented `slex` fences**. Display components render information; ToolHost components collect structured user input and return it programmatically. ### Submit `submit:actions` reads the fields listed in `returnKeys`, calls the ToolHost runtime, and resolves the `ToolRenderHandle.promise` with a `ToolResult`. Do not use `submit` in display fences or component demos. Use `button` for ordinary interactions; use `submit:actions` only when the host is waiting for a structured tool result. ## Public API ### `renderToolCall(call, container) → ToolRenderHandle` Compiles a tool call into a SlexExpression, mounts it, and returns a handle. ```ts function renderToolCall(call: ToolCall, container: HTMLElement): ToolRenderHandle; ``` ```ts type ToolRenderHandle = { promise: Promise; // Resolves when user submits or ignores dispose: () => void; // Clean up the rendered UI }; type ToolResult = | { toolCallId?: string; toolName: string; status: "submitted"; value: Record } | { toolCallId?: string; toolName: string; status: "ignored"; value: null }; ``` **Usage:** ```js import { renderToolCall } from "slexkit"; const handle = renderToolCall( { id: "call_001", name: "confirm-action", arguments: { title: "Delete file?", description: "This action cannot be undone.", confirmLabel: "Delete", requireReason: true, }, }, document.getElementById("tool-container"), ); handle.promise.then((result) => { console.log(result.status); // "submitted" or "ignored" console.log(result.value); // { confirmed: true, reason: "Obsolete file" } handle.dispose(); }); ``` ### `registerToolTemplate(name, compiler)` Register a custom tool template. The compiler function receives the tool arguments and returns a `SlexExpression`. ```ts function registerToolTemplate(name: string, compiler: ToolTemplateCompiler): void; type ToolTemplateCompiler> = ( args: TArgs, runtime: ToolRuntime, call: ToolCall, ) => SlexExpression; type ToolRuntime = { submit: (value: Record) => void; ignore: () => void; }; ``` ## Built-in templates ### `confirm-action` Yes/no confirmation dialog. Supports an optional reason field. **Arguments (`ConfirmActionArguments`):** | Field | Type | Default | Description | |-------|------|---------|-------------| | `title` | `string` | `"Confirm action"` | Dialog title | | `description` | `string` | — | Optional explanation text | | `confirmLabel` | `string` | `"Confirm"` | Submit button label | | `ignoreLabel` | `string` | `"Ignore"` | Cancel button label | | `requireReason` | `boolean` | `false` | Show a reason text input | | `reasonLabel` | `string` | `"Reason"` | Label for the reason input | | `reasonPlaceholder` | `string` | `"Add a reason"` | Placeholder for the reason input | **Result value:** | Key | Type | Description | |-----|------|-------------| | `confirmed` | `boolean` | Always `true` when submitted | | `reason` | `string` | User's reason text (only if `requireReason: true`) | **Example:** ```js renderToolCall({ name: "confirm-action", arguments: { title: "Delete project?", description: "This will permanently delete all files.", confirmLabel: "Delete", requireReason: true, }, }, container); ``` ### `choose-options` / `option-list` Single or multi-select option list. `option-list` is an alias for `choose-options` — behavior is identical. **Arguments (`ChooseOptionsArguments` / `OptionListArguments`):** | Field | Type | Default | Description | |-------|------|---------|-------------| | `title` | `string` | `"Choose options"` | Dialog title | | `description` | `string` | — | Optional explanation text | | `options` / `items` | `OptionListItem[]` | `[]` | List of selectable items | | `multiple` | `boolean` | `true` | Allow multiple selection | | `selected` | `string[]` | auto | Pre-selected item IDs | | `minSelected` | `number` | `0` | Minimum required selections | | `maxSelected` | `number` | `Infinity` | Maximum allowed selections | | `submitLabel` | `string` | `"Submit"` | Submit button label | | `ignoreLabel` | `string` | `"Ignore"` | Cancel button label | **OptionListItem:** | Field | Type | Description | |-------|------|-------------| | `label` | `string` | Display text (required) | | `id` | `string` | Unique identifier (defaults to `value` or index) | | `value` | `string` | Submitted value (defaults to `id`) | | `description` | `string` | Secondary text shown after label | | `selected` | `boolean` | Pre-selected state | | `disabled` | `boolean` | Disabled state | **Rendering:** - When `multiple: true` (default): renders **checkboxes** - When `multiple: false`: renders a **radio group** **Result value:** | Key | Type | Description | |-----|------|-------------| | `selected` | `string[]` | IDs of selected items | **Example:** ```js renderToolCall({ name: "choose-options", arguments: { title: "Select dependencies", options: [ { id: "react", label: "React", description: "UI library" }, { id: "vue", label: "Vue", description: "Progressive framework" }, { id: "svelte", label: "Svelte", description: "Compiled framework", selected: true }, ], multiple: true, minSelected: 1, maxSelected: 2, }, }, container); ``` ### `fill-form` Multi-field form with various field types. **Arguments (`FillFormArguments`):** | Field | Type | Default | Description | |-------|------|---------|-------------| | `title` | `string` | `"Fill form"` | Form title | | `description` | `string` | — | Optional explanation text | | `fields` | `FormField[]` | `[]` | Form field definitions | | `values` | `Record` | — | Initial field values | | `submitLabel` | `string` | `"Submit"` | Submit button label | | `ignoreLabel` | `string` | `"Ignore"` | Cancel button label | **FormField:** | Field | Type | Default | Description | |-------|------|---------|-------------| | `name` | `string` | (required) | Field name (used as key in result value) | | `type` | `FormFieldType` | `"text"` | Field type | | `label` | `string` | `name` | Display label | | `description` | `string` | — | Help text below the field | | `placeholder` | `string` | — | Input placeholder | | `required` | `boolean` | `false` | Require non-empty value to submit | | `disabled` | `boolean` | `false` | Disable the field | | `value` | `unknown` | — | Initial value | | `options` | `Array<{label, value}>` | — | Options for `select` type | **FormFieldType:** | Type | Renders | Description | |------|---------|-------------| | `text` | `` | Free-form text | | `number` | `` | Numeric input, value is `number \| null` | | `engineering` | `` with SI prefix parsing | Accepts values like `"10kΩ"`, `"100nF"`, `"1.5MegHz"`. Parsed with `parseEngineeringNumber()`. State includes `raw`, `number`, `valid`, `prefix`, `unit`, `normalized` | | `select` | `