Skip to content

feat: launch Relayflow agents from personas - #28

Merged
khaliqgant merged 3 commits into
mainfrom
codex/issue-306-persona-spawn
Aug 8, 2026
Merged

feat: launch Relayflow agents from personas#28
khaliqgant merged 3 commits into
mainfrom
codex/issue-306-persona-spawn

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Aug 7, 2026

Copy link
Copy Markdown
Member

Summary

  • let Relayflow agent definitions use persona in place of cli + role, in YAML and the TypeScript builder
  • resolve ids and JSON paths through @agentworkforce/persona-registry, then prepare skills, MCP servers, sidecars, harness settings, model, and isolated autosync mount through persona-kit in process
  • layer each workflow step task over the persona's standing instructions
  • require broker worker_ready plus authoritative agent inventory before continuing, releasing the worker and disposing its prepared runtime on any failure
  • keep raw CLI and non-interactive process paths explicit and type-safe

This is the Relayflows part of AgentWorkforce/workforce#306. It does not shell out to agentworkforce.

Verification

  • primitive builds — exit 0
  • core TypeScript check — exit 0
  • persona runtime, builder, and workflow-runner tests — 79 passed
  • full core suite — not passing: 805 passed and 8 baseline run-script tests failed because this checkout has no tsx binary and their npx tsx fallback exited 127
  • staged whitespace, secret-pattern, and home-path scans — 0 findings

Stack / blockers

Depends on AgentWorkforce/workforce#307 and the subsequent Workforce 4.1.38+ publication. @agentworkforce/persona-registry and the persona-kit autosync contract are not published yet, so a clean install/lock refresh is intentionally blocked until that upstream release; the local validation used the checked-out Workforce packages.


Summary by cubic

Launch Relayflow agents directly from AgentWorkforce personas to simplify config and run with the persona’s harness, model, and settings. Adds strict schema and template validation, and waits for runtime readiness and broker registration before executing steps.

  • New Features

    • Add persona to agent config and builder (agent('name', { persona: 'id' })) as an alternative to cli. Resolve and activate personas via @agentworkforce/persona-registry and @agentworkforce/persona-kit, installing skills and launching in an isolated autosync mount; layer workflow tasks over standing instructions.
    • Wait for broker worker_ready, verify registration via inventory, then proceed; dispose the persona runtime and release the worker on failure.
    • Validation and guardrails across YAML/schema/templates: require exactly one of cli or persona; persona agents are interactive-only and cannot set role, preset, or constraints.model; template loader rejects malformed cli/persona values; persona agents are blocked from non-interactive paths (process backend, diagnostics).
  • Migration

    • YAML: use persona: <id> instead of cli/role; do not combine with cli, role, or preset; do not set constraints.model; personas must be interactive (do not use interactive: false).
    • Requires Workforce 4.1.38+ (@agentworkforce/persona-kit, @agentworkforce/persona-registry).

Written for commit 955e0d3. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@miyaontherelay, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 32 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6bf5e077-1e6c-4fa0-a326-0457833d9558

📥 Commits

Reviewing files that changed from the base of the PR and between 56d0c24 and 955e0d3.

📒 Files selected for processing (2)
  • packages/core/src/__tests__/yaml-validation.test.ts
  • packages/core/src/templates.ts
📝 Walkthrough

Walkthrough

The workflow now accepts persona-based agents. Schemas and builders enforce exclusive cli or persona configuration. The runner resolves and activates personas, passes runtime settings to interactive agents, tracks readiness, and cleans up temporary resources.

Changes

Persona agent support

