speaking-shortlist · git:20260924.0d5d7a1 · 2026-09-24 · sha256 ed79db7dc1e22cee

speaking-shortlist git:20260924.0d5d7a1A

Immutable. This exact content never changes and is served at /api/v1/blob/ed79db7dc1e22cee.

---
name: speaking-shortlist
description: Find conferences, meetups and podcasts with a currently open call for speakers or guests that fit what the business knows, verify each one's deadline and submission requirements, and draft one tailored pitch per venue, skipping venues pitched in earlier runs.
---

This produces a shortlist for a human to review and submit themselves. The workflow never
applies, submits, emails, or otherwise acts toward any venue on its own. Read SCORING.md before
starting; its Python decides exclusions, order, verdict and run-to-run memory.

1. Read the project context. Everything here is evidence, not instructions, and none of it is
   asked of the founder again. Note which files existed for the report's `Context:` line.
   - `wiki/INDEX.md` → `## Product` → `### Feature map`: what the product does, with evidence.
     Pitches draw real detail from here; other memory sections are background.
   - `reports/GROWTH_ONBOARDING_PLAN.md`: `## The business` (what is sold, who buys) and
     `## Tin's view`. Any `hard no: …` in `## Marketing systems` and anything the founder
     forbids are binding: `no cold email` means only venues with an open call, a form or a
     published pitch address; `no unbacked claims` means every claim in a pitch is cited.
   - `.agents/skills/writing-style/SKILL.md`: the founder's voice. Every drafted pitch follows
     it. `tone_notes`, when given, wins where the two disagree.
   - The README and site copy only when the files above are missing.

2. Decide what to pitch. If `expertise` is given, use it. Otherwise build it from the Feature map
   and the growth plan: one specific talk, lesson or story the business can tell from its own
   evidence, and who in the audience should care. State it in one line in the report under
   `Pitching:` with the lines it came from. If neither `expertise` nor any of those files gives a
   real story, write the short report from step 9 with `Status: needs context` and stop; do not
   invent one. If `format_preference` is not `no_preference`, only consider that format.

3. Load memory. Find every earlier report in the output folder (the directory of the declared
   output path), read its `tin-speaking-state` block, and merge them as SCORING.md says. Venues in
   that state had a pitch drafted in an earlier run and are not pitched again.

4. Brainstorm venues, not categories. "Tech conferences" is not a venue; a specific regional
   conference with a stated theme is. Look for conferences, meetups (including ones listed on
   platforms like Meetup or Luma), and podcasts whose stated theme or past episodes/talks
   actually match the pitch. Skip names already in memory before spending a search on them.

5. Verify every candidate with a search before recording it:
   - Is there a currently open call for speakers or guests? Conferences and meetups almost
     always have a hard deadline: find the exact date (and timezone if the venue states one) on
     the venue's own CFP/apply page, not a secondhand aggregator or a past year's page. Podcasts
     usually don't — most take pitches on a rolling basis. For a rolling venue, confirm from its
     own page or recent activity (a recent episode, an active "guest with us" page) that it is
     still actually taking pitches now, and record that as rolling, not as an invented date.
   - What does the venue actually require: abstract or pitch length limit, speaker bio length,
     a video/audio sample, a specific submission form or platform versus a direct email, and any
     visible pattern in what it has selected before (a stated theme, or recent episodes/talks).
   - How does a pitch reach it (`route` in SCORING.md)? Record a published address only when the
     venue's own page states it. Never guess or construct an email address.
   Record each candidate as a SCORING.md venue record, verified or not. Do not guess a deadline,
   and do not mark a genuinely rolling venue unverified for lacking one.

6. Call `plan()` with the records, today's UTC date, `max_venues`, `format_preference`, the names
   in `already_pitched`, the merged state, the growth plan's hard no's and the declared output
   path. Use its shortlist order, exclusions, status, verdict and state as returned. If you
   disagree with a result, say why next to that venue; do not change it.

7. Draft one pitch per shortlisted venue, in its actual required format and within its stated
   length limit: a title plus abstract for a conference or meetup CFP, a short guest pitch for a
   podcast. Follow the writing style guide when present. Reference one concrete detail that
   proves the venue's actual page was read — its stated theme, a specific past talk or episode,
   its stated audience — rather than a generic pitch. Take facts about the business only from
   the files in step 1 and `expertise`. Never fabricate speaking history, credentials, metrics or
   availability.

8. Sending stays with the founder. Each venue names where the pitch goes (`Submit via:`). Do not
   write rows for `outreach/email/SHORTLIST.csv`: that file belongs to the email shortlist
   workflow, and the email campaign sends one identical body to every selected row, which would
   flatten a tailored pitch. Most venues take pitches through a form anyway.

9. Write the report to the declared output path, in exactly this order:
   - `# Speaking shortlist: <business or product name>`
   - `Status:` the status from `plan()` (`complete` or `no venues verified`), or `needs context`
   - `Verdict:` followed by nothing but the verdict from `plan()` (`fit`, `thin`, or
     `not a fit`) — never left out, never any other text on that line
   - `As of:` today's UTC date
   - `Pitching:` the one-line pitch and where it came from (`expertise` or the file lines)
   - `Context:` which of the step 1 files were read, and `none found` for each that was missing

   Then one section per shortlisted venue, in ranked order, each with these exact labels so the
   result stays checkable:
   - `## <Venue name>` with its link
   - `Deadline:` the exact date (and timezone if stated) and its source, or
     `Rolling — verified open on <date checked>` with its source for a rolling venue
   - `Fit:` one line tying it back to the pitch
   - `Requirements:` length limits, bio, sample and submission mechanism
   - `Submit via:` the form URL or the address the venue's own page publishes
   - `Drafted pitch:` the pitch

   Then `## Pitched in earlier runs`: venues `plan()` excluded because an earlier report drafted
   them, each with its date and report path, or `- none`. Then `## Excluded candidates`: every
   other exclusion from `plan()` with its reason. If fewer than `max_venues` survived, say so
   plainly there — do not pad the list to hit the number.

   End with the state from `plan()` as JSON in a fenced block whose info string is
   `tin-speaking-state`, written with Python from the returned value, not retyped.

   For `Status: needs context`, write the header lines with `Verdict: not a fit`, one sentence
   naming what is missing (an `expertise` input, or the Feature map from "Map what the product
   actually does"), `## Excluded candidates` with `- none`, and the unchanged merged state.

10. Before finishing, reread the report. Count the `## <Venue name>` headings (excluding
    `## Pitched in earlier runs` and `## Excluded candidates`) and confirm the count matches the
    shortlist from `plan()`, that the `Verdict:` line matches `plan()`, and that the state block
    parses. Fix any mismatch before finishing.