Skip to content

[factory] Accept a persona in relay spawn and relayflow steps, via the SDK — not a CLI shell-out #306

Description

@khaliqgant

Note: this body was rewritten after the original claim was falsified. The comments below preserve how it got here — the first version asserted personas could not be launched non-interactively at all, which is false. Read this body, not the opening comment.

The gap

A persona can be launched three ways today, and only one of them takes a persona.

Surface Takes a persona?
agentworkforce agent <persona> (interactive TTY) yes
Agent Relay spawn action nocli + free-text task + target_node
Relayflow steps no{ name, cli, role, preset } (see relayflows/workflows/ci/fix-mcp-spawn.yaml)

So anything placed on a fleet node, or run as a workflow step, is a hand-written prompt rather than a persona.

Why that loses more than convenience

A persona is not a prompt. nango-integrations declares agentsMdContent, skills (each with a source that gets installed), mcpServers, harness, model, and harnessSettings. Pasting its text into a task string carries one of those. The spawned agent has no skills installed and no MCP server — it works from memory of a workflow the persona exists to enforce.

And it fails silently. Nothing errors. The agent runs, sounds correct, and is missing its tools. A wrong path that works badly is worse than one that fails.

The practical consequence: every remote agent is a fresh, unversioned approximation of a capability that already exists in a reviewed file, and improvements to that file never reach the fleet.

The capability already exists — this is a caller problem

@agentworkforce/deploy exports a real programmatic entrypoint:

export async function deploy(opts: DeployOptions, resolvers?: DeployResolvers): Promise<DeployResult>

plus preflightPersona, the mode launchers (devLauncher / sandboxLauncher / cloudLauncher), ModeLaunchHandle / ModeLaunchInput / ModeLauncher, and createBufferedIO. It validates declared persona inputs up front with typed errors rather than failing inside a child process.

@agentworkforce/local-surface already composes that into Agent Relay: defineWorkforcePersonaNode(options): FleetNodeDefinition, whose launchPersonaRunner calls deploy() with mode: 'dev', detach: true, bridged: true, noPrompt: true (local-surface/src/index.ts:145). The bridged flag exists specifically so the persona survives a non-interactive parent whose stdin ends.

So non-interactive, in-process persona launch is built, deliberate, and already wired to @agent-relay/fleet. What is missing is that spawn and relayflow steps do not reach for it.

Constraint — SDK surfaces only

Do not implement this by shelling out to agentworkforce agent. pear/src/main/broker.ts:2991 does exactly that, and it is not the pattern to copy. Shelling out:

  • makes a CLI binary a runtime dependency of every calling host — unacceptable for an arbitrary fleet node or cloud sandbox;
  • couples two release trains across a process boundary with no type checking (relayfile mount recently rejected --workspace / --local-dir, flags its own help text advertised);
  • forces stdout scraping for state — pear parses readiness out of log lines with personaHarnessReadyFromOutput;
  • drives a TTY-oriented command from a daemon.

Notably pear already depends on @agentworkforce/deploy and shells out anyway. The library is there; the caller reaches past it.

What done looks like

  1. Agent Relay spawn accepts a persona (name or path) as an alternative to cli + task, resolved through the same registry agentworkforce uses (built-in / cwd / personal / configured dirs). harness and model come from the persona spec. A task supplied alongside layers the concrete assignment over the persona's standing instructions.
  2. Relayflow steps accept a persona in place of cli + role, with the same resolution.
  3. Both go through @agentworkforce/deploy / local-surface in process. No agentworkforce binary required on the node, no output parsing.
  4. Launch is deduped and verified. Borrow the discipline from pear even though not its mechanism: coalesce concurrent launches of the same persona (personaSpawnRequestKey keys on project + persona; a fleet needs the node-scoped equivalent), and confirm broker registration and harness readiness before reporting success, releasing the agent if either fails. A launched process is not a running persona.
  5. Discoverability. Nothing today points a caller from spawn toward defineWorkforcePersonaNode. Whatever ships, make the working path findable from the wrong one.

Cross-repo

The persona resolution and SDK live here (workforce). The spawn action lives in relay. Relayflow step schema lives in relayflows. Expect changes in more than one repo; do not merge anything — the merge gate is the principal's.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:teamFactory recipe: dispatch a team of agentsfactoryFactory dispatch gate labelworkforceFactory route: AgentWorkforce/workforce

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions