> ## Documentation Index
> Fetch the complete documentation index at: https://docs.2501.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Scenario Structure

> Directory layout and the scenario.json format

A scenario is a directory containing a `scenario.json` file and optional Ansible playbooks. All scenarios live under a shared root (default: `/etc/2501/runner/scenarios`).

***

## Directory Layout

```
scenarios/
  <category>/
    <NNN-scenario-name>/
      scenario.json       # required
      prepare.yml         # optional: Ansible setup before execution
      restore.yml         # optional: Ansible teardown after execution
      validate.yml        # optional: Ansible verification after execution
      inventory.ini       # optional: Ansible inventory
      [support files]     # config snippets, fixtures, test data, etc.
```

The category and numeric prefix (`NNN`) are conventions for organization: they have no special meaning to the runner. The runner uses the full relative path from the scenarios root as the scenario key (e.g. `nginx/001-broken-config`).

***

## scenario.json

The only required file. At minimum, three fields are needed:

```json theme={null}
{
  "key": "nginx/001-broken-config",
  "name": "Nginx Broken Configuration",
  "description": "@2501 the nginx service on the web server is not running. Investigate the issue and fix it so the service is running correctly."
}
```

### Required Fields

| Field         | Description                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------- |
| `key`         | Unique identifier. Must match the relative directory path (e.g. `nginx/001-broken-config`).             |
| `name`        | Human-readable name shown in reports.                                                                   |
| `description` | The instruction sent to the agent. Write it as you would a real task: describe symptoms, not solutions. |

### Optional Fields

| Field        | Description                                                                                    |
| ------------ | ---------------------------------------------------------------------------------------------- |
| `tags`       | String array for grouping. Pass a tag to `-s` to run all matching scenarios (e.g. `-s nginx`). |
| `hosts`      | Target host definitions. See [Hosts & Agents](/0.3.0/scenario-runner/hosts-and-agents).        |
| `agents`     | Agent definitions. See [Hosts & Agents](/0.3.0/scenario-runner/hosts-and-agents).              |
| `validation` | Validation rules. See [Validation](/0.3.0/scenario-runner/validation).                         |

***

## Writing Good Descriptions

The `description` is the exact instruction the agent receives. A few guidelines:

* **Describe symptoms, not solutions.** "The nginx service is not running after a configuration change" is better than "Fix the nginx config file."
* **Be concrete.** Reference the host name, service name, or observable behavior when you know it.
* **Keep it realistic.** Write it as you would a real support ticket or runbook task.

***

## Scenario Keys and Tags

The `key` must exactly match the directory path relative to the scenarios root:

```
scenarios/nginx/001-broken-config/scenario.json
                                   └─ key: "nginx/001-broken-config"
```

Tags are free-form strings for grouping. A scenario can have multiple tags:

```json theme={null}
{
  "key": "nginx/001-broken-config",
  "name": "Nginx Broken Configuration",
  "description": "...",
  "tags": ["nginx", "web", "config"]
}
```

Run all scenarios with a given tag:

```bash theme={null}
2501-runner run -s nginx
2501-runner run -s web
```

Tags and explicit keys can be mixed:

```bash theme={null}
2501-runner run -s nginx,disk/001-cleanup
```

***

## Minimal Example

```json theme={null}
{
  "key": "disk/001-cleanup",
  "name": "Disk Space Cleanup",
  "description": "@2501 disk usage on sandbox-app-01 is above 90%. Identify what is consuming the most space and free up at least 5GB without deleting application data.",
  "tags": ["disk", "storage"],
  "hosts": [
    { "host_id": "hst_abc123" }
  ],
  "agents": [
    {
      "agent_id": "agt_xyz789",
      "host_id": "hst_abc123"
    }
  ],
  "validation": {
    "job": [
      {
        "label": "Job resolved successfully",
        "validator": "job_resolution_status",
        "pattern": "success"
      }
    ],
    "tasks": [
      {
        "label": "Agent checked disk usage",
        "validator": "pattern_match",
        "pattern": "df\\s|du\\s|ncdu",
        "where": "executed_commands"
      }
    ]
  }
}
```

For complete worked examples with playbooks, see [Examples](/0.3.0/scenario-runner/examples).
