Technology Sep 04, 2026 · 7 min read

Your Gemini Answer Has Citations. Is It Actually Grounded?

Adding citations to an AI answer feels like the moment the system becomes trustworthy. The response looks researched. Source links appear beside the text. The model is no longer answering only from its training data. But a cited answer can still be wrong. A citation may support a nearby sentence...

DE
DEV Community
by Raju Dandigam
Your Gemini Answer Has Citations. Is It Actually Grounded?

Adding citations to an AI answer feels like the moment the system becomes trustworthy.

The response looks researched. Source links appear beside the text. The model is no longer answering only from its training data.

But a cited answer can still be wrong.

A citation may support a nearby sentence rather than the claim the user cares about. A source may be authoritative while the retrieved passage is stale. File Search may query the wrong store or document version. The model may retrieve good evidence and then write a conclusion that goes beyond it.

Grounding is a capability. Trust still requires an application contract.

Series note: This is Part 6 of Reliable Google AI Agents in TypeScript. The Interactions API examples use its post-May-2026 steps schema and were checked against @google/genai 2.21.0. The API remains beta, so pin and retest the SDK before copying production code.

Retrieval success is not answer success

Gemini can ground responses with Google Search for current public information and File Search for indexed domain-specific documents. The Interactions API exposes the execution steps and inline citation annotations, giving the application more evidence than a text completion alone.

A minimal Google Search interaction looks like this:

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

const interaction = await ai.interactions.create({
  model: process.env.GEMINI_MODEL ?? "gemini-3.8-flash",
  input: "What changed in the public policy this week?",
  tools: [{ type: "google_search" }],
});

The synthesized text is only one part of the result. The steps show whether search occurred and where citations attach.

type Citation = {
  title?: string;
  url?: string;
  citedText: string;
};

const citations: Citation[] = [];

for (const step of interaction.steps ?? []) {
  if (step.type !== "model_output") continue;

  for (const contentBlock of step.content ?? []) {
    if (contentBlock.type !== "text") continue;

    for (const annotation of contentBlock.annotations ?? []) {
      if (annotation.type !== "url_citation") continue;

      citations.push({
        title: annotation.title,
        url: annotation.url,
        citedText: contentBlock.text.slice(
          annotation.startIndex,
          annotation.endIndex,
        ),
      });
    }
  }
}

This follows the current JavaScript shape: a model_output step contains text blocks, and url_citation annotations use camel-cased startIndex and endIndex properties in the SDK.

Now the application can do more than render a row of links. It can decide whether the answer satisfied an evidence policy.

Define the evidence contract before the prompt

Evidence requirements should depend on risk. A casual summary and a policy answer should not share the same release rule.

type EvidenceContract = {
  groundingRequired: boolean;
  minimumCitations: number;
  requireCitationForEveryMaterialClaim: boolean;
  allowedSourceTypes: Array<"web" | "file_search">;
  onMissingEvidence: "suppress" | "degrade" | "human_review";
};

const contract: EvidenceContract = {
  groundingRequired: true,
  minimumCitations: 2,
  requireCitationForEveryMaterialClaim: true,
  allowedSourceTypes: ["web"],
  onMissingEvidence: "suppress",
};

“At least two citations” is only a structural check. It does not prove that every material claim is supported. But the contract forces the team to define the expected evidence and failure behavior before a polished answer appears.

The runtime can check deterministically that:

  • the required grounding tool ran;
  • the response contains citation annotations;
  • the intended File Search store and metadata filter were used;
  • an ungrounded fallback did not silently reach the user;
  • a suppression or human-review path ran when evidence was missing.

Semantic entailment still requires a targeted evaluator or human review. Separate what the system can prove from what it merely hopes.

Search and File Search solve different problems

Google Search is appropriate when the answer depends on current public information. File Search is appropriate when the source of truth is a controlled corpus: product documentation, policies, support material, research notes, or organizational knowledge.

Mixing them without a policy creates plausible but dangerous answers.

