Get started with AlphaEvolve on Google Cloud

1. Introduction

In this codelab, you run your first two AlphaEvolve experiments on Google Cloud. AlphaEvolve is Google DeepMind's AI-guided evolutionary coding framework: it uses Gemini to write and improve code, scored by a metric you define. You start with circle packing — a small geometry problem where you can literally watch the result get better — then repeat on a harder Travelling Salesman Problem so the pattern sticks.

Both experiments use local evaluation — the candidate code runs on your own machine, so there is no GPU and no cluster to manage. The only cloud usage is the AlphaEvolve API that generates candidates.

AlphaEvolve local loop: the AlphaEvolve agent, on Gemini Enterprise in Google Cloud, generates candidate programs; your machine's evolution loop (run_evolution.py) acquires them with acquire_programs(), scores each in a local exec() sandbox with evaluate.py, and returns scores with submit_program_evaluations().

What you'll do

  • Configure an AlphaEvolve experiment against your Google Cloud project
  • Run an evolutionary search that improves a circle-packing algorithm locally
  • Read the score, ranking, and visualization of the best evolved program
  • Repeat the loop on a Travelling Salesman Problem to generalize the pattern
  • Tune the search budget (candidates, concurrency, model)

What you'll need

  • A web browser such as Chrome
  • A Google Cloud project with billing enabled
  • Python 3.9 or later and uv
  • Basic familiarity with Python and the command line

This codelab is for AI/ML engineers and developers of all levels. No evolutionary-computation background is required.

Estimated time to complete: 45–60 minutes.

Cost: this codelab uses local evaluation (no GPU, no GKE). The only charge is AlphaEvolve API usage for generating candidates.

Tested with: the AlphaEvolve Cloud client library v0.1.0, Python 3.9+, on the circle_packing and tsp examples.

2. Before you begin

Select your project and enable the API

  1. In the Google Cloud Console, select or create a project with billing enabled, then set it in your terminal:
gcloud config set project <YOUR_PROJECT_ID>
  1. Enable the Discovery Engine API, which serves AlphaEvolve:
gcloud services enable discoveryengine.googleapis.com

Find your Gemini Enterprise app ID

AlphaEvolve is served via Gemini Enterprise (the underlying REST surface is the Discovery Engine API). You need your app's ID — not its display name — for the GE_APP_ID setting.

  1. Open the Gemini Enterprise apps page for your project.
  2. Click your app and copy the ID field (for example, gemini-enterprise-1234567890_1234567890123).

Authenticate, clone, and install

  1. Authenticate for application-default credentials:
gcloud auth application-default login
  1. Clone the samples repo and open it. You'll run every command from this repo root:
git clone https://github.com/Google-Cloud-AI/alphaevolve-on-googlecloud.git
cd alphaevolve-on-googlecloud
  1. Create a virtual environment and install the AlphaEvolve client library into it:
uv venv
uv pip install -e ".[dev]"

uv venv creates a .venv in the repo; uv pip install -e ".[dev]" installs the alpha_evolve package (editable) plus test tools. You'll launch experiments with uv run, which uses this environment automatically.

3. Understand the AlphaEvolve loop

Before running anything, understand the three pieces AlphaEvolve needs. This is the mental model you'll reuse for every experiment.

The seed program and the EVOLVE-BLOCK

AlphaEvolve only rewrites the code between two markers. Everything else in the file is fixed scaffolding it cannot touch. Open examples/circle_packing/src/program.py — the seed is a simple concentric-ring packing:

# EVOLVE-BLOCK-START
"""Constructor-based circle packing for n=26 circles"""
import numpy as np


