OpenEnv documentation

Discover environments before running them

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.5.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Discover environments before running them

openenv catalog and openenv discover implement RFC 011’s first repository profile. They read committed metadata, not candidate Python modules, images or running deployments. This is separate from AutoEnv, which resolves and loads a known environment.

Produce a versioned inventory

From a clone of the public OpenEnv repository:

openenv catalog build \
  --repository . \
  --repository-uri https://github.com/huggingface/OpenEnv.git \
  --revision HEAD \
  --publisher example.org \
  --output catalog.json

example.org is only an illustrative publication authority. A real publication must explicitly configure an authority its publisher can substantiate. Supplying the option is not identity verification, GitHub endorsement, or permission to run the listed code.

The initial inventory is precisely the regular tracked openenv.yaml files in direct child directories under envs/ at the resolved Git commit. It excludes untracked files, submodules, deployments, and community repositories not in that tree. --root changes that explicitly scoped directory. It is not a global environment census.

The producer reads the commit’s manifest, project metadata and README frontmatter. Frontmatter accepts LF, CRLF and CR line endings. An opening frontmatter marker without a closing marker is invalid metadata under each format. It keeps a source URI, environment path and full revision on each card and its Git artifact. The snapshot has a separate content digest. Builds from identical committed inputs and publisher settings are byte-identical.

An unreadable or invalid eligible environment produces an error in the build report and complete: false; the command exits nonzero. The partial report is inspectable but cannot be loaded as a complete catalog or used to infer withdrawals. Unknown license or omitted tool evidence remains unknown.

Find and inspect a complete record

openenv discover "client smoke test" --catalog catalog.json
openenv discover "client smoke test" --catalog catalog.json --json
openenv discover "" --catalog catalog.json --filter license=BSD-3-Clause
openenv catalog inspect "<identifier from the result>" --catalog catalog.json

The first baseline ranks literal, case-insensitive query-token overlap over authored descriptions, names, tags, capabilities and representative query hints. Scores describe this lexical match only. They are not measured training quality, validation, reputation or execution approval. Exact filters support license, provider, artifact_availability, name, tags and type; unsupported filters are errors rather than empty success.

An identifier is resolved only in the explicitly configured snapshot. Missing identifiers fail explicitly. No URL is guessed from an identifier. Neither the CLI nor the library fetches metadata URLs, visits deployments or passes source IDs into a Hub resolver.

Add only genuinely missing declarations

Optional environment-local discovery.json files can add reviewed task descriptions, tags, representative queries, artifact availability, applicable license declarations, or declared agent tools. Echo contains a worked example. The producer reads it from the same Git revision as the environment.

The repository includes task-focused declarations for more than the Echo smoke test. They make these source definitions easier to select without claiming measured training quality or runtime validation:

Task familySource definitionUseful declared signal
Python executionenvs/coding_envStandard output, standard error and exit status
Browser interactionenvs/browsergym_envPage observations and browser actions
Calendar schedulingenvs/calendar_envSeeded scenarios and declared MCP event tools
Chessenvs/chess_envLegal UCI moves, FEN positions and configurable opponents
Reasoning questionsenvs/reasoning_gym_envSingle-step episodes and dataset-defined answer scoring

For example, after building a snapshot, try openenv discover "Python snippets and standard error" --catalog catalog.json. These examples are a small authored subset of the complete repository inventory, not a claim that every source has equally detailed discovery metadata. Calendar’s tool names cite the existing event-tool definitions; interfaces for other sources are not inferred from their orchestration methods.

Leave representative_queries empty or supply two to five hints. The declaration, generated entry and packaged JSON schemas enforce the same bounds.

Description precedence is discovery.json, openenv.yaml, package description, then README frontmatter. An explicit reviewed license declaration takes precedence; conflicting package and README declarations remain unknown with a diagnostic. Otherwise the package or README declaration is used, then the repository’s declared source license. Mappings are retained in metadata.provenance. This is a source declaration, not a legal certification.

A package license = {file = "LICENSE"} table remains unknown: a file pointer alone does not identify an SPDX or custom license. The producer does not classify the referenced file’s contents or replace this unknown with a repository-wide license. A license table cannot contain both file and text.

Custom license text is retained internally when comparing package and README declarations; the emitted card still uses other. Two different custom texts must not match merely because both normalize to that category. Identical custom text, allowing for line endings and outer whitespace, is a consistent declaration. Two bare other markers do not establish a shared license identity. Ambiguous or conflicting declarations produce unknown and a license_conflict warning, without borrowing a positive license claim from the repository.

Tool declarations name repository-relative evidence within the environment and remain declared. Merely listing a tool name does not establish semantic safety. Simulation controls must not be exposed as agent tools. This profile rejects known control names as diagnostics but does not claim that name checks prove the boundary. Discovery never invokes a tool to inspect it.

manifest_spec_version is a manifest marker. framework_requirement is a source-declared package requirement. Neither is a runtime-protocol version or a compatibility certificate.

Profile and publication contract

The 0.1-draft profile is declaration-only, GitHub-source, revision-bound, and inline. Unsupported profile versions and validated-interface claims are explicitly rejected. It does not replace RFC 008’s normalized validation manifest, report contract, or graders. The normalized validation manifest is not a prerequisite because ordinary environments may not declare its validation block.

