# First Simulation

Define one user-critical workflow, run it with faults, and inspect the result.

This guide takes one workflow your users depend on and runs it as a simulation. By the end, you will have a workload file, an optional external mock, a network fault model, and one run you can inspect from the web UI or the `wio` CLI.

Choose a workflow that matters but is small enough to run from one command: create an account, submit a payment, process a queued job, sync data, renew a lease, or recover after a failed API call.

## 1. Install and sign in

Install the CLI:

```bash
npm install -g @workersio/cli
```

Sign in:

```bash
wio auth login
```

Then confirm you can see your projects:

```bash
wio projects ls
```

## 2. Pick a prepared project

Your project must be connected and prepared before you run a simulation.

```bash
wio projects get <project-id>
```

If the project is not prepared, request a prepare:

```bash
wio projects prepare <project-id>
```

In the web UI, open [app.workers.io](https://app.workers.io), choose the project, and wait until it is prepared before continuing.

## 3. Add a workload

A workload is the command that drives the behavior you care about and checks whether it stayed correct.

Create a file in your repo, for example:

```text
.workers/workloads/checkout.py
```

Use your real app entrypoints and checks. This example shows the shape:

```python
import json
import os
import sys
import urllib.request

BASE_URL = os.environ["APP_URL"]


def post(path, body):
    data = json.dumps(body).encode("utf-8")
    req = urllib.request.Request(
        f"{BASE_URL}{path}",
        data=data,
        headers={"content-type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=10) as res:
        return json.loads(res.read())


order = post("/checkout", {"user_id": "u_123", "sku": "starter"})

if order.get("status") != "paid":
    print(f"INVARIANT FAIL checkout_paid status={order.get('status')}")
    sys.exit(1)

print(f"INVARIANT PASS checkout_paid order_id={order.get('id')}")
```

The important parts are:

- Drive a real workflow.
- Check an invariant your users care about.
- Exit non-zero when the invariant fails.
- Print enough context to debug the failure later.

If your workflow needs a local service, make the command start that service before running the workload, or set `APP_URL` to the test endpoint you want to exercise.

## 4. Mock external services

If the workload calls an external service, add an external mock file:

```text
.workers/external-mocks.json
```

Example:

```json
{
  "data": {
    "pairs": [
      {
        "request": {
          "method": [{ "matcher": "exact", "value": "POST" }],
          "destination": [
            { "matcher": "exact", "value": "payments.example.com" }
          ],
          "path": [{ "matcher": "exact", "value": "/charge" }]
        },
        "response": {
          "status": 200,
          "body": "{\"id\":\"pay_123\",\"status\":\"succeeded\"}",
          "encodedBody": false,
          "headers": {
            "Content-Type": ["application/json"]
          }
        }
      }
    ]
  },
  "meta": {
    "schemaVersion": "v5.2"
  }
}
```

Use mocks for service behavior: success responses, retryable failures, permanent failures, unusual payloads, and state transitions.

## 5. Add a network fault

Network fault models live in your repo. For the CLI, put named network faults under:

```text
.workers/fault/net/
```

Create:

```text
.workers/fault/net/slow-network.json
```

Example:

```json
{
  "version": 1,
  "lo": {
    "default": {
      "delay": {
        "time_ms": 250,
        "jitter_ms": 50
      },
      "loss": {
        "kind": "random",
        "percent": 1
      }
    }
  }
}
```

Use fault models for transport behavior: latency, jitter, packet loss, packet corruption, duplication, reordering, rate limits, and blocked paths.

## 6. Run from the CLI

Start with a baseline run. Baseline means no network fault:

```bash
wio simulate create <project-id> \
  --command "python3 .workers/workloads/checkout.py" \
  --workload-path ".workers/workloads/checkout.py" \
  --depth 1
```

Then run the same workload with the network fault across more seeds:

```bash
wio simulate create <project-id> \
  --command "python3 .workers/workloads/checkout.py" \
  --workload-path ".workers/workloads/checkout.py" \
  --faults slow-network \
  --depth 20 \
  --timeout 300 \
  --mem 1024
```

`--depth` is the number of seeds per fault model. With one fault and `--depth 20`, Workers IO creates 20 runs. With two faults and `--depth 20`, it creates 40 runs.

## 7. Run from the web UI

Open [app.workers.io](https://app.workers.io), go to **Workloads**, and click **New Workload**.

Choose:

- Project: your prepared project.
- Workload file: `.workers/workloads/checkout.py`.
- Fault Models: `slow-network`.
- Command: `python3 .workers/workloads/checkout.py`.
- Depth: `20`.
- Timeout: `300`.
- Memory: `1024`.

Click **Start**.

## 8. Watch progress

List simulation batches:

```bash
wio simulate ls
```

Check one batch:

```bash
wio simulate status <exploration-id>
```

List failed runs:

```bash
wio workloads ls --state failed
```

In the web UI, open the run to see Logs, Workload, Fault, External Mocks, Details, and Artifacts.

## 9. Inspect and rerun

Inspect a failed run:

```bash
wio workloads get <run-id>
wio workloads logs <run-id>
```

List artifacts:

```bash
wio artifacts ls <run-id>
```

Download an artifact:

```bash
wio artifacts download <run-id> stdout.log
```

Rerun a completed run with the same details:

```bash
wio workloads rerun <run-id>
```

Rerun uses the same command, seed, fault model, memory, timeout, branch, workload file, and mock configuration. For failed runs, inspect the logs, captured files, and artifacts, then sync the fix and rerun the same workload before increasing depth.

## Next

Read [Workloads](/docs/workloads/) to design stronger workloads, then read [CLI](/docs/cli/) for the full command reference.