def construct_packing(n, random_seed: int):
    """Construct an arrangement of 26 circles in a unit square.

    The goal is to maximize the sum of their radii.
    Returns (centers, radii, sum_of_radii).
    """
    rng = np.random.default_rng(random_seed)
    centers = np.zeros((n, 2))

    # A simple starting pattern — evolution will improve this.
    centers[0] = [0.5, 0.5]                      # one circle in the center
    for i in range(8):                           # 8 in an inner ring
        angle = 2 * np.pi * i / 8
        centers[i + 1] = [0.5 + 0.3 * np.cos(angle), 0.5 + 0.3 * np.sin(angle)]
    for i in range(16):                          # 16 in an outer ring
        angle = 2 * np.pi * i / 16 * rng.uniform(0.9, 1.1)
        centers[i + 9] = [0.5 + 0.7 * np.cos(angle), 0.5 + 0.7 * np.sin(angle)]

    centers = np.clip(centers, 0.01, 0.99)       # keep everything in the square
    radii = compute_max_radii(centers, random_seed)
    return centers, radii, np.sum(radii)


def compute_max_radii(centers, random_seed: int):
    """Grow each circle to touch its nearest border or neighbor (no overlaps)."""
    # ... see src/program.py for the full helper ...
# EVOLVE-BLOCK-END

Everything outside EVOLVE-BLOCK-START / EVOLVE-BLOCK-END — including the evaluate() function and the overlap checks — stays frozen. That separation is the whole trick: Gemini can propose any packing algorithm it likes, but it cannot change how a candidate is scored.

The evaluator and the score

examples/circle_packing/src/evaluate.py runs each candidate in a sandbox and returns a score. For circle packing the metric is sum_of_radii, and higher is better:

CIRCLE_PACKING_EVALUATION_METRIC = "sum_of_radii"
CIRCLE_PACKING_EVALUATION_INPUTS = {"n": 26}

If a candidate breaks a rule — circles overlap or leave the square — the evaluator returns -inf plus an insight explaining what went wrong. Those insights feed back to Gemini so the next generation avoids the same mistake.

4. Run your first experiment

Configure the experiment

From the repo root, create your .env from the circle-packing template:

cp examples/circle_packing/example.env .env

Open .env and set just your project and app ID — everything else has working defaults for a first run:

PROJECT_ID=<YOUR_PROJECT_ID>
GE_APP_ID=<YOUR_GEMINI_ENTERPRISE_APP_ID>

The defaults generate candidates with a Gemini model mixture (MODEL_1=gemini-3.5-flash at weight 0.7, MODEL_2=gemini-3.1-pro-preview at 0.3) and cap the search at MAX_PROGRAMS_EVALUATED=10 with CONCURRENCY=4 — enough to watch the loop work quickly.

Start the evolution

Run the experiment from the repo root:

uv run python -m examples.circle_packing.src.run_evolution

This uploads the seed program, starts the search, and runs the local control loop until 10 candidates have been evaluated. Because you're calling the module directly (no wrapper), you can see exactly what runs — and edit the file to experiment.

You should see output similar to:

INFO:alpha_evolve.experiment:Creating a new AlphaEvolve experiment
INFO:alpha_evolve.controller:Evolution loop started: 4 sampler(s), 32 evaluator(s), target=10 programs
INFO:alpha_evolve.controller:Waiting for the backend to generate candidates... (generated=0, evaluated=0/10, idle=10s)
INFO:alpha_evolve.workers:Candidate 1060655338894100 evaluated → sum_of_radii=0.8114
INFO:alpha_evolve.controller:Progress: generated=2, evaluated=1/10, queued=0
...
INFO:alpha_evolve.controller:Stopping criteria met (10/10 programs evaluated).

Early candidates typically score in the 0.8–1.0 range; the search improves from there. When the loop finishes, it prints the ranked programs and renders the top packings with matplotlib.

Note: Troubleshooting: PERMISSION_DENIED or 403 usually means the Discovery Engine API is not enabled on the project. Re-check the "Before you begin" step. A run that ends immediately with "Failed to create experiment" means the credentials or GE_APP_ID in .env are wrong.

5. Read the results

