AI scenarios
Basic chat
Bit.BlazorUI.AI Scripted transportA working chat in three lines of markup. The session comes from the registered transport, and everything else is default behaviour.
Live demo
Send anything, or pick a starter prompt: the transport registered for the whole site echoes it back a few characters at a time.
A chat over the registered transport
How it works
BitAiChatSessionFactory creates a BitAiChatSession over the
IBitAiTransport registered with AddBitBlazorUIAIServices, and the session drives a
BitAiConversation. BitAiChat renders that conversation - the transcript, the
composer, the empty state with its starter prompts and the scroll-to-latest button - and sends what the
user writes through the session. The transport here is twenty lines of scripted C#; a real one wraps a
provider's SDK, and nothing on the UI side changes.
Sending a message is one turn. The session appends the user message (BitAiChatSession.SubmitAsync),
opens an empty assistant message, and calls the transport's one method,
StreamAsync(BitAiRequest, CancellationToken). The BitAiRequest carries the
conversation so far (Messages, oldest first, each an IBitAiMessage with its parts and
attachments), its ConversationId, the session's generation settings (Options), the
definitions of the tools the model may call (Tools) and the scoped Services. The
transport answers with a stream of BitAiEvents, which the session applies to the assistant
message as they arrive. This echo sends the smallest useful sequence:
BitAiMessageStartedEvent- the reply has begun, so the thinking indicator can show at once.BitAiTextDeltaEvent, three characters at a time - each one appended to the reply's text part.BitAiUsageUpdatedEvent- the tokens it used, shown under the reply (the site turnsShowUsageon).BitAiMessageCompletedEvent- the reply is finished, and the message actions appear under it.
Only the text deltas are required: the session opens the message itself on the first one, and closes it when
the stream ends. The stop button cancels the token the transport was handed, so a transport that honours it
promptly stops at once and keeps what it had written; one that fails reports it with a
BitAiErrorEvent rather than throwing (see Errors and retry).
The AiScriptedTransport.cs tab holds the helpers every scenario's script is written with
(AiScriptedTransport, AiScript); the EchoTransport.cs tab is the same echo
as a class of its own, without them - the shape of the class an app writes.
Press Enter to send, Shift and Enter for a newline. The composer grows as you type and stops at twelve rows; while a reply streams, its send button becomes a stop button. The chat takes the height of its container, so give that container one.
Registration
AddBitBlazorUIAIServices registers the package (and the core services it builds on, so it
replaces the AddBitBlazorUIServices line), then hands its callback a BitAiBuilder,
which configures everything else in one statement:
UseTransport<TTransport>(),UseTransport(transport)orUseTransport(services => ...)- the transport the factory's sessions stream from: a scoped type, one shared instance, or one built from services.AddTool(tool)andAddTool<TTool>()- the tools the model may call (Tool calling).UseApprovalPolicy<TPolicy>()- which calls wait for a human decision (Tool approval).AddModels(models, providers, defaultModelId)- the models the user can pick between (Models and usage).UseConversationStore<TStore>()- where conversations are kept (Conversations).ConfigureSessions(options => options with { ... })- theBitAiChatSessionOptionsevery session of the factory starts with: the tool loop limit, text pacing, the timeout, the request options (Streaming, Parallel tools).ConfigureUi(options => options with { ... })- the presentation defaults of the components (Options & theming).ConfigureRenderers(renderers => ...)- the app's own views for a tool, a structured schema, an artifact kind or a part kind (Custom tool UI, Forms).ConfigureGenerativeUi(registry => ...)- the components model output may render (Generative UI).Services- the service collection itself, for anything else the transport or the tools need.
Calling AddBitBlazorUIAIServices again with another callback adds to what an earlier call set
up - a module of the app can register its own tools - since nothing is registered twice. Its
trySingleton flag is for WebAssembly and Hybrid only: on Blazor Server the default approval
policy remembers one user's "allow always", and a singleton would share it with every other user.
Components used
BitAiChat- the whole chat surface over one session.BitAiMessageListandBitAiChatMessage- the transcript it renders.BitAiPromptInput- the composer under it.BitAiEmptyState- the title, the line under it and the starter prompts of an empty conversation.BitAiThinkingIndicator- what shows between sending and the first character of the reply.BitAiMessageActions- the row under a finished reply: copy, regenerate, feedback and its usage.BitAiScrollToLatest- the way back to the newest message after scrolling up.
Feedback
Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.