Adding a machine to a multi-machine fleet

Install Relay, enroll a second machine, start its broker, and verify a worker can join the fleet. Includes recovery steps for the failures that slow setup down.

Run these steps on the machine you are adding, in a terminal or over SSH. You need access to the fleet's existing Cloud workspace and at least one installed, authenticated coding harness. Each machine runs a broker.

Commands were checked against Agent Relay 11.10.4 on September 9, 2026. The troubleshooting notes cover setup, harness authentication, and disk hygiene.

1. Install and check which binary runs

curl -fsSL https://raw.githubusercontent.com/AgentWorkforce/relay/main/install.sh | bash
command -v agent-relay
agent-relay --version

The installer puts its launcher in ~/.local/bin and the standalone binaries in ~/.agentworkforce/relay/bin. Ensure the launcher is on your shell's PATH:

export PATH="$HOME/.local/bin:$PATH"
hash -r
command -v agent-relay
agent-relay --version

Add that PATH export to your shell startup file if it is not already there. Open a new terminal and check again; a PATH change inside the installer cannot update its parent shell.

An older npm i -g agent-relay install can shadow the new launcher. On Apple Silicon Macs its symlink is often /opt/homebrew/bin/agent-relay. If command -v agent-relay selects that path, the version can stay old even after a successful install. This is an npm global, not a Homebrew formula: brew uninstall agent-relay fails with “No available formula”.

If you have the old npm global, remove it with the npm installation that owns it, then check the launcher again:

npm uninstall -g agent-relay
hash -r
command -v agent-relay
agent-relay --version

Keep fleet machines on the same current release.

2. Choose the broker root and enroll

Give this node a stable directory and a name unique within the workspace. The examples use mini-node-2. Reuse the same directory for every broker command.

mkdir -p "$HOME/fleet/mini-node-2/.agentworkforce/relay"
cd "$HOME/fleet/mini-node-2"
agent-relay cloud login --device
agent-relay cloud workspaces

Complete the browser login, then select the existing workspace used by the first machine. Replace your-fleet-workspace below with its name or ID from the list:

agent-relay cloud enroll --workspace your-fleet-workspace --name mini-node-2

Creating .agentworkforce/relay in that directory makes it a broker root; otherwise project discovery can walk up to an ancestor, including your home directory.

Enrollment saves this node's credential locally. Expect an Enrolled node message with the intended workspace. Run enrollment in the broker root too: an existing project workspace pin can affect which enrollment startup selects. A fresh directory avoids accidentally inheriting an unrelated project's pin. If enrollment reports a pin conflict, resolve that binding before starting the broker; do not delete another node's credentials to work around it.

This path uses your Cloud login without copying workspace keys or enrollment tokens into commands. If an administrator already enrolled this context, use that context's directory and name and skip enrollment. See Nodes and providers for the distinction between a machine and a node.

3. Start the broker with an explicit name

cd "$HOME/fleet/mini-node-2"
agent-relay node up --no-spawn --background --broker-name mini-node-2
FlagPurpose
--no-spawnStart the broker without automatically launching agents from teams.json.
--backgroundLeave the broker running after the command returns.
--broker-nameGive this node an explicit workspace identity.

Use agent-relay node up. The installer checked for this guide still prints agent-relay up --background in its quickstart, but agent-relay up fails in 11.10.4 with error: unknown command 'up'.

Without an explicit name, startup uses the enrolled node name when available, otherwise the project directory basename. Starting from ~ can therefore try to register the broker as your username. If that name already belongs to a human, registration can fail with:

agent name X is already registered and this registration did not prove ownership

Choose a machine-specific name such as mini-node-2, then rerun the startup command. Do not remove the human identity to make room for the broker.

The broker registers with Relaycast on start. If registration fails, retry.

macOS: start the broker from a keychain-unlocked session

On macOS, start the broker from a session where the login keychain is unlocked. Workers inherit the security session of the process that spawned them, so a broker started from a locked session hands every worker a locked keychain.

This matters for any harness that stores credentials in the Keychain — including cursor-agent and the RelayFile CLI. They fail with errors that look like authentication problems but are not:

Error: Your macOS login keychain is locked.
error: resolve delegated relayfile credentials: mint delegated relayfile
       credentials: http 401 unauthorized: Unauthorized

Three properties make this easy to misdiagnose:

  • Unlocking the keychain in the macOS GUI does not unlock it for SSH. They are separate security sessions.
  • Unlocking it in one SSH session does not carry to the next one.
  • agent-relay itself does not need the keychain, so agent-relay status and agent-relay workspace active keep working while cursor-agent and relayfile fail. A working agent-relay is not evidence that the keychain is available.

Unlock and start the broker in a single interactive session. ssh -t is required so security can prompt:

ssh -t mini-node-2
security unlock-keychain "$HOME/Library/Keychains/login.keychain-db"
security set-keychain-settings "$HOME/Library/Keychains/login.keychain-db"
cd "$HOME/fleet/mini-node-2"
agent-relay node up --no-spawn --background --broker-name mini-node-2

set-keychain-settings with no flags clears the idle timeout and the lock-on-sleep behaviour, so the keychain stays unlocked while the machine is up. It does not survive a reboot — nothing can, without storing the password somewhere it should not be.

