skills/_disabled/master-builder/SKILL.md
End-to-end workflow for creating a data-driven master in Motley. Guides through cube research, outline planning, master creation, slide layout selection, content configuration, and final review. Use when asked to create a master, build a deck, or make a presentation.
npx skillsauth add motleyai/agent-skills master-builderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
End-to-end workflow for creating a data-driven master (parametrized slide deck template) in Motley.
A master is a parametrized slide deck template. It accepts parameters (customer_name, start_date, end_date) and resolves into a fully data-driven presentation. Blocks within slides reference data queries, other blocks, and context variables to produce dynamic content.
The master-building workflow has 6 phases:
Enter plan mode. Research the available data and layouts to design the deck.
Understand what data is available:
cubes_summary()
Then inspect relevant cubes to see measures, dimensions, and sample data:
inspect_cube(cube_name="revenue", num_rows=3)
inspect_cube(cube_name="customers", num_rows=3)
If the existing cubes don't have the data you need, you can create custom cubes from SQL (create_cube), add computed measures to existing cubes (add_measures), or add computed dimensions (add_dimensions). See the explore-cube skill for details.
See what slide layouts are available:
list_layout_libraries()
Inspect the structure of the target layout library:
inspect_layout_library(layout_library_id=<id>)
Visually inspect layouts using thumbnails:
get_thumbnails(doc_id=<layout_library_deck_id>, layout_names=["Cover", "KPI Dashboard", "Chart Slide", ...])
For each layout, document:
For each planned slide, specify:
Keep the outline in the plan mode conversation — no need to use the outline MCP tools.
Present the outline to the user. Incorporate feedback before proceeding.
Initialize a master from the layout library:
create_master(
layout_library_id=<id>,
name="<descriptive name>",
source_id=<source_id>
)
source_id is optional — if provided, the master's sample_parameters (start_date, end_date, client_name) are derived from the source's default filtersmaster_id for all subsequent operationsGet the full structure of the master:
inspect_document(doc_id=<id>)
This returns all slides with their block names and types. For each slide, note:
Optionally get thumbnails to see the visual appearance:
get_thumbnails(doc_id=<master_deck_id>, layout_names=["Layout1", "Layout2", ...])
For each slide in your outline:
Among the hidden slides in the master, find the one whose element structure best matches the content you need. Consider:
Important: A layout library is purely a visual template — it defines element positions, sizes, and types, nothing more. Any existing text, chart data, or table content in the layout's elements is placeholder content and must be ignored entirely. Do NOT let placeholder content influence what you put into the blocks. The only guidance for block content comes from the user's requirements and the outline you built in Phase 1.
copy_slide(
doc_id=<id>,
slide_name="<hidden_layout_name>",
new_slide_name="<descriptive_slide_name>",
position=<N>,
element_descriptions=[
{"name": "element1", "description": "Purpose of this element"},
{"name": "element2", "description": "Purpose of this element"}
],
description="Overall slide purpose"
)
The copy is automatically unhidden. The element_descriptions help the query/chart LLMs understand the context.
For each block in the slide, use the appropriate tool:
update_chart_block(
location={doc_id: <id>, slide_name: "<slide>", block_name: "<chart_block>"},
prompt="<detailed chart description>",
cube_name="<cube>"
)
Then verify:
render_chart(
location={doc_id: <id>, slide_name: "<slide>", block_name: "<chart_block>"}
)
See the update-chart skill for writing effective chart prompts.
First create query blocks for the data:
update_query_block(
parent_location={doc_id: <id>, slide_name: "<slide>", block_name: "<text_block>"},
query_name="<name>",
prompt="<what data to fetch>",
cube_name="<cube>"
)
Then set the template:
update_text_block(
location={doc_id: <id>, slide_name: "<slide>", block_name: "<text_block>"},
user_prompt="<template with {variables}>",
call_llm=<true/false>
)
Text blocks resolve immediately — check the returned content. See the update-text-block skill.
Same pattern as text — create query blocks first, then set the template:
update_query_block(
parent_location={doc_id: <id>, slide_name: "<slide>", block_name: "<table_block>"},
query_name="<name>",
prompt="<what data to fetch>",
mode="table",
cube_name="<cube>"
)
update_table_block(
location={doc_id: <id>, slide_name: "<slide>", block_name: "<table_block>"},
user_prompt="{<query_name>}",
target_shape=[<rows>, <cols>]
)
See the update-table-block skill.
render_chart to see the rendered PNGresolve_master(doc_id=<id>)
This resolves any remaining out-of-date blocks (mainly charts that haven't been individually rendered).
Get thumbnails of all visible slides:
get_thumbnails(doc_id=<master_deck_id>, layout_names=["Slide1", "Slide2", ...])
Check:
render_chart or resolve_masterupdate_text_block/update_table_block{var} for same-slide queries and context variables{Slide::Block} for cross-slide referencesupdate-text-block skill for full syntaxCritical rule: Every {variable} or {Slide::Block} reference in a template must point to something that already exists at the time you call update_text_block or update_table_block. Concretely:
{query_name}): call update_query_block to create the query BEFORE calling update_text_block/update_table_block with a template that references it{Slide::Block}): the referenced slide and block must already have content (i.e., be configured and resolved) before the referencing template is set{customer_name}, {end_month}, etc.): these are always available — no prior setup needed{chart_block_name}): the chart block must exist on the slide (it does not need to be resolved yet — the reference will resolve lazily)If a reference points to something that doesn't exist, resolution will fail.
{query_name}query_name in update_query_block must match the {variable} in the parent's user_promptupdate_master tool — master-level properties (name, sample_parameters) can only be set during create_masterdelete_query_block tool — to remove a query, update the parent block's template to not reference itdevelopment
Create branded HTML presentations using structured slide specs. Outputs JSON DeckSpec instead of raw HTML — the server handles all rendering, styling, and viewport fitting.
data-ai
Create or modify text blocks using update_text_block. Covers template syntax with variable references, LLM generation, and constrained outputs.
data-ai
Create or modify table blocks using update_table_block. Covers template syntax, target_shape constraints, and table generation patterns.
data-ai
Create or modify numerical query blocks within text or table blocks using update_query_block. Queries provide data values referenced as {query_name} in parent templates.