Skip to content

AI

AiChat

Bit.BlazorUI.AIChatbotAssistantCopilot

BitAiChat is the whole chat surface in one component: the streaming transcript, the composer with attachments, slash commands and mentions, the empty state with its starter prompts, and the scroll-to-latest button, wired to a BitAiChatSession. Give it a session, or let it create one from the transport registered with AddBitBlazorUIAIServices - a working AI chat in one line of markup. Every part it composes is a public component of its own, so anything it does can also be assembled by hand.

Notes

To use this component, you need to install the Bit.BlazorUI.AI(opens in a new tab) nuget package, as described in the Optional steps of the Getting started page.

BitAiChat talks to a model through a BitAiChatSession. Pass one in Session, or register a transport with builder.Services.AddBitBlazorUIAIServices(ai => ai.UseTransport<MyTransport>()) and the chat creates its own (and disposes it with itself). The package never calls a provider on its own: an IBitAiTransport of yours turns your provider's stream into its events. Every reply on this page comes from a scripted transport, so the demos run with no model and no API key.

The chat takes the height of its container, so give that container one. The transcript is a polite live region (role="log") and a reply is aria-busy while it streams, so a screen reader reads it once it settles rather than token by token. Pressing the scroll-to-latest button or a suggestion moves the focus to the composer, since both go away once pressed. Links and images in the model's Markdown are sanitized - script-capable URL schemes are neutralized whatever BitAiUiOptions.Images allows.

Usage

Every example is live. Open its code to see exactly what produced the component running underneath.

Basic

With no Session, the chat creates one from the registered transport - here a script that echoes what you send, a few characters at a time. Enter sends, Shift+Enter starts a new line, and while a reply streams the send button stops it.

How can I help?
Ask a question to get started.

Session

A Session of your own picks the transport and lets the page drive the conversation too: this one streams a Markdown answer, and the buttons submit from code and put the caret in the composer (FocusComposerAsync). A session you create is yours to dispose.


How can I help?
Ask a question to get started.

Conversation

Conversation opens the chat on a thread that already has history (it is used only when no Session is given), and SessionOptions sets up the session the chat creates for it. System messages are hidden by default; turn HideSystemMessages off to show them as a note in the transcript.

Which package are the AI components in?

In Bit.BlazorUI.AI, which builds on the core Bit.BlazorUI package.

Empty state

An empty conversation shows EmptyTitle, EmptyBody and the Suggestions - starter prompts a tap sends to the session. Three concrete examples do more for an empty box than any heading.

Hi, I am the docs assistant
Ask about any component, or start from one of these.

Templates

HeaderTemplate sits above the transcript and FooterTemplate under the composer, both outside the scroll area; ListHeaderTemplate and ListFooterTemplate scroll with the messages. EmptyTemplate replaces the empty state. The template's buttons drive the chat through its ActiveSession and ActiveConversation.

Support assistant
Chats with the assistant are not saved.
What can we help you with?
Replies are scripted on this page.
The assistant can make mistakes. Check important information.

Composer

Placeholder words the composer. ComposerPrefixTemplate goes before its text (a model picker, here - an app hands the picked model to its session through the RequestOptions of its options; the scripted replies of this page do not read it), ComposerSuffixTemplate beside the send button and ComposerHintTemplate under it.

How can I help?
Ask a question to get started.
Picked: demo-model-1. Enter sends, Shift+Enter starts a new line.

Custom composer

ComposerTemplate replaces the whole composer - a guided flow that answers with a set of replies rather than free text, here. Whatever it holds submits through the session.

Pick a reply to start
Ask a question to get started.

Attachments & commands

AllowAttachments (on by default) offers files - picked, pasted or dropped - up to MaxAttachmentSize (1 MB here; OnAttachmentRejected hears about the rest, and the user is told either way). AllowDictation adds a microphone where the browser can transcribe speech. Commands open on a forward slash and Mentions on an at sign: type / or @.

How can I help?
Ask a question to get started.

Last file turned away: -

Submitting yourself

Handle OnSubmit and the chat hands you what the user sent instead of submitting it - to upload the attachments to your storage first, or to add context to the prompt, as this one does - and you submit to the session yourself.

How can I help?
Ask a question to get started.

Last submission: -

Message template

MessageTemplate replaces how a message is drawn. Wrapping the built-in BitAiChatMessage keeps the streaming, the parts and the actions while adding something of your own - an avatar per role, here.

How can I help?
Ask a question to get started.

Citations & feedback

OnCitationClick reports a numbered citation chip, OnSourceClick a source card under the reply and OnFeedback a thumbs up or down - with the message, so a host can persist it. Ask the question, then click.

How can I help?
Ask a question to get started.

Last event: -

Options

UiOptions replaces the presentation settings in force for everything inside this chat - the cascaded or registered ones: this one opens the reasoning while it streams and shows timestamps and token usage under every reply.

How can I help?
Ask a question to get started.

Disabled

A disabled chat keeps its transcript readable and takes nothing in: the composer, the suggestions and the actions of every message are disabled with it.

Which package are the AI components in?

In Bit.BlazorUI.AI, which builds on the core Bit.BlazorUI package.

Cascading parameters

BitParams with a BitAiChatParams sets what the chats of an app agree on - the words of the empty state and the composer, what the composer offers, the classes and styles - for every chat inside it; a chat's own value wins (the second keeps its own placeholder). The session, the templates and the callbacks are not cascaded.

Ask the docs
Both chats take this heading and line from the BitParams around them.
Ask the docs
Both chats take this heading and line from the BitParams around them.

Style & Class

Style / Class reach the root, Styles / Classes each part (the transcript, the empty state and the scroll-to-latest button take the class-styles of their own components). The public --bit-AiChat-* variables (see the CSS variables table) re-skin it from :root, an ancestor or Style; the column of messages has its own width, --bit-AiMessageList-max-width, so set both to keep the composer lined up with it.

Styled
Ask a question to get started.

Classy
Ask a question to get started.

CSS variables
Ask a question to get started.

RTL

Use BitAiChat in right-to-left (RTL).

چطور می‌توانم کمک کنم؟
پیامی بنویسید یا یکی از پیشنهادها را انتخاب کنید.

CSS variables

The public custom properties this component reads off its root, for what no parameter covers.

Every variable is read with a fallback and never declared by the component, so it inherits like any other custom property: set one on :root (or in a [bit-theme] block) to restyle every instance, on any ancestor to restyle the ones inside it, or on the Style of one instance to restyle it - and any instance nested inside it, which inherits the value too; a parameter changes one alone, as does the real CSS property on the instance's Style / Styles when that property does not inherit (opacity: 1 keeps one disabled instance undimmed without undimming a disabled one inside it), while an inherited one such as color or font-family also reaches the nested instances that do not set it themselves. Leave a variable unset and the component falls back to the theme token beside it.

BitAiChat CSS variables

Name Default value Description
--bit-AiChat-background var(--bit-clr-bg-pri) Background of the chat, which the footer fades the last lines of the transcript into.
--bit-AiChat-max-width spacing(92) Width the composer stops growing at. Set --bit-AiMessageList-max-width to the same value to keep it lined up with the column of messages.
--bit-AiChat-footer-padding 0 spacing(2) spacing(2), 0 spacing(1.5) spacing(1.5) on a phone Inset of the footer around the composer.

API

Every parameter, public member, sub-class and enum this component exposes.

BitAiChat parameters

