# Skills

> A skill is a task inside one app, written as short plain-language steps that a run reads and carries out. Save it once and start it by id.

A skill is a task inside one app, written as short plain-language steps. A run reads each step, looks at the screen and does what it says. Save a skill once and start it by id, or send the whole definition with a run.

SkillDefinition:

```json
{
  "name": "Save a playlist",
  "app": "com.spotify.music",
  "intent": "Find a playlist by name and save it to the library.",
  "workflow": [
    { "kind": "step", "text": "Open the Search tab and search for \"Deep Focus\"" },
    {
      "kind": "if",
      "condition": "A playlist called Deep Focus is in the results",
      "then": [{ "kind": "step", "text": "Open it and tap the save button" }],
      "else": [{ "kind": "step", "text": "Stop and say that it was not found" }]
    }
  ],
  "guardrails": { "maxMinutes": 10, "stopOn": ["login wall", "captcha"] }
}
```

- `name` (string, required): Up to 80 characters.
- `app` (string, required): The Android package the skill works in, such as `com.spotify.music`.
- `intent` (string): What the skill is for, in a sentence. Up to 500 characters.
- `workflow` (Block[], required): The steps, described below.
- `guardrails` (object): When to stop, described below.

## Workflow blocks

| Block | Shape | Does |
| --- | --- | --- |
| `step` | `{ text }` | One instruction, up to 500 characters |
| `wait` | `{ seconds }` | Pauses for 1 to 600 seconds |
| `repeat` | `{ times, body }` | Runs body 1 to 50 times |
| `if` | `{ condition, then, else? }` | Checks the screen against condition and takes one branch |

A workflow holds up to 32 blocks at each level, 64 blocks in all, and nests at most 4 deep. Write steps the way you would brief a colleague: name the thing to tap by what it says or where it is. Put a password or code in a step as `{{secret:name}}`; see [Secrets](https://distilled.cx/docs/secrets/).

## Guardrails

- `maxMinutes` (integer): Stops the run on a phone after this long, from 1 to 60. Defaults to 15.
- `maxSteps` (integer): Stops after this many actions, from 1 to 200. Defaults to 60.
- `stopOn` (string[]): Up to 10 things that end the run when they appear on screen. Defaults to `["login wall", "captcha"]`.
- `maxPhones` (integer): The most phones one run of the skill uses, up to 50. 0, the default, means no cap.
- `uiTree` (boolean): Let the run read the elements on screen as well as the screenshot. Off by default.
- `allowedApps` (string[]): Up to 20 packages the run may open. Opening any other app is refused.
- `allowedHosts` (string[]): Up to 20 hosts the run may open links to.

## Endpoints

- `GET /v1/skills` (scope `skills:read`): Every saved skill.
- `POST /v1/skills` (scope `skills:write`): Saves a skill and returns it with an `id` and `enabled: true`.
- `GET /v1/skills/{id}` (scope `skills:read`): One skill.
- `PUT /v1/skills/{id}` (scope `skills:write`): Replaces a skill's definition and keeps its id. Runs already started keep their own copy.
- `POST /v1/skills/{id}/enabled` (scope `skills:write`): Turns a skill on or off with `{ enabled }`.
- `DELETE /v1/skills/{id}` (scope `skills:write`): Deletes a skill.

Source: https://distilled.cx/docs/skills/
