diff --git a/app/MindWork AI Studio/Components/ToolSelectionField.razor.cs b/app/MindWork AI Studio/Components/ToolSelectionField.razor.cs
index 45c82150..4aa03e75 100644
--- a/app/MindWork AI Studio/Components/ToolSelectionField.razor.cs
+++ b/app/MindWork AI Studio/Components/ToolSelectionField.razor.cs
@@ -51,6 +51,8 @@ public partial class ToolSelectionField : MSGComponentBase
protected override void OnParametersSet()
{
+ // Like ToolSelection, the field shows the tools which will actually run, also when the
+ // selection is read-only. See ToolSelectionRules.NormalizeSelection:
this.SelectedToolIds = ToolSelectionRules.NormalizeSelection(this.SelectedToolIds);
base.OnParametersSet();
}
diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/ConfluenceSearchTool.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/ConfluenceSearchTool.cs
index f79a78bf..17a1e177 100644
--- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/ConfluenceSearchTool.cs
+++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/ConfluenceSearchTool.cs
@@ -8,6 +8,24 @@ using AIStudio.Tools.Web;
namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations;
+///
+/// Searches the organization's Confluence Data Center wiki and returns the search page with
+/// its result links.
+///
+///
+/// The tool loads the wiki's own search page, dosearchsite.action, through the same page reader
+/// as Read Web Page. That way it needs no API token: Confluence Data Center accepts the operating
+/// system's sign-in, and the reader already brings the protections against a request leading
+/// somewhere else. The price is a dependency on the HTML of that page, and Confluence Cloud stays
+/// out, because it offers neither that page nor that sign-in. Both change once the tool uses
+/// Confluence's REST API. The model only passes words and a space key; the tool builds the CQL
+/// itself, so a model cannot turn the search into another query.
+/// The search page shows excerpts only. To read a result, the model opens it with Read Web Page,
+/// which is why selecting this tool also selects that one, see ToolSelectionRules.NormalizeSelection.
+/// Whatever the wiki returns is internal to the organization. The tool is therefore offered to
+/// High-confidence providers only, checks that again before each search, and raises the chat's
+/// required confidence to High, so the results never reach a less trusted provider later on.
+///
public sealed class ConfluenceSearchTool(WebPageRetrievalService webPageRetrievalService, PromptInjectionGuardService promptInjectionGuardService) : IToolImplementation
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfluenceSearchTool).Namespace, nameof(ConfluenceSearchTool));
diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSelectionRules.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSelectionRules.cs
index 5aaada34..79022924 100644
--- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSelectionRules.cs
+++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSelectionRules.cs
@@ -10,6 +10,19 @@ public static class ToolSelectionRules
public const string READ_WEB_PAGE_TOOL_ID = "read_web_page";
public const string SEARCH_CONFLUENCE_TOOL_ID = "search_confluence";
+ ///
+ /// Turns a set of selected tool IDs into the set which actually runs.
+ ///
+ ///
+ /// Removes duplicates and adds the tools another one depends on: Search Confluence only finds
+ /// pages, so it brings Read Web Page along to open them. An added tool keeps its own rules.
+ /// ToolRegistry still drops it when it is switched off or the provider's confidence is too
+ /// low, and Read Web Page reaches a wiki on a private or VPN address only when its host is
+ /// allowed there.
+ /// Every place which shows or stores a selection normalizes it, the tool selection fields
+ /// included. That way a chat, a template, a policy, or an assistant plugin shows the tools
+ /// which will actually run, and the audit of a plugin judges exactly those.
+ ///
public static HashSet NormalizeSelection(IEnumerable selectedToolIds)
{
var normalized = selectedToolIds.ToHashSet(StringComparer.Ordinal);