Name Type Default value Description
AllowAttachments bool true Offers attachments in the composer: files picked with its button, pasted or dropped onto it, up to MaxAttachmentSize each.
AllowDictation bool false Offers dictation in the composer: a microphone button that transcribes speech into the text, shown only where the browser can recognize speech.
Classes BitAiChatClassStyles? null Custom CSS classes for different parts of the chat.
Commands IReadOnlyList<BitAiSlashCommand>? null The commands offered when the user types a forward slash in the composer. A command either inserts its Template into the text or runs its Handler.
ComposerHintTemplate RenderFragment? null A hint rendered under the composer, such as the keys that send.
ComposerPrefixTemplate RenderFragment? null The content placed before the text of the composer, such as a model picker.
ComposerSuffixTemplate RenderFragment? null The content placed beside the send button of the composer.
ComposerTemplate RenderFragment? null The content that replaces the whole composer. Whatever it holds submits through the session (ActiveSession) itself.
Conversation BitAiConversation? null The conversation to show, such as one restored from history. Used only when no Session is supplied - a supplied session owns its own conversation. Passing another one switches the chat to it: the session the chat created for the old one is replaced.
EmptyBody string? null The supporting line of the empty state. Defaults to the EmptyBody of the string table ("Ask a question to get started.").
EmptyTemplate RenderFragment? null The content that replaces the empty state (and with it EmptyTitle, EmptyBody and Suggestions) while the conversation has no message to show - the system messages it hides do not count.
EmptyTitle string? null The heading of the empty state. Defaults to the EmptyTitle of the string table ("How can I help?").
FooterTemplate RenderFragment? null The content below the composer, outside the scroll area, such as a disclaimer.
HeaderTemplate RenderFragment? null The content above the transcript, outside the scroll area, such as a title bar.
HideSystemMessages bool true Hides the system (and developer) messages from the transcript. Turned off, they are shown as a centered note.
ListFooterTemplate RenderFragment? null The content at the bottom of the scroll area, below the last message.
ListHeaderTemplate RenderFragment? null The content at the top of the scroll area, above the first message. Past BitAiUiOptions.VirtualizeThreshold messages it is drawn once the reader has scrolled up to the first message, along with it.
MaxAttachmentSize long 10485760 The largest file the composer will stage, in bytes (10 MB by default). A larger one is turned away, the user is told, and OnAttachmentRejected is raised.
Mentions IReadOnlyList<BitAiMentionItem>? null The items offered when the user types an at sign in the composer: files, people or data sources the application resolves by their Id later. A chosen one is inserted as @Label.
MessageTemplate RenderFragment<BitAiMessage>? null The template that replaces how a message is rendered. It is keyed by the message and adds no element of its own; render a BitAiChatMessage inside it to keep the built-in streaming, parts and actions.
OnAttachmentRejected EventCallback<BitAiAttachmentRejection> The callback for each file the composer turns away (too large, of a type it does not take, one too many). The user is told either way; this is the same information for the application.
OnCitationClick EventCallback<BitAiCitation> The callback for when the user activates a numbered citation in a reply.
OnFeedback EventCallback<BitAiMessageFeedback> The callback for when the user records feedback on a reply (thumbs up or down, or withdrawn), so a host can persist it. The message's Feedback is already updated when it is raised.
OnSourceClick EventCallback<BitAiCitationSource> The callback for when the user activates a source card in the list of sources under a reply.
OnSubmit EventCallback<BitAiPromptSubmission> The callback for when the user submits (the composer or a suggestion). Handle it to submit yourself - after uploading the attachments, or adding context to the text - through the session; leave it unset and the chat submits to the session.
Placeholder string? null The placeholder of the composer, which is also its accessible name. Defaults to the PromptPlaceholder of the string table ("Send a message...").
Session BitAiChatSession? null The session to drive. When unset, the chat creates one - through the registered BitAiChatSessionFactory, or over the registered IBitAiTransport - and disposes it with itself; a supplied session belongs to the page, which disposes it.
SessionOptions BitAiChatSessionOptions? null The settings of a session this component creates. Ignored when a Session is supplied, which carries its own. Left null, the defaults configured with AddBitBlazorUIAIServices (ai.ConfigureSessions) apply. Options that name no Strings take the ones of the UI options in force, and SmoothStreaming off in those options drops their Pacing.
Styles BitAiChatClassStyles? null Custom CSS styles for different parts of the chat.
Suggestions IReadOnlyList<string>? null The example prompts offered in the empty state. A tap submits one as it is.
UiOptions BitAiUiOptions? null The presentation settings of everything inside this chat (the string table, the render interval, what a message shows), in place of the ones a BitAiOptionsProvider cascades or AddBitBlazorUIAIServices registers - a whole record, not merged with them. A session the chat creates follows them too: its errors are worded in their Strings, and with SmoothStreaming off its text is not paced.

