alfworldpythonverified

alfworld household skill

Six task-level household skills (pick, clean, heat, cool, examine-in-light, pick-two) over a fixed action layer with an object-location memory; one call per task.

rec_3cb33e42fc984a789c990fbdb8b63944 · banked 2026-09-04 · by neruva
SKILL.md
Not yet certified

This skill has no published checker, so its evidence cannot be reproduced from here.

Evidence

  • ratchet check 11/12 train games; generality gate 12/12 held-out train games; forged by claude-sonnet-5 for $0.52 from 24 train games
  • ALFWorld valid_unseen, all 134 games: deepseek-chat + rungs 134/134, 1.05 model turns/game, 0 execution errors, $0.04 total; SKILL-DISCO best row 99.3 at 3.2 turns (GPT-4o)
  • requires scripts/primitives.py and scripts/priors.py from the alfworld-household skill folder

Use it

# in Claude Code (MCP tools from neruva-mcp)
rung_search(q="alfworld_household_rungs")
rung_install(id="rec_3cb33e42fc984a789c990fbdb8b63944", dir="~/.claude/skills")
# the skill folder is now loaded like any other skill

Usage guide

What the model reads to call the skill. This is the whole interface.

Show the guide
Skill library usage guide (ALFWorld)

Import: the module is already imported for you with `World` and `search_order`
bound. Call the functions with a live `w = World(game)` instance and TYPE
name strings (lowercase, singular, as they literally appear in the game,
e.g. 'apple', 'countertop', 'desklamp', 'sinkbasin', 'microwave', 'fridge').
Do NOT pass instance names like 'apple 1' — the skills find and pick the
concrete instance for you. Every function returns True/False for success.

1) pick_and_place(w, obj, dest)
   "put a <obj> in/on <dest>"
   e.g. task "put a pillow on the sofa" -> pick_and_place(w, 'pillow', 'sofa')

2) clean_and_place(w, obj, dest)
   "put a clean <obj> in/on <dest>" / "clean some <obj> and put it in <dest>"
   e.g. task "put a clean lettuce in diningtable"
        -> clean_and_place(w, 'lettuce', 'diningtable')

3) heat_and_place(w, obj, dest)
   "heat some <obj> and put it in/on <dest>" / "put a hot <obj> in <dest>"
   e.g. task "heat some egg and put it in garbagecan"
        -> heat_and_place(w, 'egg', 'garbagecan')

4) cool_and_place(w, obj, dest)
   "cool some <obj> and put it in/on <dest>" / "put a cool <obj> in <dest>"
   e.g. task "cool some potato and put it in microwave"
        -> cool_and_place(w, 'potato', 'microwave')

5) examine_in_light(w, obj, lamp)
   "look at <obj> under the <lamp>" / "examine the <obj> with the <lamp>"
   lamp is usually 'desklamp' or 'floorlamp'.
   e.g. task "examine the book with the desklamp"
        -> examine_in_light(w, 'book', 'desklamp')

6) pick_two_and_place(w, obj, dest)
   "put two <obj> in/on <dest>" / "find two <obj> and put them in <dest>"
   e.g. task "put two cds in safe" -> pick_two_and_place(w, 'cd', 'safe')

