my-agent-crew

Canvas

Phiên bản: 0.20.0 · Cập nhật: 2026-10-14

Canvas là tài liệu có phiên bản mà người và agent cùng sửa. Nó mở cạnh khung chat trên web, sống lâu hơn cuộc trò chuyện đã sinh ra nó, và mỗi lần ghi là một phiên bản mới. Trang này nói canvas dùng để làm gì, ai ghi được gì, và những hợp đồng người dùng thấy: tên tool, endpoint, event, tên tệp gửi qua Telegram. Tham số từng tool nằm ở tools.md.

1. Canvas là gì, khi nào dùng

Chat hợp với câu trả lời đọc một lần. Canvas dành cho nội dung dài hoặc có cấu trúc mà người sẽ đọc lại, sửa hay dùng tiếp: kế hoạch, báo cáo, bản nháp, một tệp code hoàn chỉnh, một trang web, một hình vẽ, một sơ đồ. Mô tả của artifact_create dặn agent đúng như vậy: câu hỏi và trao đổi thì để trong chat, và sau khi tạo canvas thì câu trả lời chỉ nói ngắn đã viết gì, không chép lại nội dung.

Khi người nhận không ngồi ở web chat (lượt qua Telegram, lượt của job), agent được dặn chặt hơn: chỉ tạo canvas khi được dặn, hoặc khi tài liệu dài và sẽ còn sửa tiếp. Người cũng tự tạo được canvas: nút “Canvas” trên một hội thoại mở “Canvas của hội thoại”, trong đó có “Canvas mới”.

2. Loại nội dung và trần cỡ

Trần cỡ tính cho một phiên bản. Bản vượt trần bị từ chối nguyên vẹn, không lưu gì.

Loại Trần một phiên bản Ai tạo được Hiện ra thế nào
markdown 512 KB người, agent văn bản đã dựng; “Sửa” cho mã nguồn
code 512 KB người, agent mã nguồn, kèm tên ngôn ngữ (tối đa 40 ký tự)
mermaid 512 KB người, agent sơ đồ, vẽ trong khung cách ly
html 4 MB người, agent trang chạy trong khung cách ly
svg 2 MB người, agent một bức hình, không chạy script
image 2 MB chỉ qua artifact_import ảnh PNG, JPEG, GIF hoặc WebP

3. Vòng sửa chung

flowchart LR
    P[Người sửa trong bảng canvas] -->|tự lưu| V[(Phiên bản mới)]
    V -->|tin nhắn kế tiếp| N[Ghi chú canvas]
    N --> A[Agent đọc ghi chú]
    A -->|artifact_edit, artifact_rewrite| V
    V -->|event artifact| P
  1. Người sửa. Bảng canvas có hai chế độ “Xem” và “Sửa”. Chữ đang gõ được tự lưu sau 1,5 giây ngừng gõ; Cmd/Ctrl+S lưu ngay. Dòng trạng thái nói “Đã lưu”, “Đang lưu…”, “Chưa lưu”.
  2. Tin nhắn mang ghi chú canvas. Agent không cần gọi tool để biết người đã sửa gì. Tin nhắn kế tiếp của người được lưu kèm một ghi chú canvas, và model đọc ghi chú đó ngay trước tin nhắn. Ghi chú nêu mỗi canvas của hội thoại đã đổi từ lần cuối agent thấy nó: diff phần người tự sửa cho nhiều nhất ba canvas, canvas mới đổi nhất trước, mỗi diff tối đa 3000 ký tự và cả ghi chú tối đa 8000 ký tự. Phiên bản của agent khác, một lần khôi phục hay một thay đổi quá dài chỉ được nêu bằng một dòng dặn agent đọc lại. Canvas không vừa ghi chú được đếm ở dòng cuối.
  3. Canvas đang mở. Chỉ tin nhắn từ web chat mới nêu thêm canvas đang mở trên thiết bị gửi tin và đoạn đang chọn trong đó. Tin gửi lúc canvas còn chữ chưa lưu thì chờ lần lưu cuối (“Đang lưu canvas…”).
  4. Agent sửa. Agent sửa bằng tool (mục 6). Mỗi lần ghi hiện thành một thẻ trong luồng chat: tiêu đề, việc đã làm (“Đã tạo”, “Đã sửa”, “Đã viết lại”, “Đã nhập”, “Đã nhập lại”, “Không đổi”), số phiên bản và nút “Mở”.
  5. Hai bên cùng sửa. Nếu agent lưu trong lúc người đang gõ, hai bản được gộp khi chúng đổi những dòng khác nhau. Khi không gộp được, một thanh báo “Có hai bản khác nhau” kèm diff, với hai lựa chọn “Giữ bản của tôi” và “Nạp bản mới”; nạp bản mới thì “Hoàn tác” được. Phía agent, artifact_rewrite bị từ chối nếu canvas đã đổi từ lúc agent đọc, và agent nhận diff của phần người khác đã đổi.

