InsightCard
rendered, live
the wire — click a line to scrub
the contract — InsightCard in catalog.json
{
"type": "object",
"properties": {
"component": {
"const": "InsightCard"
},
"headline": {
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DynamicString",
"description": "The claim, in one sentence. Required — it is the card's accessible name. The card reserves two lines for it, so write for two lines at most."
},
"subjectKind": {
"type": "string",
"description": "What kind of thing this insight is about. Required — it is merged into drill and feedback contexts."
},
"subjectId": {
"type": "string",
"description": "Stable id of the subject, e.g. 'cl-report-accuracy'. Required."
},
"summary": {
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DynamicString",
"description": "One or two sentences of supporting evidence, written for humans."
},
"signalType": {
"type": "string",
"description": "What kind of signal this is, in YOUR domain's words — \"churn_risk\", \"outage\", \"policy_drift\", \"fraud_pattern\". Free text on purpose; a closed list would be one product's taxonomy. Keep the strings stable across a surface so they group and filter."
},
"intent": {
"oneOf": [
{
"enum": [
"good",
"bad",
"warning",
"info",
"neutral"
]
},
{
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DataBinding"
}
],
"description": "Judgment of the insight; default 'neutral'. An alert is an insight whose intent earns 'bad'."
},
"trend": {
"enum": [
"up",
"down",
"flat"
],
"description": "Direction of the underlying signal — describes, never judges."
},
"metrics": {
"oneOf": [
{
"type": "array",
"items": {
"type": "object",
"description": "One figure supporting the finding. Raw values only — the renderer formats in the host locale.",
"properties": {
"label": {
"type": "string",
"description": "What the figure is, e.g. \"Cases\" or \"Revenue at risk\"."
},
"value": {
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DynamicNumber",
"description": "The raw number. Bind with {\"path\": ...} if it changes."
},
"unit": {
"type": "string",
"description": "ISO 4217 code for money (\"USD\"), or a short unit (\"ms\", \"%\"). Same convention as ops Stat."
},
"intent": {
"enum": [
"good",
"bad",
"warning",
"info",
"neutral"
],
"description": "Optional per-figure intent — this is why one array beats fixed props: each figure carries its own reading."
}
},
"required": [
"label",
"value"
],
"additionalProperties": false
}
},
{
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DataBinding"
}
],
"description": "The figures behind the claim, as {label, value, unit?, intent?}. As many as the finding needs — an empty array collapses the row. Raw numbers only; the renderer formats them."
},
"windowStart": {
"type": "string",
"description": "ISO 8601 start of the observation window."
},
"windowEnd": {
"type": "string",
"description": "ISO 8601 end of the observation window."
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Raw 0..1. Rendered as a qualitative band (low / medium / high) — a model emitting 0.87 claims precision it doesn't have, so the renderer never shows the number."
},
"tags": {
"oneOf": [
{
"type": "array",
"items": {
"type": "object",
"description": "A short labelled facet of the finding, rendered as a chip.",
"properties": {
"label": {
"type": "string",
"description": "Chip text, e.g. \"Invoice errors\"."
},
"count": {
"type": "number",
"description": "Optional raw count; the renderer formats it."
}
},
"required": [
"label"
],
"additionalProperties": false
}
},
{
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DataBinding"
}
],
"description": "Facets of the finding as {label, count?} chips. Empty collapses the chip row."
},
"drillAction": {
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/Action",
"description": "Fired when the user drills into the insight. subjectKind + subjectId are merged into its context automatically."
},
"feedbackAction": {
"$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/Action",
"description": "Fired by the thumbs pair. subjectKind, subjectId, and verdict ('up' | 'down') are merged automatically. The card shows an acknowledged state itself; respond to a 'down' by de-emphasizing via the data model."
},
"detailComponentId": {
"type": "string",
"description": "ComponentId of extra content, rendered collapsed under the card."
}
},
"required": [
"headline",
"subjectKind",
"subjectId"
]
}the prompt-pack — paste into your agent
### InsightCard — the surface card of the iceberg
The feed card carrying a claim, its evidence, its impact, and feedback. `headline`,
`subjectKind`, `subjectId` required; everything else earns its place.
| prop | type | notes |
| ------------------- | ------------------------------- | ----------------------------------------------------------------------------------------- |
| `headline` | string, required | the claim in one sentence; the card reserves two lines |
| `subjectKind` | free string, required | what the finding is about, in your words |
| `subjectId` | string, required | e.g. `"cl-report-accuracy"` |
| `summary` | string | 1–2 sentences of evidence, for humans |
| `signalType` | free string | your own word for the kind of signal, e.g. `"churn_risk"`, `"outage"`, `"policy_drift"` |
| `intent` / `trend` | intent scale / `up\|down\|flat` | judgment and direction, independent axes |
| `metrics` | metric[] \| `{"path"}` | the figures behind the claim; as many as it needs, each with optional `unit` and `intent` |
| `windowStart`/`End` | ISO 8601 strings | the observation window |
| `confidence` | number 0..1 | rendered as a band, never a number |
| `tags` | {label,count?}[] \| `{"path"}` | facet chips; empty collapses |
| `drillAction` | action | subject merged automatically |
| `feedbackAction` | action | subject + `verdict: "up"\|"down"` merged automatically |
| `detailComponentId` | ComponentId | extra content, rendered collapsed |
```
{"id":"insight_ra","component":"InsightCard","headline":"Report-accuracy complaints are accelerating","subjectKind":"cluster","subjectId":"cl-report-accuracy","summary":"Export totals not matching on-screen figures. 312 cases since 1 August, three enterprise accounts affected.","signalType":"friction","intent":"warning","trend":"up","metrics":[{"label":"Cases","value":{"path":"/ra/caseCount"}},{"label":"Revenue at risk","value":{"path":"/ra/arr"},"unit":"USD","intent":"bad"}],"windowStart":"2026-08-01T00:00:00Z","windowEnd":"2026-08-20T00:00:00Z","confidence":0.8,"tags":[{"label":"Export totals","count":204},{"label":"Rounding","count":68}],"drillAction":{"event":{"name":"insight_drilled","context":{"view":"impact"}}},"feedbackAction":{"event":{"name":"insight_feedback"}}}
```