Skip to main content
Search the podcast catalog by what is said in episodes — by meaning (semantic_search), by exact phrase (keyword_search), or both at once (hybrid ranking). This is THE way to retrieve relevant dialogue, segments, and clips: each result is one segment of one episode with bounded transcript windows pinpointing the highest-relevance lines, plus any highlight clips that overlap the segment, inline on the match.
This tool replaces the old search_dialogue and list_clips tools. There is no separate clip-search tool — relevant clips arrive on these matches. A known episode’s full clip list is particle_podcast_get_episode with include: ["clips"].

Segments vs clips

  • Segments partition an episode’s transcript — where start_line/end_line are present, every spoken line belongs to exactly one segment and one segment’s end_line + 1 is the next one’s start_line. They are contiguous in transcript lines, not in wall-clock seconds: the seconds between one segment’s end_seconds and the next’s start_seconds contain no transcribed speech. These matches do not carry the line ranges themselves — fetch them with particle_podcast_get_episode and include: ["segments"], where their absence marks an episode segmented by an earlier version, a small share of which do leave lines uncovered. Search ranks segments and returns the matching ones.
  • Clips are sparse, engagement-ranked highlights that overlap some segments. When a clip overlaps a ranked segment, it appears under an Overlapping clips: line on that match.
Use this for “find dialogue about a topic”. For “every line naming a person or company” use particle_podcast_find_mentions instead — person_slug and company_slug here narrow ranked results, they don’t drive the ranking. What semantic_search is not good at:

Crafting the query

semantic_search and keyword_search do different jobs. Most disappointing results come from using one where the other belongs. semantic_search carries the idea. Write it as a sentence describing what should be discussed, in the words a speaker would actually use. It is paraphrase-tolerant, so it finds the topic however it happens to be phrased. keyword_search carries words that must be literally spoken. Every word must appear in the same passage, so it is for one or two exact tokens — a ticker, a product name, a drug name — not for a description. A sentence here returns nothing, because no passage contains all of those words. Use both when a topic must also contain an exact term. The result is their intersection, which is narrow by design. If it comes back empty, keyword_match: "ranked" relaxes the keyword side back to a relevance hint.
Never put a name in semantic_search. Resolve it with particle_person_resolve, particle_company_resolve, or particle_entity_resolve and pass the slug. Searching for "Sam Altman" as text finds passages that sound like him; person_slug: "sam-altman" finds the episodes actually featuring him.

Start broad, then narrow

Every filter compounds, and each one can remove all results on its own. Issue the query with semantic_search alone first, confirm the topic has coverage, then add filters. If a search returns nothing because of your filters, the tool returns an error that names the specific parameter responsible and the corrected call to make — it is measured by re-running your query with each filter removed, not guessed. Act on it rather than re-issuing variations of the same query. When the query text genuinely matches nothing, you get an ordinary empty result instead, which is the signal to rephrase semantic_search. role is the filter most likely to surprise: guest/host/panelist/ correspondent mean the person spoke in that specific capacity, speaker means they spoke in any of them, and mention means they were talked about rather than speaking. Omitting role covers speaking and mentions both, and is almost always what you want. These are the same values /v1/podcasts/episodes accepts.

Inputs

At least one of semantic_search or keyword_search is required.

Output

A markdown document with ## Dialogue matches (N) and one ### Segment title section per match. Each section carries bulleted KV rows: - **Episode:**, - **Podcast:**, - **Podcast slug:**, - **Published:**, - **Episode slug:**, - **Segment type:**, - **Match:** (the source: semantic, keyword, or hybrid), then one or more bullets formatted Window @ start–end (or Preview @ … for truncated windows) followed by indented dialogue lines. Every line that matched the query is rendered with the entire Speaker: text wrapped in bold (a window can contain several matched lines); surrounding context renders as **Speaker:** text. When highlight clips overlap the segment, they appear under an Overlapping clips: line as bullets formatted Title (TYPE, score N) @ start–end — clip ID: <id>. When more pages exist, a horizontal rule and a **Cursor:** <value> line are appended. Bolded lines mark the lines that ranked for the current query (a window can contain several). This is a different signal from the bolding in particle_podcast_find_mentions, where a bolded line means “this line names the resolved entity” — they answer different questions and can both be true within the same episode for different reasons. Sample (semantic_search="how AI affects the labor market", limit=2):
The string after - **Episode slug:** is what you can feed into particle_podcast_get_episode for the full transcript or clip list, or into particle_podcast_find_mentions (format=detail, episode_slug) for mention windows around a specific person.

Example

For hybrid ranking, populate both semantic_search and keyword_search: