Skip to main content
UncategorizedPrediction545 lines

Scenario Planning

Quick Summary18 lines
Scenario planning is a structured methodology for exploring multiple plausible futures rather than predicting a single one. Developed at Royal Dutch Shell in the 1970s and refined by the Global Business Network (GBN), it helps organizations prepare for uncertainty by building detailed narratives of how the future might unfold. Unlike forecasting, which asks "What will happen?", scenario planning asks "What could happen, and how would we respond?"

## Key Points

- Structural breaks occur (pandemics, financial crises, technological disruptions)
- Multiple interacting uncertainties create unpredictable combinations
- Human decisions and responses change the trajectory
- Black swan events invalidate historical patterns
- "What will the future look like?" (too vague)
- "Will AI replace jobs?" (too narrow, binary)
- "How should our company position itself in the healthcare market over the next 10 years?"
- "What workforce strategy should we adopt given potential AI disruption by 2030?"
- "How might the energy transition reshape our industry's competitive landscape by 2035?"
- Specific enough to guide research
- Broad enough to allow diverse scenarios
- Relevant to actual strategic decisions
skilldb get prediction-skills/scenario-planningFull skill: 545 lines
Paste into your CLAUDE.md or agent config

Scenario Planning

Overview

Scenario planning is a structured methodology for exploring multiple plausible futures rather than predicting a single one. Developed at Royal Dutch Shell in the 1970s and refined by the Global Business Network (GBN), it helps organizations prepare for uncertainty by building detailed narratives of how the future might unfold. Unlike forecasting, which asks "What will happen?", scenario planning asks "What could happen, and how would we respond?"

The Core Philosophy

Why Not Just Forecast?

Traditional forecasting extrapolates from the past and assumes continuity. It fails spectacularly when:

  • Structural breaks occur (pandemics, financial crises, technological disruptions)
  • Multiple interacting uncertainties create unpredictable combinations
  • Human decisions and responses change the trajectory
  • Black swan events invalidate historical patterns

Scenario planning embraces uncertainty as irreducible and builds strategic flexibility instead of point predictions.

The Shell Story

In the early 1970s, Shell's scenario planners (led by Pierre Wack) developed scenarios that included an oil price shock. While other oil companies were caught off guard by the 1973 OPEC embargo, Shell had already stress-tested their strategies against this possibility. Shell rose from the weakest of the "Seven Sisters" to one of the two strongest within a decade.

The GBN/Shell Method

Step 1: Define the Focal Question

The scenario planning exercise must center on a specific strategic question:

Bad focal questions:
- "What will the future look like?" (too vague)
- "Will AI replace jobs?" (too narrow, binary)

Good focal questions:
- "How should our company position itself in the healthcare market over the next 10 years?"
- "What workforce strategy should we adopt given potential AI disruption by 2030?"
- "How might the energy transition reshape our industry's competitive landscape by 2035?"

The focal question should be:

  • Specific enough to guide research
  • Broad enough to allow diverse scenarios
  • Relevant to actual strategic decisions
  • Time-bounded (5-20 year horizon typically)

Step 2: Identify Driving Forces

Map the forces that will shape the answer to your focal question:

class DrivingForce:
    """A force that shapes the future relevant to the focal question."""

    def __init__(self, name: str, category: str, description: str):
        self.name = name
        self.category = category  # STEEP: Social, Tech, Economic, Environmental, Political
        self.description = description
        self.impact = 0  # 1-5 scale
        self.uncertainty = 0  # 1-5 scale

    def __repr__(self):
        return f"{self.name} (Impact: {self.impact}, Uncertainty: {self.uncertainty})"


def identify_driving_forces(focal_question: str) -> list:
    """Systematic identification of driving forces using STEEP framework."""
    categories = {
        'Social': [
            'Demographics', 'Consumer behavior', 'Cultural values',
            'Education levels', 'Urbanization', 'Health trends',
            'Inequality', 'Migration patterns'
        ],
        'Technological': [
            'AI/ML capabilities', 'Energy technology', 'Biotech',
            'Computing power', 'Connectivity', 'Automation',
            'Materials science', 'Space technology'
        ],
        'Economic': [
            'Growth rates', 'Interest rates', 'Trade patterns',
            'Currency dynamics', 'Labor markets', 'Commodity prices',
            'Financial innovation', 'Debt levels'
        ],
        'Environmental': [
            'Climate change', 'Resource scarcity', 'Biodiversity',
            'Pollution', 'Extreme weather', 'Energy transition',
            'Water availability', 'Land use'
        ],
        'Political': [
            'Geopolitical alignment', 'Regulation', 'Trade policy',
            'Political stability', 'International cooperation',
            'Military dynamics', 'Governance models', 'Populism'
        ]
    }

    forces = []
    for category, subcategories in categories.items():
        for sub in subcategories:
            force = DrivingForce(
                name=sub,
                category=category,
                description=f"How {sub.lower()} affects {focal_question}"
            )
            forces.append(force)
    return forces

Step 3: Rank by Impact and Uncertainty

Plot all driving forces on a 2x2 matrix:

High Uncertainty
    |
    |  SCENARIO       MONITOR
    |  DRIVERS        (wild cards)
    |
    |  PREDETERMINED  LOW PRIORITY
    |  ELEMENTS
    |__________________ High Impact
         Low                High
def prioritize_forces(forces: list) -> dict:
    """Separate forces into categories based on impact/uncertainty."""

    predetermined = []  # High impact, low uncertainty (will happen)
    scenario_drivers = []  # High impact, high uncertainty (define scenarios)
    monitors = []  # Low impact, high uncertainty (watch these)
    background = []  # Low impact, low uncertainty (ignore)

    for force in forces:
        if force.impact >= 4 and force.uncertainty >= 4:
            scenario_drivers.append(force)
        elif force.impact >= 4 and force.uncertainty < 4:
            predetermined.append(force)
        elif force.impact < 4 and force.uncertainty >= 4:
            monitors.append(force)
        else:
            background.append(force)

    return {
        'scenario_drivers': scenario_drivers,
        'predetermined': predetermined,
        'monitors': monitors,
        'background': background
    }

Predetermined elements appear in ALL scenarios (e.g., aging demographics in developed nations). Scenario drivers are the axes that differentiate your scenarios.

Step 4: Select Scenario Axes

Choose the two most critical uncertainties as your scenario axes. This creates a 2x2 matrix with four distinct scenarios.

Example for "Future of Urban Transportation by 2035":

Axis 1: Autonomous vehicle technology
        (Breakthrough <-----> Incremental progress)

Axis 2: Urban policy orientation
        (Car-centric <-----> Transit/density-centric)

        Transit-Centric Policy
              |
    "Green    |    "Autonomous
     Transit  |     Transit Hub"
     City"    |
              |
  ————————————+————————————————
              |
    "Car      |    "Robot
     Status   |     Car
     Quo"     |     Paradise"
              |
        Car-Centric Policy
  Incremental AV          Breakthrough AV

Step 5: Build Scenario Narratives

Each quadrant becomes a detailed narrative — a story of how the world arrives at that state:

class Scenario:
    """A detailed scenario narrative."""

    def __init__(self, name: str, tagline: str):
        self.name = name
        self.tagline = tagline  # One-line summary
        self.narrative = ""  # Full story
        self.key_events = []  # Timeline of events
        self.implications = {}  # Implications by stakeholder
        self.early_indicators = []  # Signs this scenario is unfolding
        self.strategic_responses = []  # What to do if this happens

    def add_event(self, year: int, event: str, probability_driver: str):
        self.key_events.append({
            'year': year,
            'event': event,
            'driver': probability_driver
        })

    def add_implication(self, stakeholder: str, impact: str, severity: int):
        if stakeholder not in self.implications:
            self.implications[stakeholder] = []
        self.implications[stakeholder].append({
            'impact': impact,
            'severity': severity  # 1-5
        })


def build_scenario_set(axes: tuple, focal_question: str) -> list:
    """Build four scenarios from two axes."""
    axis1_name, axis1_poles = axes[0]
    axis2_name, axis2_poles = axes[1]

    scenarios = []
    quadrants = [
        (axis1_poles[0], axis2_poles[0]),
        (axis1_poles[0], axis2_poles[1]),
        (axis1_poles[1], axis2_poles[0]),
        (axis1_poles[1], axis2_poles[1])
    ]

    for pole1, pole2 in quadrants:
        scenario = Scenario(
            name=f"{pole1} + {pole2}",
            tagline=f"A world where {pole1.lower()} meets {pole2.lower()}"
        )
        scenarios.append(scenario)

    return scenarios

Step 6: Identify Early Indicators

For each scenario, define observable signals that would indicate it is beginning to unfold:

class EarlyIndicator:
    """An observable signal that a scenario is materializing."""

    def __init__(self, description: str, data_source: str,
                 threshold: str, scenario: str):
        self.description = description
        self.data_source = data_source
        self.threshold = threshold
        self.scenario = scenario
        self.current_status = "not_triggered"

    def check(self, current_data: dict) -> bool:
        """Check if this indicator has been triggered."""
        pass  # Implementation depends on data source


