> ## 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

```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
dag = client.canvas.get_dag(handle.canvas_id)

for node in dag.nodes:
    print(f"{node.type:24} {node.status:10} {node.name}")

for edge in dag.edges:
    print(f"{edge.source_id} -> {edge.target_id}")
```

Each `CanvasNode` 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:

```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
tree = client.canvas.get_tasks(handle.canvas_id)

def print_tree(tasks, indent=0):
    for t in tasks:
        print("  " * indent + f"- {t.name} ({t.task_type}, {t.status})")
        if t.children:
            print_tree(t.children, indent + 1)

print("Completed:")
print_tree(tree.completed)
print("In progress:")
print_tree(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:

```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
task = client.canvas.get_task(handle.canvas_id, "task-abc")
print(task.status, task.name)
```

## Async versions

Every method above has an async twin on `AsyncSpineClient`:

```python theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
dag = await async_client.canvas.get_dag(canvas_id)
tree = await async_client.canvas.get_tasks(canvas_id)
task = await async_client.canvas.get_task(canvas_id, task_id)
```
