Crux
GuidesRetrieval & RAG

Grounding And Citations

Inject retrieved evidence, expose search tools, and validate that answers cite allowed sources.

Use plain retrieval when a prompt needs helpful background. Use grounding() when the answer must cite retrieved evidence and Crux should validate that citation contract.

import { prompt } from "@use-crux/core";
import { citationSchema, grounding } from "@use-crux/core/citations";
import { z } from "zod";

const groundedDocs = grounding({
  id: "docs-grounding",
  retriever: docs.retriever(),
  query: ({ input }) => input.question as string,
  limit: 6,
  citations: {
    required: true,
    quotes: "required",
  },
});

export const answerDocs = prompt({
  id: "answer-docs",
  use: [groundedDocs],
  input: z.object({ question: z.string() }),
  output: z.object({
    answer: z.string(),
    citations: z.array(citationSchema),
  }),
  system: "Answer only from the provided sources.",
  prompt: ({ input }) => input.question,
});

Knowledge bases and recipes expose convenience forms:

const groundedKnowledgeBase = docs.grounding({
  query: ({ input }) => input.question as string,
});

const groundedRecipe = docsAnswer.asGrounding({
  query: ({ input }) => input.question as string,
  citations: { required: true },
});

Injection Modes

Grounding can inject retrieved context directly, expose search tools, or do both.

const baseGrounding = {
  id: "docs-grounding",
  retriever: docs.retriever(),
  citations: { required: true },
};

grounding({
  ...baseGrounding,
  inject: "context",
  query: ({ input }) => input.question as string,
});

grounding({
  ...baseGrounding,
  inject: "tool",
  tools: { prefix: "docs", include: ["search", "getSource"] },
});

grounding({
  ...baseGrounding,
  inject: "both",
  query: ({ input }) => input.question as string,
  tools: { prefix: "docs", include: ["search", "getSource"] },
});

Use context when the prompt should always receive evidence before generation. Use tool when the model should decide whether to search. Use both when an assistant should start with likely evidence and still have lookup tools for follow-up questions.

Tool-only grounding does not require a query up front. If the model cites a source before searching, citation validation fails with a clear unknown-hit issue.

Grounding Session

Each grounded generation has a grounding session. The session records:

  • hits injected as context
  • hits returned by retrieval tools

Retrieval tools return typed crux.retrieval.hits payloads. The tool middleware records those payloads into the session, and citation validation reads the session at validation time. Crux does not parse tool strings or close over mutable hit arrays.

This keeps single-process runtimes and serialized runtimes aligned: adapters can reconstruct the session from persisted typed tool results without maintaining a second evidence table.

Tool Visibility

The search tool returns lean evidence: source identity, score, content, and URL when present. It does not expose internal provenance by default.

getSource has explicit visibility:

grounding({
  id: "docs-grounding",
  retriever: docs.retriever(),
  inject: "tool",
  tools: {
    prefix: "docs",
    include: ["search", "getSource"],
    getSource: { visibility: "discovered" },
  },
});
VisibilityMeaning
discoveredgetSource can read only hits already recorded in the grounding session.
namespacegetSource can read any active indexed chunk in the retriever namespace.

Use namespace visibility when you want the model to expand known source ids. Use discovered visibility when source access should stay tied to prior search results.

Rendering

Default rendering is source-oriented and citation friendly. Customize it when your UI needs page numbers, URLs, titles, or domain-specific labels.

const groundedDocs = grounding({
  id: "docs-grounding",
  retriever: docs.retriever(),
  query: ({ input }) => input.question as string,
  render: ({ hits }) =>
    hits
      .map((hit, index) => {
        const label = `${hit.source.id}/${hit.chunkId}`;
        return `[${index + 1}] ${label}\n${hit.content}`;
      })
      .join("\n\n"),
});

What Grounding Validates

Grounding validates that the answer follows the citation contract:

grounding({
  id: "docs-grounding",
  retriever: docs.retriever(),
  citations: {
    required: true,
    quotes: "required",
  },
});

Typical constraints:

SettingMeaning
required: trueThe answer must cite retrieved or searched evidence.
quotes: 'required'Citations must include quote text from the evidence.
selectRead citations from a custom output shape.

Use normal retriever context when citations are helpful but not contractual. Use grounding when the output schema, review workflow, or user experience depends on citations being structured and checkable.

On this page