After a reboot, repeat this before starting the broker. A broker that auto-starts unattended will be in a locked session, and every worker it spawns inherits that.

4. Verify the node is connected

cd "$HOME/fleet/mini-node-2"
agent-relay node status

Look for all three indicators in the output; other lines are omitted here:

Status: RUNNING
Node delivery: CONNECTED
Node: mini-node-2 (...)

RUNNING alone is insufficient: the process can be alive while node delivery is down. Confirm the node also appears in your existing fleet's node view, under the workspace you selected. This catches enrollment into a separate workspace.

If startup is still settling, give the readiness check a bounded wait:

agent-relay node status --wait-for 10

Status depends on the current project's connection metadata. A STOPPED result does not prove every broker process has exited. Check the recovery steps below before starting another copy.

5. Spawn a worker and attach

Install and authenticate the harness on this machine, under the same OS user that runs the broker. Harnesses verified on a fleet machine are codex, claude, cursor-agent, grok, gemini, and droid. Authenticate interactively before assigning unattended work.

Create a lane directory, or substitute the absolute path to an existing checkout or worktree:

mkdir -p "$HOME/lanes/fleet-smoke"
cd "$HOME/fleet/mini-node-2"
agent-relay node agent spawn codex \
  --name mini-node-2-smoke \
  --cwd "$HOME/lanes/fleet-smoke" \
  --channels general \
  --task "Send a short ready message to #general through Agent Relay, then wait for instructions."
agent-relay node agent list --pretty

Run spawn from the broker's project root, even when the worker will use a different directory. Spawn resolves .agentworkforce/relay/connection.json from the caller's current directory, not the value of --cwd. Running from the lane directory fails with No running broker found.

Attach from the same broker root:

agent-relay node agent attach mini-node-2-smoke --mode view

view is the default for agent-relay node agent attach mini-node-2-smoke; it shows the worker without forwarding input. To type into the worker's terminal:

agent-relay node agent attach mini-node-2-smoke --mode drive

In either mode, Ctrl+C detaches and leaves the worker running. Confirm its ready message reaches #general and is visible from the first machine's workspace. That checks communication across the fleet, beyond local process startup. Release the smoke-test worker when finished:

agent-relay node agent release mini-node-2-smoke

Troubleshooting

Status says STOPPED but broker processes are alive

Symptom: node status reports STOPPED, yet processes remain or a fresh start collides with an existing broker.

Fix: First return to the directory where the broker was started. By default, its metadata is <broker-root>/.agentworkforce/relay/connection.json. When the broker root is ~, that is ~/.agentworkforce/relay/connection.json. If you used --state-dir at startup, pass the same directory to status and shutdown.

Inspect file existence and process names without dumping credentials or full process arguments:

cd "$HOME/fleet/mini-node-2"
test -f .agentworkforce/relay/connection.json && echo "connection file present"
ps -eo pid,ppid,comm | grep -E 'agent-relay|PID'

A missing connection file can make status report STOPPED even with live broker processes. Before recovery, save active work and stop assigning tasks to this node. From the affected broker root, clear its orphaned processes and stale state:

agent-relay node down --force

Recheck the process list before restarting. Orphan cleanup is best-effort: if a process remains, identify its working directory and parent in your OS process tools, then terminate only the confirmed orphan with SIGTERM; use SIGKILL only if it will not exit. Do not kill other nodes or active workers. The CLI's --all shutdown option affects the entire machine and is inappropriate when other nodes are doing work. Do not delete the whole ~/.agentworkforce/relay directory; it also holds installed binaries and other state.

Once the affected broker's processes are gone, rerun the startup and status commands from steps 3 and 4.

A Claude worker cannot refresh its login

Symptom: A non-interactive lane fails with OAuth session expired and could not be refreshed.

Fix: Open an interactive terminal on the fleet machine as the broker's OS user and sign in again:

claude auth login

Complete the browser flow, then release the failed worker and spawn it again with the original task and working directory. During the observed fleet setup, Claude sessions needed this intervention; Codex and Cursor sessions stayed authenticated. That observation is not a guarantee that their credentials cannot expire.

A worker fails with "login keychain is locked"

Error: Your macOS login keychain is locked.
Run security unlock-keychain and try again.

The broker was started from a session with a locked keychain, and the worker inherited it. Unlocking the keychain now in a separate SSH session will not fix the running worker — the broker has to be restarted from an unlocked session. See Start the broker from a keychain-unlocked session.

The same cause produces http 401 unauthorized from relayfile status. Check the keychain before treating that as an authentication or account problem:

security show-keychain-info "$HOME/Library/Keychains/login.keychain-db"

A locked keychain reports User interaction is not allowed.

The machine runs out of disk space

Symptom: Installs, builds, worktree creation, or agent startup fail with No space left on device.

Fix: Check free space and identify the large lane directories:

df -h .
du -sh "$HOME/lanes"/*

Agent worktrees and repeated dependency installs accumulate quickly. Build caches, Cargo target/ directories, and stale node_modules are usually reproducible and can be reclaimed after the jobs using them have stopped. Keep lockfiles and source so dependencies and builds can be recreated.

Before removing a checkout or worktree, inspect its Git status for modified and untracked files. Preserve anything with uncommitted work, unpublished commits, or outputs you still need. Do not treat a directory as disposable just because its agent is no longer running.

Next steps