AXe Skills HubSearch /

← All skills

pptx-engine

AXe First-party 

Reference: full SKILL.md

Below is the complete skill definition this hub loads when the skill is triggered — what the agent sees as its instructions, verbatim and unabridged.

PPTX Engine Skill

Role

You are an elite presentation automation engineer. You use python-pptx to build

polished, brand-compliant PowerPoint decks programmatically. You know every layout,

placeholder, chart type, and formatting trick in the python-pptx API.

Part 1: Installation & Setup

pip install python-pptx pillow
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Inches, Pt
import copy

Part 2: Core Presentation Structure

Create a Presentation

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor

def create_imi_presentation(output_path: str) -> Presentation:
    """Create a new IMI-branded presentation."""
    prs = Presentation()

    # Set slide dimensions (16:9 widescreen)
    prs.slide_width = Inches(13.33)
    prs.slide_height = Inches(7.5)

    return prs


def add_title_slide(prs: Presentation, title: str, subtitle: str,
                    date_str: str) -> None:
    """Add a branded title slide."""
    slide_layout = prs.slide_layouts[0]  # Title slide layout
    slide = prs.slides.add_slide(slide_layout)

    # Set title
    title_shape = slide.shapes.title
    title_shape.text = title
    title_tf = title_shape.text_frame
    title_tf.paragraphs[0].runs[0].font.size = Pt(40)
    title_tf.paragraphs[0].runs[0].font.bold = True
    title_tf.paragraphs[0].runs[0].font.color.rgb = RGBColor(0x1A, 0x1A, 0x2E)

    # Set subtitle
    subtitle_shape = slide.placeholders[1]
    subtitle_shape.text = f"{subtitle}\n{date_str}"

Part 3: Slide Types for IMI Decks

Content Slide (bullet points)

def add_content_slide(prs: Presentation, title: str,
                      bullets: list[str]) -> None:
    """Add a standard content slide with bullet points."""
    slide_layout = prs.slide_layouts[1]  # Title + Content
    slide = prs.slides.add_slide(slide_layout)

    slide.shapes.title.text = title

    tf = slide.placeholders[1].text_frame
    tf.clear()

    for i, bullet in enumerate(bullets):
        if i == 0:
            para = tf.paragraphs[0]
        else:
            para = tf.add_paragraph()

        para.text = bullet
        para.level = 0
        run = para.runs[0]
        run.font.size = Pt(18)
        run.font.color.rgb = RGBColor(0x31, 0x31, 0x31)

Two-Column Comparison Slide

from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor

def add_two_column_slide(prs: Presentation, title: str,
                          left_title: str, left_points: list[str],
                          right_title: str, right_points: list[str]) -> None:
    """Add a two-column comparison slide."""
    slide_layout = prs.slide_layouts[5]  # Blank layout
    slide = prs.slides.add_slide(slide_layout)

    # Title
    txBox = slide.shapes.add_textbox(Inches(0.5), Inches(0.3), Inches(12), Inches(0.8))
    tf = txBox.text_frame
    tf.text = title
    tf.paragraphs[0].runs[0].font.size = Pt(28)
    tf.paragraphs[0].runs[0].font.bold = True

    # Left column
    left_box = slide.shapes.add_textbox(
        Inches(0.5), Inches(1.3), Inches(5.8), Inches(5.5)
    )
    _populate_text_column(left_box, left_title, left_points)

    # Right column
    right_box = slide.shapes.add_textbox(
        Inches(6.8), Inches(1.3), Inches(5.8), Inches(5.5)
    )
    _populate_text_column(right_box, right_title, right_points)


def _populate_text_column(shape, col_title: str, points: list[str]) -> None:
    tf = shape.text_frame
    tf.word_wrap = True

    # Column title
    p = tf.paragraphs[0]
    p.text = col_title
    p.runs[0].font.size = Pt(16)
    p.runs[0].font.bold = True

    # Bullet points
    for point in points:
        new_para = tf.add_paragraph()
        new_para.text = f"• {point}"
        new_para.runs[0].font.size = Pt(13)

Data Chart Slide

from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE

def add_bar_chart_slide(prs: Presentation, title: str,
                         categories: list[str],
                         series_data: dict[str, list[float]]) -> None:
    """Add a bar chart slide."""
    slide_layout = prs.slide_layouts[5]
    slide = prs.slides.add_slide(slide_layout)

    # Title
    txBox = slide.shapes.add_textbox(Inches(0.5), Inches(0.2), Inches(12), Inches(0.7))
    txBox.text_frame.text = title
    txBox.text_frame.paragraphs[0].runs[0].font.size = Pt(24)
    txBox.text_frame.paragraphs[0].runs[0].font.bold = True

    # Chart data
    chart_data = ChartData()
    chart_data.categories = categories

    for series_name, values in series_data.items():
        chart_data.add_series(series_name, values)

    # Add chart
    chart_placeholder = slide.shapes.add_chart(
        XL_CHART_TYPE.COLUMN_CLUSTERED,
        Inches(0.5), Inches(1.1),
        Inches(12), Inches(5.8),
        chart_data
    )

    chart = chart_placeholder.chart
    chart.has_legend = True
    chart.legend.position = 2  # Bottom


def add_line_chart_slide(prs: Presentation, title: str,
                          categories: list[str],
                          series_data: dict[str, list[float]]) -> None:
    """Add a line chart slide for trend data."""
    slide_layout = prs.slide_layouts[5]
    slide = prs.slides.add_slide(slide_layout)

    txBox = slide.shapes.add_textbox(Inches(0.5), Inches(0.2), Inches(12), Inches(0.7))
    txBox.text_frame.text = title
    txBox.text_frame.paragraphs[0].runs[0].font.size = Pt(24)
    txBox.text_frame.paragraphs[0].runs[0].font.bold = True

    chart_data = ChartData()
    chart_data.categories = categories
    for name, values in series_data.items():
        chart_data.add_series(name, values)

    slide.shapes.add_chart(
        XL_CHART_TYPE.LINE,
        Inches(0.5), Inches(1.1),
        Inches(12), Inches(5.8),
        chart_data
    )

Image Slide

def add_image_slide(prs: Presentation, title: str, image_path: str,
                    caption: str = "") -> None:
    """Add a slide with a full-bleed image and optional caption."""
    slide_layout = prs.slide_layouts[5]
    slide = prs.slides.add_slide(slide_layout)

    # Title
    txBox = slide.shapes.add_textbox(Inches(0.5), Inches(0.2), Inches(12), Inches(0.6))
    txBox.text_frame.text = title
    txBox.text_frame.paragraphs[0].runs[0].font.size = Pt(22)
    txBox.text_frame.paragraphs[0].runs[0].font.bold = True

    # Image
    slide.shapes.add_picture(
        image_path,
        Inches(0.5), Inches(1.0),
        width=Inches(12), height=Inches(5.5)
    )

    # Caption
    if caption:
        cap_box = slide.shapes.add_textbox(
            Inches(0.5), Inches(6.7), Inches(12), Inches(0.4)
        )
        cap_box.text_frame.text = caption
        cap_box.text_frame.paragraphs[0].runs[0].font.size = Pt(10)
        cap_box.text_frame.paragraphs[0].runs[0].font.italic = True

Part 4: Styling & Branding

IMI Brand Colors

# IMI Brand Palette
IMI_NAVY      = RGBColor(0x1A, 0x1A, 0x2E)  # Primary dark
IMI_BLUE      = RGBColor(0x16, 0x21, 0x3E)  # Secondary
IMI_TEAL      = RGBColor(0x0F, 0x3D, 0x66)  # Accent
IMI_GOLD      = RGBColor(0xE2, 0xB9, 0x5A)  # Highlight
IMI_WHITE     = RGBColor(0xFF, 0xFF, 0xFF)
IMI_LIGHT_GREY = RGBColor(0xF5, 0xF5, 0xF5)
IMI_TEXT_DARK = RGBColor(0x31, 0x31, 0x31)

def apply_slide_background(slide, color: RGBColor) -> None:
    """Apply a solid background color to a slide."""
    background = slide.background
    fill = background.fill
    fill.solid()
    fill.fore_color.rgb = color

Font Utilities

def style_run(run, size_pt: int, bold: bool = False, italic: bool = False,
              color: RGBColor = None) -> None:
    """Apply full styling to a text run."""
    run.font.size = Pt(size_pt)
    run.font.bold = bold
    run.font.italic = italic
    if color:
        run.font.color.rgb = color


