---
name: runchat-canvas-api
description: Interact with a Runchat workflow canvas via REST API. Read, create, connect, update, and run nodes programmatically. Use when given a Runchat editor URL (runchat.com/editor?id=...) or asked to build/modify a workflow on a Runchat canvas.
---

# Runchat Canvas API

You have access to a Runchat canvas — a visual node-based workflow editor.
Use the tools below to read, create, connect, and run nodes on the canvas.

## Base URL

All tool calls are made via a single endpoint:

```
POST https://runchat.com/api/v1/{runchat_id}/canvas
Authorization: Bearer {api_key}
Content-Type: application/json

{
  "tool": "<tool_name>",
  "args": { ... }
}
```

The response is always:
```json
{ "result": { ... } }
```

## Important Notes

- **Ask before running**: The `run_nodes` tool triggers execution which may consume credits. Always confirm with the user before calling it.
- **Node types**: promptNode (LLM), inputNode (user input), codeNode (JavaScript), imageNode (media generation), noteNode (documentation), runChatNode (sub-workflow).
- **Workflow**: Typically: `get_canvas` → `read_nodes` → create/update/connect → `organize_nodes` → (optionally) `run_nodes`.
- **Connections**: Use `connect_nodes` to wire outputs of one node to inputs of another. Use `read_nodes` to discover handle names.
- **Published tools**: Use `search_tools` to find published tools/runchats by keyword (returns each tool's runchat_id and input/output parameter names). Then `execute_tool` to run one directly and get its outputs, `inspect_tool` to read how it's built, or `create_node` (type "runChatNode", tool_id) to place it on this canvas. For `inspect_tool`/`execute_tool` the `runchat_id` in `args` names the TOOL to act on — the `{runchat_id}` in the URL is only the canvas/auth scope (it is ignored by these tools).

**Common handles:**
- promptNode — inputs: `messages` (any type), `prompt` (string) | outputs: `messages`
- codeNode — inputs: `code` (string) | outputs: `result`
- inputNode — outputs: `content`
- imageNode — inputs: from `get_model_params` | outputs: `image`

---

## Canvas Tools

### `get_canvas`

Get a high-level overview of all nodes and edges on the user's current canvas. Returns node IDs, types, labels, positions, and edge connections. For large canvases the response is paginated (50 nodes per page). When has_more is true, call again with the returned next_offset to fetch the next page. Do not call this to verify nodes you just created.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `offset` | number | no | Pagination offset. Omit for the first page. Use the next_offset value from a previous response to fetch the next page. |

### `read_nodes`

Read the full state of one or more nodes by ID. Returns each parameter's name, type, label, status, and current data values. Parameter data is truncated by default; when truncated the response includes the original data length so you can decide whether to re-read with a larger data_limit or with data_offset to page through. Use this to inspect what a node accepts, what data it has, and to find handle names for connect_nodes. Call get_canvas first to find node IDs.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_ids` | string[] | yes | Array of node IDs to read (from get_canvas) |
| `data_limit` | number | no | Maximum number of characters of each parameter's data to return. Defaults to 4000. Pass 0 to return the full data with no truncation. Increase only when you need more of a specific value. |
| `data_offset` | number | no | Character offset into each parameter's data before applying data_limit. Defaults to 0. Use this together with data_limit to page through long values. |

### `create_node`

Create one or more nodes on the canvas. For a single node, pass its fields directly (type required). To create several at once, pass a `nodes` array — preferred when building a workflow — with each node in pipeline order. Placement is automatic by default (the first node of a turn lands in the user's viewport and the rest chain left-to-right in creation order); pass a per-node `position` to place a node yourself, relative to the user's viewport. Returns each created node's ID and its input/output parameter names. Nodes are fully configured on creation — do not call update_node or get_canvas to verify. Only use update_node if the user explicitly asks you to change something.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `type` | `promptNode` | `inputNode` | `codeNode` | `imageNode` | `noteNode` | `runChatNode` | `artifactNode` | no | The type of node to create. promptNode = LLM/Agent, inputNode = user input widget, codeNode = JavaScript execution, imageNode = image/video/3D generation (requires model_id from the AVAILABLE MODELS catalog), noteNode = documentation/notes, runChatNode = custom user created tools, artifactNode = create/update or fetch artifacts (blog, website, slides) |
| `label` | string | no | Optional display label for the node |
| `model_id` | string | no | Required for imageNode: the api_id of the generation model (from the AVAILABLE MODELS catalog). The node will be configured with this model's parameters. Ignored for other node types. |
| `format` | `string` | `slider` | `toggle` | `image` | `file` | `select` | `button` | `code` | no | For inputNode only: the widget type to use. Defaults to 'string'. Use 'slider' for numbers, 'toggle' for booleans, 'image' for image upload, 'file' for file upload, 'select' for dropdowns, 'button' for triggers, 'code' for code input. |
| `output_format` | string | no | For promptNode only: controls the structured output format. Use "list" to get an array of strings (e.g. storyboard shots, steps, items). Use "object" with a JSON schema in initial_data.format for custom structured output. When set, the node's output is parsed and available on the "artifacts" output handle as structured data. Omit for plain text output. |
| `tool_id` | string | no | For runChatNode only: the runchat_id of a published tool (found via search_tools) to instantiate on the canvas as a runChatNode. Inputs are auto-configured from the tool definition. |
| `artifact_type` | `blog` | `website` | `slides` | no | For artifactNode only: the kind of artifact to create or fetch. Defaults to 'blog'. |
| `operation_mode` | `create` | `get` | no | For artifactNode only: 'create' to save/update artifact content, 'get' to fetch an existing artifact by ID. Defaults to 'create'. |
| `code_language` | `javascript` | `worker` | `html` | `rhino-python` | `blender-python` | `revit-csharp` | no | For codeNode only: The code language/mode for this node. Overrides the node's current mode. Use 'javascript' for sandbox-evaluated functions (default for most cases). Use 'worker' for full Cloudflare Workers (multi-file bundles + npm dependencies via package.json) — only when you actually need npm packages or multi-file structure. Use rhino-python, blender-python, or revit-csharp when connected to the respective CAD application. |
| `initial_data` | object | no | Initial values for the node's inputs. Each value is an array with one string element.

promptNode inputs:
  prompt (required): ["The task or question"]. 
  instruction: ["System prompt / persona"] (hidden, optional)
  Write real line breaks in text — actual newlines, never the literal characters \n.

codeNode inputs:
  code (required): ["javascript code"]
  Additional inputs can be named anything (use camelCase) and referenced using these same variable names in the code.

inputNode inputs:
  input: ["default value"]
  For format "select": the options object MUST be nested under the "input" key — initial_data { "input": { "data": ["opt1", "opt2", "opt3"], "selected": "opt2" } }. "data" is the list of options shown in the dropdown; "selected" is the chosen value (defaults to the first option if omitted). Do NOT place "data"/"selected" at the top level of initial_data (e.g. { "data": [...], "selected": "..." }) — that creates stray "data" and "selected" input widgets instead of a single dropdown. They must be the value of "input".

imageNode inputs:
  Use parameter names from get_model_params. Always call get_model_params before creating an imageNode. 

noteNode inputs:
  input (required): ["markdown content"]. Do not create empty notes.

runChatNode inputs:
  Use the tool's input parameter names (from inspect_tool).

artifactNode inputs:
  name: ["Artifact name"] (used in Create mode)
  content: ["content to save"] (markdown, HTML, or slides — artifact_type is auto-detected from the content format)
  artifact_id: ["id"] (only when retrieving or updating an existing artifact)
  folder: ["myFolder/subFolder"] (optional; sets the folder in Create mode, or moves the artifact in Update mode)

Example: { "prompt": ["Summarize the input text"], "instruction": ["You are a helpful editor"] } |
| `tools` | string[] | no | For promptNode only: array of runchat_ids (found via search_tools) to attach as tools the prompt can call. |
| `input_depths` | object | no | Optional depth settings for input parameters, keyed by parameter name. Depth controls how array data is processed:
  - 0 or omitted: "each" mode — iterate over each value in the array (default)
  - 1: "merge" mode — wrap all items in an array so they are processed as a group.
  - -1: "flatten" mode — nested arrays flattened one level before processing
Example: { "prompt": 0 , "image_url": 0} each prompt matches to a single image with the same index in the array.
Example: { "prompt": 0, "image_url": 1 } each prompt matches to all images as a group. |
| `position` | object | no | Optional explicit placement. x/y are offsets in canvas units from the TOP-LEFT of the user's current viewport — so {x:0,y:0} is the top-left of what they currently see — or from the canvas origin (0,0) when the viewport is unknown. Omit to auto-place (the first node lands in view, the rest chain to the right). Nodes are ~360 units wide; leave ~420 horizontal / ~260 vertical spacing to avoid overlap. When you set positions yourself you don't need to call organize_nodes. |
| `nodes` | object[] | no | Create MULTIPLE nodes in one call (preferred when building a workflow — pass them in pipeline order). Each item is a node spec taking the SAME fields as a single create_node call (type [required], label, model_id, format, output_format, tool_id, code_language, initial_data, tools, input_depths, position, …). When `nodes` is given, the top-level fields are ignored and an array of created nodes is returned. Give each item a `position` to lay them out, or omit positions to auto-chain. |

### `connect_nodes`

Connect output parameters of one node to input parameters of another — one edge, or many at once via the `edges` array. Use source_handle and target_handle to specify exactly which parameters to connect. Handles can be omitted for simple 1:1 connections where auto-matching by type is unambiguous.

Common handles and their accepted types:
- promptNode inputs: "prompt" (the model's task/instruction text), "messages" (context, prior outputs, images — accepts any type; don't funnel everything here when a more specific handle fits) | outputs: "messages"
- codeNode inputs: "code" (string) | outputs: "result"
- inputNode outputs: "content" (matches the input format)
- imageNode inputs: from get_model_params (e.g. prompt, image_url, first_frame_url) | outputs: "image"

You cannot connect to hidden parameters (instruction, format).

Do not connect an edge carrying a value you already embedded in the target node via a {{nodeId.param}} template — the value would arrive twice. Pick one channel per dependency.

A codeNode that produces CUSTOM output parameters (e.g. by returning an object that expands into multiple named output handles) only exposes those handles after it has been run — run the node first, then connect its custom outputs downstream. Until then only the built-in "result" output exists.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `source_node_id` | string | no | The ID of the source node (data flows from here) |
| `target_node_id` | string | no | The ID of the target node (data flows to here) |
| `source_handle` | string | no | The output parameter name on the source node (e.g. 'content', 'image', 'messages'). Specify this when the source has multiple outputs or when auto-matching would be ambiguous. |
| `target_handle` | string | no | The input parameter name on the target node (e.g. 'prompt', 'image_url', 'first_frame_url'). Specify this when the target has multiple inputs or when auto-matching would be ambiguous. |
| `edges` | object[] | no | Connect MULTIPLE edges in one call (preferred when wiring up a workflow). Each item is one source→target connection with the same fields as a single connect_nodes call (source_node_id [required], target_node_id [required], source_handle, target_handle). When `edges` is given, the top-level fields are ignored and a per-edge result array is returned — an edge that fails is reported individually without aborting the others. |

### `update_node`

Update an existing node's label, model, or input values. Do NOT use this to edit code in codeNodes — use edit_file (after read_files) instead.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_id` | string | yes | The ID of the node to update (from get_canvas or create_node) |
| `label` | string | no | New display label for the node |
| `model_id` | string | no | Change the model on this node (api_id from the AVAILABLE MODELS catalog). Works for promptNode, codeNode, and imageNode. |
| `inputs` | object | no | Input values to set, keyed by parameter name. Values are arrays with one string element. Use read_nodes to find valid parameter names. Example: { "prompt": ["Summarize the input"] }. For select-format inputNodes, pass an object: { "input": { "data": ["opt1", "opt2"], "selected": "opt1" } } — `data` updates the options list, `selected` updates the chosen value. Both fields are optional, so pass only what you want to change (e.g. { "input": { "selected": "opt2" } } to change selection without touching options). |
| `input_depths` | object | no | Optional depth settings for input parameters, keyed by parameter name. Depth controls array processing: 0 = "each" (default, one run per item), 1 = "merge" (wrap all into one array), -1 = "flatten" (unwrap one level). Example: { "prompt": 1 } |
| `publish_params` | string[] | no | imageNode only: model parameter names to expose as connectable input edges (e.g. ["num_images", "seed"]) so an upstream node can drive them parametrically. By default a model param the agent sets only lives in the node config/settings bar; publish it here when it must be wired in the workflow. Each published param is seeded from its current config value — combine with `inputs` in the same call to set that value first. |

### `organize_nodes`

Auto-layout nodes on the canvas using a topological organize algorithm. Arranges nodes neatly based on their connections while avoiding overlap with other nodes. Call this after completing all create_node and connect_nodes operations, not in between. Pass the IDs of the nodes you created. Nodes the user has positioned manually are never moved — they stay in place and the layout flows around them (the result reports how many were skipped).

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_ids` | string[] | yes | Array of node IDs to organize. Pass the IDs of nodes you created or want to re-layout. |

### `run_nodes`

Execute one or more nodes on the canvas. Nodes run in dependency order — upstream nodes execute first. Returns status (success/error) and output parameter names for each node. Use after setting up and connecting a workflow.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_ids` | string[] | yes | Array of node IDs to execute. Nodes run in dependency order. |

### `delete_nodes`

Delete one or more nodes from the canvas. Also removes any edges connected to the deleted nodes. Use this to clean up nodes that are no longer needed.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_ids` | string[] | yes | Array of node IDs to delete. |

### `delete_edges`

Delete one or more edges (connections) from the canvas. Use this to disconnect nodes without deleting them.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `edge_ids` | string[] | yes | Array of edge IDs to delete (from get_canvas or connect_nodes). |

---

## Tool Discovery

### `search_tools`

Search the library of published Runchat tools (and your own saved runchats) by keyword. Returns matching tools with their runchat_id, name, description, and their input/output parameter names — enough to run a tool straight away with execute_tool. You can also pass a runchat_id to create_node (type 'runChatNode', tool_id) to place it on the canvas, or to inspect_tool to read how it's built. Call this whenever you need a capability you don't already have built in — web/image search, scrapers, data tools, specialised generators — instead of assuming it doesn't exist.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | no | Keywords to match against tool names and descriptions (e.g. 'web search', 'remove background', 'pdf to text'). Omit to list popular tools. |
| `limit` | number | no | Max results to return. Defaults to 8, max 25. |

### `inspect_tool`

Inspect a published tool / runchat to see how it is built. OPTIONAL — call this if you want to view nodes in the tool workflow in order to adapt them for the users request. You do NOT need to inspect a tool just to run it with execute_tool. Returns the published inputs/outputs plus a digest of the internal nodes (models, prompts, code) and how they connect. Get the runchat_id from search_tools.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `runchat_id` | string | yes | The runchat_id of the tool to inspect (from search_tools). |

### `execute_tool`

Run a published tool / runchat directly and get its outputs back, without placing it on the canvas. Use this to call a capability you found with search_tools (e.g. run a web search, generate or process an image, fetch data) as part of your own reasoning — call it straight after search_tools, no need to inspect_tool first. Provide inputs keyed by the tool's input parameter names (search_tools returns these for each tool); the result reports any inputs that didn't match. Spends credits and requires 'run' permission. Prefer this over create_node when you only need the result, not a node the user keeps on the canvas.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `runchat_id` | string | yes | The runchat_id of the tool to run (from search_tools). |
| `inputs` | object | no | Input values keyed by the tool's input parameter names (from inspect_tool). Each value can be a string or an array of strings. Example: { "query": "eames lounge chair" }. |
| `version_num` | number | no | Optional specific published version to run. Defaults to the latest released version. |

---

## Code Editing Tools

### `edit_file`

Edit one file in a code node. Two modes: (1) targeted edit — pass `old_text` and `new_text`; old_text must match exactly (including whitespace) and must be unique in the file; new_text replaces it. Empty new_text deletes the matched span. (2) Full overwrite — pass only `new_text` (omit old_text); replaces the entire file. ALWAYS read_files first to see current content. When you call this tool, do NOT also output the full file content in your message — the tool applies the change directly.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_id` | string | yes | The ID of the code node. |
| `file` | string | yes | The file path to edit (e.g. 'index.ts', 'index.js', 'package.json'). Use read_files first to discover available paths. |
| `old_text` | string | no | Optional. When present: the exact substring to find and replace. Must be unique in the file — include surrounding context to disambiguate. When omitted: the entire file is overwritten with new_text. |
| `new_text` | string | yes | Required. The replacement text (when old_text is set) or the full new file contents (when old_text is omitted). |

### `create_files`

Create one or more new files in a worker-mode code node's bundle (e.g. package.json, lib/utils.ts). Only valid when the node's codeOutputMode is 'worker' — snippet-mode nodes have a single fixed entry file. Errors if any file already exists; use edit_file to modify existing files. The entry file is created automatically with the node — do not try to create it here.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_id` | string | yes | The ID of the worker-mode code node. |
| `files` | object[] | yes | Files to create. Paths must not collide with the entry file (index.ts) or any existing file. |

### `delete_files`

Delete one or more non-entry files from a worker-mode code node's bundle. Cannot delete the entry file. To remove the entire bundle, change the node's codeOutputMode instead.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_id` | string | yes | The ID of the worker-mode code node. |
| `files` | string[] | yes | Paths of files to delete. |

---

## Code Context Tools

### `read_files`

Read files from a code node. Returns each file's path, line-numbered content, and length. Pass `files` to read specific paths; omit it to list and read everything (always do this first when you don't know what files exist). Snippet-mode code nodes contain a single entry file (e.g. index.js, index.html, index.py). Worker-mode nodes contain index.ts plus any additional files in the bundle.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_id` | string | yes | The ID of the code node to read. |
| `files` | string[] | no | Optional. Specific file paths to read. Omit to read all files in the node. |

### `read_status`

Read the current error messages, status messages, iframe preview errors, and worker errors for a code node. Call this when debugging issues or when the user reports a problem.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `node_id` | string | yes | The ID of the code node to check. |

---

## Media Tools

### `get_model_params`

Get full parameter details for one or more models. Returns parameter names, types, and defaults — use these as the initial_data keys when creating an imageNode. Pick model_ids from the AVAILABLE MODELS catalog in the system prompt. Pass model_id for one model or model_ids for multiple. Only call once per model.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `model_id` | string | no | A single api_id of the model (from the AVAILABLE MODELS catalog) |
| `model_ids` | string[] | no | An array of api_ids to fetch details for multiple models at once |

---

## Vision Tools

### `view_image`

Fetch an image from a URL so you can see and analyze it. Use this for images produced by tool results that you haven't seen yet. Do NOT use this for raster images already visible in the conversation (e.g. PNG/JPEG the user sent or attached). EXCEPTION: SVG images can't be viewed directly — if an attached or referenced image is an SVG, use this tool to render it to PNG (to see it) or read its source (to edit the markup).

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `url` | string | yes | The URL of the image to view. Supports PNG, JPEG, GIF, WebP, and SVG formats. |
| `format` | `render` | `source` | no | For SVG URLs only: 'render' (default) rasterises the SVG to a PNG so you can see it; 'source' returns the raw SVG XML markup so you can read or edit it. Ignored for raster images. |
