Answers and citations

How ODEN returns synthesized answers and ranked citations, when to request each, and how to attribute sources in your LLM responses correctly.

Documentation2 min readUpdated 2026-07-30

Every ODEN call returns two things that work together: a synthesized answer and the ranked citations it was built from. This page explains how to extract, threshold, and render both.

The answer#

results.answer is a concise, synthesized answer to your query, generated from the retrieved sources and written in the query's natural language. It is designed to drop straight into a model's context window or a user-facing reply.

Turn it off when you only want sources — for example, when your own local LLM will do the synthesis and you just need clean, relevant retrieval material:

{ "query": "GDPR data-transfer mechanisms 2026", "answer": false }

With answer: false, results.answer is omitted and you get citations only, reducing payload size and latency.

The citations#

results.citations is a ranked list, highest score first. Each entry provides source metadata:

{
  "title": "Standard Contractual Clauses — European Commission",
  "url": "https://commission.europa.eu/...",
  "score": 0.938,
  "snippet": "The SCCs are model clauses adopted by the Commission for transfers to third countries."
}
  • Relevance thresholding: Discard citations below 0.60 to keep low-confidence sources out of your model context.
  • Snippets on demand: Set include_snippets: true to get one attributed sentence per source. Snippets are useful for showing users why a source was cited without fetching the underlying page.

How relevance scoring works#

ODEN scores each retrieved citation on a normalized scale from 0.0 to 1.0:

  • Semantic embedding similarity: Dense vector cosine similarity between the query embedding and the extracted passage embedding.
  • Domain authority and structural hygiene: Primary institutional domains and clean article structures receive higher baseline weight.
  • Freshness weighting: Recent content receives higher scores for queries exhibiting strong temporal intent (e.g., "latest", "2026", "current").
Score RangeInterpretationRecommended Action
0.85 – 1.00High confidence primary sourceInclude prominently; safe for direct factual quoting
0.65 – 0.84Relevant supporting contextInclude in context as supplementary reference
< 0.60Peripheral or weak semantic matchFilter out to minimize LLM token bloat

Citation deduplication by domain#

When searching broad topics, multiple citations may originate from the same root domain. Use this deduplication filter to ensure diverse perspectives in your prompt context:

from urllib.parse import urlparse

def filter_diverse_citations(citations: list, max_per_domain: int = 1) -> list:
    """Retain only the highest-scoring citations per unique root domain."""
    seen_domains = {}
    diverse = []
    for c in sorted(citations, key=lambda x: x["score"], reverse=True):
        domain = urlparse(c["url"]).netloc.lower()
        count = seen_domains.get(domain, 0)
        if count < max_per_domain:
            diverse.append(c)
            seen_domains[domain] = count + 1
    return diverse

Attributing sources in an LLM reply#

The primary purpose of citations is enabling LLMs to attribute their claims transparently. Format the retrieved citations as numbered footnotes in your prompt:

data = search("who won the 2026 nobel prize in physics")
sources = filter_diverse_citations(data["results"]["citations"])

context = data["results"]["answer"] + "\n\nSources:\n" + "\n".join(
    f"[{i+1}] {c['title']} ({c['url']}): {c.get('snippet', '')}"
    for i, c in enumerate(sources)
)
# Prompt instruction: "Answer concisely and cite every factual claim using [n] notation matching the sources."

Frontend UI rendering patterns#

When rendering results to users, convert citation tokens into interactive reference badges:

<!-- Example interactive HTML badge rendering -->
<p>
  According to recent regulatory guidance<a href="https://commission.europa.eu/..." class="citation-badge" title="Standard Contractual Clauses — European Commission">[1]</a>, standard contractual clauses remain valid.
</p>

Pairing inline badges with tooltip previews displaying the source title, snippet, and domain name enhances user trust and satisfies enterprise governance standards.

Caching#

Watch the cached boolean flag. Identical queries return from edge cache in tens of milliseconds. If you build autonomous agents that frequently verify repeated propositions, caching reduces latency while conserving search quota.

Next steps#