Summary
agent-relay local agent spawn / list cannot find a broker that agent-relay up started and agent-relay status reports as running, when the current directory is a subdirectory that does not itself contain a project marker. The two code paths resolve the project root differently.
Repro
$ cd /Users/me/Sites/relay-tests/demos # no .git/package.json here
$ agent-relay local up --background
Broker started.
Broker PID: 51840
$ agent-relay status
Workspace: /Users/me # <-- resolved to HOME
Local broker: running (http://127.0.0.1:3889)
$ agent-relay local agent spawn claude --name Lead
No running broker found (/Users/me/Sites/relay-tests/demos/.agentworkforce/relay/connection.json does not exist).
Start one with 'agent-relay up' or use HarnessDriverClient.spawn().
$ agent-relay local agent list
No running broker found (/Users/me/Sites/relay-tests/demos/.agentworkforce/relay/connection.json does not exist).
status finds the broker; spawn/list do not — same broker, same shell.
Root cause
Two inconsistent project-root resolutions:
-
up / status / down resolve via getProjectPaths() → findProjectRoot()
(packages/config/src/project-namespace.ts:33), which walks up the directory tree
looking for a marker (.git, package.json, Cargo.toml, go.mod, pyproject.toml,
.agentworkforce/relay). From a markerless subdir it climbs to the first ancestor with a
marker — here $HOME — and registers connection.json at
~/.agentworkforce/relay/connection.json.
-
local agent spawn / list go through run() →
deps.connect(deps.cwd()) → HarnessDriverClient.connect({ cwd })
(packages/cli/src/cli/commands/local-agent.ts:96,131). This uses the raw cwd
literally and does not walk up, so it only checks
<cwd>/.agentworkforce/relay/connection.json.
When cwd is a subdirectory without its own marker, the broker is registered under the
walked-up root while spawn/list look only in cwd → mismatch → "No running broker found."
Expected
local agent subcommands should locate the broker the same way up/status do — i.e.
resolve via findProjectRoot() / getProjectPaths().projectRoot (walk-up), or at minimum
fall back to the walked-up root before erroring. The broker that status reports as
running should always be reachable by spawn/list from the same shell.
Notes / scope
- Affects at least
local agent spawn, local agent new, local agent list. The
local agent message … subcommands take --broker-url/--state-dir/RELAY_BROKER_URL
overrides and can be pointed manually; spawn/list expose no such override, so there is
no in-CLI workaround.
- Workaround today: ensure cwd contains a marker (e.g.
git init, or
mkdir -p .agentworkforce/relay) before agent-relay up, so the broker registers in
cwd rather than resolving up to $HOME.
- General footgun: a broker accidentally rooted at
$HOME shadows every markerless subdir.
Version: agent-relay 9.0.1
Summary
agent-relay local agent spawn/listcannot find a broker thatagent-relay upstarted andagent-relay statusreports as running, when the current directory is a subdirectory that does not itself contain a project marker. The two code paths resolve the project root differently.Repro
statusfinds the broker;spawn/listdo not — same broker, same shell.Root cause
Two inconsistent project-root resolutions:
up/status/downresolve viagetProjectPaths()→findProjectRoot()(
packages/config/src/project-namespace.ts:33), which walks up the directory treelooking for a marker (
.git,package.json,Cargo.toml,go.mod,pyproject.toml,.agentworkforce/relay). From a markerless subdir it climbs to the first ancestor with amarker — here
$HOME— and registersconnection.jsonat~/.agentworkforce/relay/connection.json.local agent spawn/listgo throughrun()→deps.connect(deps.cwd())→HarnessDriverClient.connect({ cwd })(
packages/cli/src/cli/commands/local-agent.ts:96,131). This uses the raw cwdliterally and does not walk up, so it only checks
<cwd>/.agentworkforce/relay/connection.json.When cwd is a subdirectory without its own marker, the broker is registered under the
walked-up root while
spawn/listlook only in cwd → mismatch → "No running broker found."Expected
local agentsubcommands should locate the broker the same wayup/statusdo — i.e.resolve via
findProjectRoot()/getProjectPaths().projectRoot(walk-up), or at minimumfall back to the walked-up root before erroring. The broker that
statusreports asrunning should always be reachable by
spawn/listfrom the same shell.Notes / scope
local agent spawn,local agent new,local agent list. Thelocal agent message …subcommands take--broker-url/--state-dir/RELAY_BROKER_URLoverrides and can be pointed manually;
spawn/listexpose no such override, so there isno in-CLI workaround.
git init, ormkdir -p .agentworkforce/relay) beforeagent-relay up, so the broker registers incwd rather than resolving up to
$HOME.$HOMEshadows every markerless subdir.Version: agent-relay 9.0.1