code-docs/plugins/blocks/antd-x.md
AI-focused blocks built on Ant Design X components.
Provides AgentChat (a production-grade chat UI) and AgentConversations (a standalone conversation list sidebar) for Lowdefy's agent system.
Category: display
Composite chat block that integrates the AI SDK's useChat hook with Ant Design X's Bubble, Sender, and ThoughtChain components.
Key Properties:
agentId — Required. Which agent to call.conversationId — Conversation identifier for multi-turn persistencemessages — Load existing messages (external state)urlQuery — Query params passed to agent APIsharedState — Object slice of page state the agent may read and write back via the built-in update-page-state tool. See Shared State below.welcome — Welcome screen: title, description, prompts[]messageDisplay — Rendering: showThoughtChain, reasoningDisplay, toolResultDisplay, thinkingMessages, thinkingMessageDelay, thinkingMessageRotationIntervalsender — Input area: placeholder, submitType, allowSpeech, attachments, header, switches[], suggestions[]display — "drawer" or default inlineroles — Per-role config: variant, shape, avatar, namerenderMermaid — Enable mermaid diagram renderingcodeHighlighter — Enable syntax highlightingEvents (15+):
onBeforeSend — Blocking. Validation, file uploads, rate limiting. success: false cancels.onMessageComplete — Assistant message finished. Payload includes finishReason, parts, messages.onToolCall / onToolResult — Tool lifecycleonError — Connection/execution errorsonFeedback — User rating (copy, like, dislike)onUserMessage, onStop, onRegenerate, onEditMessage, onDeleteMessageonSuggestionClick, onSwitchChange, onTitleGenerated, onDataPartMethods (via CallMethod):
regenerate, setMessages, sendMessage, clearMessages, deleteMessage, stop, clearError, scrollToBottomCategory: display
Standalone conversation list sidebar, decoupled from AgentChat.
Properties:
items — Conversation list (from state/requests)activeKey — Currently selected conversationmenu — Context menu actions per conversationcreation — "New Chat" button configgroupable — Enable collapsible groupswidth — Panel widthEvents: onSelect, onNew, onMenuClick
createLowdefyChatTransport() creates a DefaultChatTransport (from AI SDK) that POSTs to /api/agent/{pageId}/{agentId}?conversationId=... with { messages, urlQuery, sharedState } in the body. sharedState is read from a ref at send time so the freshest evaluated value is sent without re-creating the transport. A new transport is created when pageId, agentId, conversationId, or urlQuery changes.
When properties.sharedState is a non-empty object, two things happen:
The transport sends the object on every turn and the server injects it into the agent's <context> block and builds an update-page-state tool describing its top-level keys.
The block registers an internal __updatePageState event wired to SetState with params: { _event: true } at mount:
methods.registerEvent({
name: '__updatePageState',
actions: [{ id: 'setState', type: 'SetState', params: { _event: true } }],
});
When the model calls update-page-state, the block's onToolCall handler:
updates against the keys in sharedStateRef.current -- unknown keys are collected into ignored and dropped (defence against hallucinated writes).methods.triggerEvent({ name: '__updatePageState', event: writable }) to run the SetState action with the filtered updates.addToolOutput({ output: { ok: true, written, ignored } }) so the model sees what took effect.See code-docs/architecture/agent-system.md#shared-state for the full end-to-end flow.
The loading assistant bubble shows typing dots by default. Three messageDisplay props let you layer a rotating label on top:
thinkingMessages -- string, or array of strings to rotate through. Leave unset for dots only.thinkingMessageDelay -- ms of continuous loading before the first label shows (default 3000, clamped to 500 ms min so near-instant responses don't flash a label).thinkingMessageRotationInterval -- ms between rotations when thinkingMessages is an array of 2+ (default 8000).The indicator stays visible on hidden-tool turns (tool calls that don't surface in the ThoughtChain) so the user still sees activity.
The useChat hook from @ai-sdk/react manages messages, status, and streaming. External messages (from props) sync when count or last ID changes, preventing infinite re-render loops. Messages clear when conversationId changes.
useAgentEvents converts AI SDK message updates to Lowdefy block events by tracking seen message/tool IDs. This prevents duplicate event firing during re-renders.
@ant-design/x — Bubble, Sender, ThoughtChain, Conversations@ai-sdk/react — useChat, DefaultChatTransportreact-markdown, remark-gfm, remark-math, rehype-katex — Markdown/LaTeXmermaid — Diagram rendering (lazy-loaded)react-syntax-highlighter — Code highlighting (lazy-loaded)| File | Purpose |
|---|---|
src/blocks/AgentChat/AgentChat.js | Main component |
src/blocks/AgentChat/LowdefyChatTransport.js | Transport factory |
src/blocks/AgentChat/useAgentEvents.js | Event bridging |
src/blocks/AgentChat/MessageBubble.js | Message rendering |
src/blocks/AgentChat/MessageList.js | Message list with auto-scroll |
src/blocks/AgentChat/ToolApproval.js | Tool confirmation UI |
src/blocks/AgentChat/WelcomeScreen.js | Welcome screen |
src/blocks/AgentChat/DrawerWrapper.js | Drawer mode wrapper |
src/blocks/AgentConversations/AgentConversations.js | Conversation list |