Chuyển đến nội dung chính
Cách trình bày tin nhắn là hợp đồng dùng chung của OpenClaw dành cho giao diện trò chuyện gửi đi phong phú. Nó cho phép tác nhân, lệnh CLI, luồng phê duyệt và plugin mô tả ý định của tin nhắn một lần, trong khi mỗi plugin kênh hiển thị theo dạng gốc phù hợp nhất có thể. Sử dụng cách trình bày cho giao diện tin nhắn có tính di động: các phần văn bản, văn bản ngữ cảnh/chân trang ngắn, đường phân cách, biểu đồ, bảng, nút, menu chọn và tiêu đề/tông màu của thẻ. Không thêm các trường mới dành riêng cho nhà cung cấp như Discord components, Slack blocks, Telegram buttons, Teams card hoặc Feishu card vào công cụ tin nhắn dùng chung. Đây là đầu ra của trình kết xuất do plugin kênh sở hữu.

Hợp đồng

Tác giả plugin nhập hợp đồng công khai từ:
Cấu trúc:
Ngữ nghĩa của nút:
  • action.type: "command" chạy một lệnh gạch chéo gốc thông qua đường dẫn lệnh của lõi. Sử dụng mục này cho các nút và menu lệnh tích hợp sẵn.
  • action.type: "callback" truyền dữ liệu plugin không trong suốt qua đường dẫn tương tác của kênh. Plugin kênh không được diễn giải lại dữ liệu callback thành lệnh gạch chéo.
  • action.type: "approval" xác định một phê duyệt bền vững của người vận hành, loại exec hoặc plugin rõ ràng của phê duyệt đó và quyết định được yêu cầu. Plugin kênh mã hóa hành động đó thành callback riêng của phương thức truyền tải và phân giải nó thông qua dịch vụ phê duyệt; chúng không được phân tích văn bản lệnh /approve hoặc suy ra loại từ ID.
  • action.type: "question" xác định một lựa chọn cho câu hỏi ask_user đang hoạt động do môi trường chạy tạo. Tương tự approval, đây là hành động trong môi trường chạy OpenClaw; tác nhân và plugin không được tự tạo ID câu hỏi. Telegram, Discord và Slack ánh xạ hành động này thành callback gốc riêng của phương thức truyền tải và phân giải lựa chọn thông qua Gateway. Khi câu hỏi được trả lời, hết hạn hoặc bị hủy, các kênh đó chỉnh sửa tin nhắn đã gửi, loại bỏ các hành động và thêm trạng thái kết thúc. WhatsApp, Signal và iMessage hiển thị tối đa bốn lựa chọn đơn dưới dạng phản ứng 1️⃣ đến 4️⃣. Các dạng câu hỏi khác được hạ cấp thành văn bản nhãn và người dùng có thể trả lời bằng văn bản thuần.
  • action.type: "url" mở một liên kết thông thường.
  • action.type: "web-app" khởi chạy ứng dụng web gốc của kênh. Đặt url cho ứng dụng dựa trên URL hoặc widgetId cho tiện ích do OpenClaw lưu trữ mà cơ chế khởi chạy thuộc quyền sở hữu của kênh; bắt buộc phải có ít nhất một trong hai. Khi có cả hai, kênh có thể ưu tiên cơ chế khởi chạy tiện ích được lưu trữ gốc và sử dụng URL ở nơi cơ chế đó không khả dụng.
  • value là giá trị callback không trong suốt kế thừa. Các điều khiển mới nên sử dụng action để plugin kênh có thể ánh xạ lệnh và callback mà không phải đoán từ văn bản.
  • url, webAppweb_app vẫn được chấp nhận làm đầu vào biên đã lỗi thời. Trình chuẩn hóa bảo toàn các trường này để trình kết xuất có thể phân biệt ngữ nghĩa kế thừa đã phát hành với hành động có kiểu rõ ràng. Trình tạo mới nên sử dụng action.
  • label là bắt buộc và cũng được dùng trong phương án dự phòng bằng văn bản.
  • style mang tính tư vấn. Trình kết xuất nên ánh xạ các kiểu không được hỗ trợ sang một giá trị mặc định an toàn thay vì làm thao tác gửi thất bại.
  • priority là tùy chọn. Khi một kênh công bố giới hạn hành động và phải loại bỏ các điều khiển, lõi giữ lại các nút có mức ưu tiên cao hơn trước và bảo toàn thứ tự ban đầu giữa các nút có cùng mức ưu tiên. Khi tất cả điều khiển đều vừa, thứ tự do tác giả xác định được bảo toàn.
  • disabled là tùy chọn. Kênh phải chủ động hỗ trợ bằng supportsDisabled; nếu không, lõi sẽ hạ cấp điều khiển bị vô hiệu hóa thành văn bản dự phòng không tương tác. Một nút bị vô hiệu hóa luôn chỉ hiển thị nhãn trong văn bản dự phòng, ngay cả khi nó mang hành động command.
  • reusable là tùy chọn. Các kênh hỗ trợ callback gốc có thể tái sử dụng có thể giữ hành động khả dụng sau một tương tác thành công. Sử dụng mục này cho các hành động có thể lặp lại hoặc có tính lũy đẳng như làm mới, kiểm tra hoặc xem thêm chi tiết; không đặt mục này cho các phê duyệt dùng một lần thông thường và hành động phá hủy.
