Install
openclaw skills install @huaweicloudskill/huawei-cloud-cloudrobo-assetManage the full lifecycle of CloudRobo assets — query repositories and catalogs, create/list/show/update/delete assets and versions, batch-delete, tag management, predefined tag discovery, Action CRUD, permission checks, marketplace search, official/community asset listing, asset lineage, and local-to-OBS import/export. Triggers include: asset import, asset export, asset version management, tag management, Action configuration, permission check, marketplace search, lineage query, repository listing, catalog listing, publication asset discovery, 资产管理, 资产导入导出, 版本管理, 标签管理, Action配置, 权限校验, 广场搜索, 血缘关系, 资产仓库, 目录查询.
openclaw skills install @huaweicloudskill/huawei-cloud-cloudrobo-assetWindows / 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.
The cloudrobo-asset skill manages the full lifecycle of CloudRobo platform assets. It
covers repository and catalog queries, asset CRUD (create/list/show/update/delete/batch-delete),
version CRUD, tag management, Action CRUD, permission checks, marketplace search,
official/community asset listing, asset lineage, and local-to-OBS import/export.
Applicable scenarios:
Architecture:
Agent / LLM
│
├── CLI → cloudrobo asset <command>
├── SDK → AssetClient (Python)
│
▼
cloudrobo-asset-manager (REST API)
/v1/repositories
/v1/catalogs
/v1/assets/*
/v1/asset-service/search
/v1/asset-service/publication-assets
/v1/asset-tags
│
├── OBS (import/export file transfer)
└── cloudrobo-obs endpoint (configured separately)
All operations target the cloudrobo-asset-manager backend. Import/export additionally
requires a cloudrobo-obs endpoint for OBS file transfer.
See references/cli-installation-guide.md for CLI installation, AK/SK authentication, and
configuration. Import/export operations require the cloudrobo-obs endpoint to be configured in
~/.cloudrobo/config.yaml or via the CLOUDROBO_ENDPOINT_cloudrobo-obs environment variable.
Multiple scenarios require a catalog_id. Only execute when the user has not provided it:
cloudrobo workspace current → read
asset_catalog_id field (the catalog bound to the current workspace)asset_catalog_id is empty:
cloudrobo asset list-repositories → get repository_idcloudrobo asset list-catalogs --repository-id <repo-id> → get catalog_idImport local files (models, datasets, etc.) into the CloudRobo asset repository.
Fast path: If local-path/README.md exists with valid frontmatter (e.g., from a previous
export-asset), only --catalog-id (for new asset) or --asset-id (for new version) is needed
— all other metadata is read from frontmatter. Without frontmatter, catalog_id, name, type
(and sub_type for simulation) must be provided via CLI.
# With frontmatter (recommended — after export)
cloudrobo asset import-asset --catalog-id <id> --local-path <path>
# Without frontmatter
cloudrobo asset import-asset --catalog-id <id> --name <name> --type <type> --local-path <path> [--sub-type <sub-type>] [--ext-metadata '{"key":"value"}']
local-path/README.md frontmatter for metadata (name, type, sub_type, description,
status, tags, version, ext_metadata, parent_asset_version_id, generation_method)--ext-metadata CLI param also supported (frontmatter overrides it)--asset-id <existing-asset-id>--asset-id <id> --version-id <vid> (uploads files directly; same-name OBS objects are overwritten idempotently)Type constraints:
image type is NOT supported by import-asset — image is a SWR reference with no local code upload semantics; use create-asset instead (CLI raises UsageError otherwise)algorithm type IS supported — importing an algorithm uploads local code to the OBS code_dir:
# Mode 1: new asset
cloudrobo asset import-asset --catalog-id <id> --name <name> --type algorithm --tags "Train" --ext-metadata '{"engine":{"image_url":"swr...","image_source":"custom"},"command":"python train.py"}' --local-path ./algo-dir
# Mode 2: new version for existing algorithm asset (no --catalog-id needed)
cloudrobo asset import-asset --asset-id <existing-algo-asset-id> --type algorithm --tags "Train" --ext-metadata '{"engine":{"image_url":"swr...","image_source":"custom"},"command":"python train.py"}' --local-path ./algo-dir
--tags is required (allowed: Data Processing / Train)--ext-metadata (must include engine and command); not passing raises ValueError, passing invalid raises ValidationError--catalog-id needed); creates asset/version with placeholder code_dir = {catalog.url}/pending (preset image backend requires code_dir){catalog.url}/{asset_id}/{version_id}/code_dir to the actual upload path on both asset-level and version-level ext_metadata (clears placeholder pending)--asset-id --version-id (Mode 3) is NOT supported for algorithm — raises ValueError (version reuse unsupported; use --asset-id for a new version)cloudrobo asset show-asset --asset-id <asset-id>Error recovery: If import fails at OBS upload (asset and version created but files not
uploaded, version stays in CREATING status), do NOT create a new version. Two recovery strategies:
list-versions --asset-id <id> to find the failed version,
re-run import-asset --asset-id <id> --version-id <vid> to upload directly (retries all files;
the version transitions to DRAFT once upload succeeds)delete-version --asset-id <id> --version-id <vid> then re-run
import-asset --asset-id <id>cloudrobo asset search-assets --keyword <keyword>cloudrobo asset show-asset --asset-id <asset-id>Browse official/community: cloudrobo asset list-publication-assets --type <type>
Export after search: Only when the user requests export. Before downloading, check that the
current account holds data_read permission on the asset version; --version-id is required —
if the user did not provide one, resolve the latest version ID via list-versions --asset-id <id>, then run:
cloudrobo asset check-permission --asset-id <id> --version-id <version-id> --permissions data_read
If the verdict is deny, do not run the export and inform the user: "当前账号无该资产数据读取
权限,仅能导出元数据(README),无法下载数据文件". Only when data_read is granted, run
cloudrobo asset export-asset --asset-id <id> --local-path <path> (default latest version; add
--version-id for specific version). Export automatically generates README.md with YAML frontmatter
containing asset metadata, enabling seamless re-import with minimal CLI parameters.
cloudrobo asset list-assets --catalog-id <catalog-id>
--type, --sub-type, --status--repository-id instead of --catalog-id for repository-level querieslist-assets --catalog-id <id> to locate asset_idcloudrobo asset list-versions --asset-id <asset-id>model, dataset, simulation, algorithm, image types require ext_metadata at creation. Consult
references/validation-rules.md for required fields by type.
cloudrobo asset create-asset --catalog-id <id> --name <name> --type model --ext-metadata '{"model_type":"planning"}'cloudrobo asset create-version --asset-id <id> --version 1.0.0 --ext-metadata '{"model_type":"planning"}'Task scenario tag constraints (algorithm/image types):
--tags is required at creation (at least 1 task scenario tag)Data Processing, TrainData Processing, Notebook, Online Deployment, Trainext_metadata.engine.asset_id), the algorithm tags must be a subset of the image tags (SDK validates; raises ValidationError otherwise)cloudrobo asset add-tags --asset-id <id> --tags "tag1,tag2"cloudrobo asset delete-tag --asset-id <id> --tag <tag>cloudrobo asset list-tags --language zh (optional --type/--sub-type filter)cloudrobo asset <command> [OPTIONS]
| Feature | Description | Example |
|---|---|---|
| Command group | cloudrobo asset | cloudrobo asset list-assets |
| Subcommand | kebab-case | list-repositories, create-asset, import-asset |
| JSON parameter | --ext-metadata '{"key":"value"}' | --ext-metadata '{"model_type":"planning"}' |
| Comma list | --tags tag1,tag2 | --tags robot,arm |
| Dry-run | --dry-run (where supported) | Preview without executing |
| Output format | JSON to stdout | out(result) |
| UUID identifiers | --asset-id, --version-id, --catalog-id | UUID format required |
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| list-repositories | [--name] [--sort-dir] [--offset] [--limit] | client.list_repositories(**params) | GET /v1/repositories |
| list-catalogs | --repository-id <id> [--name] [--sort-dir] [--offset] [--limit] | client.list_catalogs(repository_id, **params) | GET /v1/catalogs |
| show-catalog | --catalog-id <id> | client.show_catalog(catalog_id) | GET /v1/catalogs/{catalog_id} |
List return structure (unified): All list commands — list-repositories, list-catalogs,
list-assets, list-versions, list-publication-assets, list-tags — return a unified JSON
shape with a data array plus a page_info pagination object:
{"page_info": {"total": 3, "limit": 10, "offset": 0}, "data": [{"name": "my-repo", "repository_id": "a1b2c3d4-..."}]}
Always read list results from data (may be empty []) and pagination totals from page_info.total;
do not treat the top-level object as a single record.
cloudrobo asset create-asset --catalog-id <catalog-id> --type <type> [--name <name>] [--sub-type <sub-type>] [--description <desc>] [--status <status>] [--tags "tag1,tag2"] [--url <obs-or-swr-path>] [--ext-metadata '{"key":"value"}'] [--parent-asset-version-id <uuid>] [--generation-method <method>] [--dry-run]
client.create_asset(req: dict)POST /v1/assetsNote: --tags is required for algorithm/image types (task scenario tag).
Data Processing, TrainData Processing, Notebook, Online Deployment, Trainengine.asset_id), algorithm tags must be a subset of image tags (SDK validates; raises ValidationError otherwise)--sub-type applies to simulation only; for algorithm/image it is ignored (client drops it before the API call)cloudrobo asset list-assets [--repository-id <id>] [--catalog-id <id>] [--type <type>] [--sub-type <sub-type>] [--status <status>] [--name <name>] [--tags "tag1,tag2"] [--mine] [--offset <n>] [--limit <n>]
# Either --repository-id OR --catalog-id filters the list. Full parameter list: see references/api-paths.md → List Assets
client.list_assets(**params)GET /v1/assetsReturn structure: same unified list shape as Repository & Catalog — top-level data array
plus page_info ({"page_info": {"total": N}, "data": [...]}). list-versions and
list-publication-assets also follow this structure. Read records from data and totals from
page_info.total.
Note: repository-id and catalog-id — at least one must be provided; both provided =
AND filter.
cloudrobo asset update-asset --asset-id <asset-id> [--name <name>] [--description <desc>] [--status <status>] [--tags "tag1,tag2"] [--ext-metadata '{"key":"value"}'] [--dry-run]
client.update_asset(asset_id, req: dict)PUT /v1/assets/{asset_id}Note: update-asset only supports modifying name/description/status/tags/
ext-metadata — the CLI exposes no parameters for catalog_id, type, sub_type,
url, parent_asset_version_id, or generation_method, so these fields are immutable.
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| show-asset | --asset-id <id> | client.show_asset(asset_id) | GET /v1/assets/{asset_id} |
| delete-asset | --asset-id <id> [--dry-run] | client.delete_asset(asset_id) | DELETE /v1/assets/{asset_id} |
| batch-delete-assets | --asset-ids "id1,id2" [--dry-run] | client.batch_delete_assets({"asset_ids": [...]}) | POST /v1/assets/batch-delete |
cloudrobo asset create-version --asset-id <asset-id> [--version <version>] [--description <desc>] [--status <status>] [--url <obs-or-swr-path>] [--ext-metadata '{"key":"value"}'] [--parent-asset-version-id <uuid>] [--generation-method <method>] [--dry-run]
client.create_asset_version(asset_id, req: dict)POST /v1/assets/{asset_id}/versionscloudrobo asset list-versions --asset-id <asset-id> [--version <version>] [--exact-version <version>] [--sort-key <field>] [--sort-dir <asc|desc>] [--offset <n>] [--limit <n>] [--actions "FFT,LORA"] [--actions-operator <and|or>] [--ext-metadata <key=value>] [--action-status "ENABLE,DISABLE"]
client.list_asset_versions(asset_id, **params)GET /v1/assets/{asset_id}/versionscloudrobo asset update-version --asset-id <asset-id> --version-id <version-id> [--version <version>] [--description <desc>] [--status <status>] [--ext-metadata '{"key":"value"}'] [--dry-run]
client.update_asset_version(asset_id, version_id, req: dict)PUT /v1/assets/{asset_id}/versions/{version_id}Note: update-version only supports modifying version/description/status/
ext-metadata — the CLI exposes no parameters for url, parent_asset_version_id, or
generation_method, so these fields are immutable.
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| show-version | --asset-id <id> --version-id <vid> | client.show_asset_version(asset_id, version_id) | GET /v1/assets/{asset_id}/versions/{version_id} |
| delete-version | --asset-id <id> --version-id <vid> [--dry-run] | client.delete_asset_version(asset_id, version_id) | DELETE /v1/assets/{asset_id}/versions/{version_id} |
| batch-delete-versions | --asset-id <id> --version-ids "v1,v2" [--dry-run] | client.batch_delete_asset_versions(asset_id, {"version_ids": [...]}) | POST /v1/assets/{asset_id}/versions/batch-delete |
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| add-tags | --asset-id <id> --tags "t1,t2" [--dry-run] | client.add_tags(asset_id, tags) | POST /v1/assets/{asset_id}/tags |
| delete-tag | --asset-id <id> --tag <tag> [--dry-run] | client.delete_tag(asset_id, tag) | DELETE /v1/assets/{asset_id}/tags/{tag} |
| list-tags | --language <zh|en> [--type] [--sub-type] | client.list_all_tags(language, type, sub_type) | GET /v1/asset-tags |
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| list-actions | --asset-id <id> --version-id <vid> | client.list_asset_actions(asset_id, version_id) | GET /v1/assets/{asset_id}/versions/{version_id}/actions |
| show-action | --asset-id <id> --version-id <vid> --action <name> | client.show_asset_action(asset_id, version_id, action) | GET .../actions/{action} |
| delete-action | --asset-id <id> --version-id <vid> --action <name> [--dry-run] | client.delete_asset_action(asset_id, version_id, action) | DELETE .../actions/{action} |
Create/Update action (detailed):
cloudrobo asset create-action --asset-id <id> --version-id <vid> --action-info '{"action":"FFT","algorithm":{"asset_id":"...","version_id":"..."},"status":"ENABLE"}' [--dry-run]
# SDK: client.create_asset_action(asset_id, version_id, req)
# API: POST /v1/assets/{asset_id}/versions/{version_id}/actions
# action-info supports single action object {"action":"FFT",...} or batch {"actions":[{...},{...}]}
cloudrobo asset update-action --asset-id <id> --version-id <vid> --action <name> --action-info '{"status":"DISABLE"}' [--dry-run]
# SDK: client.update_asset_action(asset_id, version_id, action, req)
# API: PUT /v1/assets/{asset_id}/versions/{version_id}/actions/{action}
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| check-permission | --asset-id <id> --version-id <vid> --permissions "meta_read,data_read" | client.check_asset_permission(asset_id, version_id, req) | POST .../check-permission |
| show-lineage | --asset-id <id> --version-id <vid> --type <children|parent> | client.show_asset_tree(asset_id, version_id, type) | GET .../tree?type=<children|parent> |
Valid permissions: meta_read, meta_write, data_read, data_write, data_usable
Lineage: children = parent-to-child; parent = child-to-parent.
| Command | Key Params | SDK Method | API |
|---|---|---|---|
| search-assets | --keyword <kw> [--type] [--limit] [--offset] | client.search_assets(req) | POST /v1/asset-service/search |
| list-publication-assets | [--type] [--sub-type] [--name] [--tags] [--status] [--capabilities] [--offset] [--limit] | client.list_publication_assets(**params) | GET /v1/asset-service/publication-assets |
Full parameter list: see references/api-paths.md → List Publication Assets
cloudrobo asset import-asset --local-path <local-folder> [--catalog-id <id>] [--name <name>] [--type <type>] [--sub-type <sub-type>] [--tags "tag1,tag2"] [--ext-metadata '{"key":"value"}'] [--asset-id <id>] [--version-id <vid>] [--dry-run]
Type constraints:
image type NOT supported — CLI raises UsageError; use create-assetalgorithm type supported (Mode 1 & Mode 2) — imports local code to {catalog.url}/{asset_id}/{version_id}/, code_dir placeholder {catalog.url}/pending at creation then updated to actual path on both asset-level and version-level; user must NOT provide code_dir/boot_file; Mode 2 gets catalog_id from asset detail (no --catalog-id needed)--asset-id --version-id) NOT supported for algorithm — raises ValueErrorFrontmatter support:
local-path/README.md YAML frontmattername, type, sub_type, description, status, tags, version, ext_metadata,
parent_asset_version_id, generation_methodcatalog_id (CLI only), name (frontmatter or CLI), type (frontmatter or CLI)--asset-id): ext_metadata (backend requires it for model/dataset/image/simulation; pass via --ext-metadata or frontmatter)Modes:
--asset-id: Create new asset + version + upload to OBS; after upload, if version status is CREATING, auto-update to DRAFT--asset-id only: Create new version for existing asset + upload to OBS; ext_metadata is required (backend validates for model/dataset/image/simulation; pass via --ext-metadata or frontmatter); after upload, if version status is CREATING, auto-update to DRAFT--asset-id + --version-id: Reuse existing version, upload files directly to OBS (same-name objects are overwritten idempotently); after upload, if version status is CREATING, auto-update to DRAFT; NOT supported for algorithm assets (raises ValueError)Status flow: When no --status is specified, the backend creates the version with status CREATING. After a successful OBS upload, if the version status is still CREATING, the SDK automatically calls update-version to set it to DRAFT. If the user explicitly specifies a status (e.g., RELEASE via frontmatter), the upload succeeds but the status is not auto-modified.
cloudrobo asset check-permission --asset-id <id> --version-id <version-id> --permissions data_read
# verify verdict; only proceed with export when verdict=allow
cloudrobo asset export-asset --asset-id <id> --local-path <local-folder> [--version-id <version-id>] [--dry-run]
Permission pre-check (required): Before exporting an asset the current account may not own
(e.g. marketplace/published assets), always run check-permission --asset-id <id> --version-id <vid> --permissions data_read first (--version-id required; resolve via list-versions --asset-id <id> if unknown).
If the verdict is deny, do not run export-asset and inform the user: "当前账号无该资产数据读取
权限,仅能导出元数据(README),无法下载数据文件" — otherwise the CLI would return a misleading
status:exported result with missing data files (OBS 403).
Type constraints:
image type is NOT supported — raises ValueError (SWR reference, no downloadable files); use create-asset insteadalgorithm type IS supported — downloads code from ext_metadata.code_dir OBS path; if code_dir is missing, raises RuntimeError with recovery guidancePath requirement: --local-path must be an existing directory (raises FileNotFoundError if not found, ValueError if it's a file). The SDK creates a subdirectory {local-path}/{asset_id}/ inside it for the downloaded files.
README.md generation:
<local-path>/<asset-id>/README.md with YAML frontmattername, type, sub_type, description, status, tags, version,
ext_metadata, parent_asset_version_id, generation_method| Parameter | Required | Description | Example |
|---|---|---|---|
--catalog-id | Conditional (new asset import, most commands) | Catalog UUID | b2c3d4e5-f6a7-... |
--asset-id | Yes (asset/version ops) | Asset UUID | a1b2c3d4-... |
--version-id | Yes (version ops) | Version UUID | d4e5f6a7-b8c9-... |
--type | Conditional (import without frontmatter) | Asset type | model, dataset, algorithm, image, simulation |
--name | Conditional (import without frontmatter) | Asset name | my-model |
--sub-type | Conditional (simulation only) | Asset sub_type; algorithm/image no longer accept sub_type (client drops it if provided) | simulation: robot,environment,object,scene |
--local-path | Yes (import/export) | Local folder path | ./my-model |
--ext-metadata | Conditional (model/dataset/algorithm/image/simulation) | Extended metadata JSON | {"model_type":"planning"} |
--language | Yes (list-tags) | Tag language | zh, en |
--permissions | Yes (check-permission) | Permission list | meta_read,data_read |
--dry-run | No | Preview without executing | flag |
--description | No | Asset/version description | My model description |
--status | No | Asset/version status | CREATING, DRAFT, RELEASE, etc. |
--tags | Conditional (algorithm/image create) | Tag list (comma-separated); required for algorithm/image create; algorithm tags must be subset of referenced image tags; full replacement on update | Data Processing,Train |
--url | No | OBS or SWR path (create-asset/create-version only) | obs://bucket/path |
--generation-method | No | Asset generation method (create-asset/create-version only) | manual |
--parent-asset-version-id | No | Parent version UUID (create-asset/create-version only) | d4e5f6a7-... |
Mutating operations (create/update/delete/import/export/batch-delete) should be confirmed
by the user before execution. --dry-run can be used to preview the operation safely.
Key edge cases include: missing catalog_id, import OBS upload failure recovery, export
permission checks, immutable field validation, built-in vs workspace asset distinction,
and capabilities filter mapping. See Edge Cases for the
full table.
# Specification compliance + functional testing (read-only + --dry-run rehearsal; no side effects)
bash scripts/test-cli-commands.sh -s . -e {cli|sdk}
# Key lifecycle real execution (create→update→tag→version→delete; confirms each mutation):
# RUN_LIFECYCLE=1 REPOSITORY_ID=... CATALOG_ID=... ASSET_ID=... VERSION_ID=... bash scripts/test-cli-commands.sh -s . -e cli
Test cases: see templates/test-vars.json for the full list covering all asset operations.
show-asset/show-version/list-actions that changes took effectverdict contains allow/denycheck-permission --asset-id <id> --version-id <vid> --permissions data_read first (version-id required; resolve via list-versions if unknown); deny → inform user, do not export--dry-run with create/update/delete/import/export to validate parameters before executionreferences/validation-rules.md for required fields by typeimport-asset (not create-asset) for most scenarios — it handles the full flow (asset + version + OBS upload)--asset-id --version-id to avoid accumulating empty versionslist-tags before adding tags to ensure they are validexport-asset followed by import-asset for seamless asset migration — export generates
README.md with frontmatter, import auto-reads it to fill metadata--ext-metadata for model/dataset/simulation types to
pass pre-validation