Schemas are packaged in openenv.discovery/schemas/0.1-draft/. Regenerate them with PYTHONPATH=src python scripts/generate_discovery_schemas.py; --check detects drift. The Pydantic contract additionally enforces relational invariants such as matching artifact revisions and inventory accounting.

Resource type and schema scope

The resource media type is application/vnd.openenv.environment-card+json. It describes an environment source definition, not an installable MCP-server configuration. Clients dispatch on the explicit ARD entry type and check the card’s data.schema_version. Neither a display name nor a version string alone identifies this resource type.

The ARD entry carries search-facing fields such as displayName, description, tags, capabilities and representativeQueries. Its inline data is the Environment Card. Preserve both the entry and the complete card rather than reconstructing the latter from search snippets.

Packaged schemaApplies to
environment-card.schema.jsonOne entry.data Environment Card
catalog.schema.jsonA complete repository snapshot; its DiscoveryEntry definition describes each entry
declaration.schema.jsonProducer-side discovery.json input, not a discovered resource

The schema $id is a schema identifier, not an instruction to fetch it or a guarantee that a draft has been published at that location. Pin the agreed schema/profile revision during review. Loading these self-contained schemas does not require fetching candidate resource URLs.

Consumer validation

JSON Schema validation is necessary but is not the whole profile contract. The packaged schemas enforce object shape, required fields, relative-path safety, supported literals, conditional artifact/license-evidence presence, and exactly one orchestration interface. The relative-path profile permits printable UTF-8 (including spaces), but rejects C0, DEL, C1, and Unicode line/paragraph separators so untrusted metadata cannot forge CLI or log lines. Other rules require semantic validation:

SubjectAdditional rule
Repository sourceParse a credential-free GitHub HTTPS Git URI with no query, fragment or encoded path components; its repository identity must equal source.id
Artifact bindingEvery artifact’s uri, path and revision must equal the selected data.source tuple
Agent-tool declarationsource_revision must equal the environment revision; agent-tool protocols must be unique
LicenseParse an SPDX expression or the explicit other/unknown sentinel; evidence URLs must be credential-free HTTPS references
Framework requirementParse the declared package requirement and verify that its normalized package name is openenv; this is not runtime compatibility evidence
Entry identityRequire the canonical urn:air: prefix and the selected full source revision suffix; within a snapshot, the publisher must also match
CapabilitiesRequire a source-bound agent-tool declaration; known simulation-control names are forbidden regardless of case
SnapshotCheck source/publisher consistency, unique identities and paths, direct-child inventory scope, complete accounting and the snapshot digest before trusting a refresh

The Python models enforce these semantic rules. Consumers in other languages must implement equivalent checks; passing JSON Schema alone must not be labeled full conformance. A malformed or unsupported card must not become a resolved, validated or installable environment through guessed defaults.

Tool evidence is still a declaration. Recognizing a protocol or checking a tool name does not prove its behavior, safety or suitability for training.

Source retrieval and environment setup

Discovery reads metadata only. Source acquisition, installation and execution are separate actions:

  1. Select and validate a complete card, preserving its full identifier and snapshot provenance.
  2. Only artifact_availability: resolvable supplies an immutable artifact locator in this profile. external and unknown do not authorize a guessed download from source metadata.
  3. After the caller’s policy permits source retrieval, use the Git artifact’s uri, full revision and repository-relative path. Select that environment within the pinned checkout while retaining any required monorepo build context. The URN is not a URL, and the GitHub repository ID is not a Hub Space identifier.
  4. Review the selected environment’s setup instructions at the same revision. Build/run and provider requirements are environment-specific. Do not assume that installing the repository root installs the selected environment.

The card does not specify a universal installer, an OCI image digest, a complete dependency lock, launch arguments, resource budgets or execution permissions. framework_requirement alone is not an installation recipe. A declared MCP agent-tool interface is not enough to construct an MCP-server install action. Automated install/launch handling needs its own explicit producer-consumer contract; it must not be inferred from discovery metadata.

The first client action is read-only inspection and source navigation. A resolvable card does not establish caller access, a running deployment, reproducible build output, validated interfaces or approval to execute.

The identifier is publisher-scoped and revision-qualified. Its locator component is SHA-256 over the declared repository URI, a newline and the environment path. It is not a global canonical identity. A publisher transfer requires an explicit mapping rather than merging similarly named environments.

Publish the complete generated JSON through an owner-controlled, versioned metadata channel. Consumers pin the profile they understand and inspect the whole entries[].data card. A third-party catalog adapter may extract entries but must retain source/path/revision and the snapshot reference. Publication alone does not guarantee admission to or indexing by any finder.

The Discovery catalog workflow generates a revision-named GitHub Actions artifact from the checked-out source. It uses the hosting GitHub domain and repository-owner namespace without claiming verified publisher status. The artifact is a reviewable publication output, not a new publicly hosted registry; an operator explicitly downloads and configures it in a consumer. On PRs, it identifies the checked-out PR merge revision rather than pretending to describe released code.

The local library function compare_catalogs(previous, current) distinguishes added listings, withdrawn listings, superseded revision cards and corrected metadata for the same revision. Both inputs must be complete snapshots of the same publisher, source and inventory scope. Failed reads cannot authorize removal. Historical snapshots remain usable as explicit historical metadata.

For an independent consumer, configure the same snapshot in a compatible finder. Do not duplicate its domain rules by importing environment runtime code. The first-source milestone is useful on its own; additional providers, URL fetching, private credentials and runtime validation require their own supported profiles.

Update on GitHub