def create_indicator_dashboard(scenarios: list) -> dict:
    """Build a monitoring dashboard for all scenario indicators."""
    dashboard = {}
    for scenario in scenarios:
        dashboard[scenario.name] = {
            'indicators': scenario.early_indicators,
            'triggered_count': 0,
            'total_count': len(scenario.early_indicators),
            'probability_estimate': 0.25  # Start equal
        }
    return dashboard

The Cone of Plausibility

Visualizing the Future Space

The cone of plausibility expands from the present into the future, representing the widening range of possible outcomes:

Present                         Future
  |                              /
  |                            /   Possible (could happen)
  |                          /
  |                        / Plausible (could happen given trends)
  |                      /
  |                    / Probable (likely to happen)
  |                  /
  |                / Projected (baseline continuation)
  |              /
  |            /
  |          /
  |        /
  |      /
  |    /
  |  /
  |/
  Now        5 years        10 years       20 years
class ConeOfPlausibility:
    """Model the cone of plausibility for scenario planning."""

    def __init__(self, base_year: int, horizon_years: int):
        self.base_year = base_year
        self.horizon = horizon_years
        self.layers = {
            'projected': {'width_factor': 0.1, 'confidence': 0.8},
            'probable': {'width_factor': 0.3, 'confidence': 0.6},
            'plausible': {'width_factor': 0.6, 'confidence': 0.3},
            'possible': {'width_factor': 1.0, 'confidence': 0.1}
        }

    def get_range(self, variable: str, base_value: float,
                  year: int, layer: str = 'plausible') -> tuple:
        """Get the range of a variable at a future year."""
        years_out = year - self.base_year
        factor = self.layers[layer]['width_factor']
        spread = base_value * factor * (years_out / self.horizon) ** 0.5
        return (base_value - spread, base_value + spread)

    def classify_scenario(self, scenario_outcomes: dict,
                         base_values: dict) -> str:
        """Classify a scenario as projected/probable/plausible/possible."""
        for layer in ['projected', 'probable', 'plausible', 'possible']:
            all_in_range = True
            for var, value in scenario_outcomes.items():
                low, high = self.get_range(
                    var, base_values[var],
                    self.base_year + self.horizon, layer
                )
                if not (low <= value <= high):
                    all_in_range = False
                    break
            if all_in_range:
                return layer
        return 'impossible'

Wildcard Events

Identifying and Incorporating Wildcards

Wildcards are low-probability, high-impact events that can disrupt any scenario:

class WildcardEvent:
    """A low-probability, high-impact disruptive event."""

    def __init__(self, name: str, probability: float,
                 impact_magnitude: int, category: str):
        self.name = name
        self.probability = probability  # Annual probability
        self.impact_magnitude = impact_magnitude  # 1-10
        self.category = category
        self.affected_scenarios = []  # Which scenarios it disrupts
        self.cascade_effects = []  # Secondary effects

    @property
    def expected_impact(self) -> float:
        return self.probability * self.impact_magnitude


WILDCARD_CATALOG = [
    WildcardEvent("Major pandemic", 0.02, 9, "health"),
    WildcardEvent("Large asteroid impact", 0.0001, 10, "natural"),
    WildcardEvent("Global financial system collapse", 0.01, 8, "economic"),
    WildcardEvent("Breakthrough in fusion energy", 0.03, 8, "technology"),
    WildcardEvent("Superintelligent AI emergence", 0.01, 10, "technology"),
    WildcardEvent("Major volcanic eruption (VEI 7+)", 0.005, 9, "natural"),
    WildcardEvent("Global cyberattack on infrastructure", 0.03, 7, "security"),
    WildcardEvent("Collapse of major nation-state", 0.01, 7, "political"),
    WildcardEvent("Discovery of extraterrestrial life", 0.005, 6, "science"),
    WildcardEvent("Major climate tipping point crossed", 0.05, 8, "environment"),
]

Stress-Testing Against Wildcards

def stress_test_strategy(strategy: dict, scenarios: list,
                         wildcards: list) -> dict:
    """Test a strategy's resilience across scenarios and wildcards."""
    results = {
        'scenario_performance': {},
        'wildcard_vulnerability': {},
        'overall_robustness': 0.0
    }

    for scenario in scenarios:
        performance = evaluate_strategy_in_scenario(strategy, scenario)
        results['scenario_performance'][scenario.name] = performance

    for wildcard in wildcards:
        for scenario in scenarios:
            vulnerability = evaluate_wildcard_impact(
                strategy, scenario, wildcard
            )
            key = f"{scenario.name} + {wildcard.name}"
            results['wildcard_vulnerability'][key] = vulnerability

    # Overall robustness = worst-case performance
    all_scores = list(results['scenario_performance'].values())
    results['overall_robustness'] = min(all_scores) if all_scores else 0

    return results