Ngữ nghĩa của lựa chọn:
  • options[].action chỉ chấp nhận command hoặc callback; hành động phê duyệt và liên kết chỉ dành cho nút.
  • options[].value là giá trị ứng dụng được chọn kế thừa.
  • placeholder mang tính tư vấn và có thể bị các kênh không hỗ trợ lựa chọn gốc bỏ qua.
  • Nếu một kênh không hỗ trợ lựa chọn, văn bản dự phòng sẽ liệt kê các nhãn.
Ngữ nghĩa của biểu đồ:
  • pie yêu cầu các giá trị phân đoạn dương.
  • bar, arealine sử dụng một mảng categories có thứ tự. Mỗi chuỗi cung cấp chính xác một giá trị hữu hạn cho mỗi danh mục, theo cùng thứ tự.
  • Nhãn danh mục và tên chuỗi phải là duy nhất. Các khối biểu đồ không hợp lệ hoặc không đầy đủ bị loại bỏ trong quá trình chuẩn hóa thay vì âm thầm thay đổi dữ liệu.
  • Việc kết xuất biểu đồ gốc phải được chủ động bật thông qua presentationCapabilities.charts. Các kênh khác nhận tiêu đề biểu đồ, trục, danh mục, chuỗi và giá trị dưới dạng văn bản tất định. Đây cũng là phương án dự phòng hỗ trợ khả năng tiếp cận.
Ngữ nghĩa của bảng:
  • caption là một tiêu đề ngắn bắt buộc. headers phải chứa ít nhất một nhãn cột duy nhất, không trống.
  • rows phải chứa ít nhất một hàng. Mỗi hàng phải có chính xác một ô cho mỗi tiêu đề và mỗi ô phải là một chuỗi không trống hoặc một số hữu hạn.
  • rowHeaderColumnIndex là chỉ mục tùy chọn bắt đầu từ 0, xác định cột có các ô cần được trình kết xuất gốc cung cấp dưới dạng tiêu đề hàng.
  • Việc chuẩn hóa bảng có tính nguyên tử. Chú thích, tiêu đề, độ rộng hàng, ô hoặc chỉ mục tiêu đề hàng không hợp lệ sẽ khiến khối bảng bị loại bỏ thay vì cắt bớt hoặc sửa chữa dữ liệu của nó.
  • Việc kết xuất bảng gốc phải được chủ động bật thông qua presentationCapabilities.tables. Các kênh khác nhận chú thích và mọi hàng dưới dạng văn bản tuyến tính tất định, với khoảng trắng nội bộ được thu gọn:
Không có bộ phân biệt report riêng. Tạo báo cáo từ title, tone, text, context, chart, table và các khối hành động. Điều này giúp mỗi khối có thể được kết xuất độc lập và cung cấp cho toàn bộ báo cáo cùng một phương án dự phòng bằng văn bản tất định.

Ví dụ về trình tạo

Thẻ đơn giản:
Nút liên kết chỉ có URL:
Nút Telegram Mini App:
Menu chọn:
Biểu đồ:
Báo cáo dạng bảng:
Gửi bằng CLI:
Gửi được ghim:
Gửi có ghim với JSON tường minh:

Hợp đồng trình kết xuất