Người thấy ghi chú mà agent đã đọc: dưới tin nhắn có một chip “Kèm ngữ cảnh canvas”, mở ra là nguyên văn ghi chú, có nút “Sao chép ghi chú canvas”.

Trên màn hình rộng từ 1101 px, canvas là cột bên phải của bố cục, kéo được bề rộng và hẹp nhất 360 px. Dưới ngưỡng đó nó phủ lên khung chat; “← Chat” hoặc Escape đóng nó lại.

4. Hỏi về một đoạn

Chọn một đoạn trong canvas, ở chế độ “Sửa” hay “Xem”, thì chân bảng hiện thanh “Hỏi về đoạn đã chọn”: nó nêu các dòng chứa đoạn chọn và có ô “Câu hỏi về đoạn này”. Câu hỏi đi thành một tin nhắn, kèm đoạn chọn theo đúng phiên bản vừa lưu, nên số dòng agent thấy là số dòng người thấy.

5. Lịch sử

Nút “Lịch sử” mở “Lịch sử phiên bản”: mọi phiên bản còn lưu, ai viết, lúc nào, và diff so với bản trước.

Khi nào các lần lưu của người gộp làm một. Một lần lưu của người ghi đè lên phiên bản mới nhất thay vì tạo phiên bản mới khi đủ cả bốn điều: phiên bản mới nhất cũng do người viết; cả hai không mang ghi chú (không phải bản khôi phục hay bản nhập từ tệp); phiên bản mới nhất được tạo chưa quá 120 giây; và chưa hội thoại nào đã thấy, đã đọc hay đã được báo về nó. Điều cuối giữ cho phiên bản mà agent từng đọc không bao giờ đổi dưới tay nó. Mọi lần ghi của agent là một phiên bản riêng.

Khôi phục. “Khôi phục bản này” không xoá gì: nó chép một bản cũ thành phiên bản mới nhất, ghi chú “Khôi phục từ v…”, sau khi chữ đang gõ đã được lưu. Bản nhập từ tệp mang ghi chú “Nhập từ tệp”.

Bản nháp trên trình duyệt. Chữ chưa lưu được (mất mạng, máy chủ không phản hồi, kho đầy) nằm trong một bản nháp trên thiết bị đó. Trình duyệt giữ mười bản nháp mới nhất, mỗi bản tối đa 30 ngày. Mở lại canvas thì bản nháp được mở (“Đã mở bản nháp chưa lưu trên máy này.”) hoặc gộp với bản mới hơn trên máy chủ. Thiết bị không cho lưu bản nháp thì chữ chỉ còn trong tab.

6. Bảy tool của agent

Tool Làm gì Duyệt Giới hạn
artifact_create tạo canvas loại chữ: markdown, code, html, svg, mermaid không 30 canvas mới mỗi lượt
artifact_list liệt kê canvas agent với tới, mới sửa trước, đánh dấu bản chưa thấy không 30 canvas
artifact_read đọc nguyên văn theo trang (version, from_line, lines) không một trang vừa trần đầu ra của agent
artifact_edit thay đoạn old bằng new; replace_all; đổi title không 30 lần ghi mỗi canvas mỗi lượt
artifact_rewrite viết lại cả canvas không như trên; phải đọc hết bản mới nhất trước
artifact_import đọc một tệp workspace thành canvas, mới hoặc đã có không tính như một lần ghi
artifact_export ghi phiên bản mới nhất ra một tệp workspace có không tính là lần ghi canvas

7. Phạm vi và kênh

Agent với tới canvas nào. Agent master với tới mọi canvas. Agent khác với tới ba nhóm: canvas đã gắn với cuộc trò chuyện đang chạy; canvas được chia sẻ ở cuộc trò chuyện gốc của chuỗi giao việc; và canvas chính nó tạo.

