STORM — Sequence of LM Prompts in One Run

The strict chronological order of LM calls when STORM processes one topic. Captured from a code walkthrough on 2026-06-02.

The sequence

┌─ STAGE 1: Knowledge Curation ─────────────────────────────────────────┐

  1. FindRelatedTopic(topic)
     → returns ~5 Wikipedia URLs for related subjects
     → [non-LM]: HTTP fetch each URL, BeautifulSoup-parse the TOC

  2. GenPersona(topic, related_TOCs)
     → returns N personas as a numbered list
     → [non-LM]: prepend hardcoded "Basic fact writer" → final list of N+1 personas

  ──── then for EACH persona (run in parallel via thread pool) ────

    REPEAT max_conv_turn times:

      3. AskQuestionWithPersona(topic, persona, conv_history_so_far)
            ↑ (falls back to AskQuestion if persona is empty)
         → returns the next question this persona wants to ask the "expert"
         → break early if question is "" or starts with "Thank you so much..."

      4. QuestionToQuery(topic, question)
         → returns ~3 search queries
         → [non-LM]: retriever.fetch(queries) → web snippets

      5. AnswerQuestion(topic, question, snippets)
         → returns expert's answer (with citation markers)
         → append (question, answer, queries, results) to conv_history

└──────────────────────────────────────────────────────────────────────┘

┌─ STAGE 2: Outline Generation ─────────────────────────────────────────┐

  6. WritePageOutline(topic)
     → returns draft outline from parametric knowledge alone
     → SAVED as direct_gen_outline.txt

  7. WritePageOutlineFromConv(topic, old_outline=draft, conv=all_transcripts)
     → returns refined outline using the conversations
     → SAVED as storm_gen_outline.txt

└──────────────────────────────────────────────────────────────────────┘

┌─ STAGE 3: Article Generation ─────────────────────────────────────────┐

  ──── for EACH top-level section in storm_gen_outline (parallel) ────

    [non-LM]: ConvToSection — gather conversation turns relevant to this section

    8. WriteSection(topic, section_outline, relevant_snippets)
       → returns section text with [n]-style citations

  ──── assemble all sections in outline order → storm_gen_article.txt ────

└──────────────────────────────────────────────────────────────────────┘

┌─ STAGE 4: Article Polishing ──────────────────────────────────────────┐

  9.  WriteLeadSection(topic, full_article)
      → returns the summary paragraph that goes at the top

  10. PolishPage(full_article_with_lead)
      → optional dedupe pass over the whole article
      → SAVED as storm_gen_article_polished.txt

└──────────────────────────────────────────────────────────────────────┘

Concrete call count for our run

Run config: max_perspective=2 → 3 personas total (default + 2), max_conv_turn=2.

PromptTimes firedWhy
FindRelatedTopic1once per topic
GenPersona1once per topic
AskQuestionWithPersona63 personas × 2 turns
QuestionToQuery6one per turn
AnswerQuestion6one per turn
WritePageOutline1the draft
WritePageOutlineFromConv1the refinement
WriteSection~10one per top-level section of the outline
WriteLeadSection1summary
PolishPage1dedupe
Total~34matches the log of our actual run

Two notes about the order

AskQuestion vs. AskQuestionWithPersona are alternatives — only one fires per turn. AskQuestion is the bare fallback when no persona is supplied; STORM's main path always supplies a persona, so in practice you only see AskQuestionWithPersona in real runs. That's why the inventory lists 11 prompts but only 10 fire in any given run.
Within Stage 1, the N personas run in parallel (one thread per persona via max_thread_num), so the wall-clock order is interleaved. But within a single persona's thread, the turn-loop is strictly sequential: AskQuestion → QuestionToQuery → AnswerQuestion → next turn.

Source: stanford-storm/storm/knowledge_storm/storm_wiki/modules/ — see knowledge_curation.py, persona_generator.py, outline_generation.py, article_generation.py, article_polish.py.