← Chương trước: Phần 1 — Beyond Chatbots | Mục lục Series | Chương tiếp theo: Phần 3 — Component Registry →
Answer-first: Quản lý trạng thái GenUI phân định rõ rệt AIState (JSON serializable phía backend) và UIState (component dynamic phía client). Kiến trúc Framework-Agnostic dựa trên Astro Islands và chuẩn A2UI truyền nhận qua WebSockets hai chiều, loại bỏ hoàn toàn sự phụ thuộc vào React Server Components (RSC).
Trong phần trước, chúng ta đã thống nhất việc loại bỏ Chatbot để tiến tới Generative UI. Nhưng để AI có thể “đẻ” ra được các UI Component ngay trên màn hình người dùng, Frontend và Backend không thể chỉ giao tiếp qua các API stateless thông thường. Chúng cần chia sẻ một trạng thái (State) chung.
Vấn đề là: Bộ não của AI và Trình duyệt của người dùng nói hai ngôn ngữ hoàn toàn khác nhau.
2.1. Phân định rạch ròi: AIState và UIState
Khi xây dựng một hệ thống Agentic có Giao diện, nguyên tắc sống còn đầu tiên là phải tách biệt tuyệt đối AIState và UIState.
AIState (Não bộ của Backend)
- Bản chất: Là một mảng (array) chứa toàn bộ lịch sử hội thoại, các tool calls, và context của Agent.
- Định dạng: JSON thuần túy (Serializable). Đây là thứ sẽ được gửi thẳng vào mồm của LLM (ví dụ: OpenAI API) và lưu trữ dưới Database (PostgreSQL/Redis).
- Ví dụ:
[{"role": "user", "content": "Mua vé đi Hà Nội"}, {"role": "assistant", "tool_calls": [{"name": "book_flight", "arguments": "{"dest": "HAN"}"}]}]
UIState (Hiển thị của Frontend)
- Bản chất: Là danh sách các React/Svelte/Vue Components đang được render trên màn hình tại thời điểm hiện tại.
- Định dạng: Các Object chứa Functions, DOM Nodes, Event Listeners (Non-serializable). Bạn không thể lưu UIState vào Database.
- Ví dụ:
[<UserMessage text="Mua vé đi Hà Nội" />, <FlightBookingWidget dest="HAN" onConfirm={handleConfirm} />]
Bài toán cốt lõi của Generative UI chính là làm sao ánh xạ (map) một chuỗi JSON (AIState) thành một danh sách các Component (UIState) một cách an toàn và theo thời gian thực.
2.2. Hai trường phái kiến trúc: Next.js (RSC) vs Framework-Agnostic (Astro)
Hiện tại, thế giới Frontend chia làm hai nửa trong cách xử lý bài toán mapping này.
Trường phái 1: Next.js và React Server Components (RSC)
Đây là cách tiếp cận được Vercel (qua Vercel AI SDK UI) quảng bá rầm rộ nhất. Dù phiên bản AI SDK 7 (giữa 2026) đã mở rộng với WorkflowAgent và AI Elements, tư duy cốt lõi vẫn xoay quanh hệ sinh thái React.
- Cách hoạt động: Việc mapping từ AIState sang UIState diễn ra hoàn toàn trên Server. Server chạy LLM, nhận JSON về, và lập tức render ra React Component. Sau đó, server “stream” (truyền) thẳng Component đó xuống Client thông qua RSC payload.
- Ưu điểm: DX (Developer Experience) cực tốt. Bạn code frontend và backend chung một chỗ.
- Nhược điểm (Tử huyệt Enterprise): Bị khóa chặt (Vendor lock-in) vào Next.js và React. Nếu hệ thống lõi của bạn đang dùng Vue, Svelte, Angular, hoặc chạy trên hệ sinh thái Edge-first của Astro 6.0, mô hình này rất khó tích hợp.
Trường phái 2: Framework-Agnostic với chuẩn A2UI (Sự lựa chọn của Enterprise)
Để hệ thống không bị lỗi thời (Future-proof) và dễ dàng tích hợp vào các dự án Legacy, chúng ta bắt buộc phải đẩy logic mapping xuống Client (hoặc một Orchestrator trung gian như Astro).
- Cách hoạt động:
- Backend Agent (chạy Python/Golang/Node) gọi LLM và trả về một cấu trúc JSON chuẩn hóa (như chuẩn A2UI - Agent to User Interface).
- JSON này chỉ chứa:
Component_Name(ví dụ:flight_widget) vàProps_Data. - Frontend (Astro) đóng vai trò là Orchestrator. Nó nhận JSON này, tìm trong Component Registry của mình, bốc Svelte/Vue Component tương ứng ra, bơm Data vào và render lên màn hình.
- Ưu điểm: Backend Agent có thể viết bằng bất kỳ ngôn ngữ nào. Frontend có thể dùng Astro để mix cả React, Vue, Svelte trên cùng một trang (Islands Architecture). Bảo mật tuyệt đối vì AI không bao giờ được chạm vào mã HTML/JS, nó chỉ được trả về Data.
2.3. Giao thức Đồng bộ: SSE vs WebSockets
Khi Frontend đã biết cách render, câu hỏi tiếp theo là: Dùng đường truyền nào để Frontend nhận tín hiệu từ Agent?
Server-Sent Events (SSE) - Phù hợp cho Token Streaming
Nếu UI của bạn chỉ cần hiển thị chữ đang gõ ra từng chữ một (ChatGPT-style) hoặc hiện trạng thái đơn giản (“Đang tìm kiếm…”), SSE là quá đủ.
- Ưu điểm: Dùng HTTP tiêu chuẩn, đi qua Load Balancers/Firewalls dễ dàng, trình duyệt tự động reconnect.
- Nhược điểm: Là giao tiếp một chiều (Unidirectional). Server gửi dữ liệu xuống Client. Client muốn gửi dữ liệu lên phải gọi một HTTP POST request khác.
WebSockets - Bắt buộc cho Interactive Agents
Hệ thống Agentic phức tạp đòi hỏi sự tương tác hai chiều (Bi-directional) liên tục.
- Kịch bản: Agent A sinh ra form thanh toán trên màn hình (Server -> Client). Người dùng sửa số tiền và bấm “Xác nhận”. Tín hiệu này phải lập tức được gửi ngược về cho Agent A để nó cập nhật Context và đi tiếp (Client -> Server).
- Trong Generative UI thực thụ, trạng thái UI thay đổi từng mili-giây khi người dùng tương tác với Component do AI sinh ra. Việc dùng HTTP POST cho mỗi tương tác sẽ gây ra độ trễ (latency) không thể chấp nhận được.
- Khuyến nghị: Sử dụng WebSockets (hoặc WebRTC Data Channels cho các app realtime cực nặng) để quản lý
UIStatevàAIState.
⚠️ Lưu ý kiến trúc (Vận hành & Phục hồi): Khi dùng WebSockets, bạn sẽ phải đối phó với 2 bài toán hạ tầng lớn:
- Sticky Sessions: Load Balancer phải điều hướng connection của Client trúng đúng vào Pod/Container đang chạy Agent đó trong cụm Kubernetes.
- State Recovery (Phục hồi trạng thái): WebSockets cực kỳ dễ rớt kết nối trên môi trường mạng thực tế (như 4G/Mobile). Khi Frontend reconnect thành công, bắt buộc phải có cơ chế tự động “kéo” (sync) lại trạng thái hiện tại từ
AIStatecủa Backend để khôi phục lạiUIState, tránh việc Component bị “đóng băng” do mất tín hiệu ngầm.
← Chương trước: Phần 1 — Beyond Chatbots | Mục lục Series | Chương tiếp theo: Phần 3 — Component Registry →
❓ Câu Hỏi Thường Gặp (FAQ)
Q1: Kiến Trúc Framework-Agnostic State Management giải quyết vấn đề cốt lõi nào trong kiến trúc hệ thống?
So sánh AIState và UIState. Kiến trúc Framework-Agnostic với Astro/Svelte. Khi nào dùng SSE, khi nào bắt buộc dùng WebSockets trong Generative UI.
Q2: Những lưu ý quan trọng nhất khi triển khai thực tế là gì?
Cần chú trọng phân tầng ranh giới trách nhiệm (bounded context), thiết lập cơ chế fallback dự phòng, và giám sát chặt chẽ qua metrics OpenTelemetry để phát hiện sớm các điểm nghẽn.
Q3: Làm sao để kiểm thử và đánh giá hiệu quả sau khi áp dụng?
Áp dụng kiểm thử tải (load test), benchmark độ trễ P95/P99 trước và sau triển khai, kết hợp tracing phân tán để xác minh tính ổn định dưới tải cao.
