Skip to content

AI

AiToolApproval

Bit.BlazorUI.AI

BitAiToolApproval is the prompt shown when a tool call needs a human decision. It offers three answers, from the most cautious to the most permissive - decline, always allow, allow - because allowing once and allowing always are different decisions. The prompt follows the risk the tool declares: the allow button of a destructive tool is drawn in the error role and the prompt is washed with it, so the answer that runs it never looks like the safe one. The decision goes to the session that is waiting, which resumes the paused turn.

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.

A BitAiToolCallView ends in this prompt by itself while its call waits for a decision; render one yourself for an approval UI of your own. Which calls wait is the IBitAiToolApprovalPolicy's call: the default one asks for every tool declared Destructive (or RequiresApproval) and remembers the tools a user allowed always, which is why it is registered scoped: never pass trySingleton on Blazor Server, where a singleton would carry one user's "always" over to everyone. The prompt is a group named by its question and its buttons never submit a form, so a conversation inside one is safe. See the Tool approval scenario.

Usage

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

Basic

Hand it the Call waiting for a decision. Without a Session the decision is recorded on the call itself (Approval, and its Status moves to Pending or Rejected), which is what a layout running its own tool loop reads; OnDecision reports it either way. The question names the tool by the Title of its definition, else its name. The decision takes the prompt away with the button it was made with, so the page hands the focus to Ask again.

Allow Archive the thread to run?

Reason

The ApprovalReason of the call - why the approval is asked for, in words that say what will happen - replaces the generic question. The group keeps the generic question as its accessible name unless AriaLabel gives it another.

Send the weekly summary to the 3 people on the thread?
Send the weekly summary to the 3 people on the thread?

Risk

The prompt follows the Risk of the tool's BitAiToolDefinition (see the tables below). A ReadOnly or Write tool is asked about on the warning tint, with the allow button in the primary role; a Destructive one - irreversible or visible outside the app - on the error tint, with the allow button in the error role. The decline button is the first in the order the focus moves in. A call is decided once: a prompt whose call has been decided takes no second answer (as a session refuses one), so Ask again starts over with fresh calls.

Allow Read the logs to run?
Allow Send email to run?
Permanently delete the 128 archived records? This cannot be undone.

Last decision: none yet

Session

With the Session that asked, the decision goes to it (BitAiChatSession.Approve): the paused turn resumes - the tool runs, or is reported to the model as declined. Always allow is remembered by the approval policy, so the next call of the same tool in this session runs without asking. The prompt goes once it is answered, so the page hands the focus back to the button that asked.



Disabled

Disabled turns the three buttons off and decides nothing, and drops the activation handlers the page put on the prompt.

Permanently delete the 128 archived records? This cannot be undone.

Cascading parameters

BitParams with a BitAiToolApprovalParams sets the defaults of every prompt inside it - here the allow buttons of a region drawn round. A prompt keeps what it sets itself: the last one brings its own Styles.

Allow Send email to run?
Permanently delete the 128 archived records? This cannot be undone.
Allow Read the logs to run?

Style & Class

Style and Class land on the root, Styles and Classes on the question, the row of buttons and each of the three buttons (BitButtons, restyled through their own BitButtonClassStyles and --bit-Button-* variables). The public --bit-AiToolApproval-* variables (see the CSS variables table) inherit, so a container restyles every prompt under it.

Allow Send email to run?
Allow Send email to run?
Allow Send email to run?
Permanently delete the 128 archived records? This cannot be undone.
Allow Send email to run?

Permanently delete the 128 archived records? This cannot be undone.

RTL

In right-to-left text the question leads from the right and the buttons follow it. The question and the buttons are the BitAiStrings of the options in force - here a subclass of them, cascaded by a BitAiOptionsProvider.

۱۲۸ رکورد بایگانی‌شده برای همیشه حذف شوند؟ این کار برگشت‌پذیر نیست.

Decision: Undecided

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.

BitAiToolApproval CSS variables

Name Default value Description
--bit-AiToolApproval-color var(--bit-clr-fg-pri) Text of the question.
--bit-AiToolApproval-background var(--bit-clr-wrn-tint) Surface of the prompt.
--bit-AiToolApproval-destructive-background var(--bit-clr-err-tint) Surface of the prompt of a tool declared Destructive, which wins over --bit-AiToolApproval-background.
--bit-AiToolApproval-radius var(--bit-shp-radius-surface) Corner radius of the prompt. Inside a BitAiToolCallView the prompt is the foot of the card and square.
--bit-AiToolApproval-padding spacing(1.5) Inset of the prompt.
--bit-AiToolApproval-gap spacing(1) Room between the question and the buttons, and between the buttons.

API

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

BitAiToolApproval parameters

