Skip to main content

Chat Canvases

Canvases are special UI controls that Code Nodes can return with the _canvas helper. The helper pins a rich experience into BotDojo Chat, stores it server-side, and keeps it accessible through the canvas tray for the rest of the session. This page focuses on how Code Nodes (and tools built on top of them) emit _canvas responses so you can wire up dashboards, notebooks, or custom apps directly from your code.

Nodes that emit _canvas

  • Code Node – Return _canvas from your execute function to create or update any canvas type.
  • Build UI (Code Interpreter Canvas) – Spins up a sandboxed Python UI and always responds with _canvas metadata that reconnects to the notebook.
  • Desktop Canvas – Runs a remote desktop sandbox and returns _canvas when provisioning or refreshing the desktop session.
  • BrowserBase – Creates a BrowserBase automation session and returns _canvas the first time it provisions the browser experience.
  • Background Flow as Tool (with “Create Canvas” enabled) – Launches a background job and shares a monitoring canvas back to the chat.

All of these nodes ultimately surface their canvases by emitting an object with the _canvas key, so the mechanics for consuming them in chat are identical.

Return _canvas from a Code Node

Use the context.canvas helper inside a Code Node (or any sandboxed runtime) to manage canvases:

export async function execute(input, node, context) {
const state = await context.sessionState.get('canvas-demo');
let canvasId = await state.getVariable('canvasId');

if (!canvasId) {
const created = await context.canvas.createCanvas({
canvasId: `customer-dashboard-${context.sessionId}`,
canvasType: 'iframe',
canvasData: {
url: `https://dash.example.com/embed/${context.sessionId}`,
title: 'Customer health',
agent_enabled: false,
},
});
canvasId = created.canvasId;
await state.setVariable('canvasId', canvasId);
} else {
await context.canvas.updateCanvas({
canvasId,
canvasType: 'iframe',
canvasData: {
url: `https://dash.example.com/embed/${context.sessionId}`,
title: 'Customer health',
lastRefreshedAt: new Date().toISOString(),
},
});
}

return {
status: 'ready',
_canvas: {
canvasId,
canvasType: 'iframe',
canvasData: {
url: `https://dash.example.com/embed/${context.sessionId}`,
title: 'Customer health',
},
},
};
}

Key points:

  • Store the canvasId in session state so future invocations update the same canvas instead of creating duplicates.
  • context.canvas.loadCanvas(canvasId) returns the persisted definition if you need to inspect the current payload before deciding how to update it.
  • Returning the _canvas helper makes the chat aware of the latest state; you can keep the _canvas payload minimal (only the fields the UI needs to render).
  • Set canvasData.show_inline to show the full canvas directly in the transcript; leave it unset to rely on the preview card plus the side tray entry.

Canvas types

TypeTypical useRequired data
iframeEmbed an external web app or dashboard.canvasData.url (plus optional agent_enabled, title, show_inline).
code-interpreterLaunch or reconnect to a managed Python sandbox.canvasData.codeInterpreterParams from the Code Interpreter Canvas tool; BotDojo fills in the sandbox URL.
markdownPersist long-form formatted content outside the main transcript.canvasData.markdown and optional title.
filePreview an uploaded asset (PDF, image, etc.).canvasData should include file metadata and a signed URL created via context.store.Documents.
dojo-canvasHost a custom experience built with botdojo-canvas-client.canvasData.url (to your hosted app) and optional flags like agent_enabled or show_chat_default.

All types are stored server-side so they can be replayed later or surfaced in external integrations, and they are all selectable from a Code Node response.

Create custom canvases

Custom canvases let you ship a full agent-enabled app inside chat. Use the 'dojo-canvas' type to host a web experience that talks to the active flow through the BotDojo WebSocket. The interactive website agent example walks through wiring a Code Node that returns _canvas alongside a canvas front end built with botdojo-canvas-client. For a deeper dive into the overall pattern, see the Agentic UI solution.

  • The canvas client reuses the agent_socket_url query parameter to connect back to the agent.
  • Your app can invoke tools, stream status messages, or react to state changes from the flow.
  • Returning _canvas from your Code Node with canvasType: 'dojo-canvas' updates the embedded app without forcing users to leave the conversation.