Skip to content

Voyager — Embodied skill-library agent

Skill-library self-evolution. Grow a library of executable skills from a curriculum, repairing failed programs from environment feedback. Runs through the shared MethodPolicy runner with self_verify on (the critic). Example: examples/voyager/voyager_skill_library.py.

Paper Voyager: An Open-Ended Embodied Agent with Large Language Models — Wang et al., 2023 (arXiv:2305.16291)
Upstream code MineDojo/Voyager@55e45a88
Example examples/voyager/voyager_skill_library.py
Domain deterministic crafting world — 48 recipe goals, 16/16/16 splits
Layer L1 (blast_radius=0.6, set by the shared runner)
Fidelity environment_analoguewhat the classes mean

This port is measured in the runtime matrix: the mechanism is preserved and measured under AgentDescent's runtimes; it is not a paper-benchmark reproduction.

The mechanism

Voyager grows an add-only library of executable skills (Chroma-indexed by description embedding, name collisions versioned, top-5 retrieval), driven by a generative curriculum that proposes novel frontier tasks from the agent's state. Failed programs are repaired from environment feedback, interpreter errors, and a separate GPT-4 critic's critique — up to four rounds, never from a gold program.

Where each piece lives

Upstream mechanism Where it lives here
Add-only skill library SkillLibrary: per-goal keys that accumulate and union-merge; the reusable placeholder skill evolves under the generic key
Repair from environment errors a deterministic crafting simulator reports the first failed step; that message is all the repair prompt sees
The critic the engine's self_verify rollout: every proposal re-runs and is judged by the environment reward
Curriculum at the frontier DifficultyWeighted sampling over the task pool

Boundaries

  • A deterministic crafting world replaces Minecraft.
  • Key-match retrieval replaces embedding retrieval.
  • The task pool + difficulty sampling is an analogue of the generative curriculum, which proposes novel tasks.

Measured results — crafting world

Three seeds, async_pipeline, 80 rollouts each, 8 workers, --staleness full, reflective merge off and self_verify on (both this method's own declaration — the library overwrites a key, so a synthesised merge would not be the algorithm), deepseek-v4-flash at temperature 0.7. Recorded in bench/results/voyager-skill-library.json.

seed test quality validation accepted calls
0 0.000 → 1.000 0.000 → 1.000 2/80 1207
1 0.000 → 1.000 0.000 → 1.000 1/80 1207
2 0.000 → 0.000 0.000 → 0.000 0/80 1287

Two seeds clear the world outright and one finds nothing. accepted is 2, 1 and 0 of eighty, which is the shape of the mechanism rather than an accident: every proposal is re-rolled by the critic before it reaches the gate, and one skill that works is all the run needs.

See the caveat on PromptBreeder: one run per seed does not pin a number here either.

Upstream's library overwrites; it is not add-only

SkillManager.add_new_skill prints "Skill {name} already exists. Rewriting!", deletes the vector-store entry and reassigns self.skills[program_name]. The older code is dumped to disk as {name}V2.js and retrieval never reads itretrieve_skills returns self.skills[...]["code"]. Versioned on disk and overwritten in memory are different libraries, and only the second one is the algorithm — which is also why this port declares reflective=False.

Seed 2 finds nothing, and the world is the reason to check first

What has to be discovered here is the sequence, which is the skill the paper is about — but a world that names none of its own vocabulary makes that undiscoverable rather than hard. Steps are matched on verb plus content: an argument the world never names is matched on the verb alone, and one that follows from the goal must contain it. Feedback separates a step that is absent from one that is late, because an agent told a step is missing writes another one and never reorders. Both were needed before any seed solved this world at all; one still does not.

Run it

python -m examples.voyager.voyager_skill_library --dry-run

# one seed of the three above
python -m examples.voyager.voyager_skill_library --yes --seed 0 \
    --provider openai --model deepseek-v4-flash \
    --async --async-ratio 1 --workers 8 --budget-rollouts 80 --staleness full \
    --temperature 0.7 --max-seconds 3600

--async-ratio 1 is what this row ran at: the flag was dropped before it reached the runtime, so the run took the runner's default whatever the command line said. It is passed explicitly here because the value matters and a default can move.

Flags: the MethodPolicy command line.

Offline tests: tests/test_voyager_upstream.py, tests/test_candidate_methods.py.