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

# Component: image

> Show an image from your Knowledge Base or an allowlisted website on the canvas during a conversation.

The **`image`** component shows an image on the canvas, with an optional caption. It is display-only.

|                   |                                        |
| ----------------- | -------------------------------------- |
| Component id      | `canvas.image`                         |
| Version           | `v1`                                   |
| Action name       | `canvas_show_image`                    |
| Interaction class | Lifecycle-only (no `submit` or `skip`) |
| Default placement | `safe-area-right`                      |

Images come from two sources, both under your control:

* **Your [Knowledge Base](/sections/conversational-video-interface/knowledge-base)**: you curate the exact set of images the PAL may show, and it picks one by id.
* **Websites you allowlist**: the PAL passes an image URL it received during the conversation (typically from a [tool](/sections/conversational-video-interface/pal/tools) result), and Tavus renders it only if the URL clears a safety floor and its host matches your allowlist.

By default only the Knowledge Base source exists. The compiled action has no URL argument at all, so the PAL cannot show an image from the open web or from your site; the URL argument appears only once you enable [`web`](#web-images) with at least one allowlisted domain.

## Configuration

Attaching the skill alone does not activate `image`. It stays inactive (no action is compiled, no error) until at least one image is curated in the skill config or `web` is enabled with at least one domain.

### Curated Knowledge Base images

<Steps>
  <Step title="Add the images to your Knowledge Base">
    Upload each image with [Create Document](/api-reference/documents/create-document) and wait for it to finish processing. Curating a document that is still processing is rejected, so poll [Get Document](/api-reference/documents/get-document) (or use the callback) first.
  </Step>

  <Step title="Curate them on the PAL">
    Save the document ids you want the PAL to be able to show, each with an optional caption and an optional "when to show this" hint.
  </Step>
</Steps>

```bash theme={null}
curl -X PUT https://tavusapi.com/v2/pals/{pal_id}/skills/magic_canvas \
  -H "Content-Type: application/json" \
  -H "x-api-key: <your-api-key>" \
  -d '{
    "config": {
      "components": {
        "image": {
          "images": [
            {
              "document_id": "d1234567890",
              "caption": "Aurora Desk in walnut",
              "prompt": "Show when the user asks what the desk looks like or asks about finishes."
            },
            {
              "document_id": "d2468101214",
              "caption": "Cable tray, underside detail",
              "prompt": "Show when the user asks about cable management."
            }
          ]
        }
      }
    }
  }'
```

| Field                  | Type    | Required | Description                                                                                                                                          |
| ---------------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `images`               | array   | ✅        | The curated images, at most 50. The component activates as soon as one usable entry is saved. Order is preserved and is the order the PAL sees.      |
| `images[].document_id` | string  | ✅        | A Knowledge Base document id, returned by [Create Document](/api-reference/documents/create-document). Validated when you save the config.           |
| `images[].caption`     | string  | ❌        | The caption shown under the image, max 280 characters. Defaults to the description Tavus generates while processing the image, or the document name. |
| `images[].prompt`      | string  | ❌        | Your "when to show this image" hint, max 500 characters. Given to the PAL alongside the caption to help it choose; never shown to the user.          |
| `enabled`              | boolean | ❌        | Defaults to `true`. Set `false` to switch the component off without deleting your curated list.                                                      |
| `web`                  | object  | ❌        | The second source: image URLs from websites you allowlist. See [Web images](#web-images).                                                            |

#### Which documents can be curated

When you save the config, every `document_id` must:

* Be accessible to the account that owns the PAL. Otherwise: `400`, `One or more document_ids are not accessible`.
* Have finished processing. Documents still being ingested are rejected with `400`, `One or more document_ids are not ready for display`; curate them once processing completes.

At conversation create, Tavus additionally resolves each curated document to a displayable image. A document is skipped if it is not an image (a PDF, a website crawl, a spreadsheet) or if its processed image is unavailable. Skipped entries are simply absent from what the PAL can show; the rest of the curated list still works.

### Web images

The `web` object lets the PAL show images it finds mid-conversation, typically URLs returned by a [tool](/sections/conversational-video-interface/pal/tools) you built: a product search, a listing lookup. You allowlist the websites those URLs may come from; a URL from anywhere else is dropped before the card renders.

```bash theme={null}
curl -X PUT https://tavusapi.com/v2/pals/{pal_id}/skills/magic_canvas \
  -H "Content-Type: application/json" \
  -H "x-api-key: <your-api-key>" \
  -d '{
    "config": {
      "components": {
        "image": {
          "web": {
            "enabled": true,
            "domains": ["photos.example.com", "*.cdn.example.com"],
            "guidance": "Show the listing photo whenever search_listings returns one."
          }
        }
      }
    }
  }'
```

| Field          | Type    | Required | Description                                                                                                                                                                    |
| -------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `web.enabled`  | boolean | ❌        | Defaults to `false`, unlike the component-level `enabled`. Setting `true` requires at least one entry in `domains`. Setting `false` keeps your saved list without deleting it. |
| `web.domains`  | array   | ❌        | The websites image URLs may come from, at most 20 entries.                                                                                                                     |
| `web.guidance` | string  | ❌        | Your "when to show a web image" note, max 500 characters. Given to the PAL alongside the allowlist; never shown to the user.                                                   |

Domain entries are validated when you save the config:

* Each entry is an exact host (`photos.example.com`) or a leading wildcard (`*.cdn.example.com`). An exact host matches only itself. A wildcard matches any depth of subdomain and never the bare domain: `*.example.com` matches `a.example.com` and `a.b.example.com` but not `example.com`; list the apex separately if you want it too.
* Hostname only, max 253 characters: no scheme, port, path, or userinfo. International domains go in as punycode (`xn--...`).
* Entries are normalized on save (lowercased, trailing root dot stripped, duplicates removed), so the list you read back is the canonical form.
* IP addresses (in any spelling), `localhost`, and internal-network names (`.local`, `.internal`, `.corp`, ...) are rejected: the allowlist can only name public websites.
* Wildcards over shared platforms and public suffixes (`*.github.io`, `*.co.uk`, ...) are rejected, because they would allowlist every site anyone can register there. Wildcard your own subtree (`*.photos.example.com`) or list exact hosts instead.

<Note>
  The allowlist is for URLs the PAL **receives during the conversation**. It is
  instructed to pass only image URLs that appeared in a tool result, copied
  exactly, and never to construct or recall one from memory: an invented URL
  won't load even on an allowed website. Pair `web` with a tool that returns
  image URLs.
</Note>

<Note>
  If none of the curated documents resolve and `web` is not enabled, the
  `canvas_show_image` action is not compiled for that conversation at all. The
  PAL is never offered an image it cannot show.
</Note>

## When the PAL shows images

You can curate up to 50 Knowledge Base images on the PAL. Each `canvas_show_image` call can display 1 to 8 of them at once (and, with a live `web` allowlist, web image URLs as well). The PAL identifies each entry by curated id or by URL.

<Note>
  Multiple images on one card show as a carousel: one image at a time, with
  prev/next to step through them.
</Note>

### Arguments

| Field              | Type   | Required | Description                                                                                                                                                         |
| ------------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `images`           | array  | ✅        | Images the PAL has chosen to show on this card, 1 to 8. More than 8 and the extras are dropped. One call may mix curated ids and web URLs.                          |
| `images[].id`      | string | ✅\*      | The `document_id` of a curated image. Ids outside the curated set are dropped.                                                                                      |
| `images[].url`     | string | ✅\*      | A web image URL, max 2048 characters. Only exists on PALs with a live `web` allowlist, and only renders if it passes [URL validation](#how-a-url-becomes-an-image). |
| `images[].caption` | string | ❌        | Caption for this image, max 280 characters. For a curated image it overrides your curated caption.                                                                  |
| `images[].alt`     | string | ❌        | Web URLs only, max 240 characters. Alt text for the image, which Tavus has never seen. Defaults to the caption.                                                     |
| `title`            | string | ❌        | Heading above the card, max 120 characters.                                                                                                                         |

\* Each entry carries exactly one of `id` or `url`; an entry with both is dropped. No other arguments are accepted.

### Example invocation

```json theme={null}
{
  "title": "Homes near the park",
  "images": [
    {
      "url": "https://photos.example.com/listings/1024.jpg",
      "alt": "Blue Victorian with a bay window",
      "caption": "312 Fell St"
    },
    { "id": "d1234567890" }
  ]
}
```

### How an id becomes an image

At conversation create, Tavus resolves each curated document to a signed URL that is valid for the length of the conversation. When the PAL calls `canvas_show_image`, Tavus substitutes the id for that URL before the card reaches the browser, so the card your client renders (or your own renderer, if you [bring one](/sections/conversational-video-interface/magic-canvas/integrations/cvi-ui-sdk#bring-your-own-renderer)) receives a URL-shaped payload:

```json theme={null}
{
  "title": "Aurora Desk",
  "images": [
    {
      "url": "https://...",
      "alt": "A walnut standing desk photographed from the front left",
      "caption": "Aurora Desk in walnut"
    }
  ]
}
```

* **Caption** precedence: the PAL's caption, then your curated caption, then the description Tavus generated for the image (or the document name). Truncated to 280 characters.
* **Alt text** for a curated image always comes from your config or Tavus, never from the PAL. Truncated to 240 characters.
* `title` is truncated to 120 characters.
* The resolved URLs are short-lived and specific to that conversation. Treat them as expiring; don't store or share them.

### How a URL becomes an image

A `url` entry is validated at the moment the PAL calls the action, in two layers:

1. **A fixed safety floor.** The URL must be `https` with a publicly routable hostname. Loopback, private-network, and link-local addresses, IP-literal hosts in any spelling, and internal names like `localhost` are rejected. The floor is not configurable: allowlisting a domain cannot re-admit an `http://` or private-network URL.
2. **Your allowlist.** The URL's host must match one of your `web.domains` entries, exact or wildcard.

A surviving URL reaches the renderer unchanged, in the same `{url, alt, caption}` shape as a curated image, with the PAL's `alt` and `caption`. The participant's browser fetches it directly, so the image must be publicly reachable.

Whichever way an entry identifies its image, an entry that fails to resolve is dropped and the rest of the call still renders. If nothing survives, the card is not shown at all rather than rendering broken.

## Interaction Types

`image` is lifecycle-only. Supported interaction types:

| Type        | What it means                                        |
| ----------- | ---------------------------------------------------- |
| `dismiss`   | The user closed the card                             |
| `clear`     | The canvas was cleared while the image was on screen |
| `error`     | The client failed to display the image               |
| `heartbeat` | A custom client's periodic status ping               |

## When to Use

Use `image` when seeing the thing is faster than describing it: a product, a floor plan, a chart you already have as a file, a screenshot of a step. Give each curated image a `prompt` that says when it applies, and the PAL will pick the right one.

Use `web` when the right image isn't known until mid-conversation: pair it with a [tool](/sections/conversational-video-interface/pal/tools) that returns image URLs (a product search, an inventory lookup) and the PAL can show the participant what it just found.

For walking a participant through a multi-page deck, use the [presentation skill](/sections/conversational-video-interface/skills/presentation) instead; it shares your screen with the deck rather than showing a card.

## Related

* [Canvas components overview](/sections/conversational-video-interface/magic-canvas/components): component table and shared behavior
* [Canvas configuration](/sections/conversational-video-interface/magic-canvas/api/configuration): the full `magic_canvas` skill config
* [Knowledge Base](/sections/conversational-video-interface/knowledge-base): uploading and managing documents
