Term Explainer

A compact explanation of one term in the user's context, with their own value placed on their document's range.

Pattern

≈ 1,349 tokens per use (tool 899 · guidance 256 · typical payload 194)How token costs are estimated

Example: Term Explainer

What's potassium on my blood test?

Potassium

Blood test

Pronounced puh-TAS-ee-umAlso called K, Serum potassium

A mineral that carries an electric charge in your blood. It helps nerves and muscles, including the heart, work.

Your result

Your lab's range · Report of Sep 30

4.1 mmol/L

Within range

Your result: 4.1 mmol/L, within the range 3.5–5.1 mmol/L (Your lab's range).

Not medical advice. Ask your clinician.Source: Example Health Library (opens in a new tab)

When to use

  • The user asks what a term means where they met it: a blood test line, a card offer, a contract clause.
  • Their own value or wording is part of the question, e.g. "What's potassium on my blood test?".

When not to use

  • The user wants a full overview of a topic. Use an Encyclopedia Snippet or an Article.
  • Several terms need explaining at once. Answer in text or a Data Table.
  • The user asks what to do about a result. Answer in text and point them to a professional.

How the agent should use it

  • Keep definition to one or two plain sentences (280 characters at most). Put why it matters in the definition or the reply.
  • Only set context and range from the user's document, exactly as printed. They're data-bound. Never supply a reference range yourself; if the document gives none, leave range out and only the value is shown.
  • Never diagnose, interpret a result as a condition, or suggest treatment. The component only places the value on the document's range.
  • Set disclaimer to medical, financial or legal for those topics.
  • Offer up to 5 related terms the user is likely to meet next.
  • Lifecycle: a definition doesn't expire, so don't set expiresAt or fetchedAt. If the user shares a newer document (a new lab report), supersede the older call so an outdated value isn't read as current.

How it works

  • The range bar shows the document's range as a band, with the value's marker on it. A missing low or high runs the band to that end of the bar ("up to 200 mg/dL", "at least 40 mg/dL"), and the bar widens to fit a value far outside the range.
  • The status is text and an icon, never color alone: "Within range", "Above range" or "Below range". Bounds are inclusive, and every status uses the same neutral color, so a result never looks alarming by design.
  • Screen readers get one sentence instead of the bar, e.g. "Your result: 4.1 mmol/L, within the range 3.5–5.1 mmol/L (Your lab's reference range)."
  • The value is read from context.value ("4.1 mmol/L", "24.9%", "4,1") unless numericValue is set. Set it when the printed value is ambiguous.
  • The value is the largest text, with the status beside it and the range bar below. The range in words appears only when the bar can't be drawn; the range's source and note share one quiet line.
  • The header shows the pronunciation and other names (aka) on one line. category is read to screen readers only.
  • Disclaimer line: one short line, "Not medical advice." (and the financial and legal equivalents), adding "Ask your clinician." (or the equivalent) when context holds the user's own value. It shares the bottom line with the source.
  • Related terms ask the agent to explain that term. A button that was asked shows a check and isn't sent twice; the others stay usable, and the explainer never locks.

Installation

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

Usage

app/api/chat/route.ts
import { tool } from "ai"
import { termExplainerTool } from "@/components/genui/term-explainer.schema"

const tools = {
  [termExplainerTool.name]: tool({
    description: termExplainerTool.description,
    inputSchema: termExplainerTool.inputSchema,
    execute: async () => ({ shown: true }),
  }),
}

The explanation is the whole answer, so the tool returns immediately. A related-term tap calls onResult with:

{ action: "explain", term: "Sodium" }
components/message.tsx
<TermExplainer
  {...part.input}
  status={part.state === "input-streaming" ? "streaming" : "ready"}
  result={askedTerms[part.toolCallId]}
  onResult={(r) => {
    saveAsked(part.toolCallId, r)
    sendMessage({ text: `What does ${r.term} mean?` })
  }}
/>

With LangGraph

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

Restoring from history

The explainer never locks. Pass the terms the user already asked about as result (one result or an array) and those buttons render as asked, so they aren't sent again.

Schema

PropTypeNotes
termstring
pronunciationstring?e.g. "puh-TAS-ee-um"
categorystring?e.g. "Blood test". Screen readers only
definitionstringPlain words, up to 280 characters
context{ label, value, numericValue?, range?, note? }Data-bound, from the user's document
context.range{ low?, high?, unit, source }Data-bound. Exactly as printed; never supplied by the model
akastring[]Other names, up to 6
related{ term, short? }[]Up to 5. short is read in the button's label, not shown
source{ name, url }Reference for the definition
disclaimer"medical" | "financial" | "legal" | nullAdds a "not advice" line

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

Source

On this page