# MentorCard record

> The MentorCard record of Novior.MentorAgent.Abstractions.Models: A structured card rendered in the chat instead of being described in prose — Level 2 of…

- URL: https://docs.mentoragent.net/api/novior-mentoragent-abstractions-models/mentorcard
- Verified with: MentorAgent 1.2.0
- Last updated: 2026-10-27
- Packages: Novior.MentorAgent.Abstractions

A structured card rendered in the chat instead of being described in prose — Level 2 of generative UI (roadmap \#14). Level 1 is Markdown tables and lists; this is real UI with fields, an accent and buttons the user can press.

**A card is built by your tool, never by the model.** An `[MentorAction]` method returns a [`MentorCard`](https://docs.mentoragent.net/api/novior-mentoragent-abstractions-models/mentorcard) (or several) and MentorAgent renders it; the model only decides *when* to call that tool. This is what makes cards safe to give buttons: every label, URL and action name is written by your code, so a prompt injection cannot make the assistant render a link to somewhere you never approved. It also means a card cannot hallucinate a field.

```text title="Example"
[MentorAction("get_order", "Shows an order")]
public MentorCard GetOrder(int id)
{
    var o = _db.Orders.Find(id);
    return new MentorCard("order")
    {
        Title    = $"Order #{o.Id}",
        Subtitle = o.CustomerName,
        Accent   = o.Status == "Shipped" ? MentorCardAccent.Success : MentorCardAccent.Warning,
        Fields   = [ new("Total", o.Total.ToString("C")), new("Status", o.Status) ],
        Actions  = [ new("Open", MentorCardActionKind.Navigate, $"/orders/{o.Id}") ],
    };
}
```

## Definition

Namespace: `Novior.MentorAgent.Abstractions.Models`. Package: `Novior.MentorAgent.Abstractions`.

`public sealed record MentorCard : IEquatable<MentorCard>`

```shell
dotnet add package Novior.MentorAgent.Abstractions
```

## Constructors

`public MentorCard(string Kind)`

A structured card rendered in the chat instead of being described in prose — Level 2 of generative UI (roadmap \#14). Level 1 is Markdown tables and lists; this is real UI with fields, an accent and buttons the user can press.

**A card is built by your tool, never by the model.** An `[MentorAction]` method returns a [`MentorCard`](https://docs.mentoragent.net/api/novior-mentoragent-abstractions-models/mentorcard) (or several) and MentorAgent renders it; the model only decides *when* to call that tool. This is what makes cards safe to give buttons: every label, URL and action name is written by your code, so a prompt injection cannot make the assistant render a link to somewhere you never approved. It also means a card cannot hallucinate a field.

```text title="Example"
[MentorAction("get_order", "Shows an order")]
public MentorCard GetOrder(int id)
{
    var o = _db.Orders.Find(id);
    return new MentorCard("order")
    {
        Title    = $"Order #{o.Id}",
        Subtitle = o.CustomerName,
        Accent   = o.Status == "Shipped" ? MentorCardAccent.Success : MentorCardAccent.Warning,
        Fields   = [ new("Total", o.Total.ToString("C")), new("Status", o.Status) ],
        Actions  = [ new("Open", MentorCardActionKind.Navigate, $"/orders/{o.Id}") ],
    };
}
```

**Parameters**

- `Kind`: Your own name for this card type — `"order"`, `"product"`. The built-in renderer ignores it; a host that supplies a custom template uses it to choose one. Keep it stable, it is effectively the card's contract with the UI.

## Properties

### `Accent`

`public MentorCardAccent Accent { get; init; }`

Colour accent conveying state at a glance.

### `Actions`

`public IReadOnlyList<MentorCardAction>? Actions { get; init; }`

Buttons. Keep it to two or three — a card is a summary, not a form.

### `Fields`

`public IReadOnlyList<MentorCardField>? Fields { get; init; }`

Label/value rows, in display order.

### `ImageUrl`

`public string? ImageUrl { get; init; }`

Optional image (absolute URL or `data:` URI).

### `Kind`

`public string Kind { get; init; }`

Your own name for this card type — `"order"`, `"product"`. The built-in renderer ignores it; a host that supplies a custom template uses it to choose one. Keep it stable, it is effectively the card's contract with the UI.

### `Subtitle`

`public string? Subtitle { get; init; }`

Secondary line under the title.

### `Title`

`public string? Title { get; init; }`

Heading. Rendered as text — never as markup.

---

- Previous: [MentorAttachment record](https://docs.mentoragent.net/api/novior-mentoragent-abstractions-models/mentorattachment.md)
- Next: [MentorCardAccent enum](https://docs.mentoragent.net/api/novior-mentoragent-abstractions-models/mentorcardaccent.md)
