Skip to content

Commit 4e1e885

Browse files
khaliqgantclaude
andauthored
fix(persona): restore agent-relay MCP injection for spawn-modal personas (#191)
* fix(persona): restore agent-relay MCP injection for spawn-modal personas Persona spawns passed skipRelayPrompt: true to the broker, which not only skips broker-side MCP arg injection (harmless — the agentworkforce wrapper is not a CLI the broker recognizes) but also suppresses the RELAY_AGENT_NAME / RELAY_AGENT_TOKEN env stamps on the worker. The workforce CLI's resolveRelayMcpFromEnv requires RELAY_API_KEY + RELAY_AGENT_NAME, so it silently skipped its own relay-MCP injection and persona harnesses launched without the agent-relay MCP. Drop the flag so the broker stamps the env, and export AGENT_RELAY_BIN to the broker (inherited by workers) so the workforce CLI's `agent-relay-broker mcp-args --register` path resolves the same binary Pear runs instead of a PATH lookup that fails in packaged installs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(broker): return realBinaryPath from resolveHarnessBrokerBinary Review follow-up: the AGENT_RELAY_BIN value was reverse-engineered from the shim env key (PEAR_AGENT_RELAY_BROKER_BINARY ?? binaryPath); have the resolver own that distinction explicitly instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 0a30e1f commit 4e1e885

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

src/main/broker.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,12 @@ describe('BrokerManager local + cloud coexistence', () => {
870870
expect(local.spawnPty).not.toHaveBeenCalledWith(expect.objectContaining({
871871
args: expect.arrayContaining(['--install-in-repo'])
872872
}))
873+
// The workforce CLI only injects the agent-relay MCP into the inner
874+
// harness when the broker stamps RELAY_AGENT_NAME into the worker env,
875+
// and the broker suppresses that stamp when skipRelayPrompt is set.
876+
expect(local.spawnPty).not.toHaveBeenCalledWith(expect.objectContaining({
877+
skipRelayPrompt: true
878+
}))
873879
expect(result).toEqual({
874880
name: 'autonomous-actor',
875881
runtime: 'pty',

src/main/broker.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,10 @@ function ensureBrokerBinaryCompatShim(): string {
424424
return shimPath
425425
}
426426

427-
async function resolveHarnessBrokerBinary(workspaceKey?: string): Promise<{ binaryPath: string; env: NodeJS.ProcessEnv }> {
427+
// `binaryPath` is what Pear launches (possibly the legacy compat shim);
428+
// `realBinaryPath` is always the actual broker binary, for callers that hand
429+
// the binary itself to other processes.
430+
async function resolveHarnessBrokerBinary(workspaceKey?: string): Promise<{ binaryPath: string; realBinaryPath: string; env: NodeJS.ProcessEnv }> {
428431
const binaryPath = resolveBundledBrokerBinary()
429432
const flags = await inspectBrokerInitCliFlags(binaryPath)
430433

@@ -435,7 +438,7 @@ async function resolveHarnessBrokerBinary(workspaceKey?: string): Promise<{ bina
435438
}
436439

437440
if (flags.supportsInstanceName) {
438-
return { binaryPath, env: {} }
441+
return { binaryPath, realBinaryPath: binaryPath, env: {} }
439442
}
440443

441444
if (!flags.supportsName) {
@@ -446,6 +449,7 @@ async function resolveHarnessBrokerBinary(workspaceKey?: string): Promise<{ bina
446449
console.warn(`[broker] Broker binary uses legacy --name flag; launching through compatibility shim: ${binaryPath}`)
447450
return {
448451
binaryPath: shimPath,
452+
realBinaryPath: binaryPath,
449453
env: {
450454
PEAR_AGENT_RELAY_BROKER_BINARY: binaryPath,
451455
PEAR_AGENT_RELAY_BROKER_SUPPORTS_INSTANCE_NAME: flags.supportsInstanceName ? '1' : '0',
@@ -1555,6 +1559,13 @@ export class BrokerManager {
15551559
env: {
15561560
PATH: augmentedPath(),
15571561
...brokerBinary.env,
1562+
// Spawned workers inherit the broker's env. AGENT_RELAY_BIN is the
1563+
// ecosystem-standard broker-binary override (harness-driver
1564+
// broker-path, workforce runtime relay-mcp); it lets the workforce
1565+
// CLI's `mcp-args --register` relay-MCP injection find the same
1566+
// broker binary Pear runs — a PATH lookup fails in packaged
1567+
// installs and can hit a version-skewed global binary in dev.
1568+
AGENT_RELAY_BIN: brokerBinary.realBinaryPath,
15581569
...(agentRelayMcpCommand ? { AGENT_RELAY_MCP_COMMAND: agentRelayMcpCommand } : {})
15591570
},
15601571
onStderr: (line: string) => {
@@ -2858,13 +2869,18 @@ export class BrokerManager {
28582869
(await session.client.listAgents()).map((agent) => agent.name)
28592870
)
28602871
const personaArgs = ['agent', input.personaId]
2872+
// No skipRelayPrompt here: the workforce CLI injects the agent-relay MCP
2873+
// into the inner harness, but it only does so when the broker stamps
2874+
// RELAY_AGENT_NAME (+ RELAY_AGENT_TOKEN) into the worker env — and the
2875+
// broker suppresses those stamps when skip_relay_prompt is set. Broker-side
2876+
// arg injection stays a no-op either way because `agentworkforce` is not a
2877+
// CLI the broker recognizes, so the wrapper command is unchanged.
28612878
let nextInput: SpawnPtyInput = {
28622879
name: getAvailableAgentName(input.baseName, existingNames),
28632880
cli: input.command.cli,
28642881
args: [...input.command.args, ...personaArgs],
28652882
cwd: session.cwd,
2866-
channels: session.channels,
2867-
skipRelayPrompt: true
2883+
channels: session.channels
28682884
}
28692885

28702886
for (let attempt = 0; attempt < 20; attempt += 1) {

0 commit comments

Comments
 (0)