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:
  - utility

What 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

FieldTypeRequiredDescription
skill_idstringyesThe skill's id. Must match ^[a-z0-9_]+$: lowercase letters, digits, and underscores. No hyphens.
versionstringyesSemantic version, X.Y.Z, quoted. Validated.
descriptionstringyesOne-line summary. May be the empty string.
parameterslistnoFallback parameter list. Ignored whenever the Python signature parses. See below.
preconditionsmapnoState the world should satisfy before the skill runs. Usually empty.
postconditionsmapnoState the world should satisfy after. Usually empty.
tagslist of stringsnoFree-form labels (utility, assembly, plate_map).
safety_ruleslist of stringsnoFree-text safety constraints recorded on the skill.
high_riskbooleannoDefaults to false. When true, the skill triggers automatic checkpoints.
world_state_primemapnoAn initial scene state for the skill, carrying object_positions. Advanced.
parameter_descriptionsmap or listnoProse 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

If you do need the fallback list, these are its fields:

FieldTypeDescription
namestringMust be snake_case, ^[a-z0-9_]+$.
typestringOne of string, float, int, boolean, object, array.
descriptionstringRequired.
requiredbooleanDefaults to true.
defaultanyOnly valid when required: false.
object_schemamapNested parameter schema, for object types.
array_item_typestringItem type, for array types.
parameters:
  - name: duration
    type: float
    description: "How long to wait, in seconds."
    required: false
    default: 30

The 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

Maps 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_id must match ^[a-z0-9_]+$. Hyphens fail validation.
  • version is required and must parse as a semantic version.
  • description is required, though it may be empty.
  • Two skills cannot share a skill_id. If two folders declare the same skill_id in their metadata, the second is skipped and recorded as a failed load. (Two same-named folders each holding a metadata.yaml is 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:

  1. The YAML parses.
  2. The function in robotic_code.py has the parameters you expected, with type hints.
  3. The function name matches the skill_id.
  4. You've committed and pushed.

See also


Did this page help you?