Name Type Default value Description
Call BitAiToolCallPart The call awaiting a decision (required). Its ApprovalReason is shown as the question when it has one, and the Risk of its Definition decides how the prompt looks - read again on every render, since a session resolves the definition onto the call only as it starts running it. Without a Session, the decision is recorded on it (BitAiToolCallPart.SetApproval).
Classes BitAiToolApprovalClassStyles? null Custom CSS classes for different parts of the tool approval.
OnDecision EventCallback<BitAiApprovalDecision> Raised after a decision - Approved, ApprovedAlways or Rejected - once it has been handed to the session, or recorded on the call when there is none. Nothing is raised while the prompt is disabled, nor for a call that is no longer awaiting a decision - which the session refuses (BitAiChatSession.Approve returns false), and the prompt without one ignores: a call is decided once.
Session BitAiChatSession? null The session that is waiting for the decision, which it is handed to (BitAiChatSession.Approve): that is what resumes the paused turn, and what lets the approval policy remember an always-allow. Required for the decision to take effect in a session; without one, it is only recorded on the Call, which is what a layout driving its own tool loop reads.
Styles BitAiToolApprovalClassStyles? null Custom CSS styles for different parts of the tool approval.

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.

BitAiToolApprovalClassStyles properties

Name Type Default value Description
Root string? null Custom CSS classes/styles for the root element of the BitAiToolApproval.
Text string? null Custom CSS classes/styles for the question (or the reason the approval was asked for) of the BitAiToolApproval.
Actions string? null Custom CSS classes/styles for the row of the answer buttons of the BitAiToolApproval.
RejectButton BitButtonClassStyles? null Custom CSS classes/styles for the decline button of the BitAiToolApproval.
ApproveAlwaysButton BitButtonClassStyles? null Custom CSS classes/styles for the always-allow button of the BitAiToolApproval.
ApproveButton BitButtonClassStyles? null Custom CSS classes/styles for the allow-once button of the BitAiToolApproval.

BitAiToolDefinition properties

The provider-independent description of a tool: what it is called, what it does, what arguments it takes - and how the UI presents it. A tool created with BitAiTool.Create carries one (adjust it through the configure delegate: definition => definition with { Title = ..., Risk = ... }); the session copies it onto every call of the tool (BitAiToolCallPart.Definition).

Name Type Default value Description
BitAiToolDefinition(name) constructor Creates a definition for the tool the model calls by that name.
Name string The identifier the model uses to call the tool.
Title string? null A human-friendly label, which the approval question and the tool card name the tool by.
Description string? null What the tool does - the text the model reads when deciding to call it.
ParametersSchema JsonElement? null A JSON Schema object describing the arguments.
Risk BitAiToolRisk BitAiToolRisk.ReadOnly How much damage the tool can do. The default approval policy asks before every call of a Destructive tool, and the approval prompt of one is drawn in the error role.
RequiresApproval bool? null Whether a human must approve each call before it runs, either way. Left null, the approval policy decides - by default, from the Risk.
Icon string? null The name of the icon drawn on the header of the tool-call card (BitAiToolCallView) in place of the default wrench - a Fabric MDL2 name (BitIconName.*); a name outside the core glyphs needs the Bit.BlazorUI.Icons package.
Metadata IReadOnlyDictionary<string, object?>? null Values of the application's own, carried through to custom tool renderers.
DisplayName string The label to show for the tool: Title, else Name.

IBitAiToolApprovalPolicy properties

Decides which calls wait for a human decision before they run. AddBitBlazorUIAIServices registers BitAiDefaultToolApprovalPolicy - scoped, or a singleton with trySingleton, which a Blazor Server app must not pass since the policy remembers what a user allowed always. Replace it with ai.UseApprovalPolicy<T>() (always scoped), or hand a session one of its own (new BitAiChatSession(transport, approvalPolicy: ...)).

Name Type Default value Description
RequiresApprovalAsync(definition, invocation, cancellationToken?) ValueTask<bool> Whether this call of the tool needs a decision. Handed the definition and the invocation (with the arguments), so a policy of the app's own can decide by argument or by user. A policy that throws is treated as asking for approval.
BitAiDefaultToolApprovalPolicy.RememberAlwaysApproved(toolName) void The default policy asks for every Destructive tool and honours RequiresApproval either way, except for the tools a user allowed always - which the session records here when the decision is ApprovedAlways.

BitAiToolRisk enum

Name Value Description
ReadOnly 0 Reads data and has no side effects.
Write 1 Changes state in a way that can be undone.
Destructive 2 Destructive, irreversible or visible outside the app. The default policy asks before every call, and the prompt is drawn in the error role.

BitAiApprovalDecision enum

Name Value Description
Undecided 0 No decision has been made yet.
Approved 1 Allowed for this call only.
Rejected 2 Declined: the call does not run, and is reported to the model as a failure.
ApprovedAlways 3 Allowed, and later calls of the same tool are not asked about again.

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.