Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/skydiscover-ai/skydiscover/llms.txt

Use this file to discover all available pages before exploring further.

Get your first AI-driven discovery running in minutes with this step-by-step guide.

Prerequisites

  • Python 3.10 or higher (3.10-3.13 supported)
  • uv package manager (recommended) or pip
  • LLM API key (OpenAI, Gemini, Claude, or local model)

Quick Setup

1

Install SkyDiscover

Install the base package with uv:
git clone https://github.com/skydiscover-ai/skydiscover.git
cd skydiscover
uv sync
Or install specific extras:
# For math benchmarks
uv sync --extra math

# For multiple extras
uv sync --extra math --extra adrs
2

Set up API key

Export your LLM API key:
export OPENAI_API_KEY="sk-your-key-here"
3

Run your first discovery

Try the circle packing example (requires --extra math):
uv run skydiscover-run \
  benchmarks/math/circle_packing/initial_program.py \
  benchmarks/math/circle_packing/evaluator.py \
  --config benchmarks/math/circle_packing/config.yaml \
  --search adaevolve \
  --iterations 100
Iteration 1/100: Best score = 2.103
Iteration 5/100: Best score = 2.267
Iteration 10/100: Best score = 2.412
...
Iteration 100/100: Best score = 2.621

Best solution saved to: outputs/circle_packing_adaevolve_20260305_123456/best_solution.py
Final score: 2.621 (target: 2.635 from AlphaEvolve)

Understanding the Example

The Circle Packing Problem

The circle packing problem asks: What’s the optimal arrangement of n circles of diameter 1 in a unit circle?

Initial Program

The starting solution uses a constructor-based approach:
initial_program.py
import numpy as np

# EVOLVE-BLOCK-START
def generate_circle_packing(n):
    """Generate n circle positions within a unit circle."""
    theta = np.linspace(0, 2*np.pi, n, endpoint=False)
    r = 0.3  # Initial radius for positioning
    positions = np.array([[r*np.cos(t), r*np.sin(t)] for t in theta])
    return positions
# EVOLVE-BLOCK-END

if __name__ == "__main__":
    positions = generate_circle_packing(26)
    np.save("positions.npy", positions)
The EVOLVE-BLOCK markers tell SkyDiscover which region to optimize. Everything outside remains unchanged.

Evaluator Function

The evaluator scores how tightly circles can be packed:
evaluator.py
import numpy as np

def evaluate(program_path):
    """Score a circle packing solution."""
    # Execute the program
    exec(open(program_path).read(), globals())
    
    # Load positions
    positions = np.load("positions.npy")
    n = len(positions)
    
    # Calculate minimum pairwise distance
    min_dist = float('inf')
    for i in range(n):
        for j in range(i+1, n):
            dist = np.linalg.norm(positions[i] - positions[j])
            min_dist = min(min_dist, dist)
    
    # Score = diameter of packed circles
    # Higher is better (tighter packing)
    score = min_dist
    
    return {
        "combined_score": score,
        "artifacts": {
            "min_distance": min_dist,
            "num_circles": n
        }
    }

How Evolution Works

  1. Iteration 1: SkyDiscover runs the initial program and evaluates it
  2. Iteration 2-100: The LLM proposes improvements to the generate_circle_packing function
  3. Selection: AdaEvolve uses adaptive strategies to select which programs to evolve
  4. Evaluation: Each new program is scored by the evaluator
  5. Best tracking: The highest-scoring solution is saved

Try Your Own Problem

Option 1: Start from Scratch

Let the LLM generate a solution from just an evaluator:
uv run skydiscover-run evaluator.py \
  --search evox \
  --model gpt-5 \
  --iterations 50

Option 2: Python API

Use SkyDiscover programmatically:
from skydiscover import run_discovery

result = run_discovery(
    evaluator="evaluator.py",
    initial_program="initial_program.py",
    search="adaevolve",
    model="gpt-5",
    iterations=100
)

print(f"Best score: {result.best_score}")
print(f"Best solution:\n{result.best_solution}")

Option 3: Custom Evaluator

Create a custom optimization problem:
my_evaluator.py
def evaluate(program_path):
    # Run your custom test suite
    score = run_tests(program_path)
    
    return {
        "combined_score": score,
        "artifacts": {
            "tests_passed": 42,
            "performance_ms": 123
        }
    }
Then run:
uv run skydiscover-run my_evaluator.py \
  --search adaevolve \
  --iterations 100

Choose a Search Algorithm

Different algorithms work better for different problems:

AdaEvolve

Best for: Most problemsAdaptive multi-island search with UCB selection and paradigm breakthroughs

EvoX

Best for: Complex landscapesSelf-evolving algorithm that adapts its own strategy

Beam Search

Best for: Discrete decisionsMaintains multiple candidate solutions in parallel

Top-K

Best for: Quick experimentsSimple greedy selection of top performers

Common Workflows

If a run is interrupted, resume from the last checkpoint:
uv run skydiscover-run evaluator.py \
  --checkpoint outputs/my_run_20260305_123456/checkpoint_50 \
  --iterations 100
Distribute load across multiple LLMs:
uv run skydiscover-run evaluator.py \
  --model "gpt-5,gemini/gemini-3-pro-preview" \
  --iterations 100
Or configure in YAML:
llm:
  models:
    - name: "gpt-5"
      weight: 0.7
    - name: "gemini/gemini-3-pro-preview"
      weight: 0.3
Add to your config or command line:
config.yaml
monitor:
  enabled: true
  host: "0.0.0.0"
  port: 8080
Then visit http://localhost:8080 to see:
  • Real-time scatter plot of all programs
  • Code diffs and metrics
  • Progress charts
  • AI-generated summaries
Let the LLM read and modify multiple files:
uv run skydiscover-run initial_program.py evaluator.py \
  --agentic \
  --search adaevolve \
  --iterations 100
The LLM can now read any file in your codebase and make coordinated changes across multiple files.

Next Steps

Core Concepts

Learn how SkyDiscover works under the hood

Writing Evaluators

Best practices for creating effective scoring functions

Browse Examples

Explore math, systems, and algorithm optimization examples

Configuration Guide

Advanced configuration options and YAML reference

Troubleshooting

Make sure you’ve exported your API key:
export OPENAI_API_KEY="sk-..."
Or pass it via config:
llm:
  models:
    - name: "gpt-5"
      api_key: "sk-..."
Install the required extras for your benchmark:
uv sync --extra math  # For math benchmarks
uv sync --extra adrs  # For systems benchmarks
Reduce iteration frequency or use multiple models:
llm:
  models:
    - name: "gpt-5-mini"
      weight: 0.8
    - name: "gpt-5"
      weight: 0.2

Build docs developers (and LLMs) love