Layer / File(s) Summary
Agent contracts and builder support
packages/core/src/schema.*, packages/core/src/builder.ts, packages/core/src/templates.ts, packages/core/src/__tests__/builder-agent-round-trip.test.ts, packages/core/package.json, README.md
Agent definitions now require exactly one of cli or persona. Builders serialize persona-only agents. Documentation and tests cover the new configuration.
Persona resolution and activation
packages/core/src/persona-runtime.ts, packages/core/src/__tests__/persona-runtime.test.ts
Persona references resolve to spawn plans, CLI settings, models, arguments, and environment values. Activation creates an isolated temporary mount and provides idempotent cleanup.
Workflow runner persona execution
packages/core/src/runner.ts, packages/core/src/process-backend-executor.ts, packages/core/src/process-spawner.ts, packages/core/src/__tests__/workflow-runner.test.ts
The runner validates persona agents, activates them for interactive execution, waits for worker_ready, uses resolved runtime settings, rejects unsupported non-interactive execution, and disposes persona resources. Tests cover validation, readiness, execution, and disposal.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant WorkflowRunner
  participant PersonaRuntime
  participant ProcessSpawner
  participant Broker
  WorkflowRunner->>PersonaRuntime: resolve and activate persona
  PersonaRuntime-->>WorkflowRunner: return resolved CLI and runtime settings
  WorkflowRunner->>ProcessSpawner: spawn interactive agent
  ProcessSpawner->>Broker: emit worker_ready
  Broker-->>WorkflowRunner: confirm registration
  WorkflowRunner->>ProcessSpawner: send task
  ProcessSpawner-->>WorkflowRunner: report completion
  WorkflowRunner->>PersonaRuntime: dispose persona resources
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: willwashburn

Poem

A rabbit resolved a persona plan,
Then launched it in a mount so clean.
The worker signaled, “Ready here!”
The broker heard the message clear.
At task completion, cleanup ran—
And closed the burrow as planned.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: launching Relayflow agents from personas.
Description check ✅ Passed The description directly explains persona support, runtime behavior, validation, dependencies, and verification results.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-306-persona-spawn

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@khaliqgant
khaliqgant marked this pull request as ready for review August 8, 2026 11:12
@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18d2bc5b87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/core/src/runner.ts
Comment thread packages/core/src/builder.ts Outdated
Comment thread packages/core/src/runner.ts
Comment thread packages/core/src/schema.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/core/src/schema.json (1)

454-469: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

AgentCli enum still omits "api".

The enum now includes "grok" but still does not include "api". schema.ts's AgentCli TypeScript union includes 'api', and runner.ts/process-backend-executor.ts explicitly branch on cli === 'api'. A workflow YAML agent with cli: api, validated against this schema, fails validation even though the runtime supports it.

