Install
openclaw skills install @huaweiclouddev/huawei-cloud-cloudrobo-model-workflowModel development orchestration Skill covering asset query, model training, inference deployment, and real-robot evaluation in any combination. Supports full end-to-end pipeline or partial stages (e.g., train+deploy only, deploy+eval only). When user requirements involve two or more stages, prefer this Skill over individual module Skills. Triggers include: "用XX机器人训练XX任务", "so101 插笔", "训练部署", "部署评测", "训练评测部署", "模型开发流程", "端到端训练", "训练推理评测", "只训练不评测", "训练完部署", "model workflow", "end-to-end training", "train and deploy", "deploy and eval".
openclaw skills install @huaweiclouddev/huawei-cloud-cloudrobo-model-workflowOrchestrate the pipeline: asset query → model training → inference deployment → real-robot evaluation → result output. Use CLI commands throughout; Python SDK is prohibited.
Windows / PowerShell: Examples use bash syntax. To run on Windows PowerShell:
- Flatten
\line continuations to a single line, or end lines with a backtick.- Set env vars with
$env:NAME="value"instead ofexport NAME="value".- Single-quoted JSON
'{"a":"b"}'works as-is.
Stage 0: Use Case Parsing → Extract robot type + task, select model; parse dataset source
Stage 1: Asset Query & Dataset → Query model/algorithm/dataset assets; get default hyperparams and confirm; OpenPI model constructs data.rename_map
Stage 2: Model Training → CLI create-task creates training task, poll until complete
Stage 3: Inference Deployment → CLI infer create deploys inference service
Stage 4: Real-Robot Evaluation → CLI dispatch create-task dispatches task to real robot (session_id=workspace_id, no session creation needed)
Stage 5: Result Output → Output evaluation score and report
| Mode | User Intent Example | Stages |
|---|---|---|
| Full pipeline | "用 so101 训练插笔任务并评测" | Stage 0→5 |
| Train+Deploy | "训练完帮我部署推理服务" | Stage 0→3 |
| Deploy+Eval | "我模型训练好了,帮我部署评测" | Stage 3→5 |
Stage dependencies cannot be skipped: Evaluation depends on inference service RUNNING, deployment depends on training FINISHED, training depends on asset info. When starting from an intermediate stage, user must provide preceding output parameters.
| Start Stage | User Must Provide | Prompt |
|---|---|---|
| Stage 2 | base_model_asset_id, dataset_asset_id | "Please provide base model asset_id and dataset asset_id" |
| Stage 3 | output_model_asset_id, output_model_version_id | "Please provide training output model asset_id and version_id" |
| Stage 4 | service_id | "Please provide inference service service_id" |
| From → To | Handoff Values |
|---|---|
| Stage 0 → 1 | model_keyword, dataset_source, dataset_value, robot_type |
| Stage 1 → 2 | base_model_asset_id/version_id, algorithm_asset_id/version_id, train_method, default_hyperparams, dataset_asset_id/version_id, data.rename_map (OpenPI only) |
| Stage 2 → 3 | output_model_asset_id, output_model_version_id |
| Stage 3 → 4 | service_id |
| Stage 4 → 5 | robot_id, task_id, task_status, task_result |
HUAWEI_CLOUD_AK / HUAWEI_CLOUD_SK)cloudrobo workspace use <id>Windows/PowerShell note: PowerShell has issues parsing JSON with
|,"special characters. When passing complex JSON parameters, write JSON to a temp file and use Python subprocess to call CLI (this is not SDK, just a Python wrapper for CLI to work around PowerShell encoding issues). Seereferences/cli-installation-guide.md.
Extract from user input: robot type, task description, dataset source.
User specifies model → use directly.
User does not specify model → query marketplace preset models, use question tool to ask user:
cloudrobo asset list-publication-assets --type model
| Robot | Recommended Model |
|---|---|
| so101 / jaka / franka / general | LeRobot_PI05-Base |
| User Input | Type | Processing |
|---|---|---|
| Asset name/asset_id | user_specified | Stage 1 search this asset |
OBS path obs:// | obs_path | Stage 1 register as asset |
| Local directory path | local_path | Stage 1 upload to OBS and register |
| Not specified | need_ask | Must ask user |
cloudrobo asset search-assets --keyword "<model_keyword>"
Extract from results:
id → base_model_asset_idlatest_version_id → base_model_version_idactions[].action → train_method (e.g., FFT, LORA)actions[].algorithm.asset_id → algorithm_asset_idactions[].algorithm.version_id → algorithm_version_idtrain_method comes from model
actions[].action(e.g.,FFT,LORA), notSFT/QLORA. DefaultFFT; useLORAwhen user requests LoRA.
cloudrobo asset show-asset --asset-id <algorithm_asset_id>
Extract default hyperparams from ext_metadata.hyperparams. Each hyperparam has name, default, constraint.type, constraint.editable, description.
After getting default hyperparams, must use question tool to ask user whether to modify:
Critical: This step cannot be skipped. Even if user chooses defaults, must explicitly confirm. Fabricating parameter keys is prohibited: All keys must come from algorithm
ext_metadata.hyperparamsnamefield.
Applicable: Execute when base model is
Physical-Intelligence_PI0-BaseorPhysical-Intelligence_PI05-Base. Skip for other models.
See references/openpi-rename-map.md for full construction details.
Case A: Registered Asset
cloudrobo asset search-assets --keyword "<dataset_name_or_id>"
Extract id → dataset_asset_id, latest_version_id → dataset_version_id.
Case B: OBS Path
cloudrobo workspace current # Get asset_catalog_id
cloudrobo asset create-asset --catalog-id <catalog_id> --name "<dataset_name>" --type dataset --ext-metadata '{"annotation_status":true}'
cloudrobo asset create-version --asset-id <asset_id> --url "<obs_path>"
cloudrobo asset update-version --asset-id <asset_id> --version-id <version_id> --status RELEASE
Case C: Local Directory
cloudrobo workspace current # Get asset_catalog_id
cloudrobo asset import-asset --catalog-id <catalog_id> --type dataset --local-path <local_dir_path> --name <dataset_name>
cloudrobo asset update-version --asset-id <asset_id> --version-id <version_id> --status RELEASE
Critical:
import-assetrequires local directory to containREADME.mdwith YAML frontmatter containingext_metadata.annotation_status: true. Critical: Afterimport-asset, dataset version status isCREATING; must manually publish asRELEASE, otherwise training reports "dataset not ready".
Case D: Not Specified — Use question tool to ask user for dataset source.
Use CLI throughout.
cloudrobo train create-task --config <JSON>accepts full config JSON. Naming uniqueness:nameandoutput_models[0].model_namemust be globally unique; use timestamp suffix.
Write config JSON to temp file (avoid PowerShell special character issues):
{
"name": "so101-pen-train-<timestamp>",
"train_mode": "MODEL_TUNING",
"train_method": "FFT",
"algorithm": {
"algorithm_asset_id": "<algorithm_asset_id>",
"algorithm_version_id": "<algorithm_version_id>"
},
"input_models": [{
"model_asset_id": "<base_model_asset_id>",
"version_id": "<base_model_version_id>",
"source_type": "PUBLIC_MODEL_ASSET"
}],
"datasets": [{
"source_type": "CUSTOM_DATASET_ASSET",
"dataset_asset_id": "<dataset_asset_id>",
"version_id": "<dataset_version_id>",
"dataset_name": "<dataset_name>"
}],
"output_models": [{
"model_name": "so101-pen-output-<timestamp>",
"model_type": "vla",
"save_mode": "NEW_MODEL",
"strict": false
}],
"spec": "Ascend: 1 * SNT9B2 | 24 vCPUs | 192 GiB",
"cluster_id": "<cluster_id_from_stage1>",
"workspace_id": "<workspace_id>",
"parameters": "[{\"key\":\"batch_size\",\"desc\":\"批次大小\",\"value\":\"64\",\"constraint\":{\"type\":\"Integer\",\"editable\":true,\"required\":true,\"sensitive\":false}},{\"key\":\"steps\",\"desc\":\"训练步数\",\"value\":\"100000\",\"constraint\":{\"type\":\"Integer\",\"editable\":true,\"required\":true,\"sensitive\":false}},...]",
"env": "[]"
}
Required fields: name (unique), train_mode (fixed MODEL_TUNING), train_method (from model actions), algorithm, input_models[0].source_type (PUBLIC_MODEL_ASSET), output_models[0].model_name (unique), output_models[0].model_type (fixed vla), spec (string), cluster_id (pool ID with pool- prefix), parameters (JSON array string with full format from Step 1.1c).
parameters construction: From algorithm ext_metadata.hyperparams, construct full-format array preserving desc and constraint from the asset query:
parameters = [
{
"key": hp["name"],
"desc": hp.get("desc") or hp.get("description", ""),
"value": str(custom_overrides.get(hp["name"], hp["default"])),
"constraint": hp.get("constraint", {})
}
for hp in hyperparams
]
# Serialize to JSON string for the config
parameters_str = json.dumps(parameters, ensure_ascii=False)
Full format mandatory: Each parameter item must include
key,desc,value, andconstraint. Thedescandconstraintcome directly from the algorithm assetext_metadata.hyperparamsquery results — do not fabricate or omit them. OpenPIdata.rename_map: Thedefaultvalue is already single-quote-wrapped JSON string format. Usedefaultvalue directly. For custom mapping, seereferences/openpi-rename-map.md.
Resource specs: Single card Ascend: 1 * SNT9B2 | 24 vCPUs | 192 GiB; Dual card Ascend: 2 * SNT9B2 | 48 vCPUs | 384 GiB. Use SNT9B2 chip, not Ascend-910B.
import subprocess
with open("train_config.json", "r", encoding="utf-8") as f:
config = f.read().strip()
result = subprocess.run(
["cloudrobo", "train", "create-task", "--config", config, "-v"],
capture_output=True
)
print(result.stdout.decode("utf-8", errors="replace"))
Returns {"task_id": "<task_id>"}.
cloudrobo train show-task --task-id <task_id>
FINISHED → proceed to Stage 3FAILED/CREATE_FAILED/SUBMIT_FAILED → see references/fault-recovery.mdWAITING/RUNNING/PENDING → continue pollingcloudrobo train get-stages --task-id <task_id> # View training stages
Stage flow: scheduling → preparing → running → end
output_models returns model_asset_id and version_id at task creation (platform pre-creates). Get from show-task result. Model files become available after training FINISHED.
Use CLI throughout
cloudrobo infer create. Model source policy: The model deployed here is the training output — a space asset (空间资产), so the space-asset / Variant B path of thecloudrobo-inferskill's "Model Source → Parameter Policy" table applies: parameters (model-ext-metadata,skill-config-json) are required and constructed explicitly. This is NOT an embodiment plaza model — do NOT apply the embodiment-plaza "core params only" rule here. If a user ever asks to deploy a model straight from the embodiment plaza inside this workflow, follow thecloudrobo-inferskill's Model Deployment Workflow Variant A instead (required core params only). See thecloudrobo-inferSKILL.md → "Model Source → Parameter Policy" table as the authoritative decision source.
cloudrobo resource list-pools
Filter pools where usages includes MODEL_DEPLOYMENT, pool_type is DEDICATED (preferred) or SHARED, and nodes[].available_resources > 0.
cloudrobo resource show-pool --pool-id <resource_id>
show-pool's--pool-idusesresource_id(withoutpool-prefix).infer create's--pool-idmust usepool-<uuid>format (withpool-prefix).
Must pass
model_feature_mappingvia--model-ext-metadata. Platform does not read asset version's ext_metadata. Not passing causes immediate FAILED.
See references/model-ext-metadata.md for full r2c templates and construction steps.
Key points:
meta/info.json for feature infoinput_features/output_featureswrist_left value to wrist_rightmodel_type fieldchunk_size must match training model.action-horizon (OpenPI default 50)cloudrobo infer create --name "<infer-service-name>" --flavor "1 * SNT9B2 | 24 vCPUs | 192 GiB" --model-json '{"model_id":"<output_model_asset_id>","model_version_id":"<output_model_version_id>"}' --workspace-id <workspace_id> --pool-id "pool-<resource_id>" --pool-type DEDICATED --model-ext-metadata '<model_ext_metadata_json>' --skill-config-json '{"strict":true,"skills":[{"name":"<skill_name>","prompt":"<task_description>"}]}' --stop-schedule-json '{"duration":6,"time_unit":"HOURS"}' --deploy-timeout-minutes 30
flavor format:
1 * SNT9B2 | 24 vCPUs | 192 GiB(noAscend:prefix).--pool-id(required): Must usepool-<uuid>format. Usingresource_idwithout prefix causes immediate FAILED.--pool-type(required): Must use uppercaseDEDICATEDorSHARED.--model-json(required): The model to deploy —{"model_id":"<output_model_asset_id>","model_version_id":"<output_model_version_id>"}(fields from Stage 2 training output).--model-ext-metadata(required): Pass Step 3.2 constructed JSON. Do not includemodel_type.--skill-config-json(important): Services for real-robot evaluation must define skills, otherwise dispatchcreate-taskreturns 500. Format:{"strict":true,"skills":[{"name":"<skill_name>","prompt":"<task_description>"}]}.promptmust match Stage 4--taskparameter exactly. Do not pass--internet-access-enable: Causes predict_url to only haveinternettype; dispatch needsintranettype URL. After creation, auto-entersDEPLOYING; no need to callinfer start. If FAILED, callinfer startto retry.
cloudrobo infer show --service-id <service_id>
RUNNING → proceed to Stage 4DEPLOYING → continue pollingFAILED → call cloudrobo infer start --service-id <service_id> to retry; see references/fault-recovery.mdTiming: Query robots only after inference service is RUNNING. Key: dispatch has no
create-sessioncommand;session_idisworkspace_id, no need to create session separately.
cloudrobo robot list --workspace-id <workspace_id>
Query all robots in the workspace. Separate results into:
status = ONLINE and type matches the target robot type (e.g., ARM)status = OFFLINE or INACTIVEIf online robots found — use the question tool to ask user to confirm:
| Option | Description |
|---|---|
| Use this online robot (Recommended) | Proceed directly with the selected online robot |
| Select an offline robot to bring online | Export certificate, guide robot-side onboarding, poll until ONLINE |
| Register a new robot | Create new robot, export certificate, guide onboarding, poll until ONLINE |
Display online robot details (name, type, manufacturer, model, status) for user reference. Do not silently auto-select an online robot.
If no online robots found — present offline robots (if any) and new registration option; ask user to choose(Do not ask whether it is necessary to switch to another workspace.).
Critical: User confirmation is required before proceeding with any robot. Do not auto-select. Must pass
--workspace-id.statusvalues are uppercaseONLINE/OFFLINE/INACTIVE. For offline-robot onboarding and new-robot registration steps, seereferences/robot-selection-guide.md.
No need to create session. session_id = workspace_id. Use workspace_id as --session-id directly.
cloudrobo dispatch list-tasks --session-id <workspace_id> --limit 1 # Verify
Key:
create-tasksimultaneously creates and executes the task. No separateexecute-taskcommand.
cloudrobo dispatch create-task --session-id <workspace_id> --name "<task_name>" --task "<task_description>" --constraints-json '{"model":{"exec_model_id":"<service_id>"},"robot_id":"<robot_id>","exec_constraints":{"max_iter_num":60,"max_run_time":5}}'
--session-id: Equals workspace_id--constraints-json (required): JSON object containing:
model.exec_model_id: Inference service ID (service_id), not model asset IDrobot_id: the selected online robot IDexec_constraints: execution limits, e.g. {"max_iter_num":60,"max_run_time":5}--task: Task description/skill prompt; if skill_config.strict=true, must exactly match a skill's promptExtract id → task_id from response. Task auto-starts (status RUNNING).
cloudrobo dispatch show-task --session-id <workspace_id> --task-id <task_id>
RUNNING → continue pollingCOMPLETED → proceed to Stage 5FAILED/CANCELLED → see references/fault-recovery.mdStatus values are uppercase. Command is
show-task, notget-task-status.
cloudrobo dispatch show-task-result --session-id <workspace_id> --task-id <task_id> --limit 100
Summarize and output full pipeline results: use case, base model, training method, hyperparams, dataset ID, training task ID, inference service ID, session ID, robot ID, evaluation score, and report. Partial pipelines output corresponding summary after the last stage completes.
Full pipeline takes hours to days. Use cronjob polling + checkpoint recovery.
Polling intervals: Training 30min/72h timeout; Inference 30min/2h timeout; Evaluation 30min/1h timeout. cronjob minimum interval 30 minutes. Include full pipeline state (all IDs) in prompt for Agent to determine current stage.
Checkpoint recovery: After session interruption: read pipeline state → query current_stage task status → continue waiting / enter next stage / fault recovery.
See references/pipeline-templates.md for pipeline state tracking template.
| Stage | Command | Purpose |
|---|---|---|
| 0 | cloudrobo asset list-publication-assets --type model | List marketplace models |
| 1 | cloudrobo asset search-assets --keyword "<keyword>" | Query model/dataset assets |
| 1 | cloudrobo asset show-asset --asset-id <id> | Get asset details + hyperparams |
| 1 | cloudrobo asset create-asset | Create dataset asset |
| 1 | cloudrobo asset create-version | Create asset version |
| 1 | cloudrobo asset update-version --status RELEASE | Publish version |
| 1 | cloudrobo asset import-asset | Import local dir to OBS |
| 1 | cloudrobo workspace current | Get current workspace + catalog_id |
| 2 | cloudrobo train create-task --config <json> | Create training task |
| 2 | cloudrobo train show-task --task-id <id> | Query training status |
| 2 | cloudrobo train get-stages --task-id <id> | Get training stages |
| 2 | cloudrobo train get-events --task-id <id> --start-time <ms> --end-time <ms> | Get training events (time range required, ms) |
| 3 | cloudrobo resource list-pools | List resource pools |
| 3 | cloudrobo resource show-pool --pool-id <id> | Get pool details |
| 3 | cloudrobo infer create | Create inference service |
| 3 | cloudrobo infer show --service-id <id> | Query service status |
| 3 | cloudrobo infer start --service-id <id> | Retry failed deployment |
| 3 | cloudrobo infer list --workspace-id <id> | List services |
| 3 | cloudrobo infer list-logs --service-id <id> | View service logs |
| 4 | cloudrobo robot list --workspace-id <id> | List robots |
| 4 | cloudrobo robot show --robot-id <id> | Verify robot status (re-confirm ONLINE before dispatch) |
| 4 | cloudrobo robot create | Register new robot (when user selects Option C) |
| 4 | cloudrobo robot export-certificate --robot-id <id> | Export access config for offline robot onboarding |
| 4 | cloudrobo dispatch create-task | Create and execute task |
| 4 | cloudrobo dispatch show-task | Query task status |
| 4 | cloudrobo dispatch list-tasks | List tasks |
| 4 | cloudrobo dispatch show-task-result | Get task result/logs |
| 4 | cloudrobo dispatch cancel-task | Cancel task |
| Parameter | Required | Description | Example |
|---|---|---|---|
workspace_id | Yes | Active workspace ID | Set via cloudrobo workspace use <id> |
model_keyword | Yes | Base model name for search | LeRobot_PI05-Base |
train_method | Yes | From model actions | FFT or LORA |
spec | Yes | Resource spec string | Ascend: 1 * SNT9B2 | 24 vCPUs | 192 GiB |
parameters | Yes | Hyperparameter JSON array string | [{"key":"batch_size","value":"32"}] |
pool_id | Yes (Stage 3) | Resource pool ID with pool- prefix | pool-d1cc6d45-... |
pool_type | Yes (Stage 3) | Pool type uppercase | DEDICATED or SHARED |
model_ext_metadata | Yes (Stage 3) | Feature mapping JSON string | See references/model-ext-metadata.md |
skill_config_json | Yes (Stage 3) | Skill definition for dispatch | {"strict":true,"skills":[...]} |
service_id | Yes (Stage 4) | Inference service ID | From infer create response |
robot_id | Yes (Stage 4) | Online robot ID | From robot list response |
task | Yes (Stage 4) | Task description/prompt | "Insert the pen into the pen holder" |
Stage 3 parameters context:
model_ext_metadataandskill_config_jsonare required in this workflow because the deployed model is a space asset (training output) and real-robot evaluation (Stage 4) depends on them. This follows thecloudrobo-inferskill's space-asset / Variant B path of its "Model Source → Parameter Policy" table. When deploying an embodiment plaza model, use thecloudrobo-inferskill's Variant A instead — carry required core params only and do not passmodel_ext_metadata/skill_config_json.
references/cli-installation-guide.md — CloudRobo CLI installation and configurationreferences/iam-policies.md — Least-privilege IAM policies for CloudRoboreferences/dataflow-diagram.md — Mermaid data flow diagrams for pipelinereferences/pipeline-templates.md — Quick reference templates and hyperparameter configsreferences/openpi-rename-map.md — OpenPI model data.rename_map construction guidereferences/model-ext-metadata.md — model_ext_metadata construction with r2c templatesreferences/fault-recovery.md — Fault recovery for training, inference, and evaluationreferences/robot-selection-guide.md — Detailed robot selection, offline onboarding, and new robot registration stepsreferences/constraints.md — Full constraints and rules listreferences/verification-method.md — Verification methods and CLI command referencereferences/acceptance-criteria.md — Acceptance criteria for pipeline executioncloudrobo <Service> <Operation> [--params]
| Feature | Description | Example |
|---|---|---|
| Service name | cloudrobo service name | asset, train, infer, dispatch, robot, resource, workspace |
| Operation name | Kebab-case operation | search-assets, create-task, show-task |
| Simple parameter | --key=value | --keyword="LeRobot_PI05-Base" |
| JSON parameter | --key='<json>' | --config '{"name":"..."}' |
| Region | N/A (cloudrobo uses workspace) | Set via cloudrobo workspace use <id> |
On Windows/PowerShell, complex JSON parameters should be written to file and called via Python subprocess to avoid shell escaping issues.
create-task returns task_id, status not CREATE_FAILED; eventually FINISHEDinfer show status RUNNING; pool_id uses pool-<uuid> format, pool_type uppercase, pool supports MODEL_DEPLOYMENT; model_ext_metadata constructed from r2c template + dataset info, no model_type field, chunk_size matches model.action-horizon, gripper uses end_effector_states.positiondispatch show-task status COMPLETED; session_id = workspace_id; constraints-json model.exec_model_id is service ID; inference service has skill_config with non-empty skills; predict_url includes intranet typeSee references/verification-method.md and references/acceptance-criteria.md for detailed checklists.