Oscar Craven

Lab

How I built Roryisms in a day

120 talks and 139 posts in, 2,055 ideas out, 11 agents, one day.

Built on 14 October 2026, from 10:24 to 15:08.

Go straight to the steps and prompts

all 2,055, with the talks they come from

The shape of it

One orchestrator, three waves of agents, plain scripts in between.

  • One orchestrator. Claude Code wrote every agent’s prompt, then merged, rendered and deployed what came back.
  • Three waves of agents. Eleven agents in all: three to collect, four to extract, four to canonicalise. Each had one job and its own folder.
  • Scripts in between. Merging, removing duplicates, sorting into themes and building the page were plain scripts, because those jobs have a known right answer.
Eleven agents in three waves, one orchestrator, scripts in between.

Run it yourself

Three waves of agents, then the scripts. Each step says what it does, who does it and how long it took, then gives the prompt exactly as it was sent.

The prompts are as sent, numbers and all. For your own subject, change the topic, the folder names and the counts.

  1. Wave 1, started 10:24

    Collect the talks and the posts

    Two agents run a script that pulls the English captions of Rory Sutherland’s YouTube talks with yt-dlp and saves each one as a transcript. A third agent, on Grok, collects his posts on X that state an idea.

    Agents
    3: Collect A and Collect B on Claude Opus, Posts on Grok
    Persona
    researcher-deep for Collect A and B, researcher-news for Posts
    Time
    Started at 10:24. Wave 2 started at 11:35.
    Out
    135 transcripts (15 excluded later, leaving 120) and 139 X posts
    The collect prompt, as sent

    PROMPT.md for Collect A. Collect B had the same prompt with other search lines.

    Goal: run the transcript collection script over these three sources, in order, and report what was collected.
    
    Sources (run the script once per line, exactly as written, quoted as a single argument):
    1. https://www.youtube.com/watch?v=SG-iLV_NJL8
    2. ytsearch60:Rory Sutherland talk
    3. ytsearch40:Rory Sutherland Nudgestock
    
    Context: Oscar is building a corpus of Rory Sutherland talks (transcripts) for an R&D project on his ideas. Project folder: <project>. Read its README.md first. The collection script is <project>/scripts/collect_transcripts.sh: pass it ONE source (a YouTube URL or a ytsearchN:query string) as its single argument and it pulls English captions with yt-dlp (no video download), then converts them to markdown transcripts in <project>/transcripts/. It is idempotent (download archive in <project>/raw/archive.txt) so re-running is safe. Another agent is running the script on other source lines at the same time against the same folders; this is expected and harmless.
    
    Rules: Do NOT edit sources.txt, the scripts, or anything outside <project>/raw/ and <project>/transcripts/ (and only via the script). Do NOT commit. Do NOT use whisper or download video. If yt-dlp hits HTTP 429 / rate limiting, wait 2-3 minutes and re-run the same source; the archive resumes. Give each script run a generous timeout (10+ minutes), running in the background and polling if needed.
    
    After all your sources are done, quality-check: (1) list every transcript file in <project>/transcripts/ with its word_count from the frontmatter; (2) flag any with word_count under 800 or caption_kind missing; (3) open two transcripts at random and confirm the text reads as continuous speech without rolling repeated phrases; (4) note any ids in <project>/raw/captions/ that have .info.json but no .vtt (no captions available).
    
    RESULT.md must contain: a table of transcripts collected during your run (file, title, channel, date, minutes, words); the count of videos skipped by the filter versus fetched (from the yt-dlp output); any rate-limit events and how you handled them; the quality-check findings; a list of any sources that failed and why.
    The posts prompt, as sent

    PROMPT.md for Posts, the Grok agent.

    Goal: collect Rory Sutherland's most substantive original posts on X (handle @rorysutherland, Ogilvy vice chairman, author of Alchemy) and return them as a structured list.
    
    Context: Oscar is building a register of "Roryisms": his recurring quips, stories, and behavioural-science mechanisms (costly signalling, the opposite of a good idea can also be a good idea, psycho-logic versus logic, Eurostar wifi, Red Bull, the doorman, placebo value, satisficing, etc). The tweet pass complements a transcript corpus from his YouTube talks. Ideas matter more than verbatim wording.
    
    Scope: original posts and quote-posts by @rorysutherland from 2023-01-01 to today. Exclude plain retweets and one-line replies unless the reply contains a standalone idea. Aim for 80 to 150 posts. Prioritise posts that state an idea, a heuristic, a contrarian claim, or a story; skip pure promotion and logistics. Also include posts from the last 90 days so the register is current.
    
    Return: RESULT.md with (1) a table: date | link | post text (trimmed to the idea) | theme tag (one of: signalling, psycho-logic, pricing/value, marketing vs engineering, transport, bureaucracy/institutions, innovation/alchemy, other); (2) a short section listing the 10 to 15 themes that recur most, with counts; (3) a section noting any posts where he attributes the idea to someone else (Kahneman, Taleb, Ariely, Bernays, etc), since the register needs a "borrowed from" column; (4) your confidence that the table is representative, and what you could not access.
    
    Limits: read only, do not edit any files in the workspace other than your own RESULT.md. Every row needs a date and a link.
    The persona: researcher-deep

    PERSONA.md, used by 10 of the 11 agents.

    ---
    id: researcher-deep
    label: Deep researcher
    engine: claude
    model: opus
    permissions: research
    description: One question researched thoroughly from primary sources, with claims cross-checked and contradictions recorded. Uses Claude Opus.
    ---
    
    # Deep researcher
    
    ## Scope
    
    - One question, as stated in PROMPT.md, answered as completely as the
      sources allow.
    - Primary sources first: official documentation, papers, standards, data,
      filings, the original announcement. Secondary coverage only to find them.
    - Out of scope: anything PROMPT.md excludes, and tangents that do not change
      the answer.
    
    ## Tools
    
    - Web search and web fetch (pre-approved), reading files in this folder.
    - Read full pages before relying on them; search snippets are leads, not
      sources.
    
    ## Method
    
    1. Break the question into the sub-questions that decide the answer. Write
       them down first.
    2. For each sub-question, find at least two independent sources. Note the
       date and author of each.
    3. Cross-check: where sources disagree, record both positions and which is
       better supported, and why (recency, directness, method).
    4. Separate facts, estimates and opinions. Give numbers with their units,
       dates and source.
    5. Say what you could not find. An honest gap is more useful than a guess.
    6. Stop when further searching does not change the answer.
    
    ## Working rules
    
    - Work only in this agent folder. Do not edit files anywhere else.
    - Do not run shell commands unless PROMPT.md asks for it.
    
    ## Output contract (RESULT.md)
    
    1. `# Result: <question>`
    2. `## Answer`: the direct answer in a short paragraph.
    3. `## Findings`: one section per sub-question, each claim with source
       numbers like [2].
    4. `## Contradictions`: where sources disagree, both sides and your reading.
    5. `## Sources`: numbered list. Each: author or organisation, title, date,
       full link.
    6. `## Confidence`: high / medium / low for each main conclusion, and why.
    7. `## Open questions`: what remains unknown and what would settle it.
    The persona: researcher-news

    PERSONA.md for the Grok agent.

    ---
    id: researcher-news
    label: News researcher
    engine: grok
    model:
    permissions: research
    description: Recent news and discussion on X and the web, with dates and links on every item. Runs on Grok so it does not use Claude usage.
    ---
    
    # News researcher
    
    ## Scope
    
    - What has happened recently on the topic in PROMPT.md, and what people with
      first-hand knowledge are saying about it.
    - Default time window: the last 14 days, unless PROMPT.md gives another.
    - Out of scope: background explainers, opinion pieces without new
      information, and anything PROMPT.md excludes.
    
    ## Tools
    
    - X search on the user's paid Grok login: `x_keyword_search`,
      `x_semantic_search`, `x_user_search`, `x_thread_fetch`. Use them first for
      live discussion, announcements and first-hand accounts.
    - Web search and web fetch for the primary source behind each claim
      (official posts, filings, release notes, the original article).
    - If the X search tools are not available in this session, say so plainly as
      the first line of RESULT.md ("X search tools were not available; these
      findings come from web search only") and carry on with web search.
    
    ## Method
    
    1. Restate the question and the time window at the top of your notes.
    2. Search X with several phrasings and with the accounts most likely to know
       (the organisations and people involved). Fetch full threads before quoting.
    3. For each claim, find the earliest and most direct source. Prefer the
       organisation's own post or document over coverage of it.
    4. Separate what is confirmed from what is reported and from what is rumour.
       Engagement numbers are not evidence of accuracy.
    5. Date every item (the date of the event or post, not of the coverage).
    6. Stop when new searches only return items you already have.
    
    ## Working rules
    
    - Work only in this agent folder. Do not edit files anywhere else.
    - Do not post, like, follow or message anyone.
    - Quote briefly and link; do not paste whole articles.
    
    ## Output contract (RESULT.md)
    
    1. `# Result: <topic>`
    2. `## Summary`: three to six sentences answering the question directly.
    3. `## Findings`: numbered, newest first. Each item: date, what happened,
       status (confirmed / reported / rumour), and source numbers like [3].
    4. `## Sources`: numbered list. Each: author or account, title or first
       words, date, full link.
    5. `## Confidence`: high / medium / low for the main conclusions, and why.
    6. `## Open questions`: what could not be settled and what would settle it.
  2. Wave 2, started 11:35

    Pull out every idea

    Four agents each read 30 transcripts, one at a time, and write down every distinct idea as one line of data. Each idea gets a short name, called a key, and the agents reuse a key whenever the same story comes back.

    Agents
    4: Extract 1 to 4, on Claude Opus
    Persona
    Same persona as step 1: researcher-deep
    Time
    About 80 minutes
    Out
    5,206 ideas. The prompt gave a starting list of 38 keys; the agents made about 2,800 more.
    The prompt, as sent

    PROMPT.md for Extract 1. The other three point at their own batch file.

    Goal: extract every distinct idea Rory Sutherland expresses in a batch of 30 talk transcripts into a structured JSONL file, so the orchestrator can merge four such batches into one deduplicated register of "Roryisms".
    
    Context: Oscar is building a register of Rory Sutherland's quips, stories, mechanisms and heuristics from 120 YouTube talk transcripts, to map onto behavioural-science principles and use as a source of new ideas for new problems. Project folder: <project> (read README.md first). Your batch is the list of transcript filenames in <project>/raw/batch-1.txt; the files live in <project>/transcripts/. They are auto-caption transcripts: names and jargon are sometimes mangled, and the ideas matter more than verbatim wording.
    
    Method: work through the batch ONE transcript at a time. After each transcript, append its items to ./extract.jsonl in your folder and add a line to ./coverage.md (filename | items extracted | one-line note). Do not try to hold several transcripts in context at once. If you run low on context, your files on disk are the record; continue from the next filename not in coverage.md.
    
    What to extract, per transcript: only Rory's own ideas, not the host's. One JSON object per line with these fields:
    - video_id: from the frontmatter
    - key: kebab-case id for the underlying story or idea. REUSE a key whenever the same story or idea recurs, within this transcript or across your batch. Start from this seed vocabulary and add new keys as needed: eurostar-wifi-vs-models, red-bull-tastes-awful, uber-map-uncertainty, doorman-fallacy, placebo-value, costly-signalling, opposite-of-good-idea, psycho-logic-vs-logic, satisficing-not-optimising, tube-dot-matrix-countdown, hmrc-tax-letter-nudge, diamonds-are-worthless, coke-pepsi-challenge, design-for-the-average-fails, dishwasher-tablet-colour, hotel-shampoo-size, frequent-flyer-miles, aravind-eye-care, ikea-effect, blind-spot-of-economics, trust-as-expensive-signal, meaning-of-price, spreadsheet-no-magic, fax-faster-than-email, consultancy-blame-avoidance, london-vs-paris-trains, parking-in-brighton, mcdonalds-vs-michelin, test-counterintuitive-things, big-data-small-insight, luxury-and-status, herd-mentality, average-trap, open-plan-offices, self-checkout, performance-marketing-one-metric, hr-bottleneck
    - kind: one of quip | story | mechanism | heuristic | claim. quip = a memorable one-liner; story = a worked example or anecdote with a brand or situation; mechanism = a named psychological or economic effect; heuristic = a rule for deciding or designing; claim = a contrarian assertion about how the world works
    - text: the idea in Rory's own words or as close as the captions allow, 40 words max
    - mechanism: the underlying behavioural-science concept in standard terms (e.g. loss aversion, costly signalling, satisficing, peak-end rule, social proof, framing, reactance). Use "unclear" if none fits.
    - example: the brand, product, institution or situation used to illustrate it, or "" if none
    - domain: one of marketing | pricing | transport | government | healthcare | product-design | workplace | economics | technology | personal | other
    - attribution: "Rory" if he presents it as his own, otherwise the person he credits (Kahneman, Taleb, Ariely, Bernays, Ogilvy, Thaler, Bezos, etc)
    - approx_position: rough fraction through the transcript where it appears (0.0 to 1.0), so a reader can find it
    
    Quantity: a 10k-word talk typically yields 15 to 40 items. Capture every distinct story and every quotable line, but do not pad with host questions or generic statements. When Rory tells the same story twice in one talk, one item.
    
    Scope: in = the 30 files in batch-1.txt. Out = any other transcript, the tweets file, web research, and editing anything in the project folder.
    
    RESULT.md must contain: the count of transcripts processed and items extracted; the 15 keys that occurred most often across your batch with counts; the 10 quips you judged most striking (text + video_id); any transcripts that were mostly not Rory speaking or were too garbled to use; new keys you minted beyond the seed list, with a one-line gloss each. The JSONL in ./extract.jsonl is the main deliverable; RESULT.md summarises it.
    
    Limits: write only inside your own folder. Do not edit anything under <project>. Do not commit. Validate at the end that every line of extract.jsonl parses as JSON (python3 -c "import json,sys; [json.loads(l) for l in open('extract.jsonl')]").
  3. Wave 3, started 13:01

    Turn repeats into one entry each

    Four agents each take one slice of the 734 keys that turn up in more than one talk. They merge keys that are the same idea into one register entry, with a quotable line, a short summary and a “use it” prompt, and they keep every source.

    Agents
    4: Canon 1 to 4, on Claude Opus
    Persona
    Same persona as step 1: researcher-deep
    Time
    About 45 minutes
    Out
    518 entries
    The prompt, as sent

    PROMPT.md for Canon 1. The other three point at their own slice.

    Goal: turn one slice of extracted Rory Sutherland ideas into canonical register entries: one entry per distinct idea, no duplicate stories, every source kept.
    
    Context: Oscar is building a "Roryisms" register from 120 talk transcripts and 139 X posts, to map Rory Sutherland's ideas onto a behavioural-science principle library and use them to generate new ideas for new problems. Four extraction agents produced 4,885 items keyed by story id; the keys are noisy because each agent minted its own names, so the same idea can sit under several keys. Project folder: <project> (read README.md first).
    
    Your inputs:
    - <project>/raw/canon/slice-1.json: your slice. A dict of key -> {n_videos, n_items, items[]}. Each item has video_id, video_title, kind, text, mechanism, example, domain, attribution, approx_position. Every key in your slice must end up inside exactly one entry you write (merged with others where it is the same idea).
    - <project>/raw/canon/all-keys.txt: every key in the whole corpus with counts and a sample line, including one-off keys (1 video) that are NOT in any slice. When a one-off key is clearly the same idea as one of your entries, add it to that entry's keys list so its source is kept. Do not create entries for one-off keys on their own unless the line is a genuinely striking quip; at most 10 such entries.
    - <project>/tweets.md: 139 of his X posts with date, link and text. When a post states the same idea as an entry, attach it.
    - <project>/raw/principles.json: the behavioural-ux principle codes (A1..F6) with labels. Map each entry to the codes whose mechanism it illustrates; leave the list empty when none fits, do not force it.
    - <project>/transcripts/: the full transcripts, if you need to check wording or context for a key. Grep for the example or a phrase.
    
    Method: read your whole slice first and group keys that are the same idea (e.g. "uber-map-uncertainty" and "uber-map-reduces-anxiety" are one entry; "costly-signalling" and "red-bull-tastes-awful" are two entries, because the second is a specific story and the first the mechanism, but cross-reference them in the summary). Then write entries. Rory tells the same story many ways: pick the best phrasing for the quip and record the other framings under variants.
    
    Output: ./entries.jsonl in your folder, one JSON object per line:
    - keys: list of every extraction key folded into this entry (from your slice, plus any one-off keys from all-keys.txt that match). Exact key strings.
    - title: 3 to 8 words, the name you would use to refer to the idea
    - kind: story | quip | mechanism | heuristic | claim (the dominant kind)
    - quip: the single most quotable line, in Rory's words as closely as the captions allow, 40 words max
    - summary: 2 to 4 sentences explaining the idea, the example, and why it works. Plain prose. No em dashes anywhere in any field (use commas, colons or full stops).
    - mechanism: standard behavioural-science or economics term (loss aversion, costly signalling, satisficing, framing, social proof, peak-end rule, Goodhart's law, variance versus mean, etc)
    - principles: list of codes from principles.json, possibly empty
    - domains: list from marketing | pricing | transport | government | healthcare | product-design | workplace | economics | technology | personal | other
    - attribution: "Rory" or the person he credits
    - variants: list of 0 to 4 short alternative framings or related examples he uses for the same idea
    - use_it: one or two sentences: a question or move for applying the idea to a new problem (this is the "cross-learning" payload, make it concrete)
    - tweets: list of {date, link, text} from tweets.md that express the same idea, possibly empty
    
    Quality bar: no two entries about the same idea. Specific stories (Eurostar wifi, Red Bull, Uber map, Doubletree cookie) stay distinct from the general mechanism they illustrate, but reference each other. A key list that drops any of your slice keys is a failure: validate at the end with python3 that the union of your keys lists equals the set of keys in slice-1.json, and that every line parses as JSON.
    
    RESULT.md must contain: counts (slice keys in, entries out, one-off keys folded in, tweets attached); a table of your entries (title | kind | keys count | sources count | principles); the 5 proposed themes you would group your entries under, each with a one-line blurb and the entry titles; anything you were unsure about merging.
    
    Limits: write only inside your own folder. Do not edit anything under <project>. Do not commit. No web research needed.
  4. Scripts, no agents

    Merge, check and publish

    Plain scripts merge the four sets of entries, remove duplicates and sort the entries into 12 themes by fixed rules. Then they build the register, render the page and deploy it.

    Run by
    The orchestrator, Claude Code
    Duplicates
    518 entries down to 468. Two entries merge only if they share two keys, or one key and a similar title.
    Live
    The public page went up at 15:08.
    Out
    468 entries in 12 themes. The 1,587 ideas he told only once were added later that day: 2,055 in all.

    No prompt here. These jobs have a known right answer, so no agent spends tokens on them.

Why a fleet and not one agent

Too much to read

120 transcripts are over a million words. One agent would read them one at a time for about five hours. Four read 30 each, in 80 minutes.

The right engine per job

Grok searched X. Claude Opus read the talks. Scripts did the merging, so no agent spent tokens on work with a known answer.

Nothing to untangle

Each agent wrote only in its own folder and reported in one file. A bad batch was replaced, not repaired.

No agent giving orders to agents

One orchestrator, workers that report back. That is the lesson from the OpenClaw bill.

What went wrong

Four mistakes, and what to do instead.

  1. A message mid-run built a second register

    I sent agent 02 a follow-up while it was working. It built a second register that overlapped the first.

    Decide who does what before you talk to an agent.

  2. One shared key merged too much

    The first rule merged two entries if they shared one key. Through chains of shared keys, it pulled 518 entries down to 385 and joined ideas that did not belong together.

    Merge only on two shared keys, or one key plus a similar title.

  3. yt-dlp forgot what it had fetched

    With --skip-download, yt-dlp does not write its download archive unless you also pass --force-write-archive. One sweep fetched 60 videos again.

    Add --force-write-archive.

  4. Dubbed videos had translated captions

    On videos YouTube dubs automatically, the English captions are translated back from the dub. 31 transcripts had to be redone.

    Ask for the en-orig track, the captions of the original speech.

Want a register of your own subject?

Tell me the subject. I read every message.