Add "api" to the enum for consistency with schema.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/schema.json` around lines 454 - 469, Update the AgentCli
enum in schema.json to include "api", matching the supported values in schema.ts
and the runtime branches handling cli === 'api'.
🧹 Nitpick comments (1)
packages/core/src/runner.ts (1)

9936-9980: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

captureAgentReport re-resolves the persona instead of reusing the CLI already resolved at spawn time.

agentDef.persona ? (resolveWorkflowPersona(agentDef.persona, cwd).cli as AgentCli) : undefined re-invokes resolveWorkflowPersona on every report capture (including per retry attempt), even though the same persona was already resolved once in spawnAndWait. Two issues:

  1. It is wasted computation on a path that already knows the resolved CLI.
  2. It uses cwd = lastEffectiveCwd, derived from resolveAgentCwd (unmounted path), while spawnAndWait resolved the same persona using resolveExecutionCwd (mounted path when the agent also has a relayfile permission mount). If a persona agent also carries permissions, these two cwd values can diverge, risking a different persona resolution outcome than the one actually spawned.

Consider threading the resolved cli (and persona id) from spawnAndWait's SpawnResult back to executeAgentStep, so captureAgentReport reuses it instead of re-resolving.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/runner.ts` around lines 9936 - 9980, Update the
spawn-to-report flow so captureAgentReport reuses the CLI resolved during
spawnAndWait rather than calling resolveWorkflowPersona with cwd again. Thread
the resolved CLI (and persona identifier if required) through SpawnResult into
executeAgentStep, then pass it to captureAgentReport and use it for
collectCliSession, preserving the exact execution-time persona resolution.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/package.json`:
- Around line 60-61: Update the dependency entries for
`@agentworkforce/persona-kit` and `@agentworkforce/persona-registry` in
packages/core/package.json so they resolve to versions actually available on
npm, or release the required 4.1.38+ versions before publishing
`@relayflows/core`.

In `@packages/core/src/builder.ts`:
- Around line 90-92: Update the persona variant of AgentOptions to match
WorkflowRunner.validateConfig: add preset?: never and narrow interactive to true
or undefined, while preserving the existing exclusions for cli, role, and model.

In `@packages/core/src/persona-runtime.ts`:
- Around line 13-46: Validate plan.cli inside resolveWorkflowPersona against the
supported AgentCli values before constructing the return object. Reuse the
existing AgentCli validation or supported-CLI set, reject unsupported
identifiers with the established error behavior, and only expose the validated
CLI value so downstream registry lookups cannot bypass validation.

In `@packages/core/src/runner.ts`:
- Around line 7066-7069: Ensure repair-agent resolution never selects
persona-only agents without a CLI: update resolveWorkflowRepairAgent and its
errorHandling.repairAgent, step.agent, and scoreRepairAgent candidate paths to
exclude them, and reject explicitly configured persona repair agents with a
clear configuration error; alternatively, resolve and activate the persona
consistently with spawnAndWait before invoking execNonInteractive. Preserve
normal repair-agent selection and make skipped persona repairs explicit rather
than swallowing the non-interactive execution failure.

---

Outside diff comments:
In `@packages/core/src/schema.json`:
- Around line 454-469: Update the AgentCli enum in schema.json to include "api",
matching the supported values in schema.ts and the runtime branches handling cli
=== 'api'.

---

Nitpick comments:
In `@packages/core/src/runner.ts`:
- Around line 9936-9980: Update the spawn-to-report flow so captureAgentReport
reuses the CLI resolved during spawnAndWait rather than calling
resolveWorkflowPersona with cwd again. Thread the resolved CLI (and persona
identifier if required) through SpawnResult into executeAgentStep, then pass it
to captureAgentReport and use it for collectCliSession, preserving the exact
execution-time persona resolution.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 03c19a00-93e1-4fc6-b219-f327e70518a8

📥 Commits

Reviewing files that changed from the base of the PR and between b086a87 and 18d2bc5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • README.md
  • packages/core/package.json
  • packages/core/src/__tests__/builder-agent-round-trip.test.ts
  • packages/core/src/__tests__/persona-runtime.test.ts
  • packages/core/src/__tests__/workflow-runner.test.ts
  • packages/core/src/builder.ts
  • packages/core/src/persona-runtime.ts
  • packages/core/src/process-backend-executor.ts
  • packages/core/src/process-spawner.ts
  • packages/core/src/runner.ts
  • packages/core/src/schema.json
  • packages/core/src/schema.ts

Comment thread packages/core/package.json
Comment thread packages/core/src/builder.ts
Comment thread packages/core/src/persona-runtime.ts
Comment thread packages/core/src/runner.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 13 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/core/src/runner.ts
Comment thread packages/core/src/persona-runtime.ts Outdated
Comment thread packages/core/src/schema.ts Outdated
Comment thread packages/core/src/schema.ts Outdated
Comment thread packages/core/src/schema.ts Outdated
Comment thread packages/core/src/runner.ts Outdated
Comment thread packages/core/src/runner.ts
Comment thread packages/core/src/__tests__/workflow-runner.test.ts
Comment thread README.md
Comment thread packages/core/src/schema.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/core/src/schema.json (1)

384-386: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Reject blank persona references in the JSON Schema.

The schema accepts persona: "" and whitespace-only values. Runtime validation rejects these values. Add a non-whitespace pattern so schema validation matches runtime behavior.

Proposed fix
 "persona": {
   "type": "string",
+  "pattern": "\\S",
   "description": "AgentWorkforce persona id or JSON path; mutually exclusive with cli"
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/schema.json` around lines 384 - 386, Update the persona
property in the JSON Schema so its string constraint rejects empty and
whitespace-only values by adding a non-whitespace pattern, while preserving
valid persona IDs and JSON paths and the existing mutual-exclusion description.
packages/core/src/runner.ts (3)

7444-7485: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Stop before spawning when persona activation exhausts the step deadline.

stepDeadline starts before activateWorkflowPersona(). If activation consumes the timeout, this code still calls spawnPty(). The readiness check then fails with zero remaining time after the harness has started.

Proposed fix
 activePersona = personaResolution
   ? await activateWorkflowPersona(personaResolution, agentCwd)
   : undefined;
