Configuration
valved init scaffolds a project’s config. This page summarizes each file; the control plane merges them into one effective config at runtime.
valved.toml — control-plane config
Section titled “valved.toml — control-plane config”The project-root config. References components by name rather than containing them.
[project]name = "jaffle-shop"default_target = "dev"
[paths]config_dir = "valved"agents_dir = "valved/agents"targets_dir = "targets"
# The state-store URL is NOT set here — it comes from the DATABASE_URL# env var (documented in .env.example), Postgres only.
# [components.<name>] blocks are OPTIONAL — omit them for "simple mode"# (components discovered by convention). Add them when a component graduates.[components.analytics]type = "dbt" # "dlt" | "dbt"mode = "separate-remote" # "same-repo" | "separate-local" | "separate-remote"url = "git@github.com:acme/analytics.git"ref = "9f3a1c7" # optional pin (SHA or tag)# branch = "main" # or track a branch HEAD[components.<name>] fields. type and mode are always required; path is required for separate-local, url for separate-remote; ref/branch are optional pins.
| Field | Applies to | Meaning |
|---|---|---|
type |
all | dlt | dbt. Required. |
mode |
all | same-repo | separate-local | separate-remote. Required. |
path |
separate-local |
Path outside the control-plane tree. |
url |
separate-remote |
Git URL. |
ref / branch |
separate-remote |
Pin to a SHA/tag, or track a branch HEAD. |
sync_mode |
separate-remote |
hard (default — git fetch && reset --hard) or soft (git pull). |
sync_before_run |
separate-remote |
Default true. Set false to skip the before-each-run sync (offline operation). |
worker_label |
all | Worker-placement label. Read live — the runtime reduces a pipeline’s components’ labels to the job’s required_label at enqueue, and only a worker started with a matching valved worker --label claims it. |
dbt_backend |
dbt | local | snowflake-native | dbt-cloud | remote. See the caution below. |
dbt_engine |
dbt | fusion | dbt-core. Omit to auto-resolve from the target’s warehouse dialect; once resolved it is written back here and reused. |
dbt_version |
dbt | The engine version pin, resolved and written back alongside dbt_engine. |
dbt_adapter_version |
dbt | Pins the warehouse adapter (dbt-snowflake and friends) independently — dbt-core and its adapters do not release in patch lockstep. Omit to pin the adapter to dbt_version. |
dbt_env |
dbt | bundled (Valved-managed engine, the default) or external (a user-installed dbt). |
dbt_path |
dbt, dbt_env = "external" |
The external dbt executable. |
profiles_dir |
dbt, dbt_env = "external" |
The dbt profiles dir to pass through as --profiles-dir. |
dbt_path and profiles_dir are rejected at config load unless dbt_env = "external". All the dbt_* fields are optional, so a dlt component — or a convention-discovered dbt component that auto-resolves — round-trips with none of them set.
Pin precedence: ref → branch → default-branch HEAD. Convention-discovered components are never pinned.
valved/connections.toml — targets
Section titled “valved/connections.toml — targets”Named targets (dev, prod, …). A target’s dialect is the block it appears under — [snowflake.<target>] or [duckdb.<target>] — and its credentials are referenced via env vars, never inlined.
[duckdb.dev]path = "./dev.duckdb" # ":memory:" for an ephemeral database
[snowflake.prod]account = "${PROD_SNOWFLAKE_ACCOUNT}"user = "${PROD_SNOWFLAKE_USER}"
# --- Authentication: pick exactly ONE of the four methods below.# The connector resolves them in this order: oauth > externalbrowser ># key-pair > password. Keep the unused methods commented — the build# agent follows whichever method is live here when it generates code.## (1) Browser SSO — interactive sessions only, no secret on disk:authenticator = "externalbrowser"## (2) Key-pair — recommended for automation/scheduled runs. If the key# is encrypted, set SNOWFLAKE_PRIVATE_KEY_PASSPHRASE in .env:# private_key_path = "${PROD_SNOWFLAKE_PRIVATE_KEY_PATH}"## (3) Password:# password = "${PROD_SNOWFLAKE_PASSWORD}"## (4) OAuth / workload identity — for a Valved running inside a platform# that issues its own token. `user` is not required: the token# identifies the caller.# authenticator = "oauth"# token_file_path = "/snowflake/session/token"# host = "${SNOWFLAKE_HOST}"# ---
role = "TRANSFORM"warehouse = "TRANSFORM_WH"database = "ANALYTICS"schema = "DBT"valved init scaffolds the default target’s [snowflake.<name>] section commented out (a fresh project loads without warehouse credentials, and a dlt ingestion needs none). Activate it by uncommenting and filling the env vars in .env, or by running valved target create <name> — not both.
OAuth / workload identity
Section titled “OAuth / workload identity”Two fields, meaningful only under authenticator = "oauth":
| Field | What it does |
|---|---|
token_file_path |
A file holding the bearer token, re-read on every connection. Prefer this: a platform-issued token is short-lived and rotated in place, so a path survives rotation where a value read once does not. |
token |
The token inline (via ${VAR} interpolation), for a token that arrives as an env var. Resolved once, so it cannot be refreshed — the weaker option. |
host is separate from the auth method — any method may set it to override the endpoint the driver derives from account — but it usually travels with OAuth, because a platform that issues a token generally also names the endpoint that token is valid against.
The motivating case is Valved running inside the warehouse’s own platform. Snowpark Container Services mounts a rotating token at /snowflake/session/token and sets SNOWFLAKE_HOST; with those two fields Valved uses them directly, with no key to store and no credential leaving the platform that issued it. Neither field is specific to that platform.
Under OAuth, user may be omitted — the token identifies its own caller. It stays required for every other method, and omitting it there is a config error at load time.
Credential indirection: ${ENV_VAR} interpolation from .env or your shell. Valved never stores secrets in the state store.
valved/runner.toml (scaffolded)
Section titled “valved/runner.toml (scaffolded)”Venv-backed execution knobs (all commented by default → built-in defaults apply). The file’s keys populate the runner section of the merged config, so [auto_fix] here is [runner.auto_fix] merged, and [plausibility] is [runner.plausibility].
# type = "local_venv"# venv_cache_dir = ".valved/venvs"# default_timeout_seconds = 1800# max_concurrent_runs = 4
# [auto_fix] # recovery budget per failure# enabled = true# max_attempts = 3
# Load-plausibility gate: a successful load must also be credible.# See Concepts → Scheduling & runs → "Load plausibility".# [plausibility]# enabled = true # opting out is explicit, never silent# suspect_ratio = 0.5 # actual < 0.5 × expected → run marked "⚠ suspect" (still success)# implausible_ratio = 0.1 # actual < 0.1 × expected → run fails ("Implausible load")
# Per-pipeline overrides (unset fields inherit the globals). `min_rows`# declares explicit per-resource row floors — the only run-over-run# judgment an append/incremental resource gets once it has history.# [plausibility.pipelines.stripe_charges]# suspect_ratio = 0.3# [plausibility.pipelines.stripe_charges.min_rows]# charges = 1000valved plan warns when a plan’s own runtime estimate reaches 80% of default_timeout_seconds, so a long first load isn’t killed at the ceiling twenty minutes in — raise the timeout before running, not after.
valved/models.toml (scaffolded)
Section titled “valved/models.toml (scaffolded)”How the harness authenticates to Anthropic and which model it defaults to.
# auth_mode = "api_key" # ANTHROPIC_API_KEY | "oauth" (ANTHROPIC_AUTH_TOKEN)# anthropic_api_key = "${ANTHROPIC_API_KEY}"# default_model = "claude-opus-5"
# [tiers] # optional named tiers a per-agent model: may reference# fast = "claude-haiku-4-5"Leave auth_mode unset to auto-resolve (API key first, then a Claude-subscription OAuth token minted via valved auth login).
valved/runtime.toml (optional — not scaffolded)
Section titled “valved/runtime.toml (optional — not scaffolded)”Tunes the runtime supervisor. Create it only to override defaults. Today it carries the archiver’s [archive] block:
[archive]interval_s = 3600jobs_window = "7d" # jobs age out before the runs they referenceruns_window = "30d"logs_window = "30d"The other supervisor loops run on built-in defaults (the scheduler and reaper tick every 30 s; a crashed worker’s jobs are reclaimed after missed heartbeats); their file-config surfaces land as they ship. The REST server’s host/port and CORS policy live in their own optional valved/api.toml ([cors] — the OSS default already allows any loopback origin for the static UI).
Control-plane recovery — defaults only
Section titled “Control-plane recovery — defaults only”Recovery is on by default, with a $5/day cost cap.
Neither value is settable from a config file today. A [recovery] block is defined in the schema (enabled, daily_token_budget_usd) but the config loader does not read it from valved.toml or from any file under valved/. Writing one is silently ignored — no error, no effect.
What the cap actually counts is broader than its name suggests. Before each diagnosis, recovery compares the ceiling against today’s total agent spend across the whole install — every agent invocation since midnight UTC, including plans, builds, asks, and reviewer passes, not just recovery diagnoses. The state store exposes no recovery-only slice, so this is a deliberate over-count: it trips sooner than a recovery-only tally would, never later.
The practical consequence: on a busy day of planning and building, the recovery budget can already be exhausted before anything fails. When the cap is hit, recovery logs and skips — it does not invoke the diagnosis agent at all, so you get no investigation for that failure.
The cap is checked once, before diagnosis; it does not interrupt one in flight. A per-invocation token bound backs it up so a single diagnosis cannot blow through the ceiling on its own.
Distinct from [runner.auto_fix] above, which governs the interactive valved el run fix loop — a different agent with a per-failure attempt budget, not a daily dollar cap.
pipelines/<name>.toml
Section titled “pipelines/<name>.toml”A pipeline’s step DAG plus an optional [seed_schedule]. There is no paused/enabled key: pause/resume is live data (valved schedule).
Write the first one by hand. The pipeline engineer that owns pipelines/** is granted edit and not create_file, so valved build can modify an existing composition but never creates one. Validate what you wrote with valved pipelines validate <name>.
Extensibility files
Section titled “Extensibility files”| File | Format | Notes |
|---|---|---|
valved/agents/<name>.md |
Markdown + YAML frontmatter | Overrides a built-in of the same name. |
valved/skills/<name>/SKILL.md |
Markdown + frontmatter | A skill; testable with valved skills test. |
valved/hooks.toml |
TOML | Lifecycle hooks. |
valved/mcp.toml |
TOML | External MCP servers Valved consumes. |
Files Valved generates
Section titled “Files Valved generates”.valved/— generated runtime state (gitignored), including.valved/token(the REST/MCP bearer token, mode0600) and.valved/venvs/..dlt/secrets.toml— dlt connector credentials (gitignored)..dlt/config.tomlis safe to commit.
The exhaustive schema for every file lives in the project’s specs/reference/config-schema.md.