Các plugin kênh khai báo khả năng hỗ trợ kết xuất trên bộ điều hợp gửi đi:
Các giá trị boolean về khả năng mô tả những gì trình kết xuất có thể làm cho tương tác. limits tùy chọn mô tả lớp bao chung mà lõi có thể điều chỉnh trước khi gọi trình kết xuất:
Lõi áp dụng các giới hạn chung cho điều khiển ngữ nghĩa trước khi kết xuất. Trình kết xuất vẫn chịu trách nhiệm xác thực và cắt bớt lần cuối theo từng nhà cung cấp đối với số lượng khối gốc, kích thước thẻ, giới hạn URL và các đặc thù của nhà cung cấp không thể biểu đạt trong hợp đồng chung. Nếu các giới hạn loại bỏ mọi điều khiển khỏi một khối, lõi giữ các nhãn dưới dạng văn bản ngữ cảnh không tương tác để thông điệp được gửi vẫn có phương án dự phòng hiển thị được.

Luồng kết xuất lõi

Trên đường gửi đi chuẩn được CLI và các hành động thông điệp tiêu chuẩn sử dụng, lõi:
  1. Chuẩn hóa tải trọng trình bày.
  2. Phân giải bộ điều hợp gửi đi của kênh đích.
  3. Đọc presentationCapabilities.
  4. Áp dụng các giới hạn khả năng chung như số lượng hành động, độ dài nhãn và số lượng tùy chọn lựa chọn khi bộ điều hợp quảng bá chúng. Các khối biểu đồ và bảng trở thành văn bản xác định trừ khi bộ điều hợp quảng bá tường minh charts: true hoặc tables: true tương ứng.
  5. Gọi renderPresentation khi bộ điều hợp có thể kết xuất tải trọng.
  6. Chuyển sang văn bản dự phòng thận trọng khi không có bộ điều hợp hoặc bộ điều hợp không thể kết xuất.
  7. Gửi tải trọng kết quả qua đường phân phối kênh thông thường.
  8. Áp dụng siêu dữ liệu phân phối như delivery.pin sau thông điệp đầu tiên được gửi thành công.
Các luồng trả lời hoặc xem trước cục bộ của kênh sử dụng trực tiếp ReplyPayload phải đi vào đường chuẩn đó hoặc hiện thực hóa cùng phương án trình bày dự phòng trước khi chiếu tải trọng xuống văn bản thuần/phương tiện. Lõi chịu trách nhiệm về hành vi dự phòng để bên tạo có thể độc lập với kênh. Các plugin kênh chịu trách nhiệm kết xuất gốc và xử lý tương tác.

Quy tắc suy giảm

Nội dung trình bày phải an toàn để gửi trên các kênh bị giới hạn. Văn bản dự phòng bao gồm:
  • title làm dòng đầu tiên
  • Các khối text dưới dạng đoạn văn thông thường
  • Các khối context dưới dạng dòng ngữ cảnh ngắn gọn
  • Các khối divider dưới dạng dấu phân cách trực quan
  • nhãn nút, bao gồm URL cho các nút liên kết
  • nhãn tùy chọn lựa chọn
  • tiêu đề, loại, trục, danh mục, chuỗi và giá trị của biểu đồ
  • chú thích, tiêu đề cột và mọi giá trị hàng của bảng

Khả năng hiển thị giá trị nút trong phương án dự phòng

Khi một kênh không thể kết xuất các điều khiển tương tác, giá trị nút và lựa chọn chuyển thành văn bản thuần. Hành vi dự phòng duy trì khả năng sử dụng đồng thời giữ dữ liệu gọi lại không rõ nghĩa ở chế độ riêng tư:
  • Các hành động có kiểu command kết xuất thành label: `command` để người dùng có thể sao chép lệnh và chạy thủ công trong trường nhập của kênh.
  • Các hành động có kiểu callback và các trường value cũ chỉ kết xuất nhãn. Giá trị gọi lại không rõ nghĩa không được hiển thị trong văn bản dự phòng.
  • Các hành động có kiểu approval chỉ kết xuất nhãn. ID và quyết định phê duyệt là dữ liệu vận chuyển và không được hiển thị qua các trình trợ giúp vô hướng chung hoặc văn bản dự phòng.
  • Các hành động url, các hành động web-app dựa trên URL và đầu vào url / webApp / web_app đã lỗi thời kết xuất văn bản URL cùng với nhãn nút, vì URL hiển thị cho người dùng. Các hành động chỉ dành cho tiện ích được lưu trữ chỉ kết xuất nhãn trên các kênh không có khả năng khởi chạy tiện ích gốc.
  • Các tùy chọn lựa chọn chỉ kết xuất nhãn. Giá trị tùy chọn bên dưới không được hiển thị trong văn bản dự phòng.