+if (stepDeadline !== undefined && Date.now() >= stepDeadline) {
+  throw new Error(`Step "${step.name}" timed out during persona activation`);
+}
 const interactiveSpawnPolicy = resolveSpawnPolicy({
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/runner.ts` around lines 7444 - 7485, Check the step
deadline immediately after the conditional activateWorkflowPersona call and
before constructing or invoking relay.spawnPty through WorkflowAgentHandle. If
the deadline has been exhausted, stop the step using the existing timeout/abort
handling path and do not start the harness; otherwise preserve the current spawn
flow.

7719-7761: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Capture the persona session before runtime disposal.

This finally block disposes activePersona before returning runtimeCwd. captureAgentReport() runs after spawnAndWait() returns at Lines 5503-5511. It can therefore receive a removed isolated mount, fail to collect the session, and silently lose persona reports and token usage.

Keep the runtime alive until reporting completes, or collect the report before activePersona.dispose().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/runner.ts` around lines 7719 - 7761, Move persona
report/session collection ahead of activePersona.dispose() in the runner flow,
or defer disposal until captureAgentReport() has completed after spawnAndWait()
returns. Ensure the runtimeCwd remains valid while reporting collects persona
session data, token usage, and related evidence, then dispose the persona
runtime afterward.

5341-5357: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Perform persona startup on custom executors.

Custom createProcessBackendExecutor implementations can be used through executor.executeAgentStep() before the process-backed synthetic executor is applied. The process-backed path rejects non-CLI personas, but an explicit executor that calls ProcessBackend.exec() bypasses spawnAndWait() and can launch persona agents without resolving the persona reference, activating the isolated mount, validating readiness, and disposing the persona runtime. Apply the persona lifecycle in executeAgentStep() for persona agents before sending the command to the backend.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/runner.ts` around lines 5341 - 5357, The executor path in
executeAgentStep must apply the persona lifecycle before invoking
executor.executeAgentStep for persona agents: resolve the persona reference,
activate its isolated mount, validate readiness, and dispose the persona runtime
afterward. Ensure this occurs for custom executors that call
ProcessBackend.exec(), while preserving the existing non-persona and
process-backed flows.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/templates.ts`:
- Around line 400-404: Update the agent-definition validation near hasCli and
hasPersona to reject any provided cli or persona value that is not a non-empty
string, including numbers such as cli: 42. Preserve the existing requirement
that exactly one valid launch field is present, so malformed fields fail before
the template is accepted.

---

Outside diff comments:
In `@packages/core/src/runner.ts`:
- Around line 7444-7485: Check the step deadline immediately after the
conditional activateWorkflowPersona call and before constructing or invoking
relay.spawnPty through WorkflowAgentHandle. If the deadline has been exhausted,
stop the step using the existing timeout/abort handling path and do not start
the harness; otherwise preserve the current spawn flow.
- Around line 7719-7761: Move persona report/session collection ahead of
activePersona.dispose() in the runner flow, or defer disposal until
captureAgentReport() has completed after spawnAndWait() returns. Ensure the
runtimeCwd remains valid while reporting collects persona session data, token
usage, and related evidence, then dispose the persona runtime afterward.
- Around line 5341-5357: The executor path in executeAgentStep must apply the
persona lifecycle before invoking executor.executeAgentStep for persona agents:
resolve the persona reference, activate its isolated mount, validate readiness,
and dispose the persona runtime afterward. Ensure this occurs for custom
executors that call ProcessBackend.exec(), while preserving the existing
non-persona and process-backed flows.

In `@packages/core/src/schema.json`:
- Around line 384-386: Update the persona property in the JSON Schema so its
string constraint rejects empty and whitespace-only values by adding a
non-whitespace pattern, while preserving valid persona IDs and JSON paths and
the existing mutual-exclusion description.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b81dd3ba-3124-4240-a2d0-e5d29cdbb5d7

📥 Commits

Reviewing files that changed from the base of the PR and between 18d2bc5 and 56d0c24.

📒 Files selected for processing (9)
  • README.md
  • packages/core/src/__tests__/builder-agent-round-trip.test.ts
  • packages/core/src/__tests__/workflow-runner.test.ts
  • packages/core/src/builder.ts
  • packages/core/src/persona-runtime.ts
  • packages/core/src/runner.ts
  • packages/core/src/schema.json
  • packages/core/src/schema.ts
  • packages/core/src/templates.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • README.md
  • packages/core/src/builder.ts
  • packages/core/src/persona-runtime.ts

Comment thread packages/core/src/templates.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 9 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/core/src/templates.ts
@khaliqgant
khaliqgant merged commit 4ac88ce into main Aug 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants