Grounding Policy¶
The grounding policy system controls what context reaches the LLM during synthesis: RAG chunk text, full canonical document attachments, or both. It provides a single decideGrounding() function that evaluates a GroundingPolicy against available inputs and returns a GroundingDecision.
This is the final stage of the Knowledge Base pipeline, applied just before the LLM synthesis call.
Import¶
import { decideGrounding, type GroundingPolicy, type GroundingDecision } from "@modernpath/agent-framework";
decideGrounding()¶
Evaluate a grounding policy and decide what inputs to send to the model.
function decideGrounding(args: {
retrievedText?: string;
preparedDocuments?: PreparedDocument[];
policy?: GroundingPolicy;
}): GroundingDecision
| Parameter | Type | Description |
|---|---|---|
args.retrievedText | string | RAG-retrieved text (chunk context from RetrievalService). |
args.preparedDocuments | PreparedDocument[] | Canonical documents prepared by CanonicalGroundingService. |
args.policy | GroundingPolicy | Policy configuration (defaults to { mode: "hybrid" }). |
Returns: A GroundingDecision indicating exactly what should be sent to the model.
Basic usage
const decision = decideGrounding({
retrievedText: ragAnswer.text,
preparedDocuments: groundingResult.allDocumentsForAttachment,
policy: { mode: "attachments_only" },
});
// Build the synthesis prompt:
const prompt = decision.retrievedTextForPrompt
? `Context:\n${decision.retrievedTextForPrompt}\n\nQuestion: ${userQuery}`
: `Question: ${userQuery}`;
// Attach documents if decision says so:
const options = decision.includeAttachments
? DocumentAttachment.getGeminiOptions(groundingResult.allDocumentsForAttachment)
: {};
const result = await client.generateContent(prompt, options);
GroundingPolicy¶
interface GroundingPolicy {
mode?: GroundingMode;
canonical?: {
whenAvailable?: CanonicalWhenAvailable;
};
chunks?: {
includeRetrievedText?: boolean;
maxChars?: number;
};
}
mode¶
| Mode | Description |
|---|---|
"chunks_only" | Only RAG chunk text is sent to the model. No document attachments. |
"attachments_only" | Only full canonical documents are attached. RAG text is excluded from the prompt. |
"hybrid" | (Default) Both RAG text and canonical documents are used. Behavior refined by sub-options. |
canonical.whenAvailable¶
Controls hybrid mode behavior when canonical attachments are available.
| Value | Description |
|---|---|
"prefer_attachments" | When canonical documents are available, exclude RAG text from the prompt (use attachments only). |
"augment_chunks" | (Default) Send both RAG text and canonical attachments. More context, but higher token usage. |
chunks.includeRetrievedText¶
Explicit override for whether RAG text is included in the prompt. When set, overrides the mode-based default.
chunks.maxChars¶
Truncate RAG text to this many characters. Helps reduce token usage and limits the surface for prompt injection from retrieved content. Default: no truncation.
GroundingDecision¶
The output of decideGrounding().
interface GroundingDecision {
/** RAG text for the prompt (possibly truncated), or "" if excluded. */
retrievedTextForPrompt: string;
/** Whether canonical documents should be attached to the model call. */
includeAttachments: boolean;
/** Whether retrieved text is included (after policy + truncation). */
includeRetrievedText: boolean;
}
Mode Behavior Matrix¶
The following table shows the default behavior for each mode, assuming both RAG text and canonical documents are available:
| Mode | retrievedTextForPrompt | includeAttachments | Notes |
|---|---|---|---|
chunks_only | RAG text | false | Simplest mode. No document fetching needed. |
attachments_only | "" | true | Full documents only. |
attachments_only (no docs available) | RAG text | true | Graceful fallback: if no documents were resolved, RAG text is included to avoid starving the model. |
hybrid + augment_chunks | RAG text | true | Both sources. Maximum context. |
hybrid + prefer_attachments (docs available) | "" | true | Attachments replace chunks when available. |
hybrid + prefer_attachments (no docs) | RAG text | true | Falls back to chunks when no attachments. |
Examples¶
Chunks Only¶
The simplest mode. Use when you do not need full document attachments.
const decision = decideGrounding({
retrievedText: "The supply temperature should be between 60-80C...",
policy: { mode: "chunks_only" },
});
// decision.retrievedTextForPrompt = "The supply temperature should be between 60-80C..."
// decision.includeAttachments = false
// decision.includeRetrievedText = true
Attachments Only¶
Use when you want the model to work exclusively from canonical documents. RAG is used only for document selection, not for prompt context.
const decision = decideGrounding({
retrievedText: "The supply temperature should be...",
preparedDocuments: [sopDocument],
policy: { mode: "attachments_only" },
});
// decision.retrievedTextForPrompt = ""
// decision.includeAttachments = true
// decision.includeRetrievedText = false
Graceful fallback
In attachments_only mode, if no canonical documents were resolved (e.g. metadata is missing or all fetches failed), the function falls back to including RAG text so the model is not left without any context.
Hybrid with Truncation¶
Send both, but limit RAG text to control token usage:
const decision = decideGrounding({
retrievedText: longRetrievedText,
preparedDocuments: [doc1, doc2],
policy: {
mode: "hybrid",
canonical: { whenAvailable: "augment_chunks" },
chunks: { maxChars: 2000 },
},
});
// decision.retrievedTextForPrompt = first 2000 chars + "\n... [truncated]"
// decision.includeAttachments = true
Hybrid with Attachment Preference¶
In hybrid mode, when canonical documents are available, use them exclusively:
const decision = decideGrounding({
retrievedText: "Some RAG context...",
preparedDocuments: [sopDocument],
policy: {
mode: "hybrid",
canonical: { whenAvailable: "prefer_attachments" },
},
});
// decision.retrievedTextForPrompt = "" (attachments take over)
// decision.includeAttachments = true
Integration Pattern¶
A typical agent synthesis step uses decideGrounding() as follows:
import {
RetrievalService,
CanonicalGroundingService,
decideGrounding,
DocumentAttachment,
GeminiClient,
} from "@modernpath/agent-framework";
async function synthesize(
query: string,
retrieval: RetrievalService,
grounding: CanonicalGroundingService,
client: GeminiClient,
ctx: { userId: number; auditingId: number },
policy: GroundingPolicy,
) {
// Step 1: Retrieve
const answer = await retrieval.search(query, "hvac-kb");
// Step 2: Resolve canonical documents
const canonical = await grounding.prepareFromSources(answer.sources, ctx);
// Step 3: Apply grounding policy
const decision = decideGrounding({
retrievedText: answer.text,
preparedDocuments: canonical.allDocumentsForAttachment,
policy,
});
// Step 4: Build prompt
const prompt = decision.retrievedTextForPrompt
? `Context:\n${decision.retrievedTextForPrompt}\n\nQuestion: ${query}`
: `Answer the following question: ${query}`;
// Step 5: Attach documents if needed
const geminiOpts = decision.includeAttachments
? DocumentAttachment.getGeminiOptions(canonical.allDocumentsForAttachment)
: {};
// Step 6: Generate
return await client.generateContent(prompt, {
systemPrompt: "You are an HVAC expert. Answer based on the provided documents.",
...geminiOpts,
});
}
Types Reference¶
GroundingMode¶
CanonicalWhenAvailable¶
Related Pages¶
- Knowledge Base Overview -- full RAG pipeline
- Retrieval -- generates the
retrievedTextinput - Canonical Grounding -- generates the
preparedDocumentsinput - Document Composition -- expands document includes before grounding