> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aion.to/llms.txt
> Use this file to discover all available pages before exploring further.

# Card

> Provider-neutral card documents for rich message rendering.

`Card` is a provider-neutral card document. The distribution compiles it into the provider's native
rich surface — Slack Block Kit, Teams Adaptive Cards, Google Chat cards, and similar.

```python theme={null}
from aion.core.agent.invocation.card import Card
```

## Import

All public symbols are re-exported from the package root:

```python theme={null}
from aion.core.agent.invocation.card import (
    Card,
    Text,
    Field,
    Fields,
    Divider,
    Button,
    Actions,
)
```

## Creation Modes

`Card` supports three mutually exclusive creation modes.

### Inline JSX

Pass a pre-rendered JSX string when you already have the document:

```python theme={null}
Card(jsx="<Card><Text>Hello</Text></Card>")
```

### Remote URL

Pass a URL when the card document is hosted remotely:

```python theme={null}
Card(url="https://cdn.example.com/cards/deploy.jsx")
```

### Builder

Pass a `title` and chain `.add()` calls to compose the card from typed components:

```python theme={null}
Card("Deployment approved")
    .add(Text("Production rollout is ready."))
    .add(
        Fields()
        .add(Field("Environment", "prod"))
        .add(Field("Run", "#42"))
    )
    .add(Divider())
    .add(
        Actions()
        .add(Button("Approve", id="approve", style="primary"))
        .add(Button("Open run", url="https://example.com/run/42"))
    )
```

`jsx` and `url` are mutually exclusive — passing both raises `ValueError`.
In builder mode the JSX is rendered lazily when the card is serialized.

## `Card` Reference

```python theme={null}
Card(
    title: str | None = None,
    *,
    jsx: str | None = None,
    url: str | None = None,
)
```

| Parameter | Description                                                                                                     |
| --------- | --------------------------------------------------------------------------------------------------------------- |
| `title`   | Card heading rendered as the `title` attribute on the root `<Card>` element. Builder mode only.                 |
| `jsx`     | Pre-rendered JSX string. Mutually exclusive with `url`. Must not be empty.                                      |
| `url`     | URL of a remotely hosted card document. Must start with `http://` or `https://`. Mutually exclusive with `jsx`. |

| Property | Type          | Description                                                  |
| -------- | ------------- | ------------------------------------------------------------ |
| `jsx`    | `str \| None` | The JSX representation. Returns `None` for URL cards.        |
| `url`    | `str \| None` | The remote URL. Returns `None` for inline and builder cards. |

| Method        | Returns | Description                                                                                                           |
| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------- |
| `.add(child)` | `Card`  | Append a component and return `self`. Builder mode only — raises `ValueError` when called on a `jsx=` or `url=` card. |

## Components

Components are building blocks for builder-mode cards. Each implements `.to_jsx() -> str`.

### `Text`

A prose block inside the card body.

```python theme={null}
Text("Production rollout is ready.")
```

### `Fields` and `Field`

`Fields` groups compact labeled values. `Field` is one labeled key-value pair inside a `Fields` group.

```python theme={null}
Fields()
    .add(Field("Environment", "prod"))
    .add(Field("Run", "#42"))
```

### `Divider`

A horizontal rule, typically placed between the body and the `Actions` section.

```python theme={null}
Divider()
```

### `Button`

An interactive control. Use `id` for server-side callbacks, `url` for links. The two are mutually
exclusive.

```python theme={null}
Button("Approve", id="approve", style="primary")
Button("Open run", url="https://example.com/run/42")
```

| Parameter | Description                                                                        |
| --------- | ---------------------------------------------------------------------------------- |
| `label`   | Visible text on the button.                                                        |
| `id`      | Callback identifier sent to the agent when clicked. Mutually exclusive with `url`. |
| `url`     | URL to open when clicked. Mutually exclusive with `id`.                            |
| `style`   | Optional visual style hint, e.g. `"primary"` or `"danger"`.                        |

### `Actions`

Groups `Button` controls at the bottom of the card.

```python theme={null}
Actions()
    .add(Button("Approve", id="approve", style="primary"))
    .add(Button("Open run", url="https://example.com/run/42"))
```

## Full Example

```python theme={null}
from aion.core.agent.invocation.card import (
    Card, Text, Fields, Field, Divider, Actions, Button,
)

card = (
    Card("Deployment approved")
    .add(Text("Production rollout is ready."))
    .add(
        Fields()
        .add(Field("Environment", "prod"))
        .add(Field("Run", "#42"))
        .add(Field("Commit", "a1b2c3d"))
    )
    .add(Divider())
    .add(
        Actions()
        .add(Button("Approve", id="approve", style="primary"))
        .add(Button("Reject", id="reject", style="danger"))
        .add(Button("Open run", url="https://example.com/run/42"))
    )
)

await thread.reply(card)
```

## Transport

When passed to `thread.reply()` or `thread.post()`, the SDK converts the card to an A2A
`TaskStatusUpdateEvent` whose message contains a single file part and
`extensions: ["https://docs.aion.to/a2a/extensions/aion/distribution/cards/1.0.0"]`.

* Inline cards (`jsx=` or builder): `raw` bytes (base64 in JSON), `filename` derived from `title`
  (e.g. `deployment-approved.card.jsx`), or `card.jsx` when no title is set.
* URL cards: `url` field only, no `raw` or `filename`.

See [Distribution/Cards extension](/a2a/extensions/aion/distribution/cards/1.0.0) for the full
wire format.

## Related Pages

* [Distribution/Cards extension](/a2a/extensions/aion/distribution/cards/1.0.0)
* [LangGraph Thread](/sdk/langgraph/api/thread)
* [ADK Thread](/sdk/google-adk/api/thread)
