Projects

WORKFLOW.md reference

Every front-matter key SI Fabrik reads, with its type, default and effect.

This page lists every key in the YAML front matter of WORKFLOW.md. Keys from the Symphony specification come first; SI Fabrik's extension keys follow. Unknown keys are ignored. For the prompt body, see Prompt template.

Values written as $NAME or ${NAME} are resolved on the host from the project and global environments. See Environment and variables.

tracker#

Where tasks come from.

KeyTypeDefaultDescription
tracker.kindstringrequiredlocal, clickup or github.
tracker.providermap{}Adapter settings; see Trackers and provider keys below.
tracker.active_stateslist or comma-separated stringby kindStates that are dispatched to agents. Must not be empty.
tracker.terminal_stateslistby kindStates that stop the agent and clean up the workspace (the branch is saved first).
tracker.board_stateslistby kindBoard columns, in order. For ClickUp, the list's own statuses are used unless you set this.
tracker.required_labelslist[]Only tasks with all of these labels are dispatched.

States are matched case-insensitively after trimming.

Kindactive_statesterminal_statesboard_states
localTodo, In ProgressDone, CanceledBacklog, Todo, In Progress, Human Review, Done, Canceled
clickupto do, in progresscomplete, closed, doneto do, in progress, review, complete (or the list's statuses)
githubopenclosedopen, closed

Tracker provider keys#

KindKeyDefaultDescription
localpath.symphony/board.jsonBoard file, relative to WORKFLOW.md.
localprefixHARIdentifier prefix, as in HAR-12. The wizard uses the first three letters of the project name.
clickupapi_token$CLICKUP_API_TOKENPersonal token (pk_…). token is accepted as an alias.
clickupsprint_folder_idA Sprints folder: use the current sprint.
clickuplist_id / list_idsFixed list or lists. Set this or sprint_folder_id.
clickupassigneeme or a user id. Other tasks aren't dispatched.
clickupinclude_subtaskstrueInclude subtasks.
clickupapi_urlhttps://api.clickup.com/api/v2API base URL.
githubreporequiredowner/name.
githubtoken$GITHUB_TOKEN, then gh auth tokenAPI token.
githubexclude_labels[human-review, blocked]Issues with any of these labels aren't dispatched.
githubapi_urlhttps://api.github.comAPI base URL (GitHub Enterprise).

polling#

KeyTypeDefaultDescription
polling.interval_msinteger30000How often the tracker is polled and running work reconciled. Minimum 1000. The wizard writes 15000.

workspace#

KeyTypeDefaultDescription
workspace.rootpath<temp>/symphony_workspaces/<project>Parent folder of the task workspaces. ~ and $VAR are expanded; relative paths resolve against the folder of WORKFLOW.md. The wizard writes ~/HarnessWorkspaces/<project>.
Note

Without workspace.root, each project gets its own folder under the system temporary directory, symphony_workspaces/<project>, rather than one folder shared by every project. Sharing would let one project see or remove another's workspaces.

hooks#

Shell scripts run at points in a workspace's life. See Workspaces and hooks.

KeyTypeDefaultDescription
hooks.after_createstringRuns once when a workspace is created. A failure removes the new workspace and fails the attempt.
hooks.before_runstringRuns before every attempt. A failure fails the attempt.
hooks.after_runstringRuns after every attempt. Failures are ignored.
hooks.before_removestringRuns before a workspace is removed. Failures are ignored.
hooks.timeout_msinteger60000Timeout for each hook. Must be positive.

agent#

KeyTypeDefaultDescription
agent.max_concurrent_agentsinteger10Agents running at once in this project. The host-wide limit also applies.
agent.max_turnsinteger20Turns per attempt. Must be positive.
agent.max_retry_backoff_msinteger300000Cap on the exponential retry delay (10 s × 2ⁿ).
agent.max_concurrent_agents_by_statemap{}Per-state caps, for example { "in progress": 2 }.

runner#

KeyTypeDefaultDescription
runner.kindstringclaude_codeclaude_code or codex. runner: codex (a plain string) also works. Without runner, a workflow that has a codex: block and no claude: block uses Codex.

claude#

Settings for the Claude Code runner.

KeyTypeDefaultDescription
claude.commandstringclaudeThe Claude Code executable.
claude.modelstringClaude Code's defaultPassed as --model, for example claude-opus-5-5.
claude.permission_modestringbypassPermissionsbypassPermissions, acceptEdits, default or plan. bypassPermissions is high-trust: use it with a sandbox.
claude.allowed_toolslist[]Passed as --allowedTools.
claude.disallowed_toolslist[]Passed as --disallowedTools.
claude.append_system_promptstringAdded to SI Fabrik's own system prompt.
claude.effortstringlow, medium, high, xhigh or max (--effort).
claude.max_budget_usdnumberClaude Code stops a session that would cost more (--max-budget-usd).
claude.extra_argslist[]Extra command-line arguments.

codex#

Settings for the Codex runner. The three timeouts apply to both runners, as in the Symphony spec.

KeyTypeDefaultDescription
codex.commandstringcodex app-serverThe Codex app-server command.
codex.modelstringModel, for example gpt-5.5-codex.
codex.approval_policyanyneverPassed through to Codex unchanged. Command and file-change approvals are accepted for the session.
codex.thread_sandboxanyworkspace-writePassed through unchanged.
codex.turn_sandbox_policyanyPassed through unchanged as the turn's sandbox policy.
codex.turn_timeout_msinteger3600000Silence timeout: a turn fails after this long without agent output.
codex.read_timeout_msinteger5000Timeout for protocol reads.
codex.stall_timeout_msinteger300000A run with no activity for this long is stopped and retried. 0 turns it off. The wizard writes 600000.

docker#

The Docker image and container settings. They also configure the image and environment of Cloudflare sandboxes.

KeyTypeDefaultDescription
docker.enabledbooleantrue if a docker: block exists, else falseRun agents in Docker. sandbox.provider overrides it.
docker.imagestringharness-agent:latestAgent image. With the browser on, the default becomes harness-agent-browser:latest.
docker.networkstringA Docker network to use instead of the egress proxy: no allowlist, and the model credential enters the container. Refused by the sandbox floor.
docker.envlist[]Host environment variable names passed into the sandbox. Push tokens and model credentials are never passed.
docker.cpusnumberno limitCPU limit (--cpus).
docker.memorystring8gMemory limit (--memory), for example 4g.
docker.extra_argslist[]Extra docker run arguments. Refused by the sandbox floor.

sandbox#

Where agents run and what they can reach. See Network policy.

KeyTypeDefaultDescription
sandbox.providerstringdocker when docker.enabled, else hostdocker, cloudflare or host. host is refused by the sandbox floor.
sandbox.network.modestringallowlistallowlist or open (any host, still through the egress proxy; not recommended).
sandbox.network.allowlist[]Extra hosts: host, *.domain, host:port or an IP.
sandbox.network.use_defaultsbooleantrueInclude the host-wide default list (Settings → Sandbox, or sandbox.network.default_allow on a server).
sandbox.hooksstringsandboxsandbox runs hooks in a disposable container with the agent's isolation; host runs them on the host (refused by the sandbox floor).
sandbox.read_only_rootbooleantrueRead-only root filesystem for agent containers. /workspace, /tmp and $HOME stay writable. false is refused by the sandbox floor.

gateway#

Route model traffic through an LLM gateway such as LiteLLM. Unset fields fall back to Settings → Model Gateway. See Model gateway.

KeyTypeDefaultDescription
gateway.enabledbooleanSettings defaultfalse opts this project out. A gateway: block without enabled turns it on.
gateway.base_urlstringSettingsGateway URL, for example http://localhost:4000.
gateway.api_keystringSettings keyUse $VAR, never an inline key.
gateway.auth_headerstringbearerbearer sets ANTHROPIC_AUTH_TOKEN; x-api-key sets ANTHROPIC_API_KEY.
gateway.modelsmapSettingsSlots: opus, sonnet, haiku, subagent, codex.
gateway.headersmap{}Extra request headers, for example { X-Team: platform }.
gateway.tagsbooleantrueSend x-litellm-tags: harness,project:<name>,issue:<id>.
gateway.disable_experimental_betasbooleanfalseSet true if the proxy returns 400 "Extra inputs are not permitted".
gateway.wire_apistringresponsesCodex only: responses or chat.

git#

Managed task branches. See Branches and pull requests.

KeyTypeDefaultDescription
git.manage_workspacebooleantrue unless you have your own after_create hookSI Fabrik clones the workspace and refreshes the base branch itself.
git.basestringthe repository's current branchWhere task branches start and PRs target.
git.savebooleantrueSave the task branch into the project repository after every attempt and before cleanup.
git.pushbooleantrue with a git: block, else falsePush the branch to remote at hand-off. Forced on when a PR is requested.
git.remotestringoriginRemote to push to.
git.pull_requeststring or booleandraft with a git: block, else offdraft, ready or off. true means draft.
git.providerstringdetected from the remote URLgithub, gitlab or none (push only).
No git block, no pull requests

Without a git: block, branches are still saved into your repository, but nothing is pushed and no PR is opened. The wizard always writes a git: block.

limits#

Guardrails for this project. See Budgets and limits.

KeyTypeDefaultDescription
limits.daily_budget_usdnumbernoneNo new attempts or continuation turns once today's spend reaches this. Resets at local midnight.
limits.daily_token_budgetintegernoneThe same, in tokens.
limits.max_cost_per_issue_usdnumbernonePark a task once its attempts together cost this much.
limits.max_attempts_per_issueinteger5Park a task after this many failed attempts in a row. 0 retries forever.
limits.pause_after_consecutive_failuresinteger5Pause the project after this many failures in a row across all tasks. 0 never pauses.

browser#

A headless Chromium with the Playwright MCP server in the sandbox. See Browser testing and previews.

KeyTypeDefaultDescription
browser.enabledbooleantrue if a browser: map existsGive agents a browser.
browser.viewportstring1280x800Window size, WIDTHxHEIGHT (each 200–4000).
browser.devicestringA Playwright device name to emulate.
browser.imagestringharness-agent-browser:latestBrowser image, unless docker.image is set to something else.

preview#

How to run the project's app in the sandbox.

KeyTypeDefaultDescription
preview.setupstringRuns once per workspace before the app starts, for example npm ci.
preview.commandstringStarts the app, for example npm run dev -- -H 0.0.0.0.
preview.portintegerPort the app listens on. Preview is on when command and port are both set.
preview.readystring/Path that answers once the app is up.
preview.ready_timeout_sinteger300How long to wait for it, 10 to 1800 seconds.

What this project uses from elsewhere, and who may use it. See Project links and Linked tasks.

KeyTypeDefaultDescription
links.packages[]list[]Packages: name, from (registry, git or source), registry, url, project, ref, token_env, username (git, default oauth2).
links.services[]list[]Services: name, env, and either url (hosted) or project (run next to the agent) with optional ref and port.
share_withlist[]Projects allowed to use this project's code and app.
accept_tasks_fromlist[]Projects whose agents may file linked tasks here.
linked_tasks_statestringBacklogWhere linked tasks land. An active state runs them without review.

server#

KeyTypeDefaultDescription
server.portintegerInformational only. The app-wide port is set in Settings → General.

See also#