fabro/docs/execution/run-configuration.mdx
Bryan Helmkamp 130339ee87 Add filename titles to TOML code blocks in docs
Every TOML example now shows which config file it belongs to
(server.toml, cli.toml, or run.toml) via Mintlify's title annotation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:06:57 -05:00

292 lines
8.5 KiB
Text

---
title: "Run Configuration"
description: "Configure workflow runs with TOML files"
---
A run config is a TOML file that bundles a workflow graph with all the settings needed to execute it — the goal, model, sandbox, setup commands, variables, and hooks. Instead of passing a dozen CLI flags, you check a `.toml` file into version control and launch with a single command:
```bash
arc run start run.toml
```
## Minimal example
A run config requires three fields:
```toml title="run.toml"
version = 1
goal = "Implement the login feature"
graph = "workflow.dot"
```
| Field | Description |
|---|---|
| `version` | Config format version. Must be `1`. |
| `goal` | What the workflow should accomplish. Passed to agents and used in retrospectives. |
| `graph` | Path to the DOT workflow file, resolved relative to the TOML file's directory. |
## Full example
```toml title="run.toml"
version = 1
goal = "Run the CI pipeline for $repo_name"
graph = "pipelines/ci.dot"
directory = "/tmp/workdir"
[llm]
model = "claude-sonnet-4-5"
provider = "anthropic"
[llm.fallbacks]
anthropic = ["gemini", "openai"]
gemini = ["anthropic", "openai"]
[setup]
commands = ["git clone $repo_url repo", "cd repo && npm install"]
timeout_ms = 120000
[sandbox]
provider = "daytona"
preserve = false
[sandbox.daytona]
auto_stop_interval = 60
[sandbox.daytona.labels]
project = "arc"
env = "ci"
[sandbox.daytona.snapshot]
name = "node-20"
cpu = 4
memory = 8
disk = 20
dockerfile = "FROM node:20-slim\nRUN apt-get update && apt-get install -y git"
[vars]
repo_name = "arc"
repo_url = "https://github.com/qltysh/arc"
[[hooks]]
event = "stage_start"
command = "./scripts/pre-check.sh"
blocking = true
sandbox = false
[[hooks]]
event = "run_complete"
command = "echo done"
```
## Sections
### `[llm]`
Override the default model and provider for all nodes that don't have an explicit model assigned via a [stylesheet](/workflows/stylesheets).
```toml title="run.toml"
[llm]
model = "claude-sonnet-4-5"
provider = "anthropic"
```
| Field | Description |
|---|---|
| `model` | Model ID or alias (e.g. `claude-sonnet-4-5`, `opus`, `gemini-pro`). See [Models](/core-concepts/models). |
| `provider` | Provider name: `anthropic`, `openai`, `gemini`, `kimi`, `zai`, `minimax`, `inception`. |
#### `[llm.fallbacks]`
Map each provider to an ordered list of fallback providers. When the primary provider is unavailable, Arc tries the fallbacks in order:
```toml title="run.toml"
[llm.fallbacks]
anthropic = ["gemini", "openai"]
gemini = ["anthropic", "openai"]
```
### `[setup]`
Shell commands to run before the workflow starts. Use this to clone repositories, install dependencies, or prepare the environment.
```toml title="run.toml"
[setup]
commands = ["pip install -r requirements.txt", "npm install"]
timeout_ms = 60000
```
| Field | Description |
|---|---|
| `commands` | List of shell commands, executed sequentially via `sh -c`. |
| `timeout_ms` | Per-command timeout in milliseconds. Default: `300000` (5 minutes). |
Each command must exit with status 0. If any command fails or times out, the run aborts before the workflow starts.
### `[sandbox]`
Configure how agent tools (bash, file edits) are executed.
```toml title="run.toml"
[sandbox]
provider = "docker"
preserve = true
```
| Field | Description |
|---|---|
| `provider` | Sandbox mode: `local` (default), `docker`, or `daytona`. |
| `preserve` | When `true`, keep the sandbox alive after the run finishes. Useful for debugging. |
#### `[sandbox.daytona]`
Additional settings when using the Daytona cloud sandbox:
```toml title="run.toml"
[sandbox.daytona]
auto_stop_interval = 60
[sandbox.daytona.labels]
project = "arc"
env = "staging"
[sandbox.daytona.snapshot]
name = "my-snapshot"
cpu = 4
memory = 8
disk = 20
dockerfile = "FROM rust:1.85-slim-bookworm\nRUN apt-get update"
```
| Field | Description |
|---|---|
| `auto_stop_interval` | Minutes of inactivity before the sandbox auto-stops. |
| `labels` | Key-value labels attached to the sandbox for filtering and identification. |
| `snapshot.name` | Snapshot name to create or use for the sandbox. |
| `snapshot.cpu` | CPU cores for the snapshot. |
| `snapshot.memory` | Memory in GB for the snapshot. |
| `snapshot.disk` | Disk in GB for the snapshot. |
| `snapshot.dockerfile` | Dockerfile content for building the snapshot image. |
| `network` | Network access mode: `"allow_all"` (default), `"block"`, or `{ allow_list = ["..."] }`. See [Sandboxing](/administration/sandboxing#network-access-control). |
### `[vars]`
Define variables that are expanded into the DOT source before the graph is parsed. See [Variables](/workflows/variables) for the full reference.
```toml title="run.toml"
[vars]
repo_name = "arc"
repo_url = "https://github.com/qltysh/arc"
language = "rust"
```
Variables can be used anywhere in the DOT file with `$name` syntax:
```dot title="c-i.dot"
digraph CI {
graph [goal="Run tests for $repo_name"]
clone [shape=parallelogram, script="git clone $repo_url repo"]
test [label="Test", prompt="Run the $language test suite."]
}
```
If a `$variable` in the DOT file has no matching entry in `[vars]`, Arc raises an error immediately. A bare `$` not followed by an identifier (e.g. `costs $5`) is left as-is.
### `[[hooks]]`
Define hooks that run in response to lifecycle events. Each hook is a TOML array entry:
```toml title="run.toml"
[[hooks]]
name = "pre-check"
event = "stage_start"
command = "./scripts/pre-check.sh"
matcher = "agent_loop"
blocking = true
timeout_ms = 30000
sandbox = false
```
| Field | Description |
|---|---|
| `name` | Optional display name for the hook. |
| `event` | Lifecycle event: `run_start`, `run_complete`, `stage_start`, `stage_complete`. |
| `command` | Shell command to execute (shorthand for `type = "command"`). |
| `matcher` | Regex matched against node ID or handler type. Limits which stages trigger this hook. |
| `blocking` | Whether the hook must complete before execution continues. Defaults vary by event. |
| `timeout_ms` | Hook timeout in milliseconds. Default: `60000` (60s). |
| `sandbox` | Run inside the sandbox (`true`, default) or on the host (`false`). |
See [Hooks](/agents/hooks) for hook types beyond simple commands (HTTP, prompt, agent).
## Top-level fields
In addition to the sections above, two optional top-level fields are available:
| Field | Description |
|---|---|
| `directory` | Working directory for the run. Defaults to the current directory. |
## Graph path resolution
The `graph` path is resolved relative to the TOML file's parent directory, not the current working directory. This means a run config and its workflow can live side by side:
```
project/
runs/
ci.toml # graph = "ci.dot"
ci.dot
```
Absolute paths are used as-is.
## Precedence
Settings can come from multiple sources. Arc resolves them in this order (first match wins):
| Source | Priority |
|---|---|
| Node-level [stylesheet](/workflows/stylesheets) | Highest |
| Run config TOML | |
| CLI flags (`--model`, `--provider`, `--sandbox`) | |
| Server defaults (`~/.arc/server.toml`) | |
| DOT graph attributes (`default_model`, `default_provider`) | |
| Built-in defaults | Lowest |
<Note>
For model and provider specifically, the precedence is: CLI flags > TOML config > server defaults > DOT graph attributes > built-in defaults. Stylesheet rules on individual nodes always take priority over all of these.
</Note>
### Server defaults
When running via `arc serve`, the server config at `~/.arc/server.toml` can set default values for `[llm]`, `[setup]`, `[sandbox]`, and `[vars]`. These defaults are applied to every run unless the run config overrides them.
For variables, defaults and run config are **merged** — the run config wins on key collisions:
```toml
# ~/.arc/server.toml
[vars]
default_key = "from_server"
shared = "from_server"
# run.toml
[vars]
shared = "from_run" # wins
task_key = "from_run"
```
The same merge behavior applies to Daytona labels. All other fields use simple "first non-empty wins" precedence.
## Validation
Arc validates the run config when it loads:
- **Version check** — Only `version = 1` is accepted. Other versions are rejected immediately.
- **Required fields** — `version`, `goal`, and `graph` are all required. Missing any of them is an error.
- **Unknown fields** — Extra fields not listed above are rejected (`deny_unknown_fields`).
- **Variable check** — Any `$variable` in the DOT file without a matching `[vars]` entry produces an error.
Use `--preflight` to validate a run config without executing it:
```bash
arc run start run.toml --preflight
```