BitAiChat public members

Name Type Default value Description
ActiveSession BitAiChatSession The session in use, whether supplied through Session or created by the chat. Reading it before the first render creates the chat's own session.
ActiveConversation BitAiConversation The conversation in use, the one of ActiveSession.
FocusComposerAsync ValueTask Puts the caret in the composer. Does nothing when a ComposerTemplate replaces it.

BitComponentBase parameters

Name Type Default value Description
AriaLabel string? null Gets or sets the accessible label for the component, used by assistive technologies.
Class string? null Gets or sets the CSS class name(s) to apply to the rendered element.
Dir BitDir? null Gets or sets the text directionality for the component's content.
Disabled bool false Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction.
ForceAnimation bool false Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested.
HtmlAttributes Dictionary<string, object> new Dictionary<string, object>() Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. An attribute written on the component wins over an entry of the same name.
Id string? null Gets or sets the unique identifier for the component's root element.
Style string? null Gets or sets the CSS style string to apply to the rendered element.
TabIndex string? null Gets or sets the tab order index for the component when navigating with the keyboard.
Visibility BitVisibility BitVisibility.Visible Gets or sets the visibility state (visible, hidden, or collapsed) of the component.

BitComponentBase public members

Name Type Default value Description
UniqueId Guid Guid.NewGuid() Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed.
RootElement ElementReference Gets the reference to the root HTML element associated with this component.

BitAiChatClassStyles properties

Name Type Default value Description
Root string? null Custom CSS classes/styles for the root element of the BitAiChat.
MessageList BitAiMessageListClassStyles? null Custom CSS classes/styles for the BitAiMessageList (the transcript) of the BitAiChat.
EmptyState BitAiEmptyStateClassStyles? null Custom CSS classes/styles for the BitAiEmptyState of the BitAiChat.
Footer string? null Custom CSS classes/styles for the footer of the BitAiChat, which holds the composer.
FooterColumn string? null Custom CSS classes/styles for the column inside the footer of the BitAiChat, which lines the composer up with the messages above it.
ScrollToLatest BitAiScrollToLatestClassStyles? null Custom CSS classes/styles for the BitAiScrollToLatest of the BitAiChat.

BitAiChatSession properties

Drives one conversation: submission, streaming, tool execution, approval, cancellation, retry and regeneration. Create one with the injected BitAiChatSessionFactory (Create(conversation, options)), which brings the registered transport, tools and approval policy, or with new BitAiChatSession(transport, conversation, options, ...). Submitting while a turn is in flight is a no-op. Dispose it (DisposeAsync) when the page goes: that cancels the turn in flight and detaches every handler.

Name Type Default value Description
Conversation BitAiConversation The conversation this session drives, given to its constructor or created with it.
Options BitAiChatSessionOptions new() The settings in force, given to its constructor. It is settable - assign a changed copy (session.Options with { ... }) - and each turn reads the ones in force as it starts.
Processor BitAiConversationStreamProcessor The reducer that applies the events of the transport to the conversation: it turns them into parts, tool calls, artifacts and agent steps. Its EventApplied event is raised for every event once it is applied, which suits logging and tracing.
Strings BitAiStrings BitAiStrings.Default The text of the errors the session writes itself: the Strings of its Options, else BitAiStrings.Default.
IsGenerating bool false True while a turn is in flight.
LastError BitAiError? null The failure of the last turn, cleared when a new turn starts.
SubmitAsync(text, attachments?, cancellationToken?) Task<BitAiMessage?> Appends a user message (the text may be empty when attachments carry the request) and generates a reply. Returns the assistant message, or null when a turn was already running.
RegenerateAsync(messageId?, cancellationToken?) Task<BitAiMessage?> Regenerates an assistant message - the most recent one when no id is given - discarding it and everything after it. Returns the new assistant message, or null when there was no assistant message to regenerate or a turn was already running.
RetryAsync(cancellationToken?) Task<BitAiMessage?> Retries the last turn after a failure: the failed assistant message is removed and the user message before it is answered again. Returns null when the conversation is empty or a turn was already running.
EditAsync(messageId, text, cancellationToken?) Task<BitAiMessage?> Replaces the text of a user message and regenerates everything after it. Returns null when no user message of that id was found or a turn was already running.
Stop() void Stops the current turn. The partial answer is kept and marked cancelled. Safe to call from any thread, and a no-op with no turn in flight.
Approve(toolCallId, decision) bool Records a human decision (a BitAiApprovalDecision) on a tool call that is waiting for one. Returns false, changing nothing, when no call of that id is waiting - it has run, been decided or been cancelled, or is not known.
RespondToAgentAsync(runId, answer, cancellationToken?) Task<BitAiMessage?> Answers a question an agent run is blocked on (appended as a user message), then continues the turn. Returns null when that run was not waiting for input or a turn was already running.
StateChanged event Action? Raised whenever anything the UI cares about changes. Coarse by design and raised from whatever thread the stream is on: marshal it with InvokeAsync, and coalesce the renders it asks for.
TurnCompleted event Action<BitAiMessage>? Raised when a turn ends, successfully or not, with its assistant message.
ApprovalRequested event Action<BitAiToolCallPart>? Raised when a tool call needs a human decision.
DisposeAsync() ValueTask Ends the session: cancels the turn in flight and any decision it waits for, and detaches every handler, so no event is raised after it. A session the page created is the page's to dispose; one a BitAiChat created, the chat disposes.

BitAiChatSessionOptions properties

The settings of a BitAiChatSession, an immutable record. Every one has a defensible default: tools execute automatically, destructive ones ask first, and a runaway tool loop is bounded. AddBitBlazorUIAIServices sets the defaults of the sessions its factory creates (ai.ConfigureSessions).

Name Type Default value Description
AutoTitle bool true Derives the title of the conversation from the first user message when it has none.
CatchTransportExceptions bool true Whether a failed turn only leaves a retryable error on the assistant message, rather than throwing. Either way the message ends failed with the error on it; turned off, the exception also reaches the caller of the turn (SubmitAsync and the rest).
ExecuteTools bool true Executes the tool calls of the model in the session. Turn it off when the transport runs the tools on the server and only reports them as events.
MaxToolRoundtrips int 10 How many times the session feeds tool results back and asks the model again in one turn - the bound that keeps a model calling tools in a loop from spending without end.
Pacing BitAiTextPacingOptions? BitAiTextPacingOptions.Default Evens out bursty text output so it renders at a steady rate. Null renders the deltas exactly as the transport produces them; contradicting settings throw when the options are built.
RequestOptions BitAiRequestOptions? null The generation settings (the model, the temperature, the token limit, ...) passed to the transport on every request.
Strings BitAiStrings? null The text of the errors the session writes itself: a stopped or timed-out turn, a declined tool call, the tool loop limit. Null uses the strings of the UI options in force where the session is created by the factory or a BitAiChat, else BitAiStrings.Default.
Timeout TimeSpan? null How long to wait for the whole turn, tool round trips included. Null sets no limit beyond what the transport enforces.
ToolResultHoldTime TimeSpan 10 seconds How long a tool result the transport reports ahead of the call it answers is held for that call to start. A call that starts in time is given the result and is not run again; when none has, the result is dropped, leaving an error part (code orphaned_tool_result, carrying a BitAiOrphanedToolResultException) on the message, and the session logs it. Zero drops such a result at once; a negative value throws when the options are built.

BitVisibility enum

Name Value Description
Visible 0 The content of the component is visible.
Hidden 1 The content of the component is hidden, but the space it takes on the page remains (visibility:hidden).
Collapsed 2 The component is hidden (display:none).

BitDir enum

Name Value Description
Ltr 0 Ltr (left to right) is to be used for languages that are written from the left to the right (like English).
Rtl 1 Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic).
Auto 2 Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element.

Feedback

Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.