Citations

An answer whose claims link to the sources behind them.

Pattern

≈ 862 tokens per use (tool 382 · guidance 209 · typical payload 271)How token costs are estimated

Example: Citations

What water temperature should I use for matcha?

Use water at 70–80°C, well below boiling Brew Guide +1. Hotter water pulls out bitter compounds and dulls the colour Tea Atlas.

If you don't have a thermometer, boil the water and let it rest for about 3 minutes Home Cook. Whisk in a quick zigzag rather than circles to get a fine foam Brew Guide.

When to use

  • Your answer relies on facts from web pages or documents you retrieved.
  • The user asked where something comes from, or the claims are worth checking.

When not to use

  • You have no retrieved sources. Never cite from memory or invent a source.
  • The answer is your own reasoning, opinion or a calculation.
  • Casual conversation where sources add nothing.

How it works

The agent writes ordinary text and marks each claim with the number of its source:

{
  "text": "Use water at **70–80°C** [1][2]. Hotter water tastes bitter [2].",
  "sources": [{ "title": "…", "url": "https://…" }, { "title": "…", "url": "https://…" }]
}
  • Each marker becomes a chip. It shows the site name, with "+1" when the chip covers several sources, or a number when marker is "number".
  • Hovering or focusing a chip opens a preview of each source behind it: title, publisher, date and the supporting quote.
  • The sources list starts open, one line per source: its number, title and publisher with the date. Quotes live in the chip preview, not the list. Clicking a chip scrolls to its source and highlights it.
  • Missing sources are flagged. A marker that points to a source that wasn't provided shows a dashed ? instead of disappearing.
  • The text can be streamed. Chips for sources that haven't arrived yet show a placeholder, and a marker that's still being written is hidden.

Text supports paragraphs (separated by a blank line), - list items and **bold**.

Safety

  • Only http: and https: URLs become links. Anything else, such as javascript:, renders as plain text.
  • External links open in a new tab with rel="noopener noreferrer nofollow".
  • No favicons are fetched. The list toggle shows letter badges, so rendering an answer doesn't call third-party servers.

How the agent should use it

  • Only cite pages you actually retrieved in this conversation, with their exact URLs.
  • Put each marker right after the claim it supports, and only cite a source for claims it really supports.
  • Quotes must be verbatim. If you can't quote it, leave quote out.
  • Prefer primary and recent sources, and drop sources you didn't use.

Installation

npx shadcn@latest add https://your-site.com/r/citations.json

Usage

Citations are display-only. Nothing is sent back, so the tool can return immediately:

app/api/chat/route.ts
import { tool } from "ai"
import { citationsTool } from "@/components/genui/citations.schema"

const tools = {
  [citationsTool.name]: tool({
    description: citationsTool.description,
    inputSchema: citationsTool.inputSchema,
    execute: async () => ({ shown: true }),
  }),
}
components/message.tsx
import { Citations } from "@/components/genui/citations"

function ToolPart({ part }) {
  if (part.type !== "tool-answer_with_sources") return null

  return (
    <Citations
      {...part.input}
      status={part.state === "input-streaming" ? "streaming" : "ready"}
    />
  )
}

With LangGraph

Push it from a graph node with ui.push({ name: "answer_with_sources", props: { toolCallId, ...args } }, { message }), and render the thread's UI messages with the Renderer.

Schema

PropTypeNotes
textstringThe answer, with [n] markers
sourcesSource[]1–20. [n] refers to the nth source
marker"domain" | "number"Default domain
display"inline" | "sources"Host prop. sources shows only the sources list, for hosts that render the answer text themselves. Default inline

Source

FieldTypeNotes
titlestringData-bound
urlstringData-bound. http(s) only
publisherstring?Display name. Defaults to the domain
quotestring?Data-bound. The verbatim supporting passage, up to 300 characters
publishedstring?ISO date

Host props: status (streaming or ready) and className.

Source

On this page