Skip to content

Submit to the Hub

The galapagos Hub is a registry for scaffold cards, task cards, and discoveries, with a leaderboard that exposes each row's review status. Everything bundled in the library mirrors to the Hub (library ⊆ hub). You contribute three kinds of artifact: a scaffold card, a task card, or a discovery (a claimed result for review).

1. Lay out the repo

A submission is a repo, HuggingFace-Hub-style: the folder that holds card.yaml. submit uploads card.yaml plus every file the card references — component file paths and any assets — so the Hub can serve the repo's files, not just a metadata stub. All referenced paths must live under the card's directory (no .. escapes or absolute paths).

my_task/
├── card.yaml            # the manifest (points at the files below)
├── initial_program.py   # components.initial_program (the seed)
├── evaluator.py         # components.evaluator
├── Dockerfile           # the task's environment — bundled automatically, and required
├── README.md            # bundled automatically if present
└── data/small/          # assets: [ "data/small/**" ]

Big datasets are not uploaded. Declare them under external_resources (a uri + sha256); the bytes stay on their own host (HF Datasets / S3 / GCS) and load_task() fetches them at load time. See Cards → Assets and external resources.

For scaffold repos, include any default config.yaml in assets if you want it uploaded; the current bundle collector does not include a sibling config file automatically unless the card references it as an asset or component file.

2. Preview the bundle

--dry-run validates the card against its pydantic schema and lists exactly what would be uploaded, without touching the network:

galapagos submit --repo-type task --card-path my_task/card.yaml --dry-run
# valid task card: my_task  (our_org/my_task)
# bundle → 5 files, 0.6 KiB
#     card.yaml  554 B
#     evaluator.py  52 B
#     initial_program.py  44 B
#     data/small/a.txt  3 B
#     README.md  10 B
# external_resources (declared; fetched at load, not uploaded): benchmark_data

The kind is auto-detected (a card with metric(s)/domain is a task) or set with --repo-type. An invalid card prints the error and exits non-zero.

3. Get a Hub token

Uploads require an Authorization: Bearer <token> header. Mint one from a running instance (in dev, issuance is open; in prod the request must carry a Bearer credential — a Supabase login token, or the hub admin token) and export it so the CLI picks it up:

# in prod, also pass the credential: -H "authorization: Bearer <supabase-login-or-admin-token>"
export GALAPAGOS_HUB_TOKEN=$(curl -sX POST https://open-galapagos.com/api/auth/token \
     -H 'content-type: application/json' -d '{"label":"me"}' \
     | python -c 'import sys,json; print(json.load(sys.stdin)["token"])')

4. Upload the repo

# task — uploads card.yaml + referenced files, and the repo appears on the website
galapagos submit --repo-type task --card-path my_task/card.yaml
# uploaded task our_org/my_task → https://open-galapagos.com/tasks/my_task

# scaffold — same command, kind auto-detected
galapagos submit --repo-type scaffold --card-path my_scaffold/card.yaml

Point at a self-hosted Hub with --hub-url (or $GALAPAGOS_HUB_URL). Under the hood the CLI POSTs a multipart bundle to /api/{kind}/upload; the Hub re-validates the card, stores the files, and catalogs a community row. It never imports your controller/evaluator — cards + files are inert data on the Hub.

Endpoint Body Purpose
POST /api/tasks/upload multipart bundle (card.yaml + files) upload a task repo (what galapagos submit uses)
POST /api/scaffolds/upload multipart bundle (card.yaml + files) upload a scaffold repo
POST /api/tasks / POST /api/scaffolds {"card_yaml": "..."} register a card only (no files — metadata stub)
POST /api/discoveries/upload multipart bundle (card.yaml + solution/trajectory) upload a discovery repo (lands pending)
POST /api/discoveries {"card_yaml": "..."} register a discovery card only
POST /api/discoveries/{name}/review {"status": "accepted"} review a discovery (pendingaccepted | rejected)
GET /api/tasks/{name}/tree · /raw?path= list + download a repo's files (open, no token)
GET /api/scaffolds / GET /api/tasks browse the catalog (open, no token)

Library cards (the bundled ones) cannot be overwritten — a community upload with a clashing name is rejected with 409. A scaffold card with a controller (a dotted Scaffold-subclass path) is catalogued as a runnable method; a status: spec card is published as a design entry. The browser Playground runs only bundled code: the live demo runs a fixed allowlist of bundled scaffolds (openevolve, topk, best_of_n, best_of_n_attempts) on the bundled circle_packing task, and the Discovery Space uses the scaffold/provider allowlist returned by /api/discovery/options and runnable compatible bundled tasks. claude_code and meta_harness are local-only because their defaults use Claude subscription authentication; neither hosted runner imports or runs submitted controllers. See Write your own scaffold and Write your own task for how to build the cards, and Submit a scaffold for a worked end-to-end repository submission.

