Skip to main content
Agent Chat is in closed beta. Contact us at [email protected] to get access.
Start from Send a message. This page covers everything after the first message. messages is the ordered timeline. Each message has role (user or assistant) and parts.

State

Use these fields to drive the UI. See useAgentChat for types. See Reconnect (isRecovering, catchUpError). See Older messages (pagination).

Parts

Start with type === 'text'. Then handle the other part types. See useAgentChat for part types.

Thinking

While the agent turn is in progress, isRunning is true. typing is present when the agent is typing. Assistant messages can include thinking parts before text arrives. run is the same snapshot: isRunning is run.isRunning, and typing is run.typing.
The first event of a turn can create an empty assistant message before any text arrives. Keep that row in the list. Then fill it as parts arrive.

Approvals

pendingActions lists waits that block the turn. Do not mix the two action types.

Tool approval

Pass action.id from pendingActions. Do not invent approve or deny ids.

MCP connect

Cards

A Card is a structured reply. It can include a title, text, images, links, and buttons. When the agent sends a Card, the message includes a part with type: 'card'. The data is on part.card. Agents create Cards with JSX or Card({…}). That authoring API is shared with Slack and the other ACI channels: Interactive cards. You can also post the JSON with Send an agent reply. The SDK does not type part.card. card is Record<string, unknown>. Read the fields that you support. Skip child types that you do not use. Render title and the children that you support. If the subscriber clicks a button, call sendAction. The agent receives the click in onAction.
Do not send the button label with sendMessage. That call creates a new chat message. Do not call respondToAction. That function is for tool approval only.

Data, file, source

Custom data parts

The agent sends a named payload with ctx.emit. Agent Chat adds it to the in-flight assistant message as part.type === 'data'. The fields are name and data. See Emit custom events for the handler API, size limit, and other channels.
Skip data parts that your UI does not handle. The part stays on the message.

File and source

Retry a failed send

If message.status is failed, call retryMessage with that message id. Retry reuses the original idempotency key. It does not create a second message with the same text.

Resume a conversation

Pass conversationId so the hook loads history on mount.
Store the conversationId that sendMessage returns, or the conversationId field on the hook result. On the next visit, pass that id back in. The hook has no list-conversations API. You store the ids that you want to reopen. To start another chat, remount the component without conversationId, or clear the prop. agentId selects the agent. If the identifier changes, remount with the new agentId. Omit conversationId unless that conversation belongs to the new agent. A conversation id from a different agent does not resume.

Older messages

If pagination.hasMore is true, call pagination.fetchMore() to load an older page.
Overlapping fetchMore calls do not run.

Reconnect

The hook reconnects and applies missed events on its own. Show a banner from these fields.
catchUpError is separate from send and fetch error. status does not become an error state when catch-up fails.