You describe the resources you want in YAML. wxctl figures out the rest: prerequisites, ordering, and the identifier each API expects. You never write an imperative sequence of API calls.

Resources

Every resource has a kind and a ref_name. kind selects the schema and handler. ref_name is the local handle other resources use to point at it. Both are required.
kind: tool
ref_name: calculator
name: calculator
display_name: Calculator
description: A calculator tool
Put multiple resources in one file separated by ---, the standard YAML document separator:
kind: tool
ref_name: calculator
name: calculator
# ...
---
kind: agent
ref_name: math_agent
name: math_agent
# ...
Resources of kind: test are special: they are ignored by every command except wxctl test. Keep test definitions alongside the resources they exercise; plan, apply, and destroy skip them automatically.

Cross-resource references

Resources reference each other with ${kind.ref_name}. wxctl reads these references to build a dependency graph, creates resources in the right order, and substitutes each reference with whatever the target API expects: a UUID, GUID, href, CRN, or a nested object.
kind: agent
ref_name: math_agent
name: math_agent
tools:
  - ${tool.calculator}
SyntaxResolves to
${kind.ref_name}The created resource’s identifier, in the format the consuming API expects
${kind.ref_name.field}A specific field from the created resource
References cross product boundaries the same way. Here a model deployed in watsonx.ai is tracked in a watsonx.governance use case, in one config:
# space, model_entry, and inventory are defined earlier in the same file
kind: wml_function          # watsonx.ai
ref_name: churn_model
space_id: ${space.churn_space}
source_path: score.py
---
kind: wml_deployment        # watsonx.ai
ref_name: churn_deployment
asset: ${wml_function.churn_model}
space_id: ${space.churn_space}
online: {}
---
kind: model_tracking        # watsonx.governance
ref_name: track_churn_model
model: ${wml_function.churn_model}          # points at the watsonx.ai asset
model_entry: ${model_entry.churn_use_case}
model_entry_catalog_id: ${inventory.governance_inv}
space_id: ${space.churn_space}
model_tracking depends on churn_model, so wxctl provisions the watsonx.ai model first, then hands its identifier to the watsonx.governance API in the shape that API expects. You never name a product or paste an ID. Because every identifier resolves at execution time rather than living in the YAML, the same config also runs unchanged across environments: nothing is pinned to a specific instance.

Environment interpolation

Values that differ per environment (URLs, region hosts, instance IDs) come from environment variables with ${env:VAR}:
kind: model
ref_name: my_model
url: ${env:WATSONX_URL}
The variable name must match [A-Z_][A-Z0-9_]*. Interpolation runs over every string value in the configuration before validation, so a missing or empty variable is caught early. Keep secrets in the environment (or in your profile), never in the YAML itself.

Combining sources with -f

-f, --filename selects the configuration to operate on. It is repeatable, and each value can be:
  • a file,
  • a directory: every .yaml / .yml file in it is read in sorted order, or
  • -: read from standard input.
All sources are concatenated with --- separators into a single multi-document configuration, so cross-resource references resolve across files.
wxctl plan -f base.yaml -f overrides/        # a file plus a directory
cat extras.yaml | wxctl plan -f base.yaml -f -   # mixed with stdin

Next steps

Pipeline

How wxctl turns your YAML into ordered API calls.

Profiles & credentials

How wxctl authenticates to each service.