Dashboard|

The chat

<AgentChat>, theming, and building your own layout with useAgentChat.

AgentChat

import { AgentChat } from 'cencori/react';
 
<AgentChat
    api="/api/chat"
    greeting="How can I help?"
    prompts={['Revenue this month', { label: 'Top customers', prompt: 'Who are our top 5 customers by MRR?' }]}
    placeholder="Ask anything…"
    toolLabels={{ get_sales: 'Reading sales', issue_refund: 'Refund the order' }}
    theme={{ colorScheme: 'auto', accent: '#2563eb', radius: 'md' }}
/>
PropUse it for
apiYour route serving the agent
widgetKeyInstead of api: chat with an agent built in the console, by its website key (cwk_...). See below
agent, publishableKey, baseUrlInstead of api: chat with a stored agent straight from the browser
greeting, promptsWhat shows before the first message
placeholderThe message box placeholder
showToolCallsShow tool calls as steps in the reply. Default true
toolLabelsFriendly names for tool steps and approval cards
themeSee below
headers, bodyExtra headers (auth, CSRF) and body fields on every request
sessionIdOpen an existing conversation
onSessionIdSave the session id when the server assigns one
onActionSee Actions and forms
onErrorCalled when a request fails
className, styleOn the outer element

It fills its container. Give the parent a height.

What the user sees

  • Replies stream in, with Markdown.
  • Tool calls show as steps ("Reading sales") that expand to show arguments and results.
  • Widgets draw as they're written, then become usable once finished. Only the latest reply's widgets take clicks.
  • Approvals show a card with Approve and Decline. The message box waits until every call is decided.
  • Handoffs show as "Handed to Billing".
  • Errors show with Try again. The user can stop a reply mid-stream.

Theming

<AgentChat api="/api/chat" theme={{ colorScheme: 'dark', accent: '#16a34a', accentForeground: '#fff', radius: 'lg', density: 'compact', fontFamily: 'Inter, sans-serif' }} />
OptionValues
colorSchemelight, dark, auto (follows the system, the default)
accent, accentForegroundButtons, the send button, the first chart series
radiusnone, sm, md, lg, or pixels
densitynormal, compact
fontFamilyAny CSS font stack

For full control, set the CSS variables on any parent: --cen-bg, --cen-fg, --cen-muted, --cen-muted-fg, --cen-border, --cen-surface, --cen-accent, --cen-accent-fg, --cen-user-bg, --cen-success, --cen-warning, --cen-danger, --cen-info, --cen-chart-2 to --cen-chart-6, --cen-radius, --cen-font.

The styles are scoped to .cen-chat and need no Tailwind or CSS import.

Agents built in the console

An agent built under Business Agents in the console works in <AgentChat> with its website key: no backend, no API key.

<AgentChat widgetKey="cwk_..." greeting="How can we help?" />
  • Find the key on the agent's Website page (it's the data-key in the embed snippet).
  • The chat works on the sites listed there, like the website widget. Add your site first.
  • The agent runs exactly as published: its knowledge, tools, payments and bookings. It can also answer with widgets.
  • Conversations appear in the agent's inbox, and you can take one over from there.
  • Each conversation has the website widget's limits (length, pace, conversations per visitor).

Your own layout

Use the parts with useAgentChat():

'use client';
import { useAgentChat, Transcript, Composer } from 'cencori/react';
 
export function SupportPanel() {
    const chat = useAgentChat({ api: '/api/chat' });
    return (
        <aside className="panel">
            <header>Support · {chat.status}</header>
            <Transcript chat={chat} greeting="Hi! Ask me anything." />
            <Composer chat={chat} placeholder="Type a message" />
        </aside>
    );
}

Or pass it to <AgentChat chat={chat} /> to keep the default layout while controlling it from outside.

Fully custom

useAgentChat() returns everything to draw a chat yourself:

FieldWhat it is
messages{ id, role, parts, agent?, action?, status? }[]. Parts: text, tool, widget, handoff, approval
statusidle, streaming, awaiting_approval, error
error, sessionId
send(text)Send a message
sendAction(action, { widgetId, label })Run a widget action
approve(callId), reject(callId, message?)Decide on a pending tool call
stop(), retry(), reset()

Draw widgets with <Widget widget={part.widget} id={part.id} onAction={chat.sendAction} />, and approvals with <ApprovalCard>. <ToolCall> draws a tool step.