“Chia sẻ” nghĩa là agent được giao việc từ hội thoại đó cũng với tới. Một canvas được chia sẻ khi agent tạo hay sửa nó trong hội thoại, hoặc khi người mở nó ở đó. Xuất ra tệp và nhập lại một tệp không đổi chỉ gắn canvas với cuộc trò chuyện, không chia sẻ nó.

Kênh nào được ghi.

Lượt đến từ Tạo, sửa, viết lại, nhập Liệt kê, đọc Xuất ra tệp
Web chat được được được, chờ duyệt
Telegram được được được, chờ duyệt
Job theo lịch được được được, chờ duyệt
API inbound không được được, chờ duyệt

Lượt từ API inbound không có ai mở web để xem canvas, nên bốn tool ghi bị từ chối bằng câu “Kênh của lượt này chưa mở được canvas, nên chưa ghi gì. Viết thẳng nội dung vào câu trả lời.” System prompt của lượt đó đã dặn trước: “Kênh này chưa mở được canvas: trả lời thẳng trong tin nhắn”.

Agent được giao việc không có kênh riêng: nó theo kênh của cuộc trò chuyện gốc của chuỗi. Giao việc từ web chat thì agent con ghi được; giao việc từ một lượt API inbound thì không. Một trường hợp cũ: chuỗi giao việc tạo từ trước khi máy chủ ghi kênh của gốc thì không có kênh gốc nào để theo, và agent con trong chuỗi đó không ghi được canvas.

8. HTML và Mermaid chạy cách ly

Canvas html là một trang do agent viết, và nó chạy thật: script, style, thư viện từ CDN. Canvas mermaid được vẽ bằng thư viện Mermaid ghim phiên bản 11.17.2, tải kèm mã băm toàn vẹn, ở mức bảo mật nghiêm ngặt. Cả hai chạy trong một khung cách ly. Canvas svg và image chỉ hiện như một bức hình nên không chạy gì.

Khung được làm Khung không được làm
chạy script và style viết ngay trong trang gọi API của ứng dụng hay đọc dữ liệu trình duyệt của ứng dụng
tải script, style, font từ cdnjs.cloudflare.com, cdn.jsdelivr.net, unpkg.com gửi bất kỳ yêu cầu mạng nào từ script
tải font từ Google Fonts gửi form
dùng ảnh và media nhúng sẵn trong trang (data:, blob:) tải ảnh hay media từ địa chỉ ngoài
  mở kết nối WebRTC, bị nhúng ở trang khác, tự chuyển sang địa chỉ khác

Trang luôn được dựng từ phiên bản đã lưu và trình duyệt không giữ bản sao. Khi có bản mới, khung báo “Có bản mới · Nạp lại”. Trang tự chuyển địa chỉ thì bị dừng.

Bàn phím. Trang chỉ được giữ bàn phím sau khi người thật sự bấm vào nó; lúc đó bảng báo “Bàn phím đang ở trang”. Trang tự giành bàn phím thì bị lấy lại, và đến lần giành thứ năm thì trang bị dừng với dòng “Trang liên tục giành bàn phím nên đã bị dừng.” cùng nút “Nạp lại”.

“Gửi lỗi cho agent”. Trang báo lại lỗi script, tệp không tải được, yêu cầu bị chính sách chặn và promise bị từ chối. Mỗi lần tải, trang gửi được tối đa 20 báo cáo, mỗi báo cáo tối đa 2000 ký tự; bảng giữ tối đa 50 báo cáo. Nút “Gửi lỗi cho agent” gửi năm lỗi mới nhất thành một tin nhắn, mở đầu bằng lời nhắc rằng phần lỗi do chính trang ghi lại, có thể bị bịa ra, và chỉ là dữ liệu chứ không phải yêu cầu.

9. Cầu nối với workspace

artifact_import đọc một tệp trong workspace của agent thành canvas. Loại được suy từ đuôi tệp: .md thành markdown; .html thành html; .svg thành svg; .mmd thành mermaid; ảnh thành image; đuôi của các ngôn ngữ lập trình quen thuộc, YAML, JSON và tệp chữ thuần thành code. Đuôi lạ bị từ chối, trừ khi lượt gọi tự nêu loại. Tệp phải nằm trong workspace, là tệp thường, đọc được như UTF-8 (trừ ảnh) và vừa trần của loại. Tệp không đổi so với bản mới nhất thì không tạo phiên bản.

