Term Explainer
A compact explanation of one term in the user's context, with their own value placed on their document's range.
≈ 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 testPronounced 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).
Related
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
definitionto one or two plain sentences (280 characters at most). Put why it matters in the definition or the reply. - Only set
contextandrangefrom the user's document, exactly as printed. They're data-bound. Never supply a reference range yourself; if the document gives none, leaverangeout 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
disclaimertomedical,financialorlegalfor those topics. - Offer up to 5
relatedterms the user is likely to meet next. - Lifecycle: a definition doesn't expire, so don't set
expiresAtorfetchedAt. 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
loworhighruns 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") unlessnumericValueis 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
noteshare one quiet line. - The header shows the pronunciation and other names (
aka) on one line.categoryis 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
contextholds 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
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" }<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
| Prop | Type | Notes |
|---|---|---|
term | string | |
pronunciation | string? | e.g. "puh-TAS-ee-um" |
category | string? | e.g. "Blood test". Screen readers only |
definition | string | Plain 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 |
aka | string[] | 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" | null | Adds a "not advice" line |
Host props: status (streaming or ready), onResult, result and className.
Source
Encyclopedia Snippet
A short, credited encyclopedia-style summary of a person, thing or place, with key facts and links to read more.
Event Details
One event the user is interested in or invited to, with the time in the event's timezone, the venue, key facts, agenda and speakers, and RSVP and calendar actions.