Skip to content

feat(deploy_env): carry the universe artifact to the env provider - #122

Open
mandykwok-scale wants to merge 3 commits into
mainfrom
mandy/deploy-env-artifact-params
Open

mandykwok-scale wants to merge 3 commits into
mainfrom
mandy/deploy-env-artifact-params

Conversation

@mandykwok-scale

@mandykwok-scale mandykwok-scale commented Oct 8, 2026 •

Copy link
Copy Markdown

Motivation

A warm environment pool keys on environment and universe — two deployments are only interchangeable when both match.

Today deploy_env names only the env. The universe arrives later, via load_artifact, so an EnvironmentProvider has no way to tell which universe a run will use. The alternative is inferring it by walking the taxonomy for the load_artifact step, which guesses at something the DAG could simply state.

Change

artifact_id / artifact_version become optional params on DeployEnvTaskStep, forwarded to env.deploy() and from there — via deploy_through_provider(**options) — to the provider. The artifact is also declared as an EntityRef, so it is a tracked, version-pinnable reference like env_id already is.

Why this is inert for everything that exists

Forwarding reuses the signature guard already used for litellm_api_key:

if self.artifact_id is not None and ("artifact_id" in params or accepts_kwargs):
    deploy_kwargs["artifact_id"] = self.artifact_id
    deploy_kwargs["artifact_version"] = self.artifact_version

Built-in envs take a fixed param list and would TypeError on an unexpected kwarg — which is what that guard exists for. An env that does not declare artifact_id never receives it, and a step that names no artifact passes nothing.

load_artifact is untouched and still does the loading. This only tells the provider what is coming.

This does nothing on its own

No env declares artifact_id yet, so the guard skips it every time. The companion PR adds it to the built-in envs and providers. Landing them separately keeps this reviewable as the pure contract addition it is.

Test plan

Four unit tests in tst/unit/task_step/deploy_env_test.py: forwarded to an env that accepts kwargs; omitted for an env with a fixed param list, which must not raise; absent when the step names no artifact; survives a to_dict / from_dict round trip.

38 passed, 1 failed — the failure (test_preflight_reports_an_env_this_process_cannot_load[unregistered-type]) reproduces on a clean tree in this venv, where agentenvhub_sdk registers extra env types. Unrelated.

🤖 Generated with Claude Code

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the latest edit does not change behavior.

Summary

Deploy steps can now carry the artifact ID and version for the environment’s run, so an opted-in environment can receive that reference before load_artifact loads it. The step records the artifact as a version-pinnable reference and only passes fields accepted by the environment.

  • Deploy steps can name the artifact their environment will use.

Reviews (3) · Last reviewed commit: "style(deploy_env): drop the comment on t..." · Reviewed by Greptile

A warm environment pool keys on environment *and* universe — two deployments
are only interchangeable when both match. Today `deploy_env` names only the
env, and the universe arrives later via `load_artifact`, so a provider cannot
tell which universe the run will use without inferring it from the taxonomy.

`artifact_id` / `artifact_version` are optional and forwarded under the same
signature guard as `litellm_api_key`: built-in envs take a fixed param list and
would TypeError on an unexpected kwarg, so an env that does not declare them
never sees them. A step that names no artifact passes none. Both are inert for
every existing taxonomy.

`load_artifact` is unchanged and still does the loading; this only tells the
provider what is coming.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread src/agent_env/task_step/task_steps/deploy_env.py Outdated
Comment thread src/agent_env/task_step/task_steps/deploy_env.py
mandykwok-scale and others added 2 commits October 8, 2026 16:45
…name

Two review findings.

Slotting the new params next to `env_version` changed what an existing
positional argument meant: a caller passing ttl_seconds fifth would have been
setting artifact_id, and the env would have got the default TTL. They are
appended now, so every existing position still means what it did.

The guard checked for `artifact_id` and then sent both fields, so an env
declaring the id but not the version — with no `**kwargs` to absorb it — would
have raised on an unexpected keyword. Each field is gated on its own name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
super().__init__(id, version, depends_on=depends_on, fail_task_on_error=fail_task_on_error)
self.env_id = env_id
self.env_version = env_version
# The universe this deployment is for. Carried so a provider can see which artifact the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this, since we should not assume that the artifact is a universe.

self.env_id = env_id
self.env_version = env_version
# The universe this deployment is for. Carried so a provider can see which artifact the
# run will load, without inferring it from the taxonomy; load_artifact still loads it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets remove this comment as well (leaking scale internals to public repo)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants