Configure the Agent's appearance, composer, permissions, capabilities, Markdown, and start screen.
The SDK groups related options so the top-level HeroUIAgent API stays compact.
Prefer designing these visually? The appearance editor previews every option below, and the embed applies what you save there without a deploy.
Every option on this page can be set in two places, and the embed resolves them in this order:
HeroUIAgent — anything you write in code.The merge runs field by field, not group by group. Overriding one color leaves the rest of the theme — and the launcher, greeting, and composer — exactly as the dashboard defines them:
// Pins the accent. Everything else still comes from the dashboard.
<HeroUIAgent
getAuthToken={getAuthToken}
agentId={process.env.NEXT_PUBLIC_HEROUI_AGENT_ID!}
appearance={{theme: {colors: {accent: "#7c3aed"}}}}
/>Set remoteConfig to false to skip step 2 entirely and configure the embed only from props.
Three things are always code, because no configuration document can carry them: getAuthToken and agentId (identity), tools and context (functions), and onFeedback (a callback).
| Option | Type | Default | Description |
|---|---|---|---|
viewMode | 'floating' | 'sidebar' | 'floating' | Open in a corner panel or a full-height right sidebar. |
shouldCloseOnInteractOutside | boolean | (element: Element) => boolean | Omitted (close) | Close the floating panel on outside interact. false or a predicate returning false keeps it open; filter by element for partial opt-out. |
launcher.position | 'bottom-left' | 'bottom-right' | 'bottom-right' | Corner used by the launcher and floating panel. |
launcher.offset | {x?: number; y?: number} | Responsive | Pixel offset from the anchored side and bottom edges. Values are clamped from 0 to 200. |
launcher.icon | string | Built in | Image URL rendered inside the launcher instead of the default spark mark. Use a square asset of at least 70x70 pixels. |
launcher.background | AgentThemeColor | Accent | Fill of the launcher button. Useful when a custom icon needs a different backdrop; the mark inside gets a contrasting foreground automatically. |
launcher.style | CSSProperties | None | Advanced: inline styles merged onto the launcher button, overriding the stylesheet. Use for anything the options above do not cover. |
panel.initialWidth | number | string | 440 | Floating panel width before expanding. A number is pixels; any CSS length also works. |
panel.initialHeight | number | string | max(420px, 56dvh) | Floating panel height before expanding. A number is pixels; any CSS length also works. |
panel.expanded | boolean | false | Open the floating panel already expanded. |
panel.expandable | boolean | true | Show the expand control in the panel header. Turn it off to pin the panel to one size. |
theme.colorScheme | 'light' | 'dark' | 'system' | 'system' | Color scheme selection. |
theme.radius | 'sharp' | 'soft' | 'round' | 'pill' | 'round' | Corner-radius preset across the embed. |
theme.colors | AgentThemeColors | Built in | Override accent, background, foreground, surface, secondary surface, overlay, and tooltip colors. |
theme.typography | AgentTypography | Built in | Set the font family and a base size clamped from 12 to 18 pixels. |
Each theme color accepts one CSS color for both schemes or {light, dark} values. Unset tokens retain their built-in scheme defaults. Use overlay for dropdown and popover surfaces; use tooltip for tooltip surfaces. Tooltip text contrast is derived automatically.
The panel options apply to floating mode only — a sidebar is docked full-height, and below 640 pixels the panel covers the screen. Both sizes are capped to the viewport, and expanding grows the panel in both directions, never narrower than initialWidth.
<HeroUIAgent
appearance={{
shouldCloseOnInteractOutside: false,
panel: {initialHeight: 620, initialWidth: 480},
}}
getAuthToken={getAuthToken}
agentId={process.env.NEXT_PUBLIC_HEROUI_AGENT_ID!}
/>Use shouldCloseOnInteractOutside: false or () => false when visitors need to interact with the
host page while the floating panel stays open — for example, selecting rows for a client tool. A
predicate can keep the panel open only for certain elements, such as
(element) => !element.closest('[data-keep-agent-open]'). Escape still closes the panel.
| Option | Type | Default | Description |
|---|---|---|---|
attachments | AgentAttachmentContentType[] | false | All supported | Narrow accepted file types or remove attachment controls. |
defaultModel | AgentModelId | Hosted default | Model used for new turns. Also seeds the optional picker. |
dictation | boolean | true | Show microphone recording and transcription controls. |
disclaimer | string | false | false | Verification notice below the composer. Supports inline Markdown links, normalizes bare domains to HTTPS, and is limited to 240 characters. |
modelPicker | boolean | false | Let users choose from the hosted model allowlist. |
placeholder | string | 'Ask anything…' | Composer placeholder, limited to 120 characters. |
| Option | Type | Default | Description |
|---|---|---|---|
defaultMode | 'ask' | 'auto' | 'full' | 'auto' | Ask for every tool, only approval-gated tools, or no declared tools. |
showPicker | boolean | false | Show the permission picker so the end user can change modes. |
The picker appears in the composer, beside the model picker, and offers three choices: Ask for approval (ask), Approve for me (auto), and Full access (full). A person's selection persists for the conversation.
Two things to know before enabling it:
tools. With no client tools there is nothing to approve, so the picker stays hidden and showPicker has no visible effect.full, which bypasses every needsApproval flag on your declared tools and overrides your defaultMode. Leave it off when any tool can do something irreversible.| Option | Type | Default | Description |
|---|---|---|---|
webSearch | boolean | false | Allow the hosted Agent to search the public web for current information. |
imageSearch | boolean | true | Allow image results when web search is enabled. |
newsSearch | boolean | false | Allow recent news results with publication dates when web search is enabled. |
Web results are treated as untrusted external content and kept separate from client-tool datasets.
| Option | Type | Default | Description |
|---|---|---|---|
greeting | string | 'Ask about your data' | Empty-conversation heading, limited to 120 characters. |
prompts | string[] | — | Up to five suggested prompts, each limited to 160 characters. |
promptShortcuts | boolean | false | Enable Ctrl+1 through Ctrl+5 for visible prompts. |
| Option | Type | Default | Description |
|---|---|---|---|
animated | boolean | AnimateOptions | Blur-in words | Animate newly streamed content or provide Streamdown animation options. |
caret | 'block' | 'circle' | false | 'block' | Streaming caret style. |
plugins.renderers | AgentMarkdownRenderer[] | — | Custom renderers selected by fenced-code language. |
Define custom renderer components outside render so their identity remains stable.
import type {AgentMarkdownRendererProps} from "@heroui/agent";
function DiagramRenderer({code, isIncomplete}: AgentMarkdownRendererProps) {
return <Diagram pending={isIncomplete} source={code} />;
}
<HeroUIAgent
getAuthToken={getAuthToken}
markdown={{
caret: "circle",
plugins: {renderers: [{component: DiagramRenderer, language: ["diagram"]}]},
}}
agentId={process.env.NEXT_PUBLIC_HEROUI_AGENT_ID!}
/>;