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

# Running a Simulation

> silo run, its flags, and repeated rollouts

```bash theme={null}
npx @burn0/silo run --env demo --task TASK-002 --agent ./silo.agent.ts
```

```
  Silo Run

  Task          TASK-002 — Rehome a departed rep's open pipeline
  Result        PASS
  Reward        1.00
  Duration      0.0s

  Tool calls    3
  Successful    3
  Errors        0

  Checks        5 / 5
  Required      3 / 3

  Run saved: .silo/runs/run_20260915020238_9s01
```

| Flag                   | Default           | Purpose                            |
| ---------------------- | ----------------- | ---------------------------------- |
| `--env <name>`         | required          | Which environment to run in        |
| `--task <id>`          | required          | Which task to attempt              |
| `--agent <path>`       | `./silo.agent.ts` | Your agent module                  |
| `--runs <n>`           | `1`               | Repeat the task from a fresh world |
| `--max-tool-calls <n>` | `100`             | Abort after this many tool calls   |
| `--timeout-ms <n>`     | `120000`          | Abort after this long              |

## Every rollout starts clean

`createState()` is called fresh for each rollout, so one run cannot contaminate the next. That is what makes repeated runs comparable and what lets you attribute a difference in score to the agent rather than to leftover state.

It is also why `createState()` must return a newly cloned object. Return a cached import directly and rollout two inherits rollout one's mutations — see [State](/silo/environments/state).

## Repeating a task

Agents are not deterministic. One passing run tells you a task is achievable, not that your agent achieves it.

```bash theme={null}
npx @burn0/silo run --env demo --task TASK-004 --agent ./solver.ts --runs 3
```

```
  Silo Runs

  Task          TASK-004 — Report the weighted value of open pipeline
  Rollouts      3
  Passed        3 / 3
  Mean reward   1.00
  Best          1.00
  Worst         1.00

  run 1         PASS    reward 1.00  ·  1 calls  ·  completed
  run 2         PASS    reward 1.00  ·  1 calls  ·  completed
  run 3         PASS    reward 1.00  ·  1 calls  ·  completed
```

Rollouts run sequentially, each from a fresh world, and each writes its own run directory. The spread is the interesting part: `Best 1.00 / Worst 0.20` means an agent that sometimes finds the answer, which is a different problem from one that never does.

## Comparing agents

`--agent` is just a path, so the natural way to compare two approaches is to point at each in turn against the same task and seed:

```bash theme={null}
npx @burn0/silo run --env demo --task TASK-002 --agent ./agents/haiku-loop.ts --runs 5
npx @burn0/silo run --env demo --task TASK-002 --agent ./agents/sonnet-loop.ts --runs 5
```

Because the world is identical each time, the difference in pass rate is attributable to the agent.

## Limits

```bash theme={null}
npx @burn0/silo run --env demo --task TASK-001 --max-tool-calls 50 --timeout-ms 60000
```

When either limit trips, the run's `signal` aborts, further `callTool` calls stop, and the run terminates with `max_tool_calls` or `timeout`. A long-running loop should check `signal.aborted` and return what it has rather than spinning.

Limits are recorded in `run.json`, so a run that hit one is legible after the fact rather than looking like an agent that gave up.

## When a run does not complete

Every run ends with one of four reasons:

| `terminationReason` | Meaning                            |
| ------------------- | ---------------------------------- |
| `completed`         | The agent returned normally        |
| `max_tool_calls`    | The tool-call budget was exhausted |
| `timeout`           | The time budget was exhausted      |
| `agent_error`       | The agent threw                    |

<Note>
  `agent_error` with **0 tool calls and a near-zero duration** almost always means the agent never reached its model — usually a model server that is not running. A genuine model failure shows up as tool errors or a timeout, after some work.
</Note>

A run that fails still produces artifacts. A rollout that dies before its first tool call writes a trace containing the task, the config and the failure, because an empty directory is the least useful thing to find when something broke.

## Where results go

```
.silo/runs/<runId>/
├── trace.jsonl
├── result.json
├── state-diff.json
└── run.json
```

Run ids are collision-free, so concurrent runs and `--runs` sweeps never overwrite each other. See [Run Artifacts](/silo/running/artifacts).
