Agent cards
A card is a structured tool output the host renders as UI. Two ways one appears: a domain tool attaches it to its result, or the agent calls visualize and picks a presentation itself — which is what makes it visually flexible rather than limited to what someone pre-built. Each kind below is shown with the exact spec that produced it.
How the agent chooses
The model never sees this page. It sees the one-line summary under each name below, embedded in the visualize tool description — so those summaries, not the schemas, are what actually steer the choice. Kinds are registered with their validator and renderer together; a test asserts the two sets match exactly, so a card can never validate with nowhere to render.
Many items sharing the same fields. Search results, inventories, case lists, line items, survey rows.
{
"kind": "table",
"title": "Open support tickets",
"columns": [
{
"key": "id",
"label": "Ticket",
"pill": true
},
{
"key": "subject",
"label": "Subject"
},
{
"key": "priority",
"label": "Priority"
},
{
"key": "age",
"label": "Age",
"format": "duration",
"align": "right"
}
],
"rows": [
{
"id": "SUP-1041",
"subject": "Login loop on SSO",
"priority": "High",
"age": 190000
},
{
"id": "SUP-1038",
"subject": "Export missing columns",
"priority": "Normal",
"age": 5400000
},
{
"id": "SUP-1022",
"subject": "Billing address won't save",
"priority": "Low",
"age": 86400000
}
],
"sortBy": "age",
"sortDir": "desc"
}| SUP-1022 | Billing address won't save | Low | 24.0h |
| SUP-1038 | Export missing columns | Normal | 1.5h |
| SUP-1041 | Login loop on SSO | High | 3m 10s |
A row of headline numbers, optionally with change vs a prior period. Totals, counts, rates, before/after.
{
"kind": "stats",
"title": "This quarter",
"items": [
{
"label": "Active users",
"value": 18420,
"format": "number",
"delta": 6.4,
"deltaFormat": "percent"
},
{
"label": "Churn",
"value": 2.1,
"format": "percent",
"delta": -0.4,
"deltaFormat": "percent"
},
{
"label": "NPS",
"value": 46,
"format": "number",
"hint": "n=1,204"
},
{
"label": "Median resolution",
"value": 7800000,
"format": "duration"
}
]
}A matrix of options against criteria. Reach for this whenever the user is CHOOSING between things — vendors, clauses, plans, candidates, approaches. Boolean values render as ✓/✗.
{
"kind": "comparison",
"title": "Vendor shortlist",
"options": [
{
"id": "a",
"label": "Northwind",
"note": "incumbent"
},
{
"id": "b",
"label": "Vertex",
"note": "recommended",
"highlight": true
},
{
"id": "c",
"label": "Basis",
"note": "low cost"
}
],
"criteria": [
{
"label": "Annual cost",
"values": {
"a": "$84k",
"b": "$61k",
"c": "$28k"
},
"weight": "high"
},
{
"label": "SSO included",
"values": {
"a": false,
"b": true,
"c": false
},
"weight": "high"
},
{
"label": "Data residency (EU)",
"values": {
"a": true,
"b": true,
"c": false
},
"detail": "Required by the DPA"
},
{
"label": "Migration effort",
"values": {
"a": "none",
"b": "3 weeks",
"c": "6 weeks"
}
},
{
"label": "Support SLA",
"values": {
"a": "4h",
"b": "8h",
"c": null
}
},
{
"label": "Exit clause",
"values": {
"a": false,
"b": true,
"c": true
}
}
]
}Northwind incumbent | Vertex recommended | Basis low cost | |
|---|---|---|---|
| Annual cost | $84k | $61k | $28k |
| SSO included | |||
| Data residency (EU) Required by the DPA | |||
| Migration effort | none | 3 weeks | 6 weeks |
| Support SLA | 4h | 8h | — |
| Exit clause |
Labelled detail rows describing ONE thing. A record, a contract's key terms, a config, a profile.
{
"kind": "keyvalue",
"title": "Master services agreement",
"items": [
{
"label": "Counterparty",
"value": "Vertex Systems Ltd"
},
{
"label": "Effective",
"value": 1782259200000,
"format": "datetime"
},
{
"label": "Initial term",
"value": "24 months"
},
{
"label": "Liability cap",
"value": "12 months' fees",
"tone": "positive"
},
{
"label": "Governing law",
"value": "England & Wales"
},
{
"label": "Reference",
"value": "MSA-2026-0417",
"mono": true
}
]
}- Counterparty
- Vertex Systems Ltd
- Effective
- 6/24/2026, 12:00:00 AM
- Initial term
- 24 months
- Liability cap
- 12 months' fees
- Governing law
- England & Wales
- Reference
- MSA-2026-0417
Nested structure. Document outlines, org charts, taxonomies, decision trees, dependency chains, file layouts.
{
"kind": "tree",
"title": "Agreement structure",
"nodes": [
{
"label": "1. Definitions",
"children": [
{
"label": "1.1 Interpretation"
},
{
"label": "1.2 Defined terms",
"detail": "41 terms"
}
]
},
{
"label": "8. Liability",
"tone": "warning",
"detail": "flagged in review",
"children": [
{
"label": "8.1 Mutual cap",
"tone": "positive"
},
{
"label": "8.2 Supplier carve-outs",
"tone": "negative",
"detail": "unlimited exposure"
},
{
"label": "8.3 Consequential loss"
}
]
},
{
"label": "11. Data protection",
"children": [
{
"label": "11.4 Breach notification",
"tone": "warning",
"detail": "no fixed window"
}
]
}
]
}- 1. Definitions
- 1.1 Interpretation
- 1.2 Defined terms41 terms
- 8. Liabilityflagged in review
- 8.1 Mutual cap
- 8.2 Supplier carve-outsunlimited exposure
- 8.3 Consequential loss
- 11. Data protection
- 11.4 Breach notificationno fixed window
Plot shape over time or across categories. `variant:"series"` with `series[]` for line/area/bar/scatter; `variant:"candlestick"` with `candles[]` for OHLC.
{
"kind": "chart",
"title": "Weekly signups by channel",
"variant": "series",
"xType": "time",
"yLabel": "signups",
"series": [
{
"name": "Organic",
"type": "line",
"points": [
[
1783728000000,
100
],
[
1783814400000,
105.32633636155383
],
[
1783900800000,
110.22043763683685
],
[
1783987200000,
114.29765181769476
],
[
1784073600000,
117.26325481635975
],
[
1784160000000,
118.94489549302118
],
[
1784246400000,
119.31156912190818
],
[
1784332800000,
118.47703058085989
],
[
1784419200000,
116.68727151962975
],
[
1784505600000,
114.2934400967184
],
[
1784592000000,
111.71318444549418
],
[
1784678400000,
109.38467541693987
],
[
1784764800000,
107.71837005630486
],
[
1784851200000,
107.05182598475086
],
[
1784937600000,
107.61254099482485
],
[
1785024000000,
109.49290870404234
],
[
1785110400000,
112.64004730118904
],
[
1785196800000,
116.86162109906829
],
[
1785283200000,
121.84701402161289
],
[
1785369600000,
127.20152411858606
],
[
1785456000000,
132.48981476685464
],
[
1785542400000,
137.28383918462546
],
[
1785628800000,
141.20996243542567
],
[
1785715200000,
143.99009344383649
]
]
},
{
"name": "Paid",
"type": "line",
"points": [
[
1783728000000,
68
],
[
1783814400000,
71.30232854416337
],
[
1783900800000,
74.33667133483884
],
[
1783987200000,
76.86454412697074
],
[
1784073600000,
78.70321798614304
],
[
1784160000000,
79.74583520567313
],
[
1784246400000,
79.97317285558307
],
[
1784332800000,
79.45575896013312
],
[
1784419200000,
78.34610834217044
],
[
1784505600000,
76.8619328599654
],
[
1784592000000,
75.26217435620639
],
[
1784678400000,
73.81849875850271
],
[
1784764800000,
72.78538943490902
],
[
1784851200000,
72.37213211054554
],
[
1784937600000,
72.7197754167914
],
[
1785024000000,
73.88560339650624
],
[
1785110400000,
75.8368293267372
],
[
1785196800000,
78.45420508142234
],
[
1785283200000,
81.5451486934
],
[
1785369600000,
84.86494495352336
],
[
1785456000000,
88.14368515544987
],
[
1785542400000,
91.11598029446779
],
[
1785628800000,
93.5501767099639
],
[
1785715200000,
95.27385793517863
]
]
},
{
"name": "Referral",
"type": "area",
"points": [
[
1783728000000,
28.000000000000004
],
[
1783814400000,
29.491374181235074
],
[
1783900800000,
30.86172253831432
],
[
1783987200000,
32.00334250895453
],
[
1784073600000,
32.833711348580735
],
[
1784160000000,
33.30457073804593
],
[
1784246400000,
33.40723935413429
],
[
1784332800000,
33.173568562640774
],
[
1784419200000,
32.67243602549633
],
[
1784505600000,
32.002163227081155
],
[
1784592000000,
31.279691644738374
],
[
1784678400000,
30.627709116743166
],
[
1784764800000,
30.161143615765365
],
[
1784851200000,
29.974511275730244
],
[
1784937600000,
30.131511478550962
],
[
1785024000000,
30.658014437131857
],
[
1785110400000,
31.539213244332934
],
[
1785196800000,
32.721253907739126
],
[
1785283200000,
34.11716392605161
],
[
1785369600000,
35.6164267532041
],
[
1785456000000,
37.097148134719305
],
[
1785542400000,
38.439474971695134
],
[
1785628800000,
39.53878948191919
],
[
1785715200000,
40.31722616427422
]
]
}
],
"annotations": [
{
"type": "hline",
"value": 100,
"label": "target",
"tone": "info"
}
]
}Staged drop-off, in order. Conversion funnels, hiring pipelines, application intake, case attrition. Stages must be ordered widest to narrowest.
{
"kind": "funnel",
"title": "Hiring pipeline — Q3",
"format": "number",
"stages": [
{
"label": "Applications",
"value": 1840
},
{
"label": "Screened",
"value": 412,
"note": "CV review"
},
{
"label": "Phone screen",
"value": 168
},
{
"label": "On-site",
"value": 54
},
{
"label": "Offer",
"value": 12
},
{
"label": "Accepted",
"value": 9
}
]
}One value on a scale, with optional named bands. Risk levels, readiness scores, sentiment, confidence, utilisation. Label the bands so the number means something.
{
"kind": "gauge",
"title": "Contract risk",
"value": 62,
"min": 0,
"max": 100,
"label": "Negotiate before signing",
"bands": [
{
"from": 0,
"to": 30,
"label": "Acceptable",
"tone": "positive"
},
{
"from": 30,
"to": 60,
"label": "Negotiate",
"tone": "warning"
},
{
"from": 60,
"to": 100,
"label": "Do not sign",
"tone": "negative"
}
]
}An ordered sequence of events with times and status. Best for history, schedules, execution traces.
{
"kind": "timeline",
"title": "Incident 2026-0731",
"events": [
{
"at": 1785456000000,
"label": "Elevated error rate detected",
"tone": "warning"
},
{
"at": 1785456900000,
"label": "Paged on-call",
"detail": "ack in 4m"
},
{
"at": 1785459600000,
"label": "Root cause identified",
"detail": "connection pool exhaustion"
},
{
"at": 1785461400000,
"label": "Mitigated",
"tone": "positive"
},
{
"at": 1785542400000,
"label": "Post-mortem published",
"tone": "info"
}
]
}- Elevated error rate detected7/31/2026, 12:00:00 AM
- Paged on-call7/31/2026, 12:15:00 AMack in 4m
- Root cause identified7/31/2026, 1:00:00 AMconnection pool exhaustion
- Mitigated7/31/2026, 1:30:00 AM
- Post-mortem published8/1/2026, 12:00:00 AM
Multi-step work with per-step status. Best for long or background operations the user is waiting on.
{
"kind": "progress",
"title": "Market entry research",
"steps": [
{
"label": "Size the addressable market",
"status": "done",
"detail": "3 sources reconciled"
},
{
"label": "Map the regulatory surface",
"status": "done"
},
{
"label": "Interview 5 prospective buyers",
"status": "active",
"detail": "2 of 5 complete"
},
{
"label": "Draft the go/no-go memo",
"status": "pending"
}
]
}- Size the addressable market3 sources reconciled
- Map the regulatory surface
- Interview 5 prospective buyers2 of 5 complete
- Draft the go/no-go memo
Items with a state. Compliance reviews, launch readiness, document requirements, audit findings, QA passes. Use `group` to section a long list.
{
"kind": "checklist",
"title": "GDPR readiness",
"items": [
{
"label": "Lawful basis documented for each purpose",
"status": "done",
"group": "Governance"
},
{
"label": "Records of processing maintained (Art. 30)",
"status": "done",
"group": "Governance"
},
{
"label": "DPA signed with every sub-processor",
"status": "blocked",
"detail": "Two missing.",
"group": "Vendors"
},
{
"label": "Transfer mechanism for non-EEA processing",
"status": "blocked",
"detail": "Outdated SCC set.",
"group": "Vendors"
},
{
"label": "Breach notification within 72 hours",
"status": "todo",
"detail": "Process exists, not written down.",
"group": "Operations"
},
{
"label": "DSAR workflow with a 30-day clock",
"status": "done",
"group": "Operations"
},
{
"label": "DPIA for high-risk processing",
"status": "na",
"detail": "None in scope.",
"group": "Operations"
}
]
}- Lawful basis documented for each purpose
- Records of processing maintained (Art. 30)
- DPA signed with every sub-processorTwo missing.
- Transfer mechanism for non-EEA processingOutdated SCC set.
- Breach notification within 72 hoursProcess exists, not written down.
- DSAR workflow with a 30-day clock
- DPIA for high-risk processingNone in scope.
Formatted long-form text. Use only when structure genuinely needs headings/lists — plain replies do not need a card.
{
"kind": "markdown",
"title": "Recommendation",
"body": "## Summary\n\nMove to **Vertex**. The migration costs three weeks, and it closes the two gaps that matter: SSO on every seat and an exit clause.\n\n- Annual saving: `$23k`\n- Residual risk: no SOC 2 until Q1\n- Decision needed by the 14th"
}Summary
Move to Vertex. The migration costs three weeks, and it closes the two gaps that matter: SSO on every seat and an exit clause.
- Annual saving:
$23k - Residual risk: no SOC 2 until Q1
- Decision needed by the 14th
A document the user will keep, read in a previewer and come back to. Use for something worth revising — a draft, a report, a set of notes — not for a long reply. Returns an id later turns use to re-read or edit it.
{
"kind": "document",
"docId": "doc_vendor_review",
"title": "Vendor review",
"revision": 3,
"markdown": "# Vendor review\n\nTwo shortlisted suppliers, scored against the criteria agreed in March.\n\n## Findings\n\nThe **cheaper** option fails the SSO requirement outright. Closing that gap\nlater costs more than the difference in list price, so it is not a saving.\n\n- Coverage: 18 of 22 requirements met\n- Blocking gap: no SSO on non-admin seats\n- Exit clause: 90 days, uncapped\n\n## Recommendation\n\nProceed with the second supplier and hold 10% of year one against the\noutstanding audit.\n\n```\nrenewal_date = 2027-03-01\nnotice_period = 90d\n```"
}Vendor review
Two shortlisted suppliers, scored against the criteria agreed in March.
Findings
The cheaper option fails the SSO requirement outright. Closing that gap
later costs more than the difference in list price, so it is not a saving.
- Coverage: 18 of 22 requirements met
- Blocking gap: no SSO on non-admin seats
- Exit clause: 90 days, uncapped
Recommendation
Proceed with the second supplier and hold 10% of year one against the
outstanding audit.
renewal_date = 2027-03-01
notice_period = 90dOne short highlighted note. Disclaimers, caveats, prerequisites, limits on what you checked. Use `danger` for anything the reader would regret missing.
{
"kind": "callout",
"tone": "warning",
"title": "Not legal advice",
"body": "This review flags commercial risk in the drafting. It is not legal advice and does not replace review by a qualified lawyer in the governing jurisdiction."
}The sources behind what you just said. Use whenever a claim rests on specific documents — case law, statutes, papers, filings, articles, internal docs. Quote the passage relied on in `snippet`.
{
"kind": "citations",
"title": "Authority relied on",
"items": [
{
"title": "Photo Production Ltd v Securicor Transport Ltd",
"source": "House of Lords",
"date": "1980",
"locator": "[1980] AC 827",
"snippet": "A clearly worded exclusion clause may exclude liability even for a fundamental breach, where that is the parties' true bargain.",
"relevance": "high"
},
{
"title": "Unfair Contract Terms Act 1977",
"source": "UK statute",
"date": "1977",
"locator": "s.3(2)(a)",
"snippet": "Against a party dealing on the other's written standard terms, an exclusion is effective only so far as it satisfies the requirement of reasonableness.",
"relevance": "high"
},
{
"title": "Regulation (EU) 2016/679",
"source": "EU regulation",
"date": "2016",
"locator": "Art. 33(1)",
"snippet": "The controller shall notify the supervisory authority without undue delay and, where feasible, not later than 72 hours after having become aware of it.",
"relevance": "medium"
}
]
}- Photo Production Ltd v Securicor Transport Ltdhigh
A clearly worded exclusion clause may exclude liability even for a fundamental breach, where that is the parties' true bargain.
- Unfair Contract Terms Act 1977high
Against a party dealing on the other's written standard terms, an exclusion is effective only so far as it satisfies the requirement of reasonableness.
- Regulation (EU) 2016/679medium
The controller shall notify the supervisory authority without undue delay and, where feasible, not later than 72 hours after having become aware of it.
A code block with language and optional filename.
{
"kind": "code",
"title": "Usage",
"language": "ts",
"filename": "agent.ts",
"code": "const provider = createOpenAIProvider({\n transport: createProxyTransport({ url: \"/api/agent\" }),\n dialect: \"responses\",\n});\n\nfor await (const event of runAgent(messages, config)) {\n render(event);\n}"
}const provider = createOpenAIProvider({ transport: createProxyTransport({ url: "/api/agent" }), dialect: "responses",}); for await (const event of runAgent(messages, config)) { render(event);}Before/after comparison of two texts.
{
"kind": "diff",
"title": "Clause 8.2 — proposed redline",
"before": "The Supplier's liability under this Agreement shall be unlimited\nin respect of any breach of its obligations.",
"after": "The Supplier's liability under this Agreement shall not exceed\nthe total fees paid in the twelve (12) months preceding the claim,\nsave in respect of death, personal injury or fraud."
}Images, audio, or video with captions.
{
"kind": "media",
"title": "Creative variants",
"layout": "grid",
"items": [
{
"url": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22320%22%20height%3D%22180%22%3E%3Crect%20width%3D%22320%22%20height%3D%22180%22%20fill%3D%22%233a6df0%22%2F%3E%3Ctext%20x%3D%22160%22%20y%3D%2298%22%20font-family%3D%22sans-serif%22%20font-size%3D%2220%22%20fill%3D%22white%22%20text-anchor%3D%22middle%22%3EVariant%20A%3C%2Ftext%3E%3C%2Fsvg%3E",
"caption": "Variant A — 2.4% CTR"
},
{
"url": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22320%22%20height%3D%22180%22%3E%3Crect%20width%3D%22320%22%20height%3D%22180%22%20fill%3D%22%2317864b%22%2F%3E%3Ctext%20x%3D%22160%22%20y%3D%2298%22%20font-family%3D%22sans-serif%22%20font-size%3D%2220%22%20fill%3D%22white%22%20text-anchor%3D%22middle%22%3EVariant%20B%3C%2Ftext%3E%3C%2Fsvg%3E",
"caption": "Variant B — 3.9% CTR"
}
]
}A drafted message for the user to send themselves. Use when the outcome of the work is something that has to reach someone.
{
"kind": "email",
"to": [
"counsel@example.com"
],
"cc": [
"procurement@example.com"
],
"subject": "Vendor review — redline for your read",
"body": "Hi,\n\nAttached is the vendor review with the SSO gap called out and the\nrecommendation caveated on the audit. Two things worth your eye:\n\n1. The exit clause is 90 days, uncapped.\n2. We are holding 10% of year one.\n\nThanks"
}Interactive kinds
These pause the run. The tool call suspends, the card renders, and the user's answer becomes the tool result the model reads on its next step — that is the human-in-the-loop seam. They render at top level and are never collapsed, because a hidden question is an unanswerable one.
Ask the user to pick from options. Use instead of guessing when several candidates fit. Each option may carry `meta` facts shown on its row.
{
"kind": "choice",
"title": "Which policy did you mean?",
"prompt": "Three documents match “retention”.",
"options": [
{
"id": "a",
"label": "Data Retention Policy",
"description": "v4 · approved Mar 2026",
"meta": [
{
"label": "Pages",
"value": 11
}
]
},
{
"id": "b",
"label": "Employee Retention Plan",
"description": "HR · draft",
"meta": [
{
"label": "Pages",
"value": 6
}
]
},
{
"id": "c",
"label": "Records Retention Schedule",
"description": "Superseded",
"disabled": true,
"disabledReason": "Replaced by v4"
}
]
}Three documents match “retention”.
Collect structured input. Use when you need several values at once rather than a back-and-forth.
{
"kind": "form",
"title": "Draft the notice",
"description": "Values are validated before the letter is generated.",
"fields": [
{
"name": "counterparty",
"label": "Counterparty",
"type": "text",
"required": true,
"value": "Vertex Systems Ltd"
},
{
"name": "days",
"label": "Notice period",
"type": "number",
"min": 0,
"max": 180,
"step": 1,
"value": 60,
"suffix": "days"
},
{
"name": "reason",
"label": "Ground",
"type": "select",
"options": [
{
"value": "convenience",
"label": "Convenience"
},
{
"value": "cause",
"label": "Material breach"
}
],
"value": "convenience"
},
{
"name": "cc",
"label": "Copy legal",
"type": "boolean",
"value": true
},
{
"name": "notes",
"label": "Notes",
"type": "textarea",
"placeholder": "Optional"
}
],
"submitLabel": "Generate notice"
}Get explicit approval before a consequential action. `summary` must state exactly what will happen — amounts, targets, and anything irreversible.
{
"kind": "confirm",
"title": "Send the termination notice",
"description": "This dispatches the letter to the counterparty's notice address on record.",
"summary": [
{
"label": "Recipient",
"value": "Vertex Systems Ltd"
},
{
"label": "Effective",
"value": "60 days from today"
},
{
"label": "Ground",
"value": "Convenience",
"tone": "neutral"
},
{
"label": "Reference",
"value": "MSA-2026-0417",
"mono": true
}
],
"confirmLabel": "Send notice",
"danger": true
}This dispatches the letter to the counterparty's notice address on record.
- Recipient
- Vertex Systems Ltd
- Effective
- 60 days from today
- Ground
- Convenience
- Reference
- MSA-2026-0417
Propose changes to a document and let the user accept them hunk by hunk. The only way to change a document — nothing is written until this is answered.
{
"kind": "editreview",
"docId": "doc_vendor_review",
"title": "Vendor review",
"revision": 3,
"summary": "Name the supplier, and soften the recommendation to match the audit caveat.",
"hunks": [
{
"index": 0,
"block": 3,
"removed": [
"The **cheaper** option fails the SSO requirement outright."
],
"added": [
"Supplier A fails the SSO requirement outright."
]
},
{
"index": 1,
"block": 7,
"removed": [
"Proceed with the second supplier and hold 10% of year one against the",
"outstanding audit."
],
"added": [
"Proceed with Supplier B, subject to the audit closing, and hold 10% of",
"year one against it."
]
}
]
}Name the supplier, and soften the recommendation to match the audit caveat.
- The **cheaper** option fails the SSO requirement outright.Supplier A fails the SSO requirement outright.
- Proceed with the second supplier and hold 10% of year one against theoutstanding audit.Proceed with Supplier B, subject to the audit closing, and hold 10% ofyear one against it.
Failure modes are visible, not silent
An unknown kind renders a labelled fallback with its payload, and a card whose data was trimmed out of persisted history says so. Both beat the alternative, which is a card that quietly disappears.
{
"kind": "sankey",
"nodes": []
}