artifact_export ghi phiên bản mới nhất ra một tệp và luôn chờ duyệt. Đích phải nằm trong workspace sau khi giải mọi liên kết, phải nằm trong write_paths của agent nếu khoá đó được đặt (agent.yaml), và không được là thư mục hay một symlink. Tệp được ghi trọn vẹn hoặc không ghi gì.

Kit hook. Hook của kit nghe hai tool này như các tool workspace tương ứng: hook nêu Read hoặc workspace_read được hỏi về artifact_import, hook nêu Write hoặc workspace_write được hỏi về artifact_export. Payload giữ tên thật ở tool_name, đưa Read hoặc Write ở tool_alias, và đường dẫn ở tool_input.path. Vì vậy hook quyết định theo đường dẫn chặn được một lần xuất. Hook quyết định theo nội dung thì không: payload của artifact_export không mang nội dung sắp ghi.

Dòng nguồn và “Nhập lại”. Canvas nhập từ tệp có dòng “Nguồn:” ở đầu bảng. Nút “Nhập lại” lưu chữ đang gõ, đọc lại tệp và, nếu tệp đã khác, ghi nó thành phiên bản mới của người (“Đã nhập lại thành v…. Bản trước ở Lịch sử.”); tệp không đổi thì báo “Tệp nguồn không đổi.”. Khi lượt nhập có nêu một địa chỉ nguồn (source_url, http hoặc https, tối đa 2000 ký tự, không kèm tên đăng nhập hay mật khẩu), dòng nguồn có thêm liên kết “Mở nguồn”. Địa chỉ đó là lời của agent; không gì kiểm chứng nó.

10. Thư viện và trang riêng

11. Xem trước khi agent đang viết

Một canvas dài mất nhiều giây để model viết xong. Trong lúc đó web chat hiện một thẻ “Agent đang viết…” và, trên màn hình rộng, chữ đổ dần vào cột canvas ở dạng chỉ đọc. Không gì được lưu cho tới khi lượt gọi kết thúc.

12. Telegram và job

Chat không hiện được canvas, nên có hai đường đưa canvas tới người đọc ở xa. channels.md nói phần còn lại của kênh.

Gửi canvas như một tệp. Một dòng riêng FILE: artifact:<id> hoặc MEDIA: artifact:<id> trong câu trả lời gửi phiên bản mới nhất. Loại canvas quyết định cách gửi, không phải tiền tố: ảnh đi như ảnh, mọi loại khác đi như tài liệu.

Loại Tên tệp nhận được
markdown <tiêu đề>.md
code đuôi của ngôn ngữ rồi thêm .txt, hoặc chỉ .txt
html <tiêu đề>.html.txt
svg <tiêu đề>.svg.txt
mermaid <tiêu đề>.mmd.txt
image đuôi theo chính các byte của ảnh

Đuôi .txt để điện thoại mở tệp ra đọc chứ không chạy nó. Chú thích là "<tiêu đề>" v<n>, kèm liên kết nếu cả hai vừa 1024 ký tự. Tệp quá 20 MB không được gửi. Agent chỉ gửi được canvas nó với tới; canvas ngoài tầm và canvas không tồn tại nhận cùng một câu trả lời. Canvas nhập từ một tệp workspace có đuôi không thuộc loại gửi qua chat được thì không gửi.

Ở lượt Telegram và lượt job, kết quả của artifact_create và artifact_import nhắc lại đúng dòng này kèm mã của canvas vừa tạo, và không nói “người thấy nó cạnh khung chat”. Lần kiểm trên Telegram thật ngày 2026-10-05 cho thấy thiếu lời nhắc ấy thì agent xuất canvas ra workspace rồi gửi tệp đó: mất chú thích, và trang HTML hay ảnh bị từ chối vì đuôi tệp.

Lọc bí mật. Nội dung chữ, tiêu đề và chú thích đi qua bộ lọc trước khi rời máy chủ. Bộ lọc che giá trị của các biến môi trường có tên chứa KEY, TOKEN, SECRET, PASSWORD hoặc CREDENTIAL khi giá trị dài từ 8 ký tự, cùng chuỗi có dạng token Bearer, khoá sk- và JWT. Ảnh không được lọc. Xem giới hạn ở cuối trang.