Các bộ điều hợp kênh bổ sung hướng dẫn lệnh thủ công trong giao diện dự phòng của mình (ví dụ: hướng dẫn bình luận tài liệu Feishu) phải suy ra kiểm tra sự hiện diện của lệnh từ chính các khối trình bày mà trình kết xuất dự phòng sử dụng, để văn bản hướng dẫn chỉ xuất hiện khi một lệnh thủ công thực sự được hiển thị. Các điều khiển gốc không được hỗ trợ nên suy giảm thay vì làm toàn bộ lượt gửi thất bại. Ví dụ:
  • Telegram khi tắt nút nội tuyến sẽ gửi văn bản dự phòng.
  • Một kênh không hỗ trợ lựa chọn sẽ liệt kê các tùy chọn lựa chọn dưới dạng văn bản.
  • Một kênh không hỗ trợ biểu đồ gốc sẽ liệt kê dữ liệu biểu đồ dưới dạng văn bản.
  • Một kênh không hỗ trợ bảng gốc sẽ liệt kê mọi hàng của bảng dưới dạng văn bản.
  • Một nút chỉ có URL trở thành nút liên kết gốc hoặc dòng URL dự phòng.
  • Lỗi ghim tùy chọn không làm thông điệp đã gửi thất bại.
Ngoại lệ chính là delivery.pin.required: true; nếu yêu cầu ghim là bắt buộc và kênh không thể ghim thông điệp đã gửi, quá trình phân phối sẽ báo lỗi.

Ánh xạ nhà cung cấp

Các trình kết xuất đi kèm hiện tại: Khả năng tương thích tải trọng gốc theo nhà cung cấp là một cơ chế hỗ trợ chuyển tiếp cho các bên tạo phản hồi hiện có. Đây không phải là lý do để thêm các trường gốc dùng chung mới.

Presentation so với InteractiveReply

InteractiveReply là tập con nội bộ cũ hơn được các trình trợ giúp phê duyệt và tương tác sử dụng. Nó hỗ trợ:
  • văn bản
  • nút
  • lựa chọn
MessagePresentation là hợp đồng gửi dùng chung chuẩn. Nó bổ sung:
  • tiêu đề
  • sắc thái
  • ngữ cảnh
  • dấu phân cách
  • biểu đồ
  • bảng
  • nút chỉ có URL
  • siêu dữ liệu phân phối chung thông qua ReplyPayload.delivery
Sử dụng các trình trợ giúp từ openclaw/plugin-sdk/interactive-runtime khi kết nối mã cũ:
Mã mới nên trực tiếp chấp nhận hoặc tạo MessagePresentation. Các tải trọng interactive hiện có là tập con đã lỗi thời của presentation; hỗ trợ khi chạy vẫn được duy trì cho các bên tạo cũ. Các trình trợ giúp chưa lỗi thời cần biết:
  • normalizeMessagePresentation(raw) / hasMessagePresentationBlocks(value) xác thực và ép kiểu một payload không định kiểu (ví dụ: JSON từ cờ CLI --presentation) thành MessagePresentation.
  • isMessagePresentationInteractiveBlock(block) thu hẹp một khối thành hợp buttons | select.
  • resolveMessagePresentationButtonAction(button)resolveMessagePresentationOptionAction(option) trả về hành động có kiểu chuẩn tắc trong khi vẫn chấp nhận các trường biên đã lỗi thời. Một action tường minh luôn được ưu tiên.
  • resolveMessagePresentationActionValue(action) / resolveMessagePresentationControlValue(control) chỉ đọc các giá trị vô hướng của lệnh/lệnh gọi lại. Một hành động chuẩn tắc không vô hướng không bao giờ chuyển tiếp sang value bóng kế thừa, nhờ đó ID phê duyệt và đích liên kết vẫn giữ nguyên kiểu.
  • renderMessagePresentationChartFallbackText(block) / renderMessagePresentationTableFallbackText(block) kết xuất một khối dữ liệu có cấu trúc thành văn bản xác định cho các đường dẫn dự phòng dành riêng cho từng kênh.
