Repository navigation
feat(j5): an outside agent can message, start and stop agents - #560
Open
Jacksondr5 wants to merge 8 commits into
Open
Jacksondr5 wants to merge 8 commits into
Jacksondr5 wants to merge 8 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Jacksondr5
force-pushed
the
j5code/spawn-519
branch
from
October 12, 2026 05:34
2edbd48 to
3ad9b31
Compare
Jacksondr5
force-pushed
the
j5code/outside-agents-498
branch
from
October 12, 2026 05:40
0a9dd9d to
b971c45
Compare
Jacksondr5
force-pushed
the
j5code/spawn-519
branch
from
October 12, 2026 06:03
3ad9b31 to
0dbcbf8
Compare
Jacksondr5
force-pushed
the
j5code/outside-agents-498
branch
from
October 12, 2026 06:20
dada229 to
c7f1531
Compare
Jacksondr5
force-pushed
the
j5code/spawn-519
branch
3 times, most recently
from
October 12, 2026 06:45
af1d67b to
572fb63
Compare
Jacksondr5
force-pushed
the
j5code/outside-agents-498
branch
from
October 12, 2026 06:49
c7f1531 to
25b8bee
Compare
Jacksondr5
added a commit
that referenced
this pull request
Oct 12, 2026
Jacksondr5
force-pushed
the
j5code/outside-agents-498
branch
from
October 12, 2026 07:16
25b8bee to
9ad520d
Compare
Jacksondr5
force-pushed
the
j5code/spawn-519
branch
from
October 12, 2026 07:23
572fb63 to
2d415cd
Compare
Jacksondr5
force-pushed
the
j5code/outside-agents-498
branch
from
October 12, 2026 07:30
9ad520d to
69791c2
Compare
Jacksondr5
force-pushed
the
j5code/spawn-519
branch
from
October 12, 2026 07:31
2d415cd to
9b87419
Compare
…stop them An agent signed in from outside the app (an MCP OAuth client) had no identity in J5's ledger, so every J5 tool that acts for a calling thread refused it with upstream's generic error. It could watch the fleet but not take part (#498). Each sign-in is now the participant `outside:<session id>`, shown by the label its client registered and kept in a new `j5_a2a_outside_agent` table. - `j5_send_message`: a plain message to an agent on this server, recorded in the receiver's project. The level the sign-in was approved at caps every send, a queued one included. Asks, replies, people, peer servers and unknown ids are refused with the legal move named. Retry keys use the client session's namespace. - Delivery uses a new envelope that names the outside agent by its label and id and says no reply can reach it. Nothing can be delivered to one, for any sender, and a peer server may not deliver as one. - `j5_list_participants` opens to every outside agent and needs `project_id`. - `j5_stop_agent` opens under the same cap, with no Captain exemption. - The Crew tools, `j5_clear_own_ask` and the playbook run tools stay refused, now with an error that names what an outside agent can do instead. They are declared `writes` and refuse in the handler. `j5_spawn_agent` and `delegate_task` keep upstream's refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Slice 1 of #498 told an outside agent to "start an agent with j5_spawn_agent and brief it" for everything it is refused, but the spawn tool itself still refused it. - `j5_spawn_agent` is declared `startsThreads` with no modes. That keeps every check a thread caller gets, admits an outside agent and refuses a read-only client. The handler's own mode checks, wording and retry refusal are unchanged; for an outside agent their limit is the level the sign-in was approved at, and omitted modes are that level. - An outside agent names the project (`project_id` or `scratch`) and cannot pick the `shared` workspace. Both refusals name the legal move. - A persona's policy must be within the approved level for an outside agent. A thread caller's persona spawn keeps having no ceiling. - The new agent has no placement parent and records `outside:<session id>` as its spawner. The label is written with the placement, through the same upsert a send uses. Placement accepts an outside spawner it has a record of. - The first turn names the outside agent by its label and says no reply can reach it, in the identity block the web parser already reads. - Retry keys use the client session's namespace. - The participant-identities read resolves an `outside:` id to its label, and the Fleet read names the outside spawner in a new optional `outsideSpawner` field on `FleetAgent`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A message from an outside agent arrived as raw envelope text, and an agent one started read "Agent-spawned" on the Fleet page with nothing naming who started it (#498). - Thread card: the outside-agent envelope renders as the peer card, named by the outside agent's label and marked "Outside agent" the way a machine sender is marked "Automation". The label in the envelope stands in until the participant-identities read answers, so no new read is made. The instruction sentence stays envelope text for the receiving agent. A queued delivery is labelled the same way. - Fleet page: an agent with `outsideSpawner` reads "Started by outside agent <label>", or its id when the client registered no label. - Spawn brief: "Spawned by" and "Brief from" mark an `outside:` spawner as an outside agent, and say "an outside agent" instead of "Unnamed participant" while its label is unread. Mobile renders no A2A cards and has no Fleet surface, so nothing changes there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, and review findings - `actsAsThreadCaller` and `readsAsThreadCaller` declare a tool that needs a calling thread and refuse an outside agent with its legal move. The five Crew and ask tools, the playbook tools and `delegate_task` use them, so a new handler cannot admit an outside agent by forgetting a check. The playbook reads and `delegate_task` gave upstream's generic refusal before. - `j5_spawn_agent` is declared `writes`, as send and stop are. - `j5_list_participants` lists a project that has no thread yet as its people and no agents, for every caller, instead of failing on the missing ledger. For an outside agent no row accepts an Exchange or an urgency, and a person accepts nothing. - An outside send resolves its receiver once before the send and once inside it, and checks replay once. It returns no backlog notice. - The outside agent's label is written once. Placement no longer checks for the row its own transaction writes. - The thread card names an outside sender from the identities read alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cap is checked at send The tool reference kept two "Outside agents" paragraphs beside rules that read as universal. Each rule now states its outside-agent case, and the Errors lists cover them. The definition and D2 say the approved level is checked when a call is made: a message already sent is still delivered after the receiver's modes are raised or the sign-in is revoked. D2 no longer says `delegate_task` keeps upstream's refusal. The module README keeps only what the code does not say. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… keeps the name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 of 8 tasks
Jacksondr5
force-pushed
the
j5code/outside-agents-498
branch
from
October 12, 2026 07:36
69791c2 to
83c224a
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
An agent signed in from outside the app (Claude Code or Codex in a terminal, ChatGPT, a bot) could read the fleet on J5 but could not message, start or stop an agent. Upstream's docs promise all three, and J5 hides upstream's own send and launch tools. Closes #498.
Stacked on #557 (which is stacked on #553). Review this PR's own four commits.
What changed
An outside agent gets an identity in J5's ledger, one per sign-in:
outside:<session id>, shown by the label the client registered. The design and each decision are in #498 (Jackson, 2026-10-11).j5_send_messageaccepts an outside agent. It sends plain messages to agents on this server only. Nothing can be delivered to it, so asks, replies and messages addressed to it are refused, each with the legal move named. Its message is recorded in the receiver's project, and the envelope tells the receiving agent who sent it and that no reply can reach it.j5_spawn_agentaccepts an outside agent that names a project, or asks for none. The new agent sits at the top level of its project with the outside agent as its spawner.j5_list_participants(with aproject_id) andj5_stop_agentaccept an outside agent.delegate_tasknow also requires the orchestration capability (every thread session has it), and listing a project that has no agent threads yet returns an empty listing where it returned an error.delegate_task,j5_stop_crew,j5_archive_crewandj5_clear_own_asktell an outside agent to start an agent and brief it. One helper makes that refusal for every thread-only tool.A new table,
j5_a2a_outside_agent(ledger migration 33), keeps each outside agent's label for the envelope and the clients.UI changes
Web only, captured at 1280×800 on the live-test servers. Every state is new: on the base (#557) an outside agent's send and spawn are refused, so there is no "before" to show.
No video was captured in this pass, so the shots do not show the queued row turning into a delivered card.
Live testing
Pass, at
25b8bee1a3against baseaf1d67b344, by a Peer Agent followingj5-live-test. Report:test-reports/j5code-outside-agents-498.md. The head has since been rebased over docs-only commits beneath it.Ran live: a real OAuth sign-in as an outside agent; listing, sending, spawning, retrying and stopping; every refusal, with its text; one receiving turn each on Codex (Luna) and Claude (Haiku); one turn sent through the UI; a restart at rest and a restart during a held turn; migration 33 on a copy and on a fresh home; a refused send to an agent on a peer server; a read-only sign-in; revoking the sign-in; an in-app agent asked in plain words to answer an outside agent's message and to message another agent; the browser pass after the rebase.
Not exercised live:
j5_archive_crew,j5_clear_own_askand the playbook tools other than start and current. Unit tests cover these.j5_spawn_agent. The tool refused the test home's Haiku model because it exposes no reasoning options, so the spawn was verified on Luna.Nothing needs a person to test by hand.
Observed and not caused by this PR: a Haiku thread switched from Full access to Auto failed its next turn with "auto mode unavailable for this model"; and an in-app agent listing another, empty project sees the person's row labelled with the agent's own project.
Checklist
FORK.md(case text and file-table row) in this PR (none edited)docs/j5/product/upstream.md(D2 rewritten)AGENTS.md)docs/j5/product/and user docs rewritten where this changes themSurfaces: web changed; desktop wraps web; mobile has no matching surface. Not provider-shaped. An outside agent reaches this server only, in every connection mode. Reverse state: revoking the session in Settings → Connections retires the identity.
Built by Claude Opus 5.5 in Claude Code, with subagents for the three slices.
🤖 Generated with Claude Code