Repository navigation
feat(bundle): run a bundle from the Hugging Face Hub with agent-env run hf:// - #460
Open
earakely-scale wants to merge 13 commits into
Open
earakely-scale wants to merge 13 commits into
earakely-scale wants to merge 13 commits into
Conversation
…un hf:// Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… against a pinned public dataset Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ass, which 2.x bases on httpx2 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pe, check a Hub bundle's plugins in OpenEnv, and take an unlistable parent as written Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
verifiers main removed the eval's platform push (PrimeIntellect-ai/verifiers#3046), and with it the --no-push flag, which its config now rejects as an extra input. 0.4.0 still pushes by default, so the taskset test passes --no-push only when vf-eval --help lists it: both the pinned and the main jobs run the same test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… show the card's setup only for what setup fixes, and group missing store entities The plan raises NotInStore (a BundleError carrying the missing agents, envs and artifacts) when the store lacks one, and preflight does for a missing default agent; the run attaches the card's setup command only to that or to UnmetRequirements. Each missing entity is one problem at its first use, with how many more use it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…main removed vf-eval verifiers main removed vf-eval (PrimeIntellect-ai/verifiers#2610) for vf-run, which takes the same config, saves the traces and exits non-zero when an episode isn't ok, as the masked row is. The test uses vf-eval when it's on PATH, as on 0.4.0, with --no-push after the config when its help names it, and vf-run otherwise, then judges both by the traces; the workflow puts whichever of the two the installed verifiers has on PATH. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dle may declare, type the ledger's namespace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…b commits are kept under Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, stored with each run as before Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d its id root A bundle outside bundles/ was looked up in the card by its last folder name, so /a/x and /b/x shared a table while their ids differed; both now use its path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and the download, checking requirements on every fetch fetch_bundle now checks what the bundle requires on every call, a cached commit included, and adds the card's setup note itself, so HubBundle.check_plugins and its two callers go, and agent-env run has one offer_to_install path with locate_bundle inside its try. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…field comments, shorter docstrings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FD-4352 (M4.4).
agent-env run hf://<org>/<repo>[@<revision>][/<path>]runs an AgentEnv bundle straight from a Hugging Face Hub dataset repo, asagent-env runruns a folder, with nothing installed beyondpip install agentenv-framework.What it does
/, as the Hub's ownhf://paths takerefs%2Fpr%2F3) becomes a commit sha throughHfApi.repo_info(repo_type="dataset"). Gated and private repos go through huggingface_hub's own login; a repo the Hub won't serve fails with the Hub's message and a note tohf auth loginor setHF_TOKEN./<path>if given; else the only folder underbundles/, or the one the card'sagentenv: defaultnames (several with no default stop with thehf://reference of each); else the repo root when it has a kind folder.bundles/comes before the root, so a dataset with a roottasks/of parquet files (the plugin's publish layout, GridSimEnv-AgentEnv) runs the bundle underbundles/.README.md, at the sha, into a plain folder$XDG_CACHE_HOME/agentenv/hf/<org>/<repo>/<sha>(~/.cachewhen unset or relative), no Hub-cache links. The commit's file list and the bundles downloaded are kept in.cache/agentenv/commit.jsonthere, so a later run of the commit downloads nothing: a reference pinned to the sha makes no network call at all, and a branch or tag costs onerepo_info. Commands on the same commit take a lock on it (holding_locks) while they list, download and record.bundle.tomlas today; a bundle without one requires the plugins the card'sagentenv: bundles: <name>: pluginslists, refused with theagent-env plugin add '<spec>'line (and, in a terminal, the same offer to install asbundle.tomlgets). The card'ssetupis shown only when setting up could fix the refusal (see below), never run. A card whoseagentenv: bundlesentry has the wrong shape is refused naming the field.run_bundlewith id root@hf/<org>/<repo>, plus/<name>for a bundle underbundles/(a/<path>elsewhere roots at@hf/<org>/<repo>/<path>). The revision is not in the id: a rerun of the commit reuses what the last one wrote, and a new commit writes new versions of the same entities.<org>/<repo> at <sha12>, bundle <path>; each task run's context carriesmetadata["bundle_source"] = {hub, repo, revision, sha, path}, stored with the instance, and the summary prints it (From <org>/<repo> at <sha12>, bundle <path>).New module
bundle/hub.py;locate_bundlerecogniseshf://before paths and installed names and now returnsLocated(root, id_root, hub).Follow-up changes (Edgar, after a VM check of GridSimEnv-AgentEnv)
Setup note only when setup can fix it. The plan raises
NotInStore, aBundleErrorcarryingmissing(kind, id), whenever a reference names an agent, env or artifact the store doesn't hold, mixed with other problems or not, and preflight does for a missing default agent.agent-env runattaches the card'ssetupnote only toNotInStoreorUnmetRequirements; a refusal with neither (a model-endpoint preflight error, say) and a task that fails at run time no longer get it.Requirements before the download.
hub._fetchchecks beforesnapshot_download: a bundle with abundle.tomlhas that file alone downloaded first and checked by a folder's rules (parse.read_requires, URL refusal included), else the card's plugins are checked. The refusal is the sameagent-env plugin addline plus the setup note; OpenEnv'sbuild_appgoes through the same path. Since folded into one check on every fetch (below).Missing store entities grouped. Each agent, env or artifact the store doesn't hold is one problem at its first use,
(and N more uses)in preflight's format; the plan's other problems stay one line each. Folder runs get it too. GridSimEnv-AgentEnv's 2,200 lines become one:tasks/dam-v1-2014-01-03-LZ_SOUTH-2h-c.json: step 'deploy-agent': a2a_agent_id (and 2199 more uses): there is no agent 'gridsim-llm' in the store, then the setup note.verifiers main without
vf-eval. verifiers main removedvf-eval(refactor(eval): remove vf-eval PrimeIntellect-ai/verifiers#2610) forvf-run, sotaskset (verifiers main)skipped and failed the skip policy.tst/verifiers/taskset_test.pynow runsvf-evalwhen it's on PATH (0.4.0,--no-pushafter the config when its help names it, as before) andvf-runotherwise, with the same config;vf-runexits 1 because the masked row isn't ok, which the test asserts, and both are judged by the same trace assertions.verifiers.ymlputs whichever of the two the installed verifiers has on PATH. Reproduced on a fresh VM as the workflow sets up (Python 3.13.18, the nemo-gym extra fromuv.lock, verifiers in its own venv): main 0.4.1.dev147 throughvf-runand 0.4.0 throughvf-evalboth pass with no skips, and with neither on PATH the test skips asverifiers_installed.Maintainability fixes (Edgar, from a review)
fetch_bundlechecks what the bundle requires on every call, a cached commit included (itsbundle.tomlby a folder's rules, else the card's plugins), and adds the card's setup note itself;HubBundle.check_pluginsand its calls incli/run.pyand OpenEnv are gone, andagent-env runhas oneoffer_to_installpath, withlocate_bundleinside its try.HubSource. Where a Hub bundle came from is a frozenHubSource(describe(),to_metadata(),from_metadata());run_bundle(source=)takes it, and the storedbundle_sourcekeeps exactly its shape.store.ids.namespace_prefix()builds@<namespace>/inlocal_namespace,validate_local_idandRoutingDocumentStore.check_id; a bare declared id's message says what this bundle may declare ('@local/', and for a Hub bundle its own root);Ledger.for_plancasts the namespace of a write's id, always local.config/runtime.pykeeps its localstore.idsimport and"local"defaults: importingagent_env.store.idsat its top is circular (agent_env.storeimportsagent_env.config), checked on the VM._bundle_namekeys both the card's table and the id root: the folder underbundles/, the path for a folder elsewhere (so/a/xand/b/xno longer share a table), the repo's name for the root._fetchsplit into_commit(the commit's record and card), a pure_select(pick, id root, needs, source) and_download(the requirement check, then the download), with the per-commit lock and record as before._pick's docstring and the README (now with the card's YAML); therunhelp keeps the reference format and points to the README; thehubmodule docstring is three lines.cache_root()moved toconfig/paths.pybesidestate_root(), same XDG rule ($XDG_CACHE_HOME/agentenv, else~/.cache/agentenv).ruff checkclean; full unit suite 12656 passed, 7 skipped;run_bundle_test.pyplustst/integration/store22 passed;tst/integration/openenv7 passed. New tests: a cached commit refused by the CLI and OpenEnv with no Hub call, the pure_select,/a/xand/b/xkept apart,cache_root, and a Hub bundle's declarable-prefix message.Decisions (Edgar, Nov 2)
@hfis a second local namespace, routed to the local stores like@local, with its own documents file (hf.dbbesidelocal.db) and inside the write fence; services still refuse every@id.agent-env run; the plugin'shf runbecomes a thin call into it later./<path>, thenbundles/(only one, or the card's default), then the root.--yes;--dry-rundownloads, checks and shows what would run, and runs nothing.@hfas a local namespacestore/ids.py:is_local_id()andvalidate_local_id()know both namespaces; newlocal_namespace(). An@hfid encodes to its ownlocal/hf-…-<hash>segment;@localencodings are unchanged.store/routing.py:RoutingDocumentStoretakes a store per local namespace; a run's records follow its namespace (local_run_namespace()), unplaced reads consult the run's own namespace first, and the fence and outward-reference refusal cover both. The bundle ledger keeps each row in its entity's namespace store, so an installed bundle's@localentity pulled into an@hfrun keeps one row.is_local_id():plan.py(alias lookup, bundle-ref check, routing guard),importer.py_output_names,resolve.pyoutput ids,parse.pydeclared ids,routing.py,document_store.reject_reserved_id; the existingis_local_id()callers (object/image routing inconfig/runtime.py, snapshot and collect steps, verifiers,deploy_agent, the GitHub-build refusal) now cover@hftoo.@local-only, since each builds or matches an installed bundle's or a folder's id, and those are always@local:plugins/_bundles.pyInstalledBundle.id_root;parse.py_id_root(a folder's id root) andsegment_problem(uses@local/only as a vehicle to validate one name);plan.py_pulledand_bundle_name;importer.py_installed_for;register.pyRegistrationLedger._bundle(installed:<dist>/<name>).parse.foreign_hub_id): an@hfid is accepted only under the bundle's own id root, which onlyhf://produces. A folder or installed bundle can't declare one (nor name a task output by one, checked inresolve.py), and a Hub bundle can't declare another repo's.@localdeclarations are unchanged, Hub bundles included.-,_,., at most 96 each) all passvalidate_local_idand the byte limit; the reference parser refuses anything else, and a/<path>that can't be an id root is refused with the reason.Also: on a case-insensitive filesystem,
agent-env run desktoprun from~took~/Desktopas the folder and failed with "not a bundle". Bare text now counts as a folder only when each name in it is spelled as written in its parent's listing (NFC-compared); path-like text stays a path.Packaging and docs
huggingface_hub>=1.0is a direct dependency (already in every install through litellm → tokenizers, locked at 1.33.0). Its HTTP errors are caught by its ownHfHubHTTPError, since 2.x bases them on httpx2, not httpx (the CodeBuild run resolved 2.x and caught that).uv.lockgains two lines (relocked with uv 0.10.0;uv==0.13.1 lock --checkpasses). THIRD_PARTY_NOTICES.md already lists huggingface_hub 1.33.0.bundle/andstore/rows mentionhf://and@hf.agent-env --help(1.39 s → 1.46 s on the test VM).agent_env.openenv.build_apptakes its bundle throughlocate_bundle, so it now also accepts anhf://reference, and checks the card's plugins as the CLI does.Tests
On an agent-environments-admin EC2 VM (c6i.2xlarge, Ubuntu 24.04, Python 3.12, Docker 29.9 and
registry:2on :5000):ruff check: clean.pytest tst/unit packages/agentenv-protocol/tests -n 8: 12641 passed, 7 skipped; the 2 failures (test_chromium_app,run_docker_container_test) neededunzip, failed the same onmain, and pass once it's installed.New
tst/unit/bundle/hub_test.py(fakeHfApi): references with and without@revisionand/<path>and bad ones; picking by path, the only bundle underbundles/beside a roottasks/of data files, the card's default, several with no default, the root, no bundle; only the bundle and card downloaded; a commit reused with no call (pinned) or onlyrepo_info(branch); the Hub's refusal with the login note; through the CLI, the source line first, the@hf/me/ds/helloid root,bundle_sourcein each instance, the rerun reusing v1, ledger rows inhf.dband nothing inlocal.db; a dry run that downloads and runs nothing; card plugins refused with theplugin addline and ignored beside abundle.toml; the card's setup shown on failure.Extended:
routing_test(@hfdocuments and run records inhf.db, the fence, outward references, derived ids, objects routed locally,hf.dbcan't be the configured store),local_id_acceptance_test(services and the@localstore refuse@hf),ids_test,parse_testandresolve_test(@hfids only under a Hub bundle's own root),installed_test(Desktop/doesn't hide an installeddesktopwith a case-insensitive lookup simulated; an exactly spelled folder still wins),plan_test,explorer_app_test.Integration (
tst/integration/cli/run_bundle_test.py, real Hub):agent-env run hf://earakely-scale/agentenv-hf-smoke@5fbd709207a73e2aeb73a77e272a61003d1be768/bundles/hellopasses, a rerun reuses every write, onlybundles/hello/and the card are downloaded, the instance records the source; without the path the same commit stops listingbundles/helloandbundles/v3. With the rest ofrun_bundle_test.pyandtst/integration/store: 22 passed.By hand on the VM:
hf://earakely-scale/GridSimEnv-AgentEnvpicksbundles/gridsim-v1past the root'stasks/,runs/and other result folders (5637 files listed, the bundle alone downloaded);hf://earakely-scale/CuaDriverBench-AgentEnv, which has nobundles/yet, takes its root and stops with "no tasks or evals to run"; a repo that doesn't exist fails with the Hub's 401 message and the login note.hub_test.pyand the real-Hub integration test pass on huggingface_hub 1.0.0, 1.33.0 and 2.4.0.Follow-up changes, on a fresh VM (c6i.2xlarge): full unit suite 12651 passed, 7 skipped;
run_bundle_test.pyplustst/integration/store(real Hub included) 22 passed. New and extended tests:plan_test(three tasks sharing one missing agent give one grouped line andNotInStore; a refusal without a store gap isn't one),hub_test(the card's plugins and abundle.toml, by requirement and by URL, refused with nosnapshot_download; the setup note on a mixed refusal and not on one without a gap; OpenEnv refused before the download). By hand:hf://earakely-scale/GridSimEnv-AgentEnvat 744e139e without the plugin stops having downloaded only the card (544K, no bundle), and with it a dry run prints 5 lines.Follow-ups
hf runbecomes a thin call into core (no prompt,@hfids) in a release requiring this version.earakely-scale/agentenv-hf-smoke, pinned by sha; a dedicated fixture repo could replace it.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; no new blocking issues were found.Summary
Adds
agent-env run hf://…to fetch and run bundles from Hugging Face Hub datasets.No new actionable issues were found in the changes since the previous review. The earlier threads were also rechecked.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR A["hf:// reference"] --> B["Resolve commit and read file list"] B --> C["Pick bundle and read card"] C --> D["Check plugin requirements"] D --> E["Download selected bundle or reuse cache"] E --> F["Plan and run bundle"] F --> G["Store entities and runs under @hf"] F --> H["Record bundle_source"]Reviews (7) · Last reviewed commit: "docs(bundle): the Hub bundle rules once,..." · Reviewed by Greptile