Use this skill whenever the user asks to write, generate, or create a podcast script or podcast episode — from a topic, or from source material such as a news digest, newsletter, email review, or set of articles — and optionally convert it to audio with Azure Text-to-Speech. Handles the initial request and every follow-up refinement (source, topic, length, cast, narration) in the same task.
npx skills add https://github.com/microsoft/cat-agent-skills --skill generating-podcast-script
Produces a two-host, NotebookLM-style conversational episode: a readable script
plus a multi-voice SSML document ready for Azure Text-to-Speech.
Ask only for what is missing. Do not ask for optional fields that have safe
defaults.
| Input | Required | Default |
|---|---|---|
| source or topic | Yes | — (source material such as a digest/newsletter/articles, or a plain topic) |
| duration | No | medium — short ≈ 3 min / ~450 words, medium ≈ 6 min / ~900 words, long ≈ 12 min / ~1,800 words |
| language | No | English |
| cast | No | Two hosts, NOVA and MILES (see Step 4) |
| generate_audio | No | Ask after the script is ready |
All word targets assume ~150 spoken words per minute. Stay within 10 percent of
target.
Derive a lowercase-hyphenated <slug> from the source or topic (max 6 words,
ASCII only).
Skip this step when the user gave a bare topic with no source material.
Extract every distinct article or item. For each, capture:
Merge duplicates covering the same event. Discard boilerplate, footers,
disclaimers, legal notices, unsubscribe text, and image captions.
Rank items by newsworthiness and reader impact. Keep the top 4 to 6 for full
treatment (fewer for short, more for long). Group the remainder into one
fast rapid fire segment. If the material has a dominant theme, lead with it
and thread it through the episode.
Two hosts, always the same personalities, always distinct voices:
en-US-AvaMultilingualNeural. Lead host. Warm, curious,quick. Drives the agenda, asks the question the listener is thinking, reacts
out loud, reframes jargon into plain language. Slightly faster cadence.
en-US-AndrewMultilingualNeural. Analyst. Calm, dry,precise. Supplies context, numbers, caveats, second-order implications.
Slightly slower, lower pitch. Occasionally pushes back on Nova.
Neither host is a narrator. They talk to each other, not to the microphone.
tension. No "welcome to the podcast", no channel branding, no music cues.
hook → the facts → why it matters → a short exchange of interpretation →
handoff line into the next story. Vary who leads each segment.
tempo.
then a short human sign-off. Alternate whether Nova or Miles ends.
This is what makes it sound conversational rather than read-aloud.
turns with the other host interjecting.
up", "here's the part I didn't expect", "yeah, and that's the thing", "hmm".
Roughly one marker every 4 to 5 turns. Never let it become a tic.
explain.
people, companies, or politics are not.
reporting".
report is careful to call that unconfirmed".
emojis, no bullet points, and no URLs in the spoken text.
Applies to every word that will be spoken.
2026, "three point two billion dollars" not $3.2B, "about fifteen
percent" not ~15%.
<say-as interpret-as="characters">API</say-as>.<sub alias="phonetic spelling">Name</sub>.<lang xml:lang="fr-FR">...</lang>.
& → &, < → <,> → >.
Write the human-readable transcript to:
/app/created/<slug>_Podcast_Script.txt
This file — and only this file — may carry NOVA: / MILES: speaker labels so
a person can follow along. It contains no stage directions and no markdown. The
spoken text itself must already satisfy Steps 6 and 7 so it can be lifted into
SSML unchanged.
Produce the SSML document and nothing else — no preamble, no explanation, no
code fences, no trailing notes inside the artifact. Write it verbatim to:
/app/created/<slug>_Podcast.ssml
Rules:
<speak> element with version="1.0",xmlns="http://www.w3.org/2001/10/synthesis",
xmlns:mstts="http://www.w3.org/2001/mstts", xml:lang="en-US".
<voice> element per conversational turn. Alternate speakers. Never putboth hosts inside one <voice> element.
<prosody> so it never sounds flat. Baselines: Novarate="+6%" pitch="+2%", Miles rate="-2%" pitch="-4%". Nudge per line to
match the emotion of the sentence.
<mstts:express-as style="..."> where the voice supports it. Preferredstyles: chat for banter, friendly for explanation,
narration-professional for the factual core of a story, excited sparingly
for the cold open. An unsupported style is ignored by the service, so keep
styles optional — never structural.
<break time="250ms"/> between turns within a segment,<break time="700ms"/> between segments, <break time="400ms"/> before a
punchline or a pivot. Never exceed 900ms.
<break> must sit inside a <voice> element. A <break> placedbetween <voice> elements — as a direct child of <speak> — is invalid in a
multi-voice document and will fail synthesis. Two <voice> elements may sit
directly next to each other with nothing between them. To pause *between*
turns, put the break at the end of the preceding turn's text, inside that
turn's <prosody>.
<emphasis level="moderate"> on at most one or two key terms per segment.<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:mstts="http://www.w3.org/2001/mstts"
xml:lang="en-US">
<voice name="en-US-AvaMultilingualNeural">
<mstts:express-as style="excited">
<prosody rate="+8%" pitch="+3%">Okay, so the number that stopped me cold
this morning was forty percent. <break time="300ms"/> Forty percent, in one
quarter. <break time="250ms"/></prosody>
</mstts:express-as>
</voice>
<voice name="en-US-AndrewMultilingualNeural">
<mstts:express-as style="chat">
<prosody rate="-2%" pitch="-4%">Right, and the part everyone's skipping is
that it's off a very small base. <break time="250ms"/> Context matters
here. <break time="700ms"/></prosody>
</mstts:express-as>
</voice>
</speak>
Note the trailing <break> closing each turn: the 250ms is the gap before the
next turn, the 700ms is the longer gap before the next segment. Nothing sits
between the two <voice> elements.
Show the user a table summarising each segment (title, one-line description,
approximate spoken duration), print both file paths, and ask:
> Would you like me to convert this to an audio file?
Only if they say yes:
ConverttexttospeechwithSSML tool is available on the agent. Ifit is not, tell the user how to add it and stop.
ConverttexttospeechwithSSML with the SSML document from Step 9 andoutputFormat: riff-24khz-16bit-mono-pcm.
/app/created/<slug>_Podcast.wav.If the document is too large for a single call, split it at a segment boundary and synthesize each part separately.
When stitching, do NOT concatenate decoded RIFF/WAV bytes; instead, append the audio at the PCM-frame level (e.g., via Python’s wave module) and write a single valid /app/created/<slug>_Podcast.wav with one header.
import base64
with open('<tool_output_file>', 'r') as f:
content = f.read().strip()
audio_bytes = base64.b64decode(content)
with open('/app/created/<slug>_Podcast.wav', 'wb') as f:
f.write(audio_bytes)
Always end with:
| Item | Details |
|---|---|
| Script file | /app/created/<slug>_Podcast_Script.txt |
| SSML file | /app/created/<slug>_Podcast.ssml |
| Word count / estimated duration | actual vs. target at ~150 wpm |
| Items covered | full segments + rapid-fire count |
| Voices | en-US-AvaMultilingualNeural (Nova), en-US-AndrewMultilingualNeural (Miles) |
| Audio file | /app/created/<slug>_Podcast.wav *(only if audio generated)* |
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Improves the quality of images, especially screenshots, by enhancing resolution, sharpness, and clarity. Perfect for preparing images for presentations, documentation, or social media posts.
Downloads videos from YouTube and other platforms for offline viewing, editing, or archival. Handles various formats and quality options.
Lightweight WSI tile extraction and preprocessing. Use for basic slide processing tissue detection, tile extraction, stain normalization for H&E images. Best for simple pipelines, dataset preparation, quick tile-based analysis. For advanced spatial proteomics, multiplexed imaging, or deep learning pipelines use pathml.
Microscopy data management platform. Access images via Python, retrieve datasets, analyze pixels, manage ROIs/annotations, batch processing, for high-content screening and microscopy workflows.
Python library for working with DICOM (Digital Imaging and Communications in Medicine) files. Use this skill when reading, writing, or modifying medical imaging data in DICOM format, extracting pixel data from medical images (CT, MRI, X-ray, ultrasound), anonymizing DICOM files, working with DICOM metadata and tags, converting DICOM images to other formats, handling compressed DICOM data, or processing medical imaging datasets. Applies to tasks involving medical image analysis, PACS systems, radiology workflows, and healthcare imaging applications.
This skill should be used when working with pre-trained transformer models for natural language processing, computer vision, audio, or multimodal tasks. Use for text generation, classification, question answering, translation, summarization, image classification, object detection, speech recognition, and fine-tuning models on custom datasets.
Take microsoft/generating-podcast-script from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.