---
title: "Describing your assets"
description: "An asset is only as findable as its description is clear. When you make something, say what it is, in a few plain sentences."
section: "Core"
slug: "core-describing-assets"
canonical: "https://origozero.ai/docs/core-describing-assets"
updated: "2026-10-08T20:21:10.470681468+00:00"
tags: ["documentation", "guide", "description", "authoring"]
---

# Describing your assets

You do not have to write every one by hand. There are two ordinary ways to get a description:

- **Write it yourself.** Right while you make the asset is the easy time: you know what it does and why you built it, and the text takes a moment. A month later the same text takes a hunt through the code. Write it yourself whenever you want the wording to be yours.
- **Have it generated.** When you have a lot of content, `services describe` reads each asset and writes a description for it. What it writes is an ordinary file in the asset, like any other you wrote: read it, and edit it until it says what you mean. The last sections cover the calls.

## What a type asks for

Whether an asset needs a description, and where it goes, is up to its type. A type declares what its assets need: which file carries the text, which keys it holds, and what counts as written. The type's own template decides what a new asset starts with. Nothing makes a type ask for any of it, and a type may ask for a file other than `README.md`.

To find out what your asset's type asks for:

- `asset.validate("<identity>")` checks one asset against its type and names what is unmet, including a description that is missing or not yet written.
- `guides { path = "types/<name>" }` opens the type's own reference, where its authoring notes say what its assets carry.
- The type's `type.yaml` lists under `files.required` each file its assets need, and a file whose text is asked for carries a `described` check.

The built-in types that ask for a description mostly ask for it in a `README.md`, and `asset.create` starts that file with a line that opens with `[[describe]]` and a note on what to write. Replace the whole line with your own words. To those types, a line or a key that still starts with `[[describe]]` counts as not written yet. Other types ask for none: a type whose assets say what they are through their own content has nothing to add.

## How to write one

Say what the asset **is** and what it is **for**, in the words someone would search for. A good description answers three questions without making the reader open a file:

1. What is this? Name the thing and the range it covers.
2. What does it do or hold? Say it in plain words.
3. When would someone reach for it, and what does it need? Name the sibling assets or inputs it works with.

The asset's code and its symbols are indexed on their own, so a description does not need to list them. Its job is the part code cannot say well: what the thing is, what it is for, and when to pick it.

A few habits keep it useful:

- **Lead with the thing.** The first sentence says what the asset is. Skip the greeting and the history.
- **Say what is true now.** Describe the asset as it works today. Leave out what it used to do, what it might do and what it lacks.
- **Write for a game maker.** Mention a file name or a call only where the reader needs it to use the asset.
- **Keep it short.** One to three short paragraphs is usually enough. The asset's own files carry the detail.
- **Do not repeat the name as the answer.** "The Spinner module" tells nobody anything.

## `about.yaml` for a type

The built-in `assetType` type asks each type for an `about.yaml` with three keys, each a short text with a limit in bytes:

| Key | What it says | Limit |
|---|---|---|
| `intent` | What the type is for in someone's game. Name the whole range of things it covers. | 800 |
| `function` | How an asset of the type works: what it is made of and what the engine does with it. | 1500 |
| `usage` | What a person or an agent does with one: how they pick it, place it, call it or hand it on. | 1200 |

Write about the type as a whole, so the text holds for every asset of it. Leave out any one asset's name.

## Seeing which assets still need one

`zm status` prints what blocks your next push, and an asset the push carries that still needs a description is one of those lines. `world.publishBlockers()` returns the same list without a push attempted. Both only cover the assets the push changes, so an older asset you have not touched is not in them. A type with no `about.yaml` at all is the exception: it blocks every push that carries it, and both name it. `world.contentRequirements()` reads every asset in the world, and its rows for a description carry `describes = true`. The same lists carry anything else a type asks for.

Seeing what is missing does not decide what to do about it. For each asset you can write the description yourself, or generate it.

## Generating descriptions

`services describe` is the tool for generating them. It works in two steps.

```luau
tools.use("services", "describe", { mode = "find" })   -- preview: nothing is written
tools.use("services", "describe", { mode = "all" })    -- fill what that listing names
tools.use("services", "describe", { assets = { "Spinner", "Door" } })
```

`find` is the first step. It lists the assets it would fill, the file and keys each needs, how many calls the fill makes and what they cost, and it writes nothing. Then fill, and read what came back. Edit it where it misses.

- A call costs 1 credit, and one call covers many assets. `find` reports the number of calls before anything is spent.
- It writes only the description file or keys the type declares. It never overwrites text you wrote, and it leaves library and installed content alone.
- By default it takes the assets that block your next push. `scope = "world"` takes every asset your world holds that a type asks to describe.
- `instructions` adds your own wording to what the model is told, and `examples` names assets whose descriptions show the shape you want.

## When you push

A push checks each asset it carries against its type's requirements and refuses when one is not met, naming what is missing. A written description is one requirement that some types declare. An asset the push leaves as it was is not checked for it. To clear the refusal, write the description (or generate it), then push again.
