Canvas Agent Skill
Use this skill when a user asks an Agent to create, update, inspect, review, annotate, or recover a Canvas document through the Xpert Canvas plugin.
The plugin has two surfaces:
- Workbench: the human review and editing surface. It can list canvases, edit the tldraw board, create AI image holders, add annotations, save versions, import/export snapshots, restore versions, mark reviewed/draft, archive, and delete canvases.
- Middleware tools: the Agent-callable system of record. These tools create Canvas metadata, apply bounded tldraw record stages, insert images, progressively query records, update lifecycle status, publish or revoke governed Artifact links, and report failures. Complete snapshot and version creation are not model-visible.
- View image: the Canvas Assistant template should include
@xpert-ai/plugin-view-image. Useview_imageto inspect the latest viewport snapshot image before reasoning about visible layout, annotations, or image feedback. - Seedream AIGC: the Canvas Assistant template should include
@xpert-ai/plugin-volcengineand theseedream_aigcbuiltin toolset withseedream_text_to_imageenabled for text-to-image generation before image insertion.
Do not treat Workbench view actions as Agent middleware tools. Use only the middleware tool names documented below when acting from an Agent.
Core Rules
Before creating a new Canvas, call canvas_list_typography_presets and map the chosen preset to the managed tldraw draw, sans, serif, or mono font slot. Do not invent font URLs.
- Do not invent document ids, version ids, page ids, shape ids, asset ids, or binding ids for existing canvases. Use Workbench context,
canvas_search_documents,canvas_get_document,canvas_list_records, orcanvas_get_record. - Before editing an existing canvas, call
canvas_get_documentunless the prompt already supplies a trustworthy current revision. This is a compact summary; it does not return the scene. - Apply edits through
canvas_patch_records. For workflows, flowcharts, process maps, and stage-based architecture diagrams, prefer the semanticworkflowfield so Canvas computes the board, spacing, embedded labels, and connectors; it is one self-contained operation. Useworkflow.mode=replace_pageonly when the user explicitly requests replacement/recreation or the page is known to contain corrupt stale content, and always pass the latest revision. For free-form work, use visible stages of at most 12 shape or record operations, preferably 6–8. Create new content with the explicit create arrays; never construct a raw tldraw record or send a complete snapshot. Agent edits update only the working copy and never create a version. - Use
canvas_insert_imageonly after image generation or when the user provides image data. PassdataUrl,base64, orworkspaceFilePath; the tool stores image data inside tldraw asset records for v1. If a generation tool labels the path asworkspacePathorfilePath, copy that value intoworkspaceFilePath. - If
env.canvasDocumentIdis present, pass it asdocumentId; do not callcanvas_create_documentfor image insertion or updates to the current Workbench canvas. - If
env.canvasInsertionTargetJsonis present, parse it and pass it astargettocanvas_insert_image. For AI image holder frames, this compact target includes the holdershapeId,pageId,width, andheight. - Version creation is human-only. If the user requests a checkpoint, finish the working-copy edits and tell them to click New version in the Workbench version panel; do not attempt a version tool call.
- Do not delete or move annotations unless the user explicitly asks. Annotation arrows and notes are review evidence.
- Do not claim a canvas was saved unless the tool call succeeded. Tool results are the source of truth.
- Do not route logic from display text or localized labels. Use explicit fields such as
selection.type,selectedShapeIds,kind,status, andsourceType. - When the user asks what is currently visible, asks you to follow markups, asks for layout critique, or asks for image edits based on annotations, call
view_imagefirst withenv.canvasSnapshotImagePathfrom trusted Workbench context. - Call
canvas_publish_artifact_linkonly after the user asks to share and, forpublic_link, explicitly confirms public access. Readcanvas_get_documentimmediately before publishing and pass its currentworkingCopyRevisionandsnapshotChecksum. The tool waits for the asynchronous Canvas export and returns the usable link. Usecanvas_revoke_artifact_linkonly when the user asks to revoke the active share.
Progressive Read And Staged Write Flow
- Call
canvas_get_documentfor status, record counts, checksum, andworkingCopyRevision. - Call
canvas_list_recordswith that exact revision and narrow filters. FollownextCursoronly whilehasMoreis true. - Call
canvas_get_recordonly for records that need exact inspection before an update or removal. - Use one stable
batchIdfor the user request. Eachcanvas_patch_recordsstage uses a newoperationId, increasingstageIndex, a shortstageLabel, andisFinalStage=trueonly on the final stage. - Chain the
workingCopyRevisionfrom each receipt into the next stage'sbaseRevision. - For a semantic workflow stage, send only
workflow; it counts as one operation. For free-form mutations, count all five explicit create arrays plus update/removal arrays and split totals above 12. For a 16-shape plan, submit 8 semantically related shapes, wait for the receipt, then submit the remaining 8 with the samebatchId, the nextstageIndex, a newoperationId, and the returnedworkingCopyRevisionasbaseRevision. - Use
createTextShapes,createGeoShapes,createNoteShapes,createFrameShapes, andcreateArrowShapesfor their matching shape kinds. Supply plain text and semantic geometry/style fields; Canvas generates omitted ids, the default/only page, valid indices, complete tldraw defaults, and richText. Put a card label increateGeoShapes[].text; never create a separate text shape for a card label. Use geo rectangles for filled backgrounds and cards; frames are outlines; arrows are connectors only. Never passcreateRecords. - Omit a new shape
idunless another entry in the same stage must refer to it asparentId. OmitparentIdonly for an empty or single-page Canvas; discover and pass the page id when multiple pages exist. - Use
updateRecordsorremoveRecordswith the checksum returned by a list/get read for existing ids. Reuse anoperationIdonly to retry the exact same payload. If content changes or a checksum conflicts, reread the affected record and use a new operation id.
Workbench Selection Context
The Workbench can send assistant.context.set when the user selects shapes. That request state is not automatically visible to the model unless the assistant prompt renders it through prompt variables.
When the prompt includes these variables, use them before searching broadly:
env.canvasDocumentIdenv.canvasVersionIdenv.canvasPageIdenv.canvasSelectionJsonenv.canvasSelectedShapeJsonenv.canvasInsertionTargetJsonenv.canvasContextJsonenv.canvasSceneDirtyenv.canvasSnapshotImagePathenv.canvasSnapshotImageUpdatedAtenv.canvasSceneSource
If env.canvasContextJson is non-empty, parse it as JSON. The expected shape is:
{
"currentCanvas": {
"documentId": "document-id",
"title": "Canvas title",
"currentVersionId": "version-id",
"currentVersionNumber": 12,
"isDirty": true,
"sceneSource": "autosave",
"snapshotImagePath": "files/canvas/documents/document-id/snapshots/current.png",
"snapshotImageUpdatedAt": "2026-06-25T15:22:28.459Z",
"insertionTarget": {
"type": "canvas.insertionTarget.v2",
"documentId": "document-id",
"pageId": "page:page",
"shapeId": "shape:id",
"width": 512,
"height": 683
},
"selection": {
"type": "canvas.selection.v1",
"pageId": "page:page",
"selectedShapeIds": ["shape:id"],
"selectedShapeCount": 1,
"shapes": [
{
"id": "shape:id",
"type": "frame",
"x": 10,
"y": 20,
"w": 512,
"h": 683,
"pageId": "page:page",
"isAiImageHolder": true
}
],
"capturedAt": "2026-06-25T15:22:28.459Z"
}
}
}
Selection rules:
- Treat
currentCanvas.selection.type === "canvas.selection.v1"as the only valid machine-readable selection discriminator. - If a valid selection exists, modify only
selectedShapeIdsunless the user explicitly asks to affect neighboring or unselected shapes. - Use compact
selection.shapesonly for orientation, bounds, and intent. Fetch the exact allowlisted record and checksum withcanvas_get_recordbefore changing geometry, style, bindings, text, asset refs, or page membership. - If
env.canvasInsertionTargetJsonorcurrentCanvas.insertionTargetexists, use it directly as thecanvas_insert_imagepositioning payload after image generation. - If
currentCanvas.isDirty === trueorenv.canvasSceneDirty === "true", Workbench may still be synchronizing. Read a freshcanvas_get_documentsummary before patching. - If
currentCanvas.snapshotImagePathorenv.canvasSnapshotImagePathis present, it points to the latest fixed viewport snapshot image, usuallyfiles/canvas/documents/{documentId}/snapshots/current.png.
Visual Snapshot Reading
Use view_image when visual understanding matters:
- Current board description, visual QA, layout critique, or “what did I draw?”
- Annotation-driven image iteration, such as arrows/text pointing to regions to change
- Comparing what is visible in the viewport with a requested change
- Any task where tldraw JSON alone would be a guess about rendered appearance
Call shape:
{
"path": "files/canvas/documents/document-id/snapshots/current.png"
}
After view_image returns, combine the visual evidence with canvas_get_document, filtered canvas_list_records, and canvas_get_record only when exact record edits are needed.
Seedream Text-To-Image Flow
Use seedream_text_to_image when the user asks to create, fill, replace, or place an AI-generated image on the Canvas.
- Read
env.canvasInsertionTargetJsonfirst. If it is non-empty and not null, use it as the exact Canvas insertion target. - Otherwise read
env.canvasContextJson. If exactly one selected shape hasisAiImageHolder,meta.canvasAiImageHolder, ormeta.cowartAiImageHolder, treat it as the target holder. - For a holder target, use its
widthandheightas the target display size, and include the target size and aspect ratio in the Seedream prompt so the generated image is composed for that slot. - Choose the Seedream
sizeby aspect ratio:1:1->2048x20483:2->2496x16642:3->1664x24964:3->2304x17283:4->1728x230416:9->2560x14409:16->1440x2560- fallback ->
2048x2048
- Call
seedream_text_to_imagewith the final visual prompt and chosensize. Do not callcanvas_insert_imageuntil Seedream returns a generated file. - From the Seedream result, pass
workspaceFilePath, plusmimeTypewhen useful, intocanvas_insert_image. - Always pass
documentIdfromenv.canvasDocumentIdor the insertion target when present. For holder targets, pass the parsed insertion target astarget; the inserted image becomes a child of the holder and moves with it. - If no holder is selected, do not ask the user to create one. Insert the generated image into the current page using
pageIdwhen available, a requested display size when provided, or the generated bitmap aspect ratio. - Do not create a version after
canvas_insert_imagesucceeds. The insertion tool updates only the current working copy; version creation remains a human Workbench action.
Tool Contracts
canvas_create_document
Create a managed Canvas metadata record only. Required input: title. Optional inputs: description, kind, tags, source, changeSummary. It never accepts a snapshot. Add content in later explicit create-field stages; the first stage creates a default page when the Canvas is empty. Do not use this when env.canvasDocumentId identifies the current Workbench canvas.
canvas_patch_records
Apply one bounded, idempotent stage without creating a version. Required inputs: documentId, operationId, batchId, stageIndex, stageLabel, isFinalStage, baseRevision, changeSummary, plus workflow or at least one explicit create, update, or remove operation. Use workflow by itself for deterministic process layouts. A free-form stage may contain at most 12 operations across all arrays; prefer semantic stages of 6–8 operations. Canvas generates complete tldraw records and converts plain text to richText. Existing-record updates/removals require their current checksum.
Semantic workflow example:
{
"workflow": {
"mode": "replace_page",
"title": "XpertAI 多智能体协作工作流",
"subtitle": "从业务需求到真实交付",
"theme": "xpert-dark",
"stages": [
{ "key": "brief", "label": "业务需求", "detail": "明确目标与边界" },
{ "key": "plan", "label": "Agent 规划", "detail": "拆解任务与资源" },
{ "key": "execute", "label": "并行执行", "detail": "多智能体协同", "emphasis": true },
{ "key": "review", "label": "人工审阅", "detail": "关键节点把关" },
{ "key": "deliver", "label": "真实交付", "detail": "沉淀可用成果" }
],
"branches": [
{ "key": "research", "label": "Research Agent", "parentStageKey": "execute" },
{ "key": "creation", "label": "Creation Agent", "parentStageKey": "execute" },
{ "key": "quality", "label": "Review Agent", "parentStageKey": "execute" }
]
}
}
Minimal creation example:
{
"createTextShapes": [
{ "x": 100, "y": 100, "text": "Hello" }
],
"createGeoShapes": [
{ "x": 100, "y": 180, "width": 240, "height": 120, "text": "Task", "fill": "semi" }
],
"createArrowShapes": [
{ "start": { "x": 340, "y": 240 }, "end": { "x": 460, "y": 240 }, "text": "Next" }
]
}
canvas_insert_image
Insert a bitmap into the current canvas working copy without creating a version. Required image input: dataUrl, base64, or workspaceFilePath. Pass documentId for the current canvas. Optional target accepts the compact Workbench insertion target with documentId, pageId, shapeId, width, and height; Canvas infers holder filling, replacement, page placement, and asset metadata.
canvas_search_documents
Find existing canvases by status, kind, search, page, and pageSize.
canvas_get_document
Read compact Canvas identity, status, revision, checksum, and record counts. It never returns scene records or a snapshot.
canvas_list_records
List up to 40 record summaries at an exact expectedRevision. Filter by typeNames, shapeTypes, pageId, parentId, or query; follow the opaque cursor only while hasMore is true.
canvas_get_record
Fetch one exact allowlisted working-copy record at an exact expectedRevision. Use its checksum before updating or removing that record.
canvas_update_document_status
Update status to draft, reviewed, or archived. Mark reviewed only after user or workflow confirmation.
canvas_report_failure
Record a failed generation, validation, import, inspection, image insertion, or patch attempt.
canvas_publish_artifact_link
Publish or reuse a governed, read-only Canvas Artifact link without creating a Canvas version. Required inputs: documentId and the latest baseRevision from canvas_get_document. Pass baseSnapshotChecksum when available and pageId to select a page; otherwise the first page is published. Optional accessMode values are public_link, organization_all, and workspace_all; optional targetMode values are version and latest. Public access requires userConfirmedPublicLink: true only after explicit user confirmation. The tool waits for the sandbox export and returns the usable shareUrl.
canvas_revoke_artifact_link
Revoke the active governed Artifact link for documentId. Call it only after the user explicitly requests revocation.