Skip to content

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

Closed

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 no — cli + 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

  1. khaliqgant commented on Aug 7, 2026

    @khaliqgant
    MemberAuthor

    Correcting this issue — the main claim was wrong

    I filed this saying a persona cannot be launched by anything other than a human at a TTY. That is false, and I should have checked the packages in this repo before asserting it.

    @agentworkforce/local-surface already exports defineWorkforcePersonaNode(options): FleetNodeDefinition — and that FleetNodeDefinition is imported from @agent-relay/fleet. A persona already runs as an Agent Relay fleet node.

    Internally it calls launchPersonaRunner → deployPersona with mode: 'dev', detach: true, bridged: true, noPrompt: true (packages/local-surface/src/index.ts:145). The bridged flag exists precisely so the persona survives a non-interactive parent whose stdin ends. So a fully non-interactive, programmatic persona launch is not only possible, it is deliberately built for and commented as such.

    There is also a whole persona SDK surface I overlooked: @agentworkforce/persona-kit, @agentworkforce/personas-core, and per-persona packs published to npm — including @agentworkforce/persona-nango-integrations@0.1.9, which exports the very persona JSON I hand-copied into a prompt.

    So the loss I described was self-inflicted. I reached for relay's raw spawn action and pasted persona text into a task string, when the persona could have been run as a fleet node with its skills, MCP servers, harness and model intact.

    What remains genuinely missing — narrower, and worth keeping

    Relay's spawn action still takes only cli + free-text task + target_node. It has no persona parameter, and does not resolve the persona registry (built-in / cwd / personal / configured dirs) that agentworkforce agent uses.

    That matters because spawn is the ergonomic path — it is what an orchestrating agent reaches for, and what I reached for. defineWorkforcePersonaNode requires standing up a fleet node definition with a channel and workspace connection; it is the right tool for a long-lived persona-backed node, not for "run this persona on that box for this task."

    So the remaining ask is narrower than the title suggests:

    1. spawn should accept a persona (name or path) resolved through the same registry, as an alternative to cli + task, with task layering the concrete assignment over the persona's standing instructions.
    2. Discoverability. Nothing pointed me from spawn toward defineWorkforcePersonaNode, and the failure mode is silent: pasting persona text into a task produces an agent that runs, sounds correct, and is missing its skills and MCP servers. Nothing errors. A wrong path that works badly is worse than one that fails.

    Retitling would be fair — the accurate framing is "relay spawn has no persona parameter, and the working path via defineWorkforcePersonaNode is undiscoverable from it", not "personas cannot be spawned".

    Also raised by Khaliq and belonging with this: a relayflow step should be able to name a persona too. Workflows in relayflows declare agents as { name, cli, role, preset } (e.g. workflows/ci/fix-mcp-spawn.yaml) — free text and a CLI choice, with the same loss. Three launch surfaces exist — interactive CLI, relay spawn, relayflow steps — and only the first takes a persona.

  2. changed the title [-]Personas cannot be spawned through Agent Relay — remote placement silently drops skills, MCP servers, harness and model[/-] [+]relay spawn and relayflow steps take a cli + free text, not a persona — and the working path (defineWorkforcePersonaNode) is undiscoverable from them[/+] on Aug 7, 2026
  3. khaliqgant commented on Aug 7, 2026

    @khaliqgant
    MemberAuthor

    pear already does this, end to end — so this is a port, not a design problem

    Khaliq pointed out it works in pear. It does, and the implementation is small and readable: pear/src/main/broker.ts, spawnPersona() at :2991 and spawnPersonaOnce() at :3003.

    The whole mechanism:

    1. Resolve the CLI — resolveAgentWorkforceCommand(cwd), which throws a specific error if absent: "AgentWorkforce CLI not found — install it to launch personas".
    2. Discover — agentworkforce list --json → persona summaries.
    3. Resolve one — agentworkforce show <personaId> --json → the spec, from which pear reads only id, description, harness, tags.
    4. Launch — delegate to agentworkforce agent <persona>.
    5. Verify it stuck — verifyPersonaBrokerRegistration(), then verifyPersonaHarnessReady(), and releaseUnreadyPersona() if either fails.

    So agentworkforce list --json and show <id> --json already exist as machine-readable resolution primitives. The registry lookup I described as missing is a solved problem with a JSON interface.

    The comment at broker.ts:3009 is the key insight and deserves quoting, because it removes most of the imagined work:

    "The actual spawn is delegated to the workforce CLI (agent <persona>), which reads the full inherited persona itself, stages skills, materializes sidecars in its sandbox mount, and injects relaycast MCP from the broker env."

    A caller does not have to understand a persona to launch one. It resolves the harness, shells out, and the CLI does skills, sidecars and MCP wiring itself. That is precisely the loss I hit by pasting persona text into a task — and pear avoids it by not trying to reconstruct the persona at all.

    What this changes about the ask

    The remaining gap is genuinely narrow: relay's spawn action needs the same three steps pear already performs — resolve via show --json, take harness from the spec, delegate to agentworkforce agent <persona> on the target node. Not new capability; the same call from a different caller.

    Two things worth lifting from pear rather than reinventing:

    • Spawn coalescing. personaSpawnRequestKey(projectId, personaId) keys in-flight dedup by project + persona, so concurrent requests for the same persona coalesce into one launch. A fleet will need the node-scoped equivalent.
    • Readiness verification, and the release on failure. Pear does not treat a launched process as a running persona: it confirms broker registration and harness readiness, and releases the agent if either fails. Given how much of today was spent on records that claimed liveness while nothing was running, that verify-then-release discipline is the part most worth copying.

    The one prerequisite pear enforces and a fleet node must too: the AgentWorkforce CLI has to be installed on the host doing the launching.

  4. khaliqgant commented on Aug 7, 2026

    @khaliqgant
    MemberAuthor

    Correction from Khaliq, and it overrides my last comment: delegating to another CLI is not acceptable. Use the SDK surface.

    I posted pear's spawnPersona() as the pattern to copy. Do not copy it. Pear shells out to agentworkforce agent <persona>, and shelling out is the wrong boundary here regardless of how neatly it is written.

    Khaliq's rule, stated plainly: we should always be using SDK surfaces.

    Why the shell-out is the wrong answer, not just a less tidy one

    • It makes a CLI binary a runtime dependency of every fleet node. Pear enforces this and even has the error for it — "AgentWorkforce CLI not found — install it to launch personas." Acceptable in a desktop app the user installed; not acceptable as a precondition for placing work on an arbitrary node, including a cloud sandbox.
    • It couples two release trains through a process boundary with no type checking. A CLI whose flags or JSON shape shift breaks the caller at runtime, and only at runtime. We hit exactly this today: relayfile mount rejected --workspace/--local-dir flags its own help text advertised.
    • It launders errors through exit codes and stdout parsing. Pear has to scrape output for readiness (personaHarnessReadyFromOutput, personaHarnessFailedFromOutput). That is a parser against another program's log format, and it is precisely the "check the output rather than the effect" pattern that produced several wrong answers today.
    • agentworkforce agent is TTY-oriented. It drops into an interactive harness session; there is no headless form. Driving an interactive command from a daemon is fragile by construction.

    The SDK surface already exists

    @agentworkforce/deploy exports a real programmatic entrypoint:

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

    plus preflightPersona, the three mode launchers (devLauncher, sandboxLauncher, cloudLauncher), ModeLaunchHandle, ModeLaunchInput, ModeLauncher, and createTerminalIO / createBufferedIO for controlling IO instead of scraping it. It validates declared persona inputs up front and throws typed errors — "Unknown input 'x'; persona declares: …" — rather than failing somewhere inside a child process.

    And @agentworkforce/local-surface already composes exactly 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). That is the library path, in-process, no CLI, and it is already wired to @agent-relay/fleet.

    Notably pear already depends on @agentworkforce/deploy@^4.1.16 and shells out anyway. So this is not a missing capability — it is a caller reaching for the wrong surface, which is the same mistake I made when I pasted persona text into a relay task.

    The ask, restated

    Relay spawn — and relayflow steps — should accept a persona and launch it through @agentworkforce/deploy / local-surface, in process. No agentworkforce binary on the node, no stdout scraping, no interactive command driven by a daemon.

    What is still worth taking from pear is the discipline, not the mechanism: dedup concurrent launches of the same persona, and verify registration and harness readiness before calling it running, releasing it if either fails. A launched process is not a running persona — today produced a long list of records asserting liveness with nothing behind them.

  5. changed the title [-]relay spawn and relayflow steps take a cli + free text, not a persona — and the working path (defineWorkforcePersonaNode) is undiscoverable from them[/-] [+][factory] Accept a persona in relay spawn and relayflow steps, via the SDK — not a CLI shell-out[/+] on Aug 7, 2026
  6. added
    factoryFactory dispatch gate label
    agent:teamFactory recipe: dispatch a team of agents
    workforceFactory route: AgentWorkforce/workforce
    on Aug 7, 2026
  7. barryollama commented on Aug 11, 2026

    @barryollama

    Merge receipt and remaining release handoff (2026-08-11)

    The SDK implementation is now merged across all three repositories:

    Workforce #307's final review inventory was 35 threads / 0 unresolved, with CI, CodeRabbit, and Cubic green. The final fix deterministically removes scratch directories in all stubbed-success persona spawn tests.

    What remains before #306 is complete

    Owner: Workforce release maintainer — AgentWorkforce/workforce

    Publish the next lockstep Workforce release (the dependent relayflows code expects 4.1.38+). Acceptance criteria:

    1. @agentworkforce/persona-registry@4.1.38+ exists on npm (it is currently unpublished).
    2. @agentworkforce/persona-kit@4.1.38+, @agentworkforce/local-surface@4.1.38+, and the other lockstep packages referenced by the release are available.
    3. Packed artifacts expose the new registry/autosync/spawn surfaces.

    No package was manually published as part of the PR merge.

    Owner: Relayflows release maintainer — AgentWorkforce/relayflows

    After the Workforce release is public, refresh/verify the clean install for main 4ac88ced57b9ebeaa51f9364d9b52d771fffa302, then rerun its normal publish workflow. Acceptance criteria:

    1. npm ci, build/typecheck, and persona runtime/schema/runner tests pass from a clean checkout using registry packages only.
    2. The previous Publish Package run 31277952687 no longer fails on unavailable Workforce 4.1.38 lockstep dependencies.
    3. Publish the resulting relayflows release through the repository workflow and verify its packed dependency/runtime behavior.

    Current npm evidence: @agentworkforce/persona-kit and @agentworkforce/local-surface are still 4.1.37; @agentworkforce/persona-registry returns npm E404. Therefore this issue should remain open until those two release steps are complete.

  8. barryollama commented on Aug 11, 2026

    @barryollama

    Workforce 4.1.38 partial publication / npm bootstrap blocker (2026-08-11)

    The authorized canonical Workforce release was dispatched from exact reviewed main SHA df37d32318d5c9efe0b2e70a160f80505e9d06b8:

    The workflow published the first six packages with npm provenance, then stopped at the first publication of the new package @agentworkforce/persona-registry:

    Package 4.1.38 state latest npm SHA-1
    @agentworkforce/events published + provenance 4.1.38 e223fde087bdae0558b03c97b1c4e8e23f6164bf
    @agentworkforce/persona-kit published + provenance 4.1.38 3e3a47f7c2c7615d4127232d04c8cdaf40836718
    @agentworkforce/runtime published + provenance 4.1.38 88dfb989a301923ba76dfbda5b4b7f8f9d5a8065
    @agentworkforce/compose published + provenance 4.1.38 70a25ae24d98041fefb6b744c21ec2714264cff6
    @agentworkforce/delivery published + provenance 4.1.38 85dfd77a6e3f137a5ca07dd9c8e6a0d786cce6bc
    @agentworkforce/workload-router published + provenance 4.1.38 7cfedde475c46f5ed2ae1f5f7229397181715591
    @agentworkforce/persona-registry failed: npm E404/no permission on first package creation — —
    @agentworkforce/deploy unattempted 4.1.37 —
    @agentworkforce/review-kit unattempted 4.1.37 —
    @agentworkforce/turn-kit unattempted 4.1.37 —
    @agentworkforce/mcp-workforce unattempted 4.1.37 —
    @agentworkforce/daytona-runner unattempted 4.1.37 —
    @agentworkforce/local-surface unattempted 4.1.37 —
    @agentworkforce/cli unattempted 4.1.37 —
    agentworkforce unattempted 4.1.37 —

    Every published package's npm attestation identifies run 31521842745, workflow .github/workflows/publish.yml, and source commit df37d32318d5c9efe0b2e70a160f80505e9d06b8.

    Preserved reviewed persona-registry artifact

    The failed package was deterministically recreated twice from detached exact SHA df37d32318d5c9efe0b2e70a160f80505e9d06b8, Node 26.5.0, pnpm 10.17.1, frozen lockfile, full workspace build, lockstep 4.1.38 versioning, and the workflow's pnpm pack command. Both packs were byte-identical:

    • Filename: agentworkforce-persona-registry-4.1.38.tgz
    • SHA-1: 918a8e0a41c3e2fc52cc6e918a604ac71ab2f9ab
    • SHA-512: 998337067daca125a8d7fc1fef8ac95df67c27954def2bdaf6cce111cb36787e0bc38129537aed4cf9da06a768bb662f5cda63ee0e59a55896191ee88c8e45b2
    • SRI: sha512-mYM3Bn2soSWo1/wf74rJXfZ8J5VN7yva9szhEcs2eH4Lw4EpU3rtTPnaBqdou2YvXNpj7g5ZpViWGR7ojI5Fsg==
    • Packed dependencies are exact: @agentworkforce/persona-kit: 4.1.38, @agentworkforce/workload-router: 4.1.38.

    No local/manual publication was attempted.

    Minimum safe recovery

    This is an npm first-package bootstrap boundary, not a code or test failure. npm requires a package to exist before its trusted publisher can be configured. An authenticated @agentworkforce npm owner must:

    1. Bootstrap @agentworkforce/persona-registry@4.1.38 from the exact preserved tarball above using the npm owner's normal 2FA-protected process.
    2. Configure that package's trusted publisher for GitHub repository AgentWorkforce/workforce, workflow .github/workflows/publish.yml, allowed action npm publish.
    3. Land a reviewed workflow recovery change with an explicit opt-in resume input (default false): at exact custom_version=4.1.38, existing versions must be verified as this release's artifacts and skipped, while missing versions are packed and published normally. The six existing packages are verifiable by npm provenance/source SHA; the bootstrapped registry artifact is verifiable by the preserved hashes above. Normal collision-fail behavior must remain the default.
    4. Dispatch the protected workflow with custom_version=4.1.38, tag=latest, dry_run=false, and the explicit resume input. This completes the remaining packages at 4.1.38 without drifting to 4.1.39, then creates the release commit/tags/GitHub Release.

    Relayflows publication remains intentionally held until the Workforce lockstep set is complete and independently verified.

  9. barryollama commented on Aug 11, 2026

    @barryollama

    DONE — Workforce 4.1.39 + Relayflows 1.0.6

    The authorized lockstep release lane is complete.

    Workforce receipts

    Exact npm SHA-1 receipts:

    events 093da641419d8d8b4516f7080a3b281e7fad63e9
    persona-kit 8d2ff275577b0ecfd0bfa9d879cd8f2a220ea5ad
    runtime 9794d5f6055df280c0feb7d535ab2e66ba7ec887
    compose 2ed1db828aa500a2bcf44872cc9f316e53378aaf
    delivery 5f28bbec885ceae3d67aea4634eeb66f73226322
    workload-router 234edf6b0bc2837ca8dfd99986c2c704e4fa3cbb
    persona-registry b67332d7a77b27fa6634374768112c861c2e541f
    deploy 992a9792affded7493b794b143f54b0dc68ac4f3
    review-kit 6780cfdf4a50b5a500903142bd60739bce758a48
    turn-kit a277d204199a6baf006590192062bc582a5fcf73
    mcp-workforce 36c6dfb0d5af7a06b0f411a761012747c9af2276
    daytona-runner 6e9220e26921182653d4287b3b2307088cb0f27b
    local-surface b0a3b5e1b0d29e117099be10078f0444d988b0b9
    cli 2a9732149e6d4f38eec427edc130fe41420240e4
    agentworkforce b7716d2585e2203f9635c42fa3d9ba8c2d3eb319
    

    A registry-only install of all 15 exact packages passed. Packed/runtime checks confirmed persona-registry exact 4.1.39 kit/router deps and resolvePersonaReference / loadLocalPersonas; persona-kit applyPersonaMount; local-surface spawn exports and spawn:persona marker; workload-router listBuiltInPersonas.

    Relayflows receipts

    • Integration PR Using a persona that produces files doesn't sync back once the persona is closed #29 merged as 6c487b254da4616a6f3bc2c5bf84b8908cc0f198.
    • Review follow-up PR chore: sync package versions to 0.5.3 #30 merged as f691a4aa573d9544da3ade472e70ef226d543cee; Cubic confirmed all findings addressed.
    • Exact merged-main gates: clean install (336 packages), full build, root/core/CLI typecheck, core 45 files / 835 tests, GitHub primitive 3 tests, Slack primitive 34 tests, Slack examples typecheck.
    • Canonical workflow 31527619125 succeeded with package=all, version=patch, dry_run=false, tag=latest.
    • Jobs: build 93899677306; GitHub 93899909247; core 93899909257; CLI 93899909276; Slack 93899909281; browser 93899909318; release 93900362857; summary 93900456354.
    • Release commit/tag target: a9996679d8ba790fca4b7de5fe7ba829de9e36ef (annotated tag object ad8f0443f6f57340350e91d177146afba2bd030f).
    • Release: https://github.com/AgentWorkforce/relayflows/releases/tag/v1.0.6
    • All five packages have latest=1.0.6 and SLSA provenance.

    Exact npm SHA-1 receipts:

    @relayflows/core 99a8b778c409185d343411d24c5b61f9f429553e
    @relayflows/cli 49f3137506d79f37bc8bdcb3bb26a781e86797fd
    @relayflows/github-primitive 63692d00e7d16c67b477395260d78b7f6c73f7fd
    @relayflows/slack-primitive 83ac0225f6b5aca4f37d6e697cb5fd4ee4402b95
    @relayflows/browser-primitive 6670615095b24a92469890d8e8060be7745866ea
    

    Registry-only installation of all five exact packages passed. The packed core tarball reproduced its registry receipt exactly (186 files, 1,781,792 bytes unpacked; SHA-512 sha512-vBjkQqnyFqrNTgKZIk16lPqosPk8i0/Pw99rFrMlYP71bSgCvnP4LDSnnX0iQPHJPEu+04S+zk/AaH2uQaGE+A==). Runtime checks confirmed core builder/runner/workflow exports, all primitive clients, CLI 1.0.6, exact internal 1.0.6 deps, Workforce persona deps ^4.1.39, persona config emission, and invalid CLI+persona rejection.

  10. khaliqgant commented on Aug 13, 2026

    @khaliqgant
    MemberAuthor

    Factory dispatch for 306
    Implementers: ar-306-impl-workforce
    Reviewer: ar-306-review-workforce

  11. khaliqgant commented on Aug 16, 2026

    @khaliqgant
    MemberAuthor

    Factory observed pull request #307 merge and completed this issue.

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