Mapping task sentences to type names:
- Strip articles ("a", "an", "the", "some") and pluralization ("two cds" ->
  obj='cd", use pick_two_and_place).
- Words like "clean", "hot"/"heated", "cold"/"cooled"/"chilled" signal which
  wrapper to use (clean_and_place / heat_and_place / cool_and_place);
  otherwise plain placement is pick_and_place.
- "examine"/"look at ... under/with the <lamp>" signals examine_in_light,
  with the lamp type taken from the sentence (desklamp/floorlamp).
- dest/obj/lamp must be the bare noun exactly as ALFWorld names it
  (e.g. 'sidetable', 'coffeetable', 'garbagecan', 'sinkbasin').

Code

176 lines of python, hashed and signed below.

Show the code
"""Task-level skills built on top of primitives.World.

Each function below performs one ALFWorld task type end-to-end using only
World's verbs (go/open/close/take/put/clean/heat/cool/use/examine) and
queries (objects_here/receptacles_of/instances_of/receptacles), plus the
externally supplied `search_order(obj_type, receptacles)` prior that orders
receptacle types by how likely they are to hold a given object type.

No task logic (search order, plans) lives in primitives.py; it all lives here.
"""

from __future__ import annotations


# ---------------------------------------------------------------------------
# internal helpers
# ---------------------------------------------------------------------------

def _refresh(w, recep):
    """Go to a receptacle, opening it if it's closed. Returns the obs text."""
    obs = w.go(recep)
    if w.is_closed_here(obs):
        obs = w.open(recep)
    return obs


def _locate_next(w, obj_type, visited, taken=()):
    """Find one instance of obj_type not already in `taken`.

    First re-checks whatever receptacle we are currently standing at (cheap,
    handles the case where two instances of obj_type sit on the same
    receptacle), then walks search_order(obj_type, ...) skipping receptacles
    already in `visited`. Mutates `visited` in place. Returns
    (instance_name, receptacle_name) or (None, None).
    """
    if w.at:
        items = w.objects_here()
        insts = [i for i in w.instances_of(obj_type, items) if i not in taken]
        if insts:
            return insts[0], w.at

    for recep in search_order(obj_type, w.receptacles):
        if recep in visited:
            continue
        visited.add(recep)
        _refresh(w, recep)
        items = w.objects_here()
        insts = [i for i in w.instances_of(obj_type, items) if i not in taken]
        if insts:
            return insts[0], recep
    return None, None


def _take(w, inst, recep):
    """Take inst from recep; returns True if now holding it."""
    w.take(inst, recep)
    return w.holding == inst


def _place(w, inst, dest_type):
    """Try to put the held instance onto/into some instance of dest_type."""
    for d in w.receptacles_of(dest_type):
        obs = w.go(d)
        if w.is_closed_here(obs):
            obs = w.open(d)
        obs = w.put(inst, d)
        if obs and ("you put" in obs.lower() or "you move" in obs.lower()):
            return True
    return False


def _find_and_take(w, obj_type, visited, taken=()):
    inst, recep = _locate_next(w, obj_type, visited, taken)
    if not inst:
        return None
    if not _take(w, inst, recep):
        return None
    return inst


# ---------------------------------------------------------------------------
# entry points
# ---------------------------------------------------------------------------

def pick_and_place(w, obj, dest):
    visited = set()
    inst = _find_and_take(w, obj, visited)
    if not inst:
        return False
    return _place(w, inst, dest)


def clean_and_place(w, obj, dest):
    visited = set()
    inst = _find_and_take(w, obj, visited)
    if not inst:
        return False

    sinks = w.receptacles_of("sinkbasin")
    if not sinks:
        return False
    sink = sinks[0]
    obs = w.go(sink)
    if w.is_closed_here(obs):
        w.open(sink)
    w.clean(inst, sink)

    return _place(w, inst, dest)


def heat_and_place(w, obj, dest):
    visited = set()
    inst = _find_and_take(w, obj, visited)
    if not inst:
        return False

    microwaves = w.receptacles_of("microwave")
    if not microwaves:
        return False
    m = microwaves[0]
    obs = w.go(m)
    if w.is_closed_here(obs):
        w.open(m)
    w.heat(inst, m)

    return _place(w, inst, dest)


def cool_and_place(w, obj, dest):
    visited = set()
    inst = _find_and_take(w, obj, visited)
    if not inst:
        return False

    fridges = w.receptacles_of("fridge")
    if not fridges:
        return False
    f = fridges[0]
    obs = w.go(f)
    if w.is_closed_here(obs):
        w.open(f)
    w.cool(inst, f)

    return _place(w, inst, dest)


def examine_in_light(w, obj, lamp):
    visited = set()
    inst = _find_and_take(w, obj, visited)
    if not inst:
        return False

    linst, lrecep = _locate_next(w, lamp, visited)
    if not linst:
        return False

    w.go(lrecep)
    w.use(linst)
    return w.won


def pick_two_and_place(w, obj, dest):
    visited = set()
    taken = []

    for _ in range(2):
        inst, recep = _locate_next(w, obj, visited, tuple(taken))
        if not inst:
            break
        if not _take(w, inst, recep):
            continue
        if _place(w, inst, dest):
            taken.append(inst)

    return len(taken) >= 2

Certificate

Code sha256 ea20b1c3a3f2f990c282e7eb9f8f6d4c2ac3b5716022cb1fd06a90b8337bcf58
Signature ed25519, present
Last re-checked
passing

Re-checked today. The signature was recomputed from the code served by the API, and the certificate matched.

A certificate proves the code has not changed. Re-running the check proves it still works today, on today's libraries.