> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getspine.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Canvas introspection

> Inspect the block graph and task tree produced by a run.

Every run writes its output into a **canvas** — a directed graph of
blocks (documents, spreadsheets, research notes, images, etc.) linked by
dependency edges. The SDK exposes three read-only introspection methods
so you can audit exactly what a run produced.

## The block graph

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const dag = await client.canvases.getDag(canvasId);

for (const node of dag.nodes) {
  console.log(`${node.type.padEnd(24)} ${node.status.padEnd(10)} ${node.name}`);
}

for (const edge of dag.edges) {
  console.log(`${edge.source_id} -> ${edge.target_id}`);
}
```

Each `Block` exposes:

| Field     | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `id`      | UUID of the block.                                            |
| `name`    | Human-readable block name.                                    |
| `type`    | Block type (e.g. `document-block`, `excel-block`).            |
| `status`  | Current state (`idle`, `running`, `completed`, `error`, ...). |
| `content` | Textual content, when applicable.                             |
| `url`     | External or pre-signed download URL, when applicable.         |
| `sources` | Source attributions (block-type specific).                    |

## The task tree

The task tree describes the agent execution that produced the canvas —
parent tasks, persona tasks, individual tool calls. It is split into
completed and in-progress subtrees:

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const tree = await client.canvases.getTasks(canvasId);

function printTree(tasks: Task[], indent = 0): void {
  for (const t of tasks) {
    console.log('  '.repeat(indent) + `- ${t.name} (${t.task_type}, ${t.status})`);
    if (t.children) printTree(t.children, indent + 1);
  }
}

console.log('Completed:');
printTree(tree.completed);
console.log('In progress:');
printTree(tree.not_completed);
```

## A single task

If you already have a task id (from a progress webhook or a previous
tree), fetch just that one with its immediate children:

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const task = await client.canvases.getTask(canvasId, taskId);
console.log(task.status, task.name);
```

## Timing

A canvas is created during `runs.create`, but its `canvas_id` may not be
populated on the very first poll — the server persists it a moment
after the run starts. Read it from the run object once status moves
past `running`, or after a short wait:

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const run = await client.runs.retrieve(runId);
if (run.status !== 'running' && run.canvas_id) {
  const canvas = await client.canvases.getDag(run.canvas_id);
}
```
