
Grounded generation (RAG)
Retrieval-Augmented Generation: retrieve relevant context, send it to the LLM, get a grounded answer with citations.
// 1. Retrieve — permission-aware search
var search = SearchRequest.For(userQuery);
var hits = (await Graph.CreateSearchAsUserAsync(search, CurrentUser, ct)).Take(8).ToArray();
// 2. Format — build numbered context for the prompt
var snippets = hits.Select((n, i) => new {
id = i + 1,
uid = n.UID,
text = Graph.GetIndexedText(n.UID, maxChars: 4000)
}).ToArray();
// 3. Generate — call the LLM with context
var prompt = $"""
Answer using ONLY the snippets below. Cite sources as [1], [2], etc.
{string.Join("\n", snippets.Select(s => $"[{s.id}] {s.text}"))}
Question: {userQuery}
""";
var answer = await Graph.CallChatModelAsync(prompt, ct);
return new { answer, citations = snippets };
Why grounding matters: without retrieved context, the LLM halluccinates. With it, answers are traceable — every claim maps to a node in the workspace that the user can open and verify.