Danh sách “Canvas vừa ghi:”. Sau lời của một lượt đã ghi canvas, chat nhận một tin riêng: dòng “Canvas vừa ghi:”, rồi mỗi canvas một dòng • "<tiêu đề>" v<n>. Nhiều nhất mười canvas được nêu; phần còn lại là dòng “… và {n} canvas khác.”. Danh sách đọc từ kết quả tool của lượt, không từ lời agent, và gồm cả canvas mà agent được giao việc đã ghi. Lần ghi không đổi gì, lần đọc và lần xuất không được nêu.

Liên kết. Đặt web_url trong config.yaml hoặc biến MY_AGENT_WEB_URL (biến môi trường thắng; xem deployment-guide.md) thì dưới mỗi canvas có dòng <web_url>/#/manage/canvas/<id>. Giá trị phải là địa chỉ http hoặc https thuần: host, cổng và đường dẫn. Không đặt thì danh sách kết bằng “Mở web UI để xem.”.

Job. Một job theo lịch ghi được canvas, và bản tin của nó kèm danh sách như trên. Job trả lời OK thì không gửi gì vào chat, kể cả danh sách.

13. API

Mọi đường dẫn nằm dưới /api.

Phương thức Đường dẫn Việc
GET /artifacts liệt kê; conversation_id, q (tên), limit (mặc định 50, tối đa 200)
POST /artifacts tạo canvas loại chữ: title, kind, content, conversation_id
GET /artifacts/usage dung lượng: count, bytes, cap, by_artifact
GET /artifacts/{id} một canvas với phiên bản mới nhất
PUT /artifacts/{id} lưu nội dung: content, base_version; bản cũ hơn máy chủ là xung đột
PATCH /artifacts/{id} đổi title
DELETE /artifacts/{id} xoá canvas cùng mọi phiên bản
GET /artifacts/{id}/versions danh sách phiên bản
GET /artifacts/{id}/versions/{version} một phiên bản
POST /artifacts/{id}/restore khôi phục: version
GET /artifacts/{id}/raw nội dung thô; version, download
GET /artifacts/{id}/render trang cách ly của canvas html hoặc mermaid; version
POST /artifacts/{id}/reimport đọc lại tệp nguồn: base_version; trả changed và artifact
GET /conversations/{id}/canvas canvas đang mở của hội thoại và đoạn đang chọn
PUT /conversations/{id}/canvas đặt chúng: artifact_id, selection

/render trả 404 cho loại không có trang để chạy. /reimport trả 422 khi canvas không có tệp nguồn hoặc tệp không hợp, 410 khi tệp hay agent không còn, 403 khi tệp nằm ngoài workspace, 413 khi tệp vượt trần, 409 khi base_version đã cũ. Tệp tải về từ /raw cũng mang đuôi .txt cho html và svg.

Event Ở đâu Mang gì
artifact luồng hoạt động artifact và conversation_ids, mỗi khi một canvas được tạo, lưu, đổi tên, khôi phục, xoá hay được agent ghi
user_context luồng trả lời của lượt context: ghi chú canvas của tin nhắn; chỉ tab đã gửi tin nhận
tool_call_delta luồng trả lời của lượt index, name, chunk, attempt; name rỗng nghĩa là bỏ các mảnh đã vẽ

Hai event sau không được lưu và không được phát lại cho tab khác, vì chúng trích nội dung canvas.

14. Với my-designer và my-presenter

Canvas nhận sản phẩm của hai bộ đó khi sản phẩm là tệp chữ mà canvas biết dựng: tệp SVG, một trang HTML tự chứa, một sơ đồ Mermaid. Agent nhập chúng bằng artifact_import, người xem và sửa tiếp trên web, rồi artifact_export ghi ngược ra workspace.

Trang HTML chỉ chạy đúng trong khung cách ly khi nó tự chứa: script, style, font từ các CDN ở mục 8, ảnh nhúng sẵn. Tệp .pptx và tệp video không nhập được: đuôi của chúng không ứng với loại canvas nào. Tệp pptx.json nhập được vì nó là JSON, nhưng chỉ thành canvas code để đọc và sửa chữ; canvas không dựng nó thành bản trình chiếu.

Giới hạn đã biết

Câu hỏi mở