The run prints the top programs ranked by sum_of_radii (higher is better). Two things to look for:

  • The score went up. The best evolved sum_of_radii should beat the seed's concentric-ring layout. Gemini typically discovers that circles near the corners and edges can grow larger, and rebalances the interior.
  • Invalid candidates are skipped. Any program that produced overlapping or out-of-bounds circles scored -inf and is skipped in the ranking — that's the constraint feedback working, not an error.

You now have the full loop: seed -> generate -> evaluate -> score -> repeat. Everything else in AlphaEvolve is a variation on where the evaluation runs.

6. Evolve a real search: TSP

Circle packing converges fast. To feel the search work on a meatier problem, evolve a Travelling Salesman Problem heuristic. The pattern is identical — only the seed and the metric change, and the TSP example reuses your .env (project, budget, and concurrency).

  1. Bump the budget in .env so the longer search has room to improve:
# in .env — raise the generation cap and the evaluation target together
MAX_PROGRAMS_GENERATED=20
MAX_PROGRAMS_EVALUATED=20
  1. Run it from the repo root:
uv run python -m examples.tsp.src.run_evolution

The seed here is a nearest-neighbor tour over 50 cities; the metric is neg_tour_length (negative average tour length across 5 fixed instances, so higher is better). Open examples/tsp/src/program.py and note that only construct_tour(distances, n) is inside the EVOLVE-BLOCK.

The two problems are the same pattern with different pieces:

Problem

Language

Evaluation

Metric (higher is better)

What evolves

circle_packing

Python

local exec()

sum_of_radii

construct_packing()

tsp

Python

local exec()

neg_tour_length

construct_tour()

As the search runs, watch neg_tour_length climb (get closer to zero) as Gemini moves beyond nearest-neighbor toward 2-opt / or-opt-style improvements — strategies you did not write.

7. Tune the search

Now that both runs work, tune the budget in .env:

  • MAX_PROGRAMS_EVALUATED — how many candidates to score. More candidates = a deeper search and higher cost/time.
  • CONCURRENCY — how many candidates are generated in flight at once.
  • MODEL_1 / MODEL_2 (with MODEL_1_WEIGHT / MODEL_2_WEIGHT) — the weighted mixture of Gemini models that generate candidates in the circle-packing run (the TSP module reads a single MODEL instead). Allowed values are gemini-3.5-flash and gemini-3.1-pro-preview. Shift weight toward the stronger model to find better programs in fewer generations.

Re-run with uv run python -m examples.circle_packing.src.run_evolution (or the tsp module) after each change.

Note: Raising MAX_PROGRAMS_EVALUATED and switching to a larger model both increase cost. Because this codelab uses local evaluation there is no GPU charge, but you still pay for AlphaEvolve API usage per generated candidate. Start small.

8. Clean up

This codelab uses local evaluation, so there is nothing billable left running — no clusters, no GPUs, no deployed services. To fully reset your checkout:

git clean -xfd   # removes .env, .venv, and generated outputs

Note: git clean -xfd deletes your .env (including your project settings) and the .venv. Skip it if you want to keep experimenting.

If you created a project only for this codelab, delete it in the Console to stop all charges.

9. Congratulations

Congratulations! You ran your first AlphaEvolve experiments on Google Cloud and evolved two algorithms — a circle packing and a TSP heuristic — using nothing but a seed program, a scoring function, and Gemini.

What you've learned

  • How AlphaEvolve's loop works: seed -> generate -> evaluate -> score -> repeat
  • The EVOLVE-BLOCK contract that lets the search optimize a recipe without gaming the metric
  • How scores and failure insights steer the next generation
  • How to configure, run, read, and tune a local-evaluation experiment

Other codelabs

These are standalone — do them in any order.

  • Evolve compiled code with a remote evaluator: evolve a Rust/C++ algorithm scored by a containerized evaluator on Cloud Run.
  • Evolve LLM fine-tuning on GKE + Ray: run heavy, parallel GPU evaluations on your own cluster.

Reference docs