> ## 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

> Scenario structure, keys, tags, and writing effective descriptions

A scenario is a directory containing a `scenario.json` file and optional Ansible playbooks. All scenarios live under a shared root (auto-detected, or set with `-p`).

## Directory Layout

```
scenarios/
  <category>/
    <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 (inventory.yml also accepted)
      [support files]     # config snippets, fixtures, test data, etc.
```

The directory names are conventions for organization: they have no special meaning to the runner. The runner walks the scenarios root recursively and indexes each scenario by the `key` field inside its `scenario.json` (the directory path is not used as the key).

***

## scenario.json

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

```json theme={null}
{
  "key": "nginx-broken-config",
  "title": "Nginx fails to start due to config syntax error",
  "description": "Nginx has a broken config and fails to start. Agent must find the syntax error, fix it, and ensure nginx is running on port 80.",
  "ticket_title": "Nginx Broken Configuration",
  "ticket_body": "The nginx web server is not running. Investigate why nginx is failing to start, fix the configuration issue, and ensure the service is running and serving traffic on port 80."
}
```

### Required Fields

| Field          | Description                                                                                                                                                                                                                    |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `key`          | Unique identifier for the scenario. Used to select the scenario with `-s` and to key its report. Free-form; conventionally the leaf directory name (e.g. `nginx-broken-config`).                                               |
| `title`        | Human-readable name shown in reports and the `validate` output.                                                                                                                                                                |
| `description`  | Internal note describing what the scenario tests. Not sent to the agent.                                                                                                                                                       |
| `ticket_title` | Title of the ticket created for the run.                                                                                                                                                                                       |
| `ticket_body`  | The instruction sent to the agent. Write it as you would a real ticket: describe symptoms, not solutions. Supports the `{{schedule_time}}` placeholder, which the runner replaces with a timestamp five minutes in the future. |

### 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](/0.8/benchmark/hosts).                                    |
| `agents`     | Agent definitions. See [Agents](/0.8/benchmark/agents).                                        |
| `validation` | Validation rules. See [Validation](/0.8/benchmark/validation).                                 |

***

## Writing Good Tickets

The `ticket_body` 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` is a free-form unique identifier defined inside `scenario.json`. The runner indexes every discovered scenario by this value, and you select a scenario by passing its key to `-s`. The key does not have to match the directory path; by convention it is the leaf directory name:

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

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

```json theme={null}
{
  "key": "nginx-broken-config",
  "title": "Nginx fails to start due to config syntax error",
  "description": "...",
  "tags": ["nginx", "web", "config"]
}
```

Run all scenarios with a given tag:

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

When a `-s` token does not match a key exactly, it is treated as a tag. Tags and explicit keys can be mixed:

```bash theme={null}
2501 runner start -s nginx,disk-cleanup
```
