Skip to content

feat(agents): spawn saved agents as Peer Agents - #147

Merged
bryantderosier merged 2 commits into
crews/02-provider-log-per-threadfrom
crews/03-saved-agents-as-peers
Sep 21, 2026
Merged

bryantderosier merged 2 commits into
crews/02-provider-log-per-threadfrom
crews/03-saved-agents-as-peers

Conversation

@bryantderosier

@bryantderosier bryantderosier commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Agents could only run a saved agent as a subagent under their own conversation. Crews need seats that are full participants, so spawn_agent now takes an optional agent id.

The saved agent's declared routes constrain the explicit provider, model, and reasoning pick; an out-of-route pick is refused naming the agent and its routes, and nothing is created. The matching route becomes the child's immutable assignment and its authority policy sets the child's runtime mode. A child's permissions come from its own saved agent's policy or from the human's approval, never from the parent: there is no parent-child permission ceiling between Peer Agents (Jackson's ruling, 2026-09-16), and upstream's own delegate rule is untouched.

The web composer sends a persona thread's locked launch route, so a remembered draft pick no longer fails every message to a Captain with an immutable-route error. The Codex approval-policy-never map and the Claude read-only allowlist pre-approve the J5 verbs, write_artifact, and the provider-native Subagent verbs by name, never the whole server, so worktree handoff, preview, and scheduling keep the provider's own verdict.

Built with Claude Fable 5.1 in Claude Code.

🤖 Generated with Claude Code

Closes #203.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 effective changed lines (test files excluded in mixed PRs). labels Sep 15, 2026
@bryantderosier
bryantderosier added this pull request to stack #153 September 15, 2026 21:36
@bryantderosier
bryantderosier force-pushed the crews/03-saved-agents-as-peers branch from e86ec05 to 9b8bc6e Compare September 15, 2026 21:44
@bryantderosier bryantderosier self-assigned this Sep 15, 2026
@bryantderosier
bryantderosier force-pushed the crews/03-saved-agents-as-peers branch from 9b8bc6e to 12e5bd4 Compare September 15, 2026 22:25

@Jacksondr5 Jacksondr5 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reviewed with the whole stack in view (148 through 152 read first, and each concern checked against the final branch) and with a second independent pass by GPT-6-Astra. The route constraint, the refuse-before-create behavior, the handler test coverage, the per-tool pre-approval lists with their toolkit cross-checks, and the composer fix are all sound, and the upstream touch points are thin appends.

Requesting changes on one thing: the escalation guards, and the doc sentence that promises them.

Today the guard is incomplete. The read-only-parent check and the approvals-on check run only when agent is supplied. A plain spawn copies the parent thread record's stored runtime mode, which the persona launch keeps as whatever the person picked (usually full-access) while the read-only sandbox is applied only when the provider opens. So a read-only Scout or Captain can spawn an unsandboxed full-access plain peer, docs/user/agents.md says it cannot, and nothing later in the stack closes it (148 refuses Crew members only). Plain delegate_task inherits the stored mode the same way.

Rather than extend the guard to every child-creation point, Jackson's ruling (2026-09-16) is to take it out. J5 does not have upstream's strict parent-child model, and we are not building protections against a well-aligned agent giving another agent more permissions: any such guard is one A2A message to a trusting peer away from bypass, and every extra rule is a rule delegate_task and spawn_agent then have to keep in sync (they already disagree: the approvals-on check exists only here, and only for one of the three prompting modes). A child's permissions come from its own saved agent's policy or from the human's approval, never from the parent.

Concretely:

  • Remove resolveAgentPersonaPeerSpawnPolicy and its test; the child's runtime mode is translateAgentPersonaProviderPolicy(assignment) for a role-ful spawn and the parent's mode for a plain one, as now, with no ceiling.
  • Leave upstream's own delegate escalation rule alone (it is upstream's).
  • Reword the doc sentence (inline) and the matching FORK.md clause at L212 ("a plain thread running with approvals on cannot spawn a write-capable saved agent with approvals off") so neither promises a ceiling.