Các kiểu InteractiveReply* kế thừa và trình trợ giúp chuyển đổi được đánh dấu @deprecated trong SDK:
  • InteractiveReply, InteractiveReplyBlock, InteractiveReplyButton, InteractiveReplyOption, InteractiveReplySelectBlockInteractiveReplyTextBlock
  • normalizeInteractiveReply(...)
  • hasInteractiveReplyBlocks(...)
  • interactiveReplyToPresentation(...)
  • presentationToInteractiveReply(...)
  • presentationToInteractiveControlsReply(...)
  • resolveInteractiveTextFallback(...)
  • reduceInteractiveReply(...)
presentationToInteractiveReply(...)presentationToInteractiveControlsReply(...) vẫn khả dụng dưới dạng cầu nối trình kết xuất cho các triển khai kênh kế thừa. Mã tạo mới không nên gọi chúng; hãy gửi presentation và để cơ chế điều chỉnh của lõi/kênh xử lý việc kết xuất. Các trình trợ giúp phê duyệt cũng có các phương án thay thế ưu tiên phần trình bày:
  • sử dụng buildApprovalPresentationFromActionDescriptors(...) thay cho buildApprovalInteractiveReplyFromActionDescriptors(...)
  • sử dụng buildApprovalPresentation(...) thay cho buildApprovalInteractiveReply(...)
  • sử dụng buildExecApprovalPresentation(...) thay cho buildExecApprovalInteractiveReply(...)
Các trình dựng đã phát hành đó vẫn dựa trên lệnh để bảo đảm khả năng tương thích với plugin. Gateway và mã kênh tích hợp sở hữu một loại phê duyệt bền vững nên sử dụng buildTypedApprovalPresentation(...), buildTypedExecApprovalPendingReplyPayload(...) hoặc buildTypedPluginApprovalPendingReplyPayload(...) để các lớp vận chuyển nhận được một hành động approval tường minh thay vì suy luận ngữ nghĩa từ văn bản /approve. renderMessagePresentationFallbackText(...) trả về chuỗi trống cho các khối trình bày không có văn bản dự phòng, chẳng hạn như một phần trình bày chỉ có đường phân cách. Các lớp vận chuyển yêu cầu nội dung gửi không trống có thể truyền emptyFallback để chủ động dùng nội dung tối thiểu mà không thay đổi hợp đồng dự phòng mặc định.

Ghim khi gửi

Ghim là hành vi gửi, không phải phần trình bày. Sử dụng delivery.pin thay cho các trường riêng của nhà cung cấp như channelData.telegram.pin. Ngữ nghĩa:
  • pin: true ghim tin nhắn đầu tiên được gửi thành công.
  • pin.notify mặc định là false.
  • pin.required mặc định là false.
  • Lỗi ghim không bắt buộc sẽ được hạ cấp và giữ nguyên tin nhắn đã gửi.
  • Lỗi ghim bắt buộc khiến quá trình gửi thất bại.
  • Tin nhắn được chia thành nhiều phần sẽ ghim phần đầu tiên đã gửi, không phải phần cuối.
Các hành động tin nhắn pin, unpinpins thủ công vẫn tồn tại cho các tin nhắn hiện có khi nhà cung cấp hỗ trợ những thao tác đó.

Danh sách kiểm tra dành cho tác giả plugin

  • Khai báo presentation từ describeMessageTool(...) khi kênh có thể kết xuất hoặc hạ cấp phần trình bày ngữ nghĩa một cách an toàn.
  • Thêm presentationCapabilities vào bộ điều hợp gửi đi của runtime.
  • Triển khai renderPresentation trong mã runtime, không phải mã thiết lập plugin của mặt phẳng điều khiển.
  • Không đưa các thư viện giao diện người dùng gốc vào các đường dẫn thiết lập/danh mục nóng.
  • Khai báo các giới hạn khả năng chung trên presentationCapabilities.limits khi đã biết chúng.
  • Giữ nguyên các giới hạn nền tảng cuối cùng trong trình kết xuất và kiểm thử.
  • Thêm kiểm thử dự phòng cho biểu đồ, bảng, nút, trường chọn, nút URL không được hỗ trợ, nội dung tiêu đề/văn bản trùng lặp và các lượt gửi kết hợp message cùng presentation.
  • Chỉ thêm hỗ trợ ghim khi gửi thông qua deliveryCapabilities.pinpinDeliveredMessage khi nhà cung cấp có thể ghim ID của tin nhắn đã gửi.
  • Không cung cấp các trường thẻ/khối/thành phần/nút mới riêng của nhà cung cấp thông qua lược đồ hành động tin nhắn dùng chung.

Tài liệu liên quan