Question Intended evidence source Common failure
“What does our refund policy say?” Current internal policy store Web result describes another company
“Did the airport announce a closure today?” Current public search Old uploaded memo is treated as live truth
“Which clause applies to this account?” Versioned policy documents plus metadata filter Right topic, wrong document version

The contract should select the authoritative source class before generation.

A File Search request can make the store and filter explicit:

const interaction = await ai.interactions.create({
  model: process.env.GEMINI_MODEL ?? "gemini-3.8-flash",
  input: "Summarize the current refund exception for enterprise accounts.",
  tools: [{
    type: "file_search",
    file_search_store_names: [process.env.POLICY_STORE!],
    metadata_filter: 'status="current" AND audience="enterprise"',
  }],
});

File Search also has a data lifecycle. Indexed data persists until it is deleted, and citation annotations may include file metadata. Store identity, document version, metadata, retention, and deletion therefore belong in the evidence design—not just the retrieval code.

Citations belong to claims, not the footer

One of the weakest grounded-answer interfaces puts every source below a long response.

That layout proves research occurred somewhere. It does not help the reader verify a specific claim.

Because Gemini returns offsets for inline URL citations, preserve the mapping between cited text and source. For File Search, preserve the corresponding file citation and useful custom metadata. Do not flatten both into an undifferentiated “Sources” box.

For higher-risk workflows, scope is also a safety mechanism. If evidence supports the date but not the cause, state the date and omit the unsupported explanation.

A smaller grounded answer is more trustworthy than a comprehensive-looking answer with decorative citations.

Validate structure without pretending to prove truth

A structural validator can report useful failures while remaining honest about its limits:

type EvidenceReport = {
  structurallyValid: boolean;
  citationCount: number;
  problems: string[];
};

function validateEvidence(
  contract: EvidenceContract,
  citations: Citation[],
  groundingStepObserved: boolean,
): EvidenceReport {
  const problems: string[] = [];

  if (contract.groundingRequired && !groundingStepObserved) {
    problems.push("Required grounding step was not observed");
  }

  if (citations.length < contract.minimumCitations) {
    problems.push("Citation count is below the configured minimum");
  }

  return {
    structurallyValid: problems.length === 0,
    citationCount: citations.length,
    problems,
  };
}

Name the result structurallyValid, not factuallyCorrect. That naming prevents a useful guardrail from being mistaken for a semantic fact-checker.

Trace the evidence path

The best debugging record is not the full raw prompt. It is the evidence path:

policy-answer
├─ classify_question        source=internal_policy
├─ file_search              store=policy-docs filter=status:current
├─ evaluate_retrieval       documents=3
├─ generate_answer
├─ validate_citations       material_claims=4 cited=4
└─ final_response

This is where AgentInspect fits naturally without pretending to judge semantic truth. Once an integration maps the application’s retrieval and validation events into a run, a trajectory contract can require grounding before the final response, prohibit public search for internal-policy questions, and package a redacted evidence bundle for review.

The trace proves which path the application took. It does not prove that every sentence is true.

Turn real failures into evidence tests

The best regression cases come from production failures:

  • If Gemini cited an outdated document, require current-version metadata.
  • If it retrieved the exception clause but ignored it, add a claim-level evaluator.
  • If search failed and the model answered anyway, suppress the response when grounding is absent.
  • If citations attached to vague neighboring text, add a UI test for claim-level placement.

Over time, the suite becomes a record of what the product considers trustworthy.

Gemini’s grounding tools provide valuable search, retrieval, steps, and annotations. The application must still decide which source is authoritative, how much evidence is enough, what happens when retrieval fails, and which decisions require a person.

Do not ask only, “Did the model include citations?”

Ask, “Can the system demonstrate why this answer was allowed to reach the user?”

That is the difference between adding sources and engineering evidence.

References

Earlier in the series: Gemini Function Calling Is Not an Agent Runtime · Testing Google ADK TypeScript Agents Without Chasing Sentences · From Local Traces to Production Observability for Google AI Agents

DE
Source

This article was originally published by DEV Community and written by Raju Dandigam.

Read original article on DEV Community
Back to Discover

Reading List