Smart Agent Teams

Workspaces

Where sat runner puts repositories, per-run git worktrees and agent scratch folders, and how to clean them up.

Every run executes in a directory on the runner's machine, its workspace. If the task belongs to a project with a repository, the agent works in a fresh git worktree on its own branch, so concurrent runs never share a checkout. Otherwise it works in a persistent scratch folder of its own. Workspaces stay on disk after the run so you can review the work. The runner never pushes anything.

Layout

The root is the runner's workdir. Under it, one folder per company, named after the company's task prefix in lower case:

PathWhat it is
.bin/satThe sat shim put first on the agent's PATH. See Adapters
.sat-agent-config/The empty configuration directory given to agents as SAT_CONFIG_DIR (mode 0700)
nf/The company with task prefix NF
nf/web-app/repo/The project's clone, made once and shared by all its runs
nf/web-app/runs/3f2a6c1e/A git worktree for one run, named after the first 8 characters of the run id
nf/agents/maya/Maya's scratch folder, for runs without a project repository

Folder names are slugs: lower case, runs of other characters replaced by -, at most 40 characters. The project "Web app" becomes web-app; the agent "Maya" becomes maya.

Where the workdir is

The first one set wins:

  1. --workdir <dir> on sat runner start
  2. SAT_WORKDIR
  3. $XDG_DATA_HOME/sat/workspaces
  4. ~/.local/share/sat/workspaces

Two runners on one machine can share a workdir. The API runs one run per agent at a time, and each project run gets its own worktree.

Runs in a project with a repository

When the run's task has a project and the project's repository is set:

Clone once

If <workdir>/<prefix>/<project>/repo has no .git, the runner clones the repository there with git clone --quiet. If it already exists, the runner runs git fetch --quiet --all --prune in it, and ignores fetch errors.

Add a worktree for the run

The runner creates a worktree at runs/<run8> on a new branch, starting from the clone's origin/HEAD (usually origin/main), or from the clone's HEAD if origin/HEAD is not set:

# run inside repo/
git worktree add --quiet -b sat/nf-12-3f2a6c1e ../runs/3f2a6c1e origin/main

The branch is sat/<task key>-<run8>, with the task key slugged (NF-12 becomes nf-12). If the worktree folder already exists, it is reused.

Run the agent there

The agent's working directory is the worktree. The first transcript entry the runner writes says where, for example Runner grace-laptop:4242 · worktree /home/grace/.local/share/sat/workspaces/nf/web-app/runs/3f2a6c1e on branch sat/nf-12-3f2a6c1e.

Clone URL rules

The runner passes the project's repository value to git clone with one rewrite:

repositoryCloned from
github.com/noteflow/web (exactly host/owner/name)https://github.com/noteflow/web
https://github.com/noteflow/web.gitUsed as given
git@github.com:noteflow/web.gitUsed as given
/srv/git/webUsed as given (a local path)

The clone runs as the runner's user, with that user's git configuration, SSH agent and credential helpers. For a private repository, give the runner's account read access. If the clone fails, the run fails with the git error, for example git clone --quiet https://github.com/noteflow/web /home/... failed: Repository not found.

Runs without a repository

A run uses the agent's scratch folder, <workdir>/<prefix>/agents/<agent>, when:

  • the run has no task (a heartbeat), or
  • the task has no project, or
  • the project has no repository.

The folder persists between runs, so the agent can keep notes and files there. The first transcript entry the runner writes is Runner <id> · scratch folder <path>.

Nothing is pushed

The runner never commits, pushes or opens pull requests. The agent's changes stay in the worktree and its local branch, where you review them:

cd ~/.local/share/sat/workspaces/nf/web-app/repo
git log --oneline main..sat/nf-12-3f2a6c1e
git diff main...sat/nf-12-3f2a6c1e

The agent itself can run git commands, including git push, if its permission mode lets it run commands and the runner's git credentials allow it. If you do not want agents to push, run the runner as an account without push rights. See Runner security.

Clean up

The runner does not delete workspaces. Worktrees and sat/... branches accumulate, one per project run. Clean them up yourself, for example from a weekly cron job.

Advice

These commands are suggestions, not something SAT runs. Check that you have kept the work you want before you remove a worktree.

REPO=~/.local/share/sat/workspaces/nf/web-app/repo

git -C "$REPO" worktree list                              # what exists
git -C "$REPO" worktree remove ../runs/3f2a6c1e            # remove one worktree
git -C "$REPO" worktree prune                              # forget worktrees whose folders you deleted
git -C "$REPO" branch --list 'sat/*' --merged origin/main \
  | xargs -r git -C "$REPO" branch -d                      # delete merged sat/ branches

Do not remove the worktree of a run that is still running; sat runner status lists them with their run ids. Scratch folders under agents/ hold an agent's notes between runs, so remove them only when you mean to reset the agent.

On this page