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 singlePUT:
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_urlonscheduling_embed. - Disable a component: set
{ "enabled": false }.
scheduling_embed only activates once scheduling_url is set. 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 namedcanvas_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
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.
localhostand cloud metadata hostnames (such asmetadata.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:
- List PAL skills
- Get PAL skill
- Attach skill to PAL
- Update PAL skill
- Detach skill from PAL
- Replace PAL skills
You can read skills on stock PALs, but you can only modify skills on PALs you own.
Reading Configuration
The single-skillGET returns the attachment as stored:
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:
- The merge is shallow, at the top level of
config: a PATCH that includescomponentsreplaces 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
nullremoves it:{ "config": { "components": null } }clears every override and returns the skill to defaults.
Replacing All Skills
PUT /v2/pals/{pal_id}/skills takes { "skills": { ... } } and replaces the PAL’s entire skill set:
attached_at.
Detaching
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. canvas_clearis added once at least one component is active.- Canvas actions never overwrite a tool you defined with the same name; your tool wins.

