Configuration Reference#
config.yaml controls repositories, providers, security, validation, checks, git publishing, and optional notification settings. The packaged example is config.example.yaml; install copies it verbatim to .worc/config.example.yaml as a commented, field-by-field reference beside the generated executable .worc/config.yaml (the reference is never loaded at runtime — only config.yaml is read). The canonical contract is the config schema in the code (config/schema.py). For definitions of all config keys and their purpose, see the Glossary.
The loader is fail-closed:
- unknown top-level keys are rejected;
- unknown keys inside known blocks are rejected;
- unknown enum values are rejected;
- semantic validation rejects unsafe or contradictory settings.
The current schema lives in src/wastech_orchestrator/config/schema.py; defaults come from src/wastech_orchestrator/config/loader.py.
Minimal Shape#
Most fields have safe defaults, but a real run needs at least a target repository and one configured provider:
repo:
url: "git@github.com:OWNER/REPO.git"
local_path: "./workspace/repo"
agents:
allowed:
- codex
providers:
codex:
command: "codex"
primary: true
Exactly one configured provider must set primary: true — the global primary that runs any flow node with no explicit provider, and the sole infrastructure-fallback target. Provider routing is per flow node (a node declares its own provider, else the global primary); there is no stage-keyed agents.routing block (removed in schema_version 11). A legacy config that still carries agents.routing loads fail-open — the key is tolerated and ignored, and upgrade-config strips it.
The config.yaml that install generates is deliberately small — smaller than this reference. It carries only what the install actually resolved (repo.*, agents.allowed + the selected agents.providers.*, git.create_pull_request / pr_base, orchestrator.auto_mode.enabled), the one block that deviates from the fail-closed dataclass defaults — the security posture, written key by key so an operator reading their own file sees the relaxation — and three affordances written at their default because you need to find them: paths.tasks_dir, an empty checks.command_sets, and telegram.enabled. Every other block is absent, and an absent key resolves to exactly the value documented here, so the generated file is what you must decide, not a transcript of the schema. Its footer lists, block by block, what it left out and where to copy it from. Add a block only to change something.
Two defaults differ between the dataclass/loader and what install writes, and both are in security (see security): strict_isolation (dataclass true, install writes false — which is the advanced mode) and allow_git_evidence (dataclass false, install writes true). Everything else install used to spell out has since been aligned with its default, logging.level (warning) and supervisor.observe.reasoning (low) included.
schema_version#
schema_version: 41
Optional top-level integer marking the config.yaml format version (current: 41 — the bump to 41 added repo.governance_paths). The orchestrator refuses a config whose schema_version is newer than it understands (clean error: message, exit 2) so an older install never misreads a newer format; an absent or older value is accepted. install stamps the current version into generated configs. It is bumped only when the config format changes, independently of the package version. See the spec's "Versioning and compatibility" section and operations → Upgrading the orchestrator.
Config Discovery#
Every command except install, clear, and completion loads config; each resolves config.yaml in this order:
- an explicit
--config PATH; <repo-root>/.worc/config.yaml, discovered by walking up from the current directory to the Git root (so any command works from any subdirectory of the repo);- otherwise the command exits non-zero with a hint to run
wastech-orchestrator install ..
There is no per-user registry and no ./config.yaml fallback: discovery is a pure walk-up to the Git root. A config generated by install uses an absolute, native path for repo.local_path, so the commands work regardless of the current directory, and watch reads tasks/pending from the repo root.
Where each key is documented#
The reference is four pages plus this one. Every config.yaml top-level key is listed here once, so that this page stays the place you look first.
Two things config.yaml no longer owns are documented on the same page as the flow graph: the prompt templates that moved into each flow's role files, and flow dispatch and per-node overrides. The flow file format itself is flow-authoring.md.
Common Examples#
Codex-only setup (Codex is the global primary; with no other allowed provider, every node runs on it and an infrastructure failure is terminal):
agents:
allowed:
- codex
providers:
codex:
command: "codex"
primary: true
model: ""
timeout_seconds: 7200
permission_profile: "workspace-write" # the access level; NOT `sandbox`
extra_args: []
Note there is no sandbox: key here: it is rejected at config load at any value (removed in schema_version 38 — the access level is permission_profile, and the provider full-access modes are refused outright; see agents.providers). upgrade-config does not delete the line for you.
Audit commit on a separate sibling branch (keeps the code branch free of the orchestrator's commit):
git:
footprint:
audit_on_branch: sibling
Conservative retry budget:
agents:
max_stage_attempts: 3
max_fix_cycles: 15
max_total_fix_iterations: 30
Validation Checklist#
Before running tasks:
worc preflightsucceeds (providers, isolation, Telegram, the command-set summary);worc validate-flow --allsucceeds — flows are not checked by preflight, and a config edit can invalidate a flow (a narrowedsupervisor.observe.mode, a provider dropped fromagents.allowed, areasoningthe resolved provider rejects). Treat config editing as done only when both are green;command -v/whereresolves provider andghexecutables in the same environment that launches the orchestrator;- exactly one provider sets
primary: true, and it is inagents.allowed; - every flow node's declared
provideris inagents.allowed; - every allowed provider has an
agents.providersentry; max_total_fix_iterations >= max_fix_cycles;agents.decomposition.max_subtasks >= 2;- the target repo's tracked
.gitignoreignores.worc/and.worc-io/(installappends both), plus the anchored/tasks/line for the lifecycle tree unless you chose to track task files; - the target clone does not track
.worc/; - no
extra_argsdisable sandbox or approvals — the two provider full-access selectors are refused at every value ofsecurity.strict_isolation, so a config carrying one never loads; security.allowed_environmentcoversPATH(a load error otherwise) and, on Windows,SystemRoot(a launch-critical preflight FAIL, re-checked atrun/watch/rerunstart);- no
security.extra_environmentvalue points at.git,.worc,.worc-io, the tasks dir, the env-file, or adenied_read_pathsmatch — checked lexically at load and canonically in preflight (assigned-paths:); - you have decided about
security.strict_isolation: a freshinstallwritesfalse, which is the advanced mode; - secrets are configured outside
config.yaml.