惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
G
Google Developers Blog
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
云风的 BLOG
云风的 BLOG
小众软件
小众软件
月光博客
月光博客
Recent Announcements
Recent Announcements
人人都是产品经理
人人都是产品经理
P
Proofpoint News Feed
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
The Cloudflare Blog
博客园_首页
美团技术团队
大猫的无限游戏
大猫的无限游戏
B
Blog
IT之家
IT之家
Jina AI
Jina AI
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

Chat SDK Documentation

History | Chat SDK History | Chat SDK List a vendor-official adapter | Chat SDK Approvals | Chat SDK Vercel Connect | Chat SDK Teams Low-Level APIs | Chat SDK CLI | Chat SDK Platform Adapters | Chat SDK State Adapters | Chat SDK Cards | Chat SDK Getting Started | Chat SDK Introduction | Chat SDK Modals | Chat SDK Slack Low-Level APIs | Chat SDK Streaming | Chat SDK Testing | Chat SDK Overview | Chat SDK toAiMessages | Chat SDK Cards | Chat SDK Overview | Chat SDK Modals | Chat SDK AI SDK Tools | Chat SDK Types | Chat SDK Message Subject | Chat SDK Conversation History | Chat SDK Transcripts | Chat SDK Slack bot with Next.js and Redis Actions | Chat SDK Direct Messages | Chat SDK Emoji | Chat SDK
Markdown | Chat SDK
Vercel · 2026-05-29 · via Chat SDK Documentation

AST builder functions and utilities for programmatic message formatting.

The SDK uses mdast (Markdown AST) as the canonical format for message formatting. Each adapter converts the AST to the platform's native format.

import {
  root, paragraph, text, strong, emphasis, strikethrough,
  inlineCode, codeBlock, link, blockquote,
  parseMarkdown, stringifyMarkdown, toPlainText, walkAst,
  tableToAscii, tableElementToAscii,
} from "chat";

The chat package re-exports mdast's union and content types so adapters and downstream code can build exhaustively-typed AST walkers without depending on mdast directly:

import type { Nodes, Root, Content } from "chat";

function render(node: Nodes): string {
  switch (node.type) {
    case "text": return node.value;
    case "strong": return node.children.map(render).join("");
    // ...
    default: throw new Error(`Unhandled: ${node satisfies never}`);
  }
}

Adapters use this pattern to make the type checker reject the build when a new mdast node type is introduced upstream.

root

Root node — the required top-level wrapper for an AST.

root([
  paragraph([text("Hello, world!")]),
])

paragraph

A paragraph block.

paragraph([text("Hello "), strong([text("world")])])

text

Plain text node.

strong

Bold text.

strong([text("important")])

emphasis

Italic text.

emphasis([text("emphasized")])

strikethrough

Strikethrough text.

strikethrough([text("removed")])

inlineCode

Inline code span.

inlineCode("const x = 1")

codeBlock

Fenced code block with optional language.

codeBlock("const x = 1;", "typescript")

Hyperlink.

link("https://example.com", [text("click here")])
link("https://example.com", [text("click here")], "tooltip title")

blockquote

Block quotation.

blockquote([paragraph([text("Quoted text")])])

parseMarkdown

Parse a markdown string into an mdast AST.

const ast = parseMarkdown("**Hello** world");

stringifyMarkdown

Convert an mdast AST back to a markdown string.

const md = stringifyMarkdown(ast); // "**Hello** world"

toPlainText

Strip all formatting and return plain text.

const plain = toPlainText(ast); // "Hello world"

markdownToPlainText

Shorthand for parsing markdown and extracting plain text.

const plain = markdownToPlainText("**Hello** world"); // "Hello world"

walkAst

Transform an AST by visiting each node. Return a new value to replace the node, or undefined to keep it unchanged.

const transformed = walkAst(ast, (node) => {
  if (isStrongNode(node)) {
    return emphasis(getNodeChildren(node));
  }
  return undefined;
});

Type guards

Functions for checking node types:

GuardMatches
isTextNode(node)Plain text
isParagraphNode(node)Paragraph
isStrongNode(node)Bold
isEmphasisNode(node)Italic
isDeleteNode(node)Strikethrough
isInlineCodeNode(node)Inline code
isCodeNode(node)Code block
isLinkNode(node)Link
isBlockquoteNode(node)Blockquote
isListNode(node)List
isListItemNode(node)List item
isTableNode(node)Table
isTableRowNode(node)Table row
isTableCellNode(node)Table cell

getNodeChildren / getNodeValue

Safely access node properties without type narrowing.

const children = getNodeChildren(node); // Content[] | undefined
const value = getNodeValue(node);       // string | undefined

tableToAscii

Render an mdast Table node as a padded ASCII table string. Used by adapters that lack native table support (Google Chat, Discord, Telegram).

import { parseMarkdown, tableToAscii, isTableNode } from "chat";

const ast = parseMarkdown("| Name | Role |\n|------|------|\n| Alice | Engineer |");
// Find the table node and convert it

Output:

Name  | Role
------|--------
Alice | Engineer

tableElementToAscii

Render a table from headers and string row arrays as a padded ASCII table. Used for card TableElement fallback rendering.

import { tableElementToAscii } from "chat";

const ascii = tableElementToAscii(
  ["Name", "Age", "Role"],
  [
    ["Alice", "30", "Engineer"],
    ["Bob", "25", "Designer"],
  ]
);

The SDK uses mdast as the canonical format and each adapter converts it to the platform's native syntax. You write standard markdown and the SDK handles the translation — but it helps to know how each platform renders common formatting.

FeatureSlackTeamsGoogle Chat
Bold**text****text***text*
Italic_text__text__text_
Strikethrough~~text~~~~text~~~text~
Code`code``code``code`
Code blocks`````````
Links[text](url)[text](url)[text](url)
ListsSupportedSupportedSupported
Blockquotes>>Simulated with > prefix
TablesNative (markdown_text)Native GFMASCII fallback
Mentions<@USER><at>name</at><users/{id}>

Slack accepts standard markdown via the markdown_text field on chat.postMessage and friends, so the SDK passes markdown through directly. Incoming Slack messages still arrive as legacy mrkdwn (*bold*, <url|text>) and are parsed transparently. If you need to send mrkdwn yourself, use { raw: "..." }.

You don't need to worry about these differences when using the SDK — the AST builders and parseMarkdown handle conversion automatically. This table is useful if you're working with raw platform payloads or debugging formatting issues.