Curiosity
Two-column slide with C# code panel and callouts highlighting search tool method features.

A permission-aware search tool

The most common tool pattern: search the workspace on the user's behalf and register citations.

[Tool("Search support tickets. Use when user describes a problem or asks 'have we seen this?'")]
public static async Task<string> SearchTickets(ToolScope scope,
    [Parameter("User's question or symptom description", required: true)] string query,
    [Parameter("Optional product SKU to scope the search", required: false)] string productSku,
    [Parameter("Max results to return (default 5)", required: false)] int limit)
{
    var search = SearchRequest.For(query);
    search.BeforeTypesFacet = new(["Ticket"]);

    if (!string.IsNullOrWhiteSpace(productSku))
        search.TargetUIDs = scope.Graph.Q()
            .StartAt("Product", productSku).In("ForProduct")
            .AsUIDEnumerable().ToArray();

    var results = (await scope.Graph.CreateSearchAsUserAsync(
        search, scope.CurrentUser, scope.CancellationToken)).Take(limit > 0 ? limit : 5);

    var output = results.Select(n => {
        var text = scope.ChatAI.GetTextFromNode(n.UID, limit: 4000);
        var id   = scope.AddSnippet(uid: n.UID, text: text);   // register citation
        return new { snippetId = id, subject = n.GetString("Subject") };
    }).ToArray();

    scope.SetToolCallDisplayName($"Searched tickets for '{query}'");
    return output.ToJson();
}

Three things to note: CurrentUser threads the user's identity through the search, TargetUIDs scopes by graph, AddSnippet wires citations into the chat response.

AI tools