Dropped after discussion: the retry re-resolving the library (a disabled agent mid-retry is the person's problem, and the thread errors visibly) and the request-id-without-payload-check behavior (pre-existing, going to an issue). The Captain-as-role question belongs to 148 and will be raised there.

Reviewed by Claude Fable 5.1 in Claude Code, with an independent pass by GPT-6-Astra in Codex.

Comment thread apps/server/src/j5/agents/agentPersonaSpawn.ts Outdated
Comment thread docs/user/agents.md Outdated
@bryantderosier
bryantderosier force-pushed the crews/03-saved-agents-as-peers branch from 12e5bd4 to 301a27b Compare September 16, 2026 11:32
@bryantderosier

Copy link
Copy Markdown
Collaborator Author

The escalation guards are out in 301a27b44, per your ruling: no parent-child permission ceiling, a child's permissions come from its own saved agent's policy or from the human's approval. The user doc, FORK.md, and the tools doc now say that instead of promising a ceiling, and the PR body no longer carries the callout.

@Jacksondr5 Jacksondr5 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Verified the fix at 301a27b44. Approving.

Reviewed by Claude Fable 5.1 in Claude Code.

Comment thread apps/server/src/j5/a2a/mcp/tools.ts Outdated
bryantderosier and others added 2 commits September 21, 2026 11:07
spawn_agent takes an optional agent id: the saved agent's declared routes constrain the explicit
provider, model, and reasoning pick, the matching route becomes the child's immutable assignment,
and its authority policy sets the child's runtime mode. A read-only persona parent cannot spawn a
write-capable agent, and a plain thread running with approvals on cannot spawn a saved agent that
would write with approvals off; human approval widens access only through a gate. The web composer
sends a persona thread's locked launch route so a remembered draft pick no longer fails every
message. The Codex approval-policy-never map and the Claude read-only allowlist pre-approve the J5
verbs, write_artifact, and the provider-native Subagent verbs by name, never the whole server.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Jackson read the description's last sentence as using "agent" for two things: the Peer Agent being spawned and the saved agent it may run as. The sentence now names the parameter and calls the saved agent a saved agent, keeping the SP4 brief-steering sentence verbatim.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bryantderosier
bryantderosier force-pushed the crews/03-saved-agents-as-peers branch from 3d373d4 to fa80d4e Compare September 21, 2026 15:07
@bryantderosier
bryantderosier merged commit 428d841 into j5/main Sep 21, 2026
19 checks passed
@bryantderosier
bryantderosier deleted the crews/03-saved-agents-as-peers branch September 21, 2026 15:38
bryantderosier added a commit that referenced this pull request Sep 21, 2026
* docs(j5): record the Crews design sessions

The worklog record for the Crews work from the definition-file design to the proposed roster, the
consolidation onto the shared handoff files, the review findings and the decisions that closed
them, the stop and archive verbs, the review of the merged agents stack's feedback and what changed
on the branch because of it, and the migration re-issue.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(j5): record the /crew decoupling and concurrent Crews

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(j5): record the stack review's three decisions and the no-ceiling ruling

The 2026-09-16 record gains the review of PRs #147 to #152: Jackson's ruling that there is
no parent-child permission ceiling, and Bryant's three choices from the 2026-09-17 review
(the lone-seat rule on the server's one command handler, delete included; one
reconciliation sweep at daemon start; the Crew record before any seat spawns), with the
alternatives each was chosen over. The 2026-09-14 record's pre-push review now points at
the ruling where it still lists the approvals-on guard as a landed fix, the Crews history
gains the 2026-09-17 entry, and the user guide says members cannot be deleted alone either.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(j5): record the second round of the stack review

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(j5): record the recovery-path rounds of the stack review

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(j5): record the launch report round of the stack review

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(crews): distinguish handoff delivery from acceptance

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 effective changed lines (test files excluded in mixed PRs). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spawn a saved agent as a full Peer Agent

2 participants