Skip to main content
To configure Magic Canvas, attach the magic_canvas skill to the PAL. The skill controls which Canvas components the PAL may use; the PAL decides at runtime when to show one. Attaching the skill enables every component with defaults; there is no per-component opt-in. Audio-only, chat, and external-meeting conversations never get Canvas actions; see how the configuration reaches a conversation.

Attaching the Skill

Attach with a single PUT:
Common configurations, shown as the PAL’s skills value:

Component Overlay

config.components is a sparse overlay, not an allowlist. Components you don’t mention stay enabled with defaults. Add an entry to:
  • Configure a component: for example, set scheduling_url on scheduling_embed.
  • Disable a component: set { "enabled": false }.
New components Tavus adds later are enabled automatically on PALs with the skill attached. Disable them per component to opt out.
Two components need config before they do anything. scheduling_embed only activates once scheduling_url is set, and image only activates once you curate at least one Knowledge Base image or enable its web allowlist. Attaching the skill without that config doesn’t error; the component stays inactive.
config is strictly validated: an unknown component name or stray field returns 400. A misspelled skill id in the URL returns 404: Unknown skill '...' on PUT and PATCH, the not-attached 404 on GET and DELETE.

When cards appear

There is no API to show a specific card. The PAL chooses when to call a Canvas action during the conversation. You influence that in three places: Tavus appends usage_guidance to the Canvas system prompt. It is ignored when blank or when no component is active. Start by disabling components the PAL should not use (config.components.<name>.enabled: false). An enabled component can still appear even if your prompts never mention it.

Components

Each active component gives the PAL one action named canvas_show_<component> (for example, canvas_show_question). When at least one component is active, the PAL also gets canvas_clear. See the components overview for descriptions and per-component reference. Every card renders inline in the safe-area-right side rail next to the PAL video. Placement is client-side; the PAL does not choose the side. Only one card is on screen at a time: showing a card replaces whatever is currently displayed.

Component Fields

images Rules

Each entry is { "document_id", "caption", "prompt" }:
  • document_id (required) is a Knowledge Base document id. (Once an image is uploaded to the Knowledge Base, it receives a document_id.) It must be accessible to the account that owns the PAL and must have finished processing, both checked when you save the config.
  • caption (optional, max 280 characters) is shown under the image. Blank falls back to the description Tavus generated for the image, then the document name.
  • prompt (optional, max 500 characters) tells the PAL when this image applies. It is never shown to the user.
The PAL selects a curated image by document_id; the URL it renders from is resolved by Tavus, never supplied by the model. See the image component for the full flow.

web Rules

image.web is { "enabled", "domains", "guidance" } and adds a second image source: URLs the PAL received during the conversation (typically from a tool result), restricted to websites you allowlist.
  • enabled (optional) defaults to false and requires at least one entry in domains to turn on. false keeps a saved list without deleting it.
  • domains (optional, max 20 entries) lists the allowed websites. Each entry is an exact host (photos.example.com) or a leading wildcard (*.cdn.example.com, matching any depth of subdomain, never the apex). Entries are hostname-only, max 253 characters, punycode for international names, and are normalized on save (lowercased, trailing dot stripped, deduplicated). IP addresses, local and internal names, and wildcards over shared suffixes (*.github.io, *.co.uk) are rejected.
  • guidance (optional, max 500 characters) tells the PAL when to show a web image. Never shown to the user.
With a live allowlist, the compiled canvas_show_image action additionally accepts images[].url; every URL is checked at render time against a fixed safety floor (https, public hostname) and then your allowlist. See how a URL becomes an image.

scheduling_url Rules

A non-empty scheduling_url must be a public HTTPS URL:
  • Must start with https:// and include a hostname.
  • At most 2048 characters.
  • localhost and cloud metadata hostnames (such as metadata.google.internal) are rejected.
  • IP-based hosts (including hex and other numeric encodings) in private, loopback, link-local, or otherwise internal address space are rejected.
  • An empty string is allowed and means “not configured yet.”

Skills API

Skill attachments live under /v2/pals/{pal_id}/skills. Full HTTP reference: Endpoints: You can read skills on stock PALs, but you can only modify skills on PALs you own.

Reading Configuration

The single-skill GET returns the attachment as stored:
The per-skill PUT, PATCH, and GET return the attachment object directly. The list GET and the bulk PUT wrap attachments in a data map keyed by skill id:

Updating with PATCH

PATCH requires a { "config": ... } body (unlike PUT, where it defaults to {}), merges it into the existing config, and returns 404 if the skill isn’t attached:
Merge rules:
  • The merge is shallow, at the top level of config: a PATCH that includes components replaces the whole overlay map rather than deep-merging per component. Send the complete set of overrides you want to end up with.
  • Setting a top-level config key to null removes it: { "config": { "components": null } } clears every override and returns the skill to defaults.
The merged result is re-validated in full.

Replacing All Skills

PUT /v2/pals/{pal_id}/skills takes { "skills": { ... } } and replaces the PAL’s entire skill set:
The bulk PUT is a full replace: any skill missing from the payload is detached. To change only Canvas, use the per-skill PUT or PATCH instead.
Skills that were already attached keep their original attached_at.

Detaching

Returns 204 with no body. Detaching removes Canvas actions from all future conversations and deletes the attachment’s config; re-attaching starts from the config you send next.

Validation Errors

Errors return { "error": "..." }:

How the configuration reaches a conversation

At conversation create, Tavus resolves the PAL’s Canvas action list once:
  • Audio-only (audio_only: true), chat, and external-meeting (meeting_url: Zoom, Teams, Meet) conversations never get Canvas actions.
  • Every other conversation with the skill attached gets one canvas_show_<component> action per active component.
  • image resolves its curated Knowledge Base documents at this point. If none of them resolve to a displayable image and web is not enabled, no canvas_show_image action is compiled. With a live web allowlist, the compiled action also accepts image URLs.
  • canvas_clear is added once at least one component is active.
  • Canvas actions never overwrite a tool you defined with the same name; your tool wins.