From zenml-io-skills
Migrate Azure Machine Learning SDK v2 pipelines, components, environments, and schedules to idiomatic ZenML pipelines. Handles concept mapping (`@pipeline` -> `@pipeline`, `@command_component` -> `@step`, `Environment(...)` -> `DockerSettings(...)`, AzureML compute -> `AzureMLOrchestratorSettings`), code translation, Azure-aware "keep AzureML" migration paths, and flags unsupported or unsafe patterns (sweep jobs, parallel jobs, managed endpoints, AzureML Registry, Responsible AI dashboard, and unverified control-flow helpers like `if_else` and `do_while`) for human review. Use this skill whenever the user mentions AzureML migration, Azure Machine Learning SDK v2 migration, converting AzureML pipelines or components, porting workflows from AzureML, replacing AzureML authoring with ZenML, or asks how AzureML concepts map to ZenML -- even if they don't explicitly say "migrate". Also use when they paste AzureML SDK v2 code, `mldesigner` components, YAML components, `load_component()` usage, MLTable/data asset definitions, or AzureML scheduling/deployment code and ask to make it work with ZenML. If the user just asks a quick conceptual question ("what's the ZenML equivalent of an AzureML Environment?"), answer it directly from the concept map -- no need to run the full migration workflow.
npx claudepluginhub joshuarweaver/cascade-ai-ml-engineering --plugin zenml-io-skillsThis skill uses the workspace's default tool permissions.
This skill translates **Azure Machine Learning SDK v2** pipelines into idiomatic ZenML pipelines. It handles the full migration workflow: analyzing AzureML pipeline code and assets, classifying each pattern, choosing when to keep AzureML as the execution plane, translating what maps cleanly, flagging what needs redesign, and producing a working ZenML project.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
This skill translates Azure Machine Learning SDK v2 pipelines into idiomatic ZenML pipelines. It handles the full migration workflow: analyzing AzureML pipeline code and assets, classifying each pattern, choosing when to keep AzureML as the execution plane, translating what maps cleanly, flagging what needs redesign, and producing a working ZenML project.
SDK v1 is out of scope. If the user is still on AzureML SDK v1, first normalize the workflow to SDK v2 concepts, then migrate the SDK v2 version to ZenML.
AzureML and ZenML solve overlapping problems, but they organize the world differently:
@step + @pipeline, with containerization handled by DockerSettings and infrastructure handled by the active stack and orchestrator settings.That means migration is not just a syntax rewrite. Some AzureML ideas translate directly, some translate approximately, and some should stay Azure-native or be redesigned.
This is not always a story of leaving Azure. Often the best migration is:
In that setup, ZenML authors the workflow, and the AzureML orchestrator submits AzureML jobs under the hood.
Before promising a keep-Azure migration, verify that the target ZenML stack can actually run on the AzureML orchestrator. The official ZenML AzureML orchestrator docs call out these prerequisites:
azure integration installedFor authentication, default authentication can be fine during development, but service principal authentication is the recommended production path. If the user wants to keep AzureML execution, ask early whether these stack prerequisites already exist. If they do not, say so plainly in the migration plan instead of making it sound like the code translation alone is sufficient.
Every AzureML concept falls into one of these categories:
| Type | Meaning | Action |
|---|---|---|
| Direct | Clean 1:1 mapping exists | Translate automatically |
| Approximate | Conceptual equivalent exists but semantics differ | Translate with caveats noted in the migration report |
| Absent | No ZenML equivalent | Flag for human review with redesign suggestions |
See references/concept-map.md for the full mapping tables.
Ask the user for the AzureML assets that actually define the workflow. They may provide:
@pipeline, @command_component, PipelineJob)mldesigner componentsload_component()Environment(...), curated environment names, Docker build contexts)uri_file, uri_folder, mltable, model assets)JobSchedule, cron, recurrence)Read everything thoroughly before doing anything else. For each workflow, identify:
if_else, do_while, parallel_for, or set_pipeline_controller_configurations?For each component identified in Phase 1, classify it as direct / approximate / absent using references/concept-map.md.
Direct translations (translate automatically):
@pipeline -> @pipeline@command_component -> @stepAzureMLOrchestratorSettings(mode=...)Schedule(...) when the AzureML orchestrator is the targetApproximate translations (translate with caveats):
Environment(image=..., conda_file=...) -> DockerSettings(...)load_component() -> rewrite as Python @stepInput / Output asset types -> step parameters and return valuesnode.compute = ... -> step-specific runtime config, step operator settings, or separate pipelinesAbsent / needs redesign (flag for human review):
if_else, do_while, parallel_for, set_pipeline_controller_configurations as safe auto-translationsBefore writing any code, present a summary to the user:
"Here's what I found in your AzureML workflow:
- Direct translations (will migrate cleanly): [list]
- Approximate translations (will work but with caveats): [list]
- Needs redesign / stays Azure-native: [list with brief explanation]
The key architectural choice is whether to keep AzureML as the execution plane via the AzureML orchestrator, or to move execution to another ZenML stack. Shall I proceed with the migration?"
If there are HIGH-severity flags, explain each one concretely:
Translate the AzureML workflow into a ZenML project. Follow these conventions strictly.
Every migrated project MUST use this layout:
migrated_pipeline/
├── steps/ # One file per step
│ ├── extract.py
│ ├── train.py
│ └── evaluate.py
├── pipelines/
│ └── my_pipeline.py # Pipeline definition
├── materializers/ # Custom materializers (if needed)
├── configs/
│ ├── dev.yaml
│ └── prod.yaml
├── run.py # CLI entry point (argparse, not click)
├── README.md
└── pyproject.toml
Key rules:
steps/run.py uses argparsepyproject.toml uses requires-python = ">=3.12"configs/dev.yaml and configs/prod.yamlREADME.md explaining what stayed Azure-native and what requires manual attentionzenml init at the project rootSee references/code-patterns.md for detailed side-by-side examples.
The core translation rule is:
@stepDockerSettings# AzureML
@command_component(name="train_model")
def train_component(input_data: Input(type="uri_folder"), epochs: int = 10):
...
# ZenML
@step
def train_step(input_data_uri: str, epochs: int = 10) -> str:
...
AzureML environments are not first-class ZenML assets. Translate them into Docker/container settings:
from zenml.config import DockerSettings
docker_settings = DockerSettings(
parent_image="mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04",
requirements=["mlflow", "scikit-learn"],
)
If the AzureML environment used a custom Docker build context, preserve that with dockerfile=... and build_context_root=....
If the user wants to keep AzureML execution, prefer AzureMLOrchestratorSettings:
from zenml.integrations.azure.flavors import AzureMLOrchestratorSettings
cluster = AzureMLOrchestratorSettings(
mode="compute-cluster",
compute_name="gpu-cluster",
size="Standard_NC6s_v3",
min_instances=0,
max_instances=4,
)
Use this as the default migration path whenever preserving Azure compute behavior is important.
AzureML asset-typed inputs/outputs (uri_file, uri_folder, mltable, model assets) do not map to first-class ZenML asset descriptors. Decide case by case:
ZenML can create AzureML cron/interval schedules when using the AzureML orchestrator, but ZenML does not fully manage schedule lifecycle on Azure afterward. Always call this out in the migration report.
When translating approximate patterns, add concise inline comments describing the changed behavior:
@step(settings={"docker": docker_settings})
def train_step(input_data_uri: str) -> str:
# Migration note: the original AzureML component used an Environment asset.
# This step uses DockerSettings instead, so environment reuse/versioning now
# lives in code and image configuration rather than in Azure asset registry state.
...
For patterns with no safe ZenML equivalent:
# TODO(migration): comment in the generated code# TODO(migration): UNSUPPORTED -- AzureML parallel job semantics are not a safe
# 1:1 ZenML translation. Keep the Azure parallel job native, or redesign this
# workload as a dynamic ZenML pipeline only after validating data partitioning,
# concurrency, and retry semantics.
After generating the ZenML project, produce a MIGRATION_REPORT.md in the project root:
# Migration Report: [AzureML Workflow] -> [ZenML Pipeline]
## Summary
- **Source**: AzureML SDK v2 workflow `[name]`
- **Target**: ZenML pipeline `[pipeline_name]`
- **Components migrated**: X direct, Y approximate, Z flagged
- **Execution target**: AzureML orchestrator / other ZenML stack
## Direct Translations
| AzureML Concept | ZenML Equivalent | Notes |
|---|---|---|
## Approximate Translations
| AzureML Concept | ZenML Equivalent | What Changed |
|---|---|---|
## Flagged for Review
| AzureML Pattern | Severity | Issue | Recommended Path |
|---|---|---|---|
## Environment Translation Summary
| AzureML Environment | ZenML DockerSettings | Notes |
|---|---|---|
## Compute Mapping
| AzureML Compute | ZenML Equivalent | Notes |
|---|---|---|
## Scheduling
- Original schedule
- Migrated schedule
- Lifecycle caveat for AzureML-managed schedules
## Limitations and Key Differences
## What's NOT Migrated
## What You Get for Free After Migration
## Recommended Next Steps
After migration is complete, always include a "Recommended Next Steps" section in the report and communicate it to the user.
zenml-quick-winsAlways suggest this first:
"Now that the migration is done, I'd recommend running the
zenml-quick-winsskill to add metadata logging, experiment tracking, and other production features to your pipeline."
For flagged patterns, include targeted docs:
https://docs.zenml.io/how-to/steps-pipelines/schedule-a-pipelinehttps://docs.zenml.io/stacks/stack-components/orchestratorshttps://docs.zenml.io/stacks/stack-components/orchestrators/azuremlhttps://docs.zenml.io/how-to/steps-pipelines/dynamic-pipelineshttps://docs.zenml.io/how-to/containerization/containerizationhttps://docs.zenml.io/how-to/project-setup-and-management/secret-managementhttps://docs.zenml.io/how-to/infrastructure-deployment/auth-managementhttps://docs.zenml.io/how-to/model-management-and-deployment"For easier access to ZenML documentation while you work, you can install the ZenML docs MCP server:
claude mcp add zenmldocs --transport http https://docs.zenml.io/~gitbook/mcp"
When there are multiple HIGH-severity flags, offer to draft a Slack message for zenml.io/slack summarizing:
If the migration reveals a genuine feature gap in ZenML, offer to open an issue on zenml-io/zenml.
/simplifyAfter code generation, suggest running /simplify to reduce migration-only comments and clean up redundant patterns.
zenml-pipeline-authoring for deeper customizationRecommend zenml-pipeline-authoring when the user needs:
These are the places where users are most likely to get surprised after migration.
AzureML treats components, environments, and many data/model artifacts as first-class registered assets. ZenML treats the main reusable unit as Python code plus build/runtime configuration. This changes how reuse, versioning, and governance are expressed.
AzureML Environment objects become DockerSettings. The operational goal is similar, but the management surface is different:
AzureML pipeline DSL allows very explicit node-level compute choices. ZenML can preserve many Azure compute settings with the AzureML orchestrator, but strongly heterogeneous per-node compute often needs a design decision instead of a literal rewrite.
AzureML uses typed asset descriptors like uri_folder and mltable. ZenML uses Python parameters, artifacts, and materializers. Similar intent, different model.
ZenML can create AzureML schedules, but it does not fully manage their lifecycle after creation on AzureML. Updating or deleting those schedules may remain a manual Azure task.
Treat if_else, do_while, parallel_for, and set_pipeline_controller_configurations as unsafe for automatic translation unless the user explicitly wants a redesign and accepts manual review.
| Anti-pattern | Why it's wrong | What to do instead |
|---|---|---|
| Converting AzureML assets into ZenML names without changing the architecture | Keeps Azure mental model but loses correctness | Rewrite around @step, @pipeline, artifacts, and orchestrator settings |
| Treating every AzureML Environment as a reusable ZenML asset | ZenML has no environment asset registry primitive | Move environment intent into DockerSettings and document the change |
| Silently converting sweep jobs into Python loops | Changes execution semantics, observability, and retry behavior | Keep Azure sweep native, or redesign with explicit HPO tooling |
Silently converting parallel jobs into .map() | Similar shape, different guarantees | Flag for review and redesign deliberately |
| Pretending MLTable is a first-class ZenML type | It is not | Keep it as a URI/reference boundary or load it explicitly inside a step |
| Dropping managed endpoint logic during migration | Changes production behavior, not just authoring | Keep endpoint deployment in Azure or call Azure SDK from a step |
Claiming if_else / do_while are safe 1:1 conversions | They are not verified here | Flag them and require manual review |
| Assuming ZenML will fully manage Azure schedules after creation | It will not | Document the lifecycle caveat in the migration report |
For topics beyond migration (stack setup, experiment tracking, deployment, authentication), query the ZenML docs at https://docs.zenml.io.