Skip to main content
The workspace configuration section controls where Symphony creates per-issue workspace directories for agent execution.

Configuration

WORKFLOW.md
workspace:
  root: ~/code/symphony-workspaces

Fields

root
string
default:"<system-temp>/symphony_workspaces"
Base directory for all agent workspaces.Each issue gets an isolated subdirectory under this root:
<workspace.root>/<sanitized-issue-identifier>/
Supports:
  • Tilde expansion: ~/code/workspaces expands to home directory
  • Environment variables: $WORKSPACE_ROOT reads from environment
  • Absolute paths: /var/symphony/workspaces
  • Relative paths: Bare names without separators (discouraged)
Path expansion rules:
  • Paths containing / or \ are expanded to absolute paths
  • Bare strings without separators are preserved as-is
  • Environment variable references using $VAR_NAME are resolved before expansion

Workspace Lifecycle

Creation and Reuse

Workspaces are persistent across runs:
  1. First run: Directory is created and after_create hook executes
  2. Subsequent runs: Existing directory is reused (no hook)
  3. Successful completion: Workspace is preserved (not deleted)
  4. Terminal states: Workspace is cleaned up on next service startup

Path Sanitization

Issue identifiers are sanitized to create safe directory names:
  • Only [A-Za-z0-9._-] characters are preserved
  • All other characters are replaced with _
  • Example: ABC-123 stays ABC-123, XYZ/456 becomes XYZ_456

Safety Invariants

Symphony enforces strict workspace path validation:
Critical: Codex agents run only inside validated workspace paths. Workspace paths must:
  • Be inside the configured workspace root (path prefix check)
  • Not equal the workspace root itself
  • Not contain symlinks that escape the root
# Workspace validation from source
defp validate_workspace_path(workspace) do
  expanded_workspace = Path.expand(workspace)
  root = Path.expand(Config.workspace_root())
  root_prefix = root <> "/"

  cond do
    expanded_workspace == root ->
      {:error, {:workspace_equals_root, expanded_workspace, root}}

    String.starts_with?(expanded_workspace <> "/", root_prefix) ->
      ensure_no_symlink_components(expanded_workspace, root)

    true ->
      {:error, {:workspace_outside_root, expanded_workspace, root}}
  end
end

Path Expansion Examples

Tilde Expansion

workspace:
  root: ~/symphony-workspaces
Expands to: /home/username/symphony-workspaces

Environment Variable

workspace:
  root: $SYMPHONY_WORKSPACE_ROOT
Resolves $SYMPHONY_WORKSPACE_ROOT from environment, then expands the path.

Absolute Path

workspace:
  root: /var/lib/symphony/workspaces
Used directly as an absolute path.

System Temp (Default)

workspace: {}
Defaults to: <system-temp-dir>/symphony_workspaces

Workspace Structure

Example workspace layout for issue ABC-123:
~/code/symphony-workspaces/
└── ABC-123/
    ├── .git/
    ├── src/
    ├── README.md
    └── ... (issue-specific files)

Configuration Reloading

Workspace root changes are applied dynamically:
  • New workspace creations use the updated root
  • Existing workspaces continue in their original location
  • Running agents are not affected by configuration changes
Changing workspace.root while agents are running can result in workspaces split across multiple directories. Consider restarting Symphony after root path changes.

Cleanup Behavior

Startup Cleanup

On service startup, Symphony:
  1. Queries the tracker for all issues in terminal states
  2. Removes workspace directories for those issues
  3. Continues startup even if cleanup fails (logs warning)

Reconciliation Cleanup

During each poll tick:
  • Running issues that transition to terminal states are stopped
  • Their workspaces are immediately cleaned up
  • Issues that become non-active (but not terminal) are stopped without cleanup

Manual Cleanup

Workspaces can be manually removed:
rm -rf ~/code/symphony-workspaces/ABC-123
The workspace will be recreated on the next run for that issue.
  • hooks - Configure workspace lifecycle scripts
  • codex - Control agent execution and sandboxing
  • agent - Manage concurrency and retry behavior

Build docs developers (and LLMs) love