SDK Reference
API reference for the agent client SDK (@limio/sdk/ai).
Everything exported from @limio/sdk/ai. For a walkthrough, start with Getting Started.
Available from Release 117 onwards.
useChat(options)
useChat(options)The conversation state machine. Bootstraps a session, lazily creates the conversation on the first send, renders optimistic messages, and rolls back on error.
const chat = useChat(options)Options
greeting
string
server greeting
Opening assistant message, shown immediately. Falls back to the agent's server-configured greeting when omitted.
autoStart
boolean
true
Bootstrap the session on mount. Set false to defer until the surface is shown, then flip to true or call start().
onError
(error: Error) => void
none
Called when a send fails, after the pending bubble is rolled back.
Returns
messages
ChatMessage[]
The conversation, including the greeting and any pending bubble.
session
Session | null
The current session once bootstrapped.
conversation
Conversation | null
The conversation once created, after the first send.
status
ChatStatus
"idle", "ready", "sending", or "error".
error
string | null
The last send error message, or null.
send
(text: string) => Promise<void>
Send the visitor's message. Optimistic; creates the conversation lazily.
reset
() => void
Start a fresh conversation: clears messages, re-seeds the greeting, drops the conversation, keeps the session.
start
() => Promise<void>
Bootstrap the session manually when autoStart is false. Idempotent.
ChatMessage
ChatMessagepending is true on the placeholder bubble shown while the agent's reply is in flight. It starts with empty content, and on a streamed reply that content fills as the text arrives while pending stays true. Render a typing indicator only while the content is empty, not for as long as the flag is set. See Streaming.
Streaming
When the agent has Stream replies enabled (see Configuring an Agent), useChat streams the reply into the pending bubble. There is nothing to turn on in your code: the hook reads the agent's setting from the session and picks the transport itself. session.streaming carries that setting if you want to read it, but the server decides per reply, so treat it as a hint rather than a guarantee.
A streamed reply arrives as a growing content on the pending message and settles into an ordinary message when it completes, holding exactly what the buffered path would have returned. Tool artifacts such as checkout links are unaffected: they arrive on the settled message either way.
Rendering a streamed reply
A pending bubble starts with empty content and fills as the reply streams, while pending stays true throughout. Test the content, not the flag: fall back to a typing indicator only while the bubble is still empty.
Keying on m.pending alone is not an error, but it hides the streamed text and delivers the reply whole at the end, which is the behaviour streaming was turned on to avoid.
useSmoothedText(text)
useSmoothedText(text)Models emit a reply in a handful of large chunks rather than character by character, so text rendered straight from content lands in visible jumps. useSmoothedText reveals a growing string at a steady, bounded rate, which reads as typing:
Only growth animates. A message that is already complete when it mounts renders whole, so settled history is never re-typed, and a string that changes rather than grows snaps to its new value instead of animating backwards. Under prefers-reduced-motion the type-in is off and text appears as it arrives.
The hook takes and returns a string, so a surface that wants both smoothing and markdown should smooth the text first and render the result with Markdown rather than passing blocks to MessageContent.
MessageContent
MessageContentRenders a message's content blocks to React: text/markdown formatted, text/plain literal, and component blocks via the registry.
content
ContentBlock[]
The message content to render.
registry
MessageComponentRegistry
Optional. Renders application/vnd.limio.component+json blocks. Omit to skip them.
conversationId
string | null
Optional. Passed to the registry as render context.
markdownClassName
string
Optional. Class on each rendered markdown block, for styling the generated HTML.
textClassName
string
Optional. Class on plain-text blocks.
For full control you can import the underlying markdown renderer, Markdown, directly.
Component registry
Maps a component name to a renderer. MessageContent uses it to render component blocks; unknown names render nothing.
register
(name: string, render: MessageComponentRenderer) => void
Add or replace a renderer.
render
(descriptor, ctx) => ReactNode
Render a descriptor; returns null if the name is unknown.
A renderer receives the component's props and a context object:
Transport
Lower-level functions for calling the Chat API directly. useChat is built on these; reach for them only when you need to bypass the hook.
createSession()
Bootstrap or confirm the visitor's session. Returns the session, including the configured greeting.
createConversation()
Start a new conversation thread.
getConversation(id)
Fetch an existing conversation.
listMessages(conversationId)
The conversation's 50 most recent messages, oldest first. Not the full history of a long chat.
sendMessage(conversationId, text)
Send a message and return the agent's reply.
sendMessageStream(conversationId, text, handlers, options?)
Send a message and stream the reply. Resolves the same final Message as sendMessage.
initiateUpload(conversationId, input)
Request a presigned upload for a document.
uploadFileToS3(init, file)
Upload the file bytes to the presigned target.
contentToText(content)
Flatten a content array to a plain string. Text blocks only; component blocks are skipped.
sendMessageStream
sendMessageStreamA superset of sendMessage: await it the same way and you get the same final Message, but the text also reaches handlers as it arrives. Calling it for an agent that has streaming switched off is safe and returns the reply in one piece, firing no deltas, so a surface can always use it.
onDelta
Each chunk of reply text. Append it to what you have already shown.
onReset
A step called tools, so the text since the last reset was preamble rather than the answer. Discard it. Agents are told not to narrate before a tool call, so this rarely fires; it is the safety net for a model that narrates regardless.
onDelta is required; onReset is optional. options.signal takes an AbortSignal to cancel the request and stop reading mid-reply, which is worth wiring to unmount.
If the connection drops after some text has rendered, the reply is unaffected: the turn finishes and is saved server-side regardless of whether anyone is listening. Recover it with listMessages, which is what useChat does before it reports an error.
Configuring the transport
By default the transport calls the Chat API same-origin, authenticated by the visitor's Limio session cookie. A component running on your shop needs no configuration. For a cross-origin embed, configureChatTransport switches to bearer-token auth:
configureChatTransport(overrides)
Set the API base URL and a bearer-token source.
resetChatTransport()
Restore the default same-origin cookie mode.
Presentation
Everything the admin configured for the agent arrives on the session as session.presentation (type ChatPresentation). Every field is optional: absent means your surface applies its own default, so read each one with a fallback.
greeting
string
Opening assistant message. useChat seeds it for you; you only need this field to render it yourself.
title
string
Chat header title.
placeholder
string
Composer placeholder.
pointers
string[]
Starter questions to offer before the visitor's first message. The displayed text is the text to send.
footer
string
Markdown shown beneath the composer. Links allowed.
launcherIcon
string
The agent's logo, for a launcher or a header avatar. A site-relative /public/... asset path: resolve it with resolveAssetUrl.
launcherLabel
string
Short call-to-action for a launcher, such as "Ask Limio".
greetingPopup
boolean
Whether the greeting should show as a popup bubble from a closed launcher.
greetingPopupDelay
number
Seconds to wait before showing that popup.
greetingPopupMessage
string
Dedicated text for the popup bubble. Prefer it over greeting when set; the opened chat still greets with greeting.
The launcher fields describe a floating launcher, which the built-in widget renders. A custom surface is free to ignore them or to use them for its own entry point.
Theming
Apply the agent's admin-configured theme (see Theming an Agent) to a custom surface. The theme arrives on the session as session.presentation.theme.
themeRootProps(theme)
The props a surface spreads onto its root element: token overrides as style, plus a data-bubble-style attribute. A no-op when the theme is absent or empty.
themeTokens(theme)
The framework-neutral half: the CSS custom-property overrides as a plain object, for non-React callers to apply with el.style.setProperty.
The overrides are Limio design-token variables, so they restyle elements whose styles consume those tokens. A surface with its own palette should read the hex fields off the theme directly instead.
ChatTheme
ChatThemeEvery field is optional; absent means the design-system default. Colours are 6-digit #hex.
accentColor
The brand colour: visitor bubbles, the launcher and buttons, unless a finer field below overrides it.
userBubbleColor
The visitor's bubbles only.
agentBubbleColor
The agent's bubbles.
headerColor
The header bar. Its text colour is derived for you, so it stays legible.
launcherColor
The launcher only.
backgroundColor
The panel surface.
textColor
Body text.
borderColor
Panel and composer borders.
bubbleStyle
A bubble decoration preset, not a colour. See below.
bubbleStyle is a BubbleStyle: "rounded" (the default), "tailed", "flat", "outlined", "shadowed", "bordered", "minimal" or "gradient". themeRootProps applies it as a data-bubble-style attribute on your root element.
The colours reach your surface as CSS variables, so they land whatever stylesheet you ship. The bubble shapes do not: the presets live in the widget's own stylesheet, keyed off that attribute. A surface with its own bubble CSS should read bubbleStyle and style its bubbles itself; a surface that wants the stock shapes should import the widget's stylesheet (@limio/chat/dist/chat.css), which is scoped to the chat root and will not touch the rest of your page.
Bubble text colour is not a field: it is derived from the bubble colour behind it, so text on a themed bubble stays readable whatever the admin picks.
Brand assets
resolveAssetUrl(value)
Resolve a site-relative /public/... asset path (such as presentation.launcherIcon) against the origin the transport talks to, so it also loads in a cross-origin embed. Absolute URLs pass through untouched.
useBrandIcon(iconPath)
React hook wrapping the above for an <img>: returns { src, onError }. src is the resolved URL, or undefined when the icon is unset or failed to load, so you can fall back to your own default rather than render a broken image.
Types
The wire types come from Limio's shared agent protocol and are re-exported for convenience: ContentBlock, Message, ToolArtifact, and Usage, plus the transport types Session, Conversation, CreateConversationResponse, ChatTransport, StreamHandlers, and ApiError.
A ContentBlock is a typed piece of message content:
Last updated
Was this helpful?

