The skill metadata file
A skill's metadata file: id, version, description, tags, and how parameters are actually derived.
A skill's metadata.yaml is what the platform knows about the skill. Its robotic_code.py is what the skill does.
The single most important thing on this page: your Python function signature defines the skill's parameters, not this file. The catalog reads the signature and overwrites whatever parameters: list the YAML declared. See Parameters below before you write a parameters: block.
Example
A fresh skill from zeon new skill my_skill:
# Skill: my_skill
skill_id: my_skill
version: "1.0.0"
description: ""
parameters: []
preconditions: {}
postconditions: {}
tags: []A filled-out one (a skill that pauses execution):
skill_id: sleep
version: "1.0.0"
description: "Pauses execution for a specified number of seconds."
# parameters are derived from the sleep() signature in robotic_code.py
tags:
- utilityWhat files a skill has
zeon new skill writes exactly two files: metadata.yaml and robotic_code.py.
Most skills grow a third. Alongside those two you will usually find a modules.py, most often a one-line shim that star-imports the runtime API so the skill body can call move_arm, get_object_pose, and the rest. Some skills use it for real helper code instead, and a skill with a lot of maths behind it may add further modules of its own. These extra files are ordinary Python; the platform does not require or inspect them.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
skill_id | string | yes | The skill's id. Must match ^[a-z0-9_]+$: lowercase letters, digits, and underscores. No hyphens. |
version | string | yes | Semantic version, X.Y.Z, quoted. Validated. |
description | string | yes | One-line summary. May be the empty string. |
parameters | list | no | Fallback parameter list. Ignored whenever the Python signature parses. See below. |
preconditions | map | no | State the world should satisfy before the skill runs. Usually empty. |
postconditions | map | no | State the world should satisfy after. Usually empty. |
tags | list of strings | no | Free-form labels (utility, assembly, plate_map). |
safety_rules | list of strings | no | Free-text safety constraints recorded on the skill. |
high_risk | boolean | no | Defaults to false. When true, the skill triggers automatic checkpoints. |
world_state_prime | map | no | An initial scene state for the skill, carrying object_positions. Advanced. |
parameter_descriptions | map or list | no | Prose overrides for parameter descriptions. See below. |
Unknown keys are ignored rather than rejected.
Parameters
The platform derives a skill's parameters from the typed function signature in robotic_code.py. The catalog parses the file, finds the function, and replaces metadata.parameters with what it read. The YAML list is used only when the signature cannot be parsed.
So for this skill:
def my_skill(duration: float = 30, message: str = "hello"):
"""Do the thing.
Args:
duration: How long to wait, in seconds.
message: What to print.
"""
...…the editor shows a duration float defaulting to 30 and a message string defaulting to "hello". Type hints carry the type, defaults carry the default, and the docstring's Args: lines become the descriptions.
Writing a
parameters:block does not override the signature. It is a fallback for when the signature can't be read. If you want to change a skill's parameters, change the Python function signature.
Overriding only the description text
To reword a parameter's description without restating its shape, use parameter_descriptions. This is the one part of the metadata that does win over the docstring:
parameter_descriptions:
duration: How long to hold position before releasing, in seconds.A list form also works: [{name: duration, description: "..."}]. Descriptions resolve in the order parameter_descriptions → docstring Args: → the bare parameter name. This override never fails the load; a malformed block is ignored.
The parameters fallback shape
parameters fallback shapeIf you do need the fallback list, these are its fields:
| Field | Type | Description |
|---|---|---|
name | string | Must be snake_case, ^[a-z0-9_]+$. |
type | string | One of string, float, int, boolean, object, array. |
description | string | Required. |
required | boolean | Defaults to true. |
default | any | Only valid when required: false. |
object_schema | map | Nested parameter schema, for object types. |
array_item_type | string | Item type, for array types. |
parameters:
- name: duration
type: float
description: "How long to wait, in seconds."
required: false
default: 30The required: false line is not optional decoration. A parameter that is required cannot carry a default, and validation rejects the skill if one does.
preconditions and postconditions
preconditions and postconditionsMaps describing what the world should look like before and after the skill runs. Most skills leave them empty and do their checking in Python.
One rule is enforced: a skill's preconditions cannot name its own skill_id as a key. That circular dependency is rejected at load.
Constraints
skill_idmust match^[a-z0-9_]+$. Hyphens fail validation.versionis required and must parse as a semantic version.descriptionis required, though it may be empty.- Two skills cannot share a
skill_id. If two folders declare the sameskill_idin their metadata, the second is skipped and recorded as a failed load. (Two same-named folders each holding ametadata.yamlis a separate case: the second found is skipped with a logged warning, and is not recorded as a failure.)
Matching skill_id to its folder name is a convention, not a rule. If skills/foo/metadata.yaml declares skill_id: bar, the platform logs a warning and uses bar. Keep them equal anyway. Every tool and every reader assumes they match.
When the file is wrong
Invalid YAML means the skill doesn't load and doesn't appear in the workflow editor.
Valid YAML with invalid values also fails the load: the skill_id pattern, the version format, parameter types, and the required-with-a-default rule are all checked. Extra keys and omitted optional fields are fine.
If the editor isn't showing the parameters you expect, check in this order:
- The YAML parses.
- The function in
robotic_code.pyhas the parameters you expected, with type hints. - The function name matches the
skill_id. - You've committed and pushed.
See also
Updated 3 days ago