> ## Documentation Index
> Fetch the complete documentation index at: https://novu-c5de82d9-nv-8794-quote-reply-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat

> Use the chat step in Novu Framework to send plain-text or rich card messages to Slack, Discord, Microsoft Teams, and other chat providers.

The `chat` step sends a message to chat platforms such as Slack, Discord, and Microsoft Teams.

Return a plain-text `body` or a rich `card`. If you return both, Novu uses `card`. Existing workflows that only return `body` keep working without changes.

## Example usage

### Plain text body

```tsx theme={null}
await step.chat('chat', async () => {
  return {
    body: 'A new post has been created',
  };
});
```

### Rich card

Build cards with the Card DSL helpers from `@novu/framework`. The Card DSL extends the raw Chat SDK card model with provider-agnostic Markdown formatting. Novu converts that formatting to the syntax each provider supports.

```tsx theme={null}
import {
  Actions,
  Card,
  CardLink,
  CardText,
  Divider,
  Image,
} from '@novu/framework';

await step.chat('chat', async () => {
  return {
    card: Card({
      title: 'Deploy finished',
      children: [
        CardText('All checks **passed** for `production`.'),
        Divider(),
        Image({
          url: 'https://example.com/status.png',
          alt: 'Status',
        }),
        Actions([
          {
            type: 'link-button',
            id: 'view',
            label: 'View deploy',
            url: 'https://example.com/deploys/123',
            style: 'primary',
          },
        ]),
        CardLink({
          url: 'https://example.com/deploys/123',
          label: 'Open in dashboard',
        }),
      ],
    }),
  };
});
```

You can also return a raw card object that matches the schema below. Prefer the helpers so TypeScript catches shape mistakes early.

Card text supports `**bold**`, `_italic_`, `~~strikethrough~~`, inline code, and `[links](https://example.com)`. For example, Slack receives equivalent `mrkdwn`, while Novu converts the same source text for other providers.

<Note>
  Link button URLs must be absolute (include `https://`). Incomplete URLs can fail provider validation at send time.
</Note>

## Chat step output

Provide at least one of `body` or `card`.

### body

* **Type**: `string`
* **Required**: No (required if `card` is omitted)
* **Description**: Plain-text message body. If the output also includes `card`, Novu uses the card and ignores `body`.

### card

* **Type**: `object` (`CardElement`)
* **Required**: No (required if `body` is omitted)
* **Description**: Structured chat card. Novu provides provider-specific rendering for Slack, Microsoft Teams, WhatsApp, and Telegram. Other providers receive a Markdown fallback generated from the card.

#### Card properties

| Property   | Type     | Required | Description                                             |
| ---------- | -------- | -------- | ------------------------------------------------------- |
| `type`     | `'card'` | Yes      | Discriminator. Set automatically when you use `Card()`. |
| `title`    | `string` | No       | Card title.                                             |
| `subtitle` | `string` | No       | Secondary title line.                                   |
| `imageUrl` | `string` | No       | Optional header image URL.                              |
| `children` | `array`  | Yes      | Ordered list of card child elements.                    |

#### Card child types

| Type          | Helpers            | Description                                                                                            |
| ------------- | ------------------ | ------------------------------------------------------------------------------------------------------ |
| `text`        | `CardText`         | Text block. Optional `style`: `plain`, `bold`, `muted`.                                                |
| `image`       | `Image`            | Image with `url` and optional `alt`.                                                                   |
| `divider`     | `Divider`          | Visual separator.                                                                                      |
| `link`        | `CardLink`         | Inline link with `label` and `url`.                                                                    |
| `actions`     | `Actions`          | Wrapper for link buttons.                                                                              |
| `link-button` | (inside `Actions`) | Button that opens a URL. Requires `label` and `url`. Optional `style`: `primary`, `danger`, `default`. |
| `fields`      |                    | Label/value pairs (`field` children).                                                                  |
| `table`       |                    | Table with `headers` and `rows`.                                                                       |
| `section`     |                    | Nested group of child elements.                                                                        |

The Dashboard [block editor](/platform/integrations/chat/writing-chat-template) authors a common subset of this model (text, image, divider, link buttons, lists, and related layout blocks). Framework also supports the layout elements listed above, including sections, fields, and tables.

## Provider overrides

When you need a provider-native payload that the shared card cannot express, use the step `providers` object. For example, Slack Block Kit:

```tsx theme={null}
await step.chat(
  'slack-rich',
  async () => ({
    body: 'Fallback text for notifications and plain-text clients',
  }),
  {
    providers: {
      slack: async ({ controls }) => ({
        blocks: [
          {
            type: 'section',
            text: {
              type: 'mrkdwn',
              text: '*Deploy finished*',
            },
          },
        ],
      }),
    },
  }
);
```

See [Providers overrides](/framework/typescript/steps#providers-overrides-object) and the [Chat channel](/platform/integrations/chat#provider-content-overrides) docs for Dashboard overrides.

## Chat step result

The `chat` step does not return a result object.

## Related

<Columns cols={2}>
  <Card title="Writing chat templates" icon="panels-top-left" href="/platform/integrations/chat/writing-chat-template">
    Dashboard block and text editors, preview, and backward compatibility.
  </Card>

  <Card title="Agent interactive cards" icon="bot" href="/agents/custom-code-agent/building-blocks/reply#interactive-cards">
    Full card kit usage for agent replies and `onAction`.
  </Card>
</Columns>