def evaluate_strategy_in_scenario(strategy: dict, scenario) -> float:
    """Score a strategy's performance in a given scenario (0-1)."""
    # In practice, this involves detailed modeling
    return 0.5  # Placeholder


def evaluate_wildcard_impact(strategy: dict, scenario, wildcard) -> float:
    """Assess how a wildcard affects strategy performance in a scenario."""
    base = evaluate_strategy_in_scenario(strategy, scenario)
    # Wildcards degrade performance by their impact magnitude
    degradation = wildcard.impact_magnitude / 10.0
    return max(0, base - degradation * 0.5)

Practical Scenario Planning Workshop

Workshop Agenda (2-Day Format)

DAY 1: EXPLORATION
09:00 - 10:00  Focal question definition and alignment
10:00 - 12:00  Driving forces brainstorm (STEEP framework)
               - Individual brainstorm (15 min)
               - Small group clustering (45 min)
               - Full group prioritization (60 min)
12:00 - 13:00  Lunch
13:00 - 15:00  Impact/Uncertainty ranking
               - Dot voting on impact (30 min)
               - Dot voting on uncertainty (30 min)
               - Discussion and calibration (60 min)
15:00 - 17:00  Axis selection and scenario naming
               - Propose candidate axes (30 min)
               - Test combinations (30 min)
               - Select final 2x2 and name scenarios (60 min)

DAY 2: CONSTRUCTION
09:00 - 12:00  Scenario narrative development (4 breakout groups)
               - Each group develops one scenario
               - Timeline of key events
               - Day-in-the-life vignettes
               - Key data points and indicators
12:00 - 13:00  Lunch
13:00 - 14:30  Scenario presentations and cross-pollination
14:30 - 16:00  Strategic implications
               - What strategies work in all scenarios?
               - What are scenario-specific strategies?
               - What are the no-regret moves?
16:00 - 17:00  Early indicator identification and action planning

Facilitation Best Practices

  1. Suspend judgment: The goal is plausibility, not probability
  2. Name scenarios memorably: "Green Sprint" is better than "Scenario B"
  3. Avoid "good" and "bad" scenarios: Each should have both opportunities and threats
  4. Include diverse perspectives: Invite outsiders, young employees, contrarians
  5. Make it vivid: Use newspaper headlines, personal stories, data visualizations
  6. Connect to decisions: Every scenario should lead to "so what should we do?"
  7. Revisit regularly: Update scenarios annually or when major events occur

Scenario-Strategy Integration

The Wind-Tunneling Approach

Test each strategic option against all scenarios:

def wind_tunnel(strategies: list, scenarios: list) -> dict:
    """Wind-tunnel strategies against scenarios."""
    matrix = {}

    for strategy in strategies:
        matrix[strategy['name']] = {}
        for scenario in scenarios:
            score = evaluate_strategy_in_scenario(strategy, scenario)
            matrix[strategy['name']][scenario.name] = score

    # Identify robust strategies (perform well across all scenarios)
    robust = {}
    for strategy_name, scores in matrix.items():
        min_score = min(scores.values())
        max_score = max(scores.values())
        avg_score = sum(scores.values()) / len(scores)
        robust[strategy_name] = {
            'min': min_score,
            'max': max_score,
            'avg': avg_score,
            'range': max_score - min_score,
            'robustness': min_score  # Maximin criterion
        }

    return {
        'matrix': matrix,
        'robustness_ranking': sorted(
            robust.items(), key=lambda x: -x[1]['robustness']
        )
    }

No-Regret Moves

Identify actions that are beneficial across ALL scenarios:

No-regret moves (good in every scenario):
  - Build organizational agility
  - Invest in talent development
  - Diversify supplier base
  - Strengthen digital capabilities

Hedging moves (insurance against specific scenarios):
  - Maintain option on alternative technology
  - Build relationships in emerging markets
  - Develop contingency supply chains

Big bets (high payoff in one scenario, cost in others):
  - Go all-in on one technology platform
  - Major acquisition in a specific market
  - Complete business model pivot

Key Takeaways

  1. Scenario planning is not about predicting the future; it is about preparing for multiple plausible futures
  2. The value is in the process (expanding mental models) as much as the output (scenario documents)
  3. Two axes creating four scenarios is the sweet spot: enough variety, manageable complexity
  4. Predetermined elements (high impact, low uncertainty) appear in all scenarios and ground them in reality
  5. Early indicators convert scenarios from static documents into active monitoring systems
  6. Wind-tunneling strategies against scenarios reveals robust vs. fragile strategic options
  7. No-regret moves are the immediate action items; hedging moves and big bets require scenario monitoring
  8. Wildcard events should stress-test even the most carefully constructed scenarios

Install this skill directly: skilldb add prediction-skills

Get CLI access →