def set_paragraph_alignment(paragraph, alignment: str) -> None:
    """Set paragraph text alignment."""
    alignments = {
        "left": PP_ALIGN.LEFT,
        "center": PP_ALIGN.CENTER,
        "right": PP_ALIGN.RIGHT,
        "justify": PP_ALIGN.JUSTIFY
    }
    paragraph.alignment = alignments.get(alignment, PP_ALIGN.LEFT)

Part 5: Speaker Notes

def add_speaker_notes(slide, notes_text: str) -> None:
    """Add speaker notes to a slide."""
    notes_slide = slide.notes_slide
    tf = notes_slide.notes_text_frame
    tf.text = notes_text

Part 6: Full Deck Assembly

def build_imi_research_deck(
    title: str,
    brand: str,
    key_findings: list[str],
    fan_index_data: dict,
    output_path: str
) -> str:
    """Build a complete IMI research presentation."""
    from datetime import datetime

    prs = create_imi_presentation(output_path)
    date_str = datetime.now().strftime("%B %Y")

    # Slide 1: Title
    add_title_slide(prs, title, f"{brand} Fan Intelligence Report", date_str)

    # Slide 2: Executive Summary
    add_content_slide(prs, "Executive Summary", key_findings[:4])

    # Slide 3: Fan Index Chart
    if fan_index_data.get("categories") and fan_index_data.get("series"):
        add_bar_chart_slide(
            prs,
            "Fan Engagement Index by Segment",
            fan_index_data["categories"],
            fan_index_data["series"]
        )

    # Slide 4: Trend Analysis
    if fan_index_data.get("trend"):
        add_line_chart_slide(
            prs,
            "Index Trend — Last 12 Months",
            fan_index_data["trend"]["months"],
            fan_index_data["trend"]["series"]
        )

    # Slide 5: Key Insights
    add_content_slide(prs, "Key Strategic Insights", key_findings[4:])

    # Save
    prs.save(output_path)
    return output_path

Output Standards

  • Always set 16:9 dimensions (13.33" × 7.5") for modern screens
  • Never use layout index > 5 unless you've inspected the template's layouts first
  • Add speaker notes to every non-title slide
  • Use RGBColor for all colour — never string hex
  • Save with .pptx extension; verify file size is reasonable (< 50MB for standard decks)
  • Test with: python3 -c "from pptx import Presentation; prs = Presentation('output.pptx'); print(f'{len(prs.slides)} slides OK')"

AXE MCP Server Integration

Every skill in the AXE Skills Hub runs with access to the AXE MCP Server — giving it the full fleet intelligence toolkit automatically. No setup required; tools are available in any AXE-powered session.

Core Tools Available

CategoryToolsUse Case
Memoryread_memory, write_memory, list_memoryPersist context across sessions
Webweb_search, web_fetchLive data, docs, research
File Opsread_file, write_fileRead/write any local file
Fleetfleet_ssh, axe_pushRun commands on JL2/JL3/JL4, send notifications
AI Modelsquery_team_channel, get_partner_stateCross-agent coordination
Dataqdrant_search, qdrant_storeSemantic memory & vector search
Pipelinehydra_addAdd high-quality outputs to Edge training
Skillshub_list_skills, hub_get_skill, hub_search_skills, hub_get_registry, hub_skill_metadataChain skills together
Secretsget_secretRetrieve API keys securely

Quick Start

# In any AXE session, tools are pre-loaded. Example chaining:

# 1. Search for context
results = qdrant_search("user query here", collection="axe_persistent_memory")

# 2. Fetch live data if needed
content = web_fetch("https://docs.example.com/api")

# 3. Write result to memory for next session
write_memory("shared/last_result.md", output)

# 4. Log quality output to Edge training pipeline
hydra_add(prompt=user_query, response=output, score=0.9, source="skill-name")

Edge Training Integration

High-quality skill outputs are automatically eligible for Edge model training via hydra_add. When a response scores ≥0.85 in evals, pipe it to the Hydra pipeline to compound Edge's knowledge. This is how skills make Edge smarter over time.

# After generating a high-quality response:
hydra_add(
    prompt=user_input,
    response=final_output,
    score=0.9,          # eval score
    source="skill-name" # tracks provenance
)

Metadata

Category
Document
Tier
community
Version
1.0.0
License
MIT
Path
skills/pptx-engine/SKILL.md

Use with an agent

Fetch this skill’s definition over the open API — no key required.

curl -s /v1/skills/pptx-engine

View source ↗