Loading a submitted task

Once uploaded, anyone pulls the repo with GalapagosTask.from_card — it downloads the bundle into the local cache ($GALAPAGOS_CACHE_DIR, default ~/.cache/galapagos) and returns a task whose files are materialized on disk. Opt into separately hosted external_resources when the task declares them:

import galapagos as gx

task = gx.GalapagosTask.from_card(
    "our_org/my_task", download_external=True
)                                             # bundled/local -> cache -> Hub
task.root                                     # the materialized repo dir
task.initial_program_source                   # the seed program's text
task.evaluator                                # the deterministic scorer

gx.GalapagosTask.from_card("our_org/my_task", local_path="./my_task")
gx.GalapagosTask.from_card("our_org/my_task", source="hub")  # always re-fetch

The default source="auto" reaches the network only once: a repo already in the cache is reused as is. source="local" restricts resolution to cards bundled in the wheel and raises for a Hub repo like our_org/my_task; source="hub" forces a fresh download over the cached copy. gx.load_task() remains a compatibility wrapper and fetches external_resources by default.

Hub scaffold repos are browsable and downloadable through the Hub file endpoints, but gx.load_scaffold("org/name") does not yet download scaffold repos into the cache. Today, load a submitted scaffold by installing/importing its controller package or by materializing the repo yourself and passing path=".../card.yaml".

5. Submit a discovery

The interesting submission is a discovery: you ran a scaffold (or an agent) on a task and found a solution worth a place on the leaderboard. That goes through the discovery repo — a bundle of card.yaml + the best solution + the run trajectory, uploaded with POST /api/discoveries/upload (or registered card-only via POST /api/discoveries with {"card_yaml": ...}). It lands pending; a reviewer flips it with POST /api/discoveries/{name}/review (pending → accepted | rejected) — accepting creates or updates the leaderboard entry from the submitted claim. The endpoint does not itself replay the trajectory or re-score the solution.

There is currently no discovery mode in galapagos submit; use the API directly or the browser Discovery Space, whose completed runs are published by the backend.

For a current ETIF run, the trajectory portion contains one trajectory/evolutionary_trajectory.jsonl stream. It contains candidate creation alongside evaluator failures, migration, crossover, adaptation, model/agent/tool activity, checkpoints, and final evaluation. Tool-enabled local runs additionally keep their tool-only ledger and cumulative checkpoint snapshots as operational artifacts.

A lightweight claim can also be filed as a VerificationCard via POST /api/verifications; it is always stored unverified and browsable via GET /api/verifications, with no review transition or leaderboard linkage. Validate it locally first, then POST it as a JSON object:

# my_discovery.yaml — the VerificationCard
task: circle_packing
scaffold: openevolve          # the scaffold OR `agent:` that produced it
submitter: you@example.com
claimed_score: 2.634
best_solution: best_program.py     # inline code, or a path/URI
trajectory: runs/openevolve/circle_packing/2026-06-08/   # the full discovery trajectory
notes: "100 iterations, gpt-5.5 via OpenRouter; reproduces best_known."
# the verifications endpoint takes the card as a JSON object (not raw YAML)
curl -X POST https://open-galapagos.com/api/verifications \
     -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
     -d "$(python -c 'import json,yaml; print(json.dumps(yaml.safe_load(open("my_discovery.yaml"))))')"
Field Meaning
task the task the discovery is on
scaffold / agent what produced it (one of the two)
claimed_score the score you are claiming
best_solution the discovered artifact (inline or a path)
trajectory path/URI to the full discovery trajectory (for reproducibility)
notes free-form reproduction notes

The submitter never sets their own initial review state: a verification always lands unverified regardless of what the card says, and a discovery repo lands pending. A reviewer may promote it to accepted or mark it rejected. Every entry appears with its review status. The current backend records that decision but does not enforce who performed the review or which reproduction checks were run, so review policy must be applied operationally.

The leaderboard

The Hub ranks entries by their submitted score, highest first (ties broken by recency). Scores are self-reported at submission time. An accepted badge records a review decision; it does not prove that the backend automatically reproduced the score. Compare entries within a single task and apply the deployment's review policy when interpreting them. Browse it filtered by task or scaffold:

curl "https://open-galapagos.com/api/leaderboard?task=circle_packing"

A leaderboard entry is submitted (with a token) via POST /api/leaderboard and lands pending; a reviewer flips it with POST /api/leaderboard/{id}/verify (pending → accepted | rejected); the board lists every entry with its status badge.

See The Hub for running a Hub instance locally and the full endpoint summary.