Documented the Confluence search tool and its implied Read Web Page selection

This commit is contained in:
Thorsten Sommer 2026-09-23 16:44:48 +02:00
parent 637fe5d3e7
commit 291bbf02ed
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
3 changed files with 33 additions and 0 deletions

View File

@ -51,6 +51,8 @@ public partial class ToolSelectionField : MSGComponentBase
protected override void OnParametersSet() 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); this.SelectedToolIds = ToolSelectionRules.NormalizeSelection(this.SelectedToolIds);
base.OnParametersSet(); base.OnParametersSet();
} }

View File

@ -8,6 +8,24 @@ using AIStudio.Tools.Web;
namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations; namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations;
/// <summary>
/// Searches the organization's Confluence Data Center wiki and returns the search page with
/// its result links.
/// </summary>
/// <remarks>
/// 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.<br/><br/>
/// 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.<br/><br/>
/// 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.
/// </remarks>
public sealed class ConfluenceSearchTool(WebPageRetrievalService webPageRetrievalService, PromptInjectionGuardService promptInjectionGuardService) : IToolImplementation public sealed class ConfluenceSearchTool(WebPageRetrievalService webPageRetrievalService, PromptInjectionGuardService promptInjectionGuardService) : IToolImplementation
{ {
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfluenceSearchTool).Namespace, nameof(ConfluenceSearchTool)); private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ConfluenceSearchTool).Namespace, nameof(ConfluenceSearchTool));

View File

@ -10,6 +10,19 @@ public static class ToolSelectionRules
public const string READ_WEB_PAGE_TOOL_ID = "read_web_page"; public const string READ_WEB_PAGE_TOOL_ID = "read_web_page";
public const string SEARCH_CONFLUENCE_TOOL_ID = "search_confluence"; public const string SEARCH_CONFLUENCE_TOOL_ID = "search_confluence";
/// <summary>
/// Turns a set of selected tool IDs into the set which actually runs.
/// </summary>
/// <remarks>
/// 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.<br/><br/>
/// 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.
/// </remarks>
public static HashSet<string> NormalizeSelection(IEnumerable<string> selectedToolIds) public static HashSet<string> NormalizeSelection(IEnumerable<string> selectedToolIds)
{ {
var normalized = selectedToolIds.ToHashSet(StringComparer.Ordinal); var normalized = selectedToolIds.ToHashSet(StringComparer.Ordinal);