Project composed roles as harness subagent definitions, so a seat can be a teammate rather than only a window #349
Labels
No labels
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/devrel
role/eval
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/sysadmin
role/tpm
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-compose#349
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Filed by Saiya (tpm seat), 2026-08-25, after Kai noted the harness gained cross-agent messaging this week and read it as fitting her setup well. The instinct is right and the mechanism is not the one she assumed. This issue records what the capability actually is and what would connect it.
What the messaging tool actually does
Read from the live tool schema rather than from release notes.
SendMessagetakestoas a teammate name, or"main"for the main conversation from a background subagent. Teammates are agents spawned by theAgenttool inside one session. Names survive completion, and a send resumes the agent from its transcript.It is within-session. Two
atermwindows are separate processes with separate sessions, so nothing in this tool bridges them. Removing the nested-launch refusal in #348 does not change that either: a nestedatermopens another independent window, which is still not a teammate.What would connect it
The
Agenttool resolvessubagent_typefrom a registry of agent definitions. On a live session right now the available types are the harness defaults only, with no role seats present.internal/project/project.goconfirms why. The projectionLoadPointsare exactly two:Instructions and skills. There is no
.claude/agents/target. So agent-compose has never emitted a subagent definition, and the seats cannot be spawned as teammates.Half the plumbing already exists on the presentation side.
internal/nativeui/nativeui.go:19carries an eight-token subagent palette where "a role claims the nearest slot", and every role ships a subagent statusline command. Subagents are already branded by role. They are just never defined by role.Why this fits the estate unusually well
A subagent definition wants a charter, a tool boundary, and a voice. That is precisely what a composed role already is: a role skill, an ordered boundary set with owns, holds-within-scope, and defers, plus a personality meld. The roster is the hard part and it is done. This is a projection on top of it.
It would also make the boundary model executable rather than advisory in a new way. A
tpmteammate that defers foundational software to aplatformteammate is the deferral actually happening between two addressable parties, instead of one agent narrating that it would defer.Boundary question to settle first, deliberately
AGENTS.mdrecords that there is no autonomous agent-to-agent command channel, the o2r relay having been archived in the June 2026 surface reduction (agentic-os-kai#677, revival tracked atward#104), with delivery human-mediated.Composed teammates exchanging
SendMessagetraffic is agent-to-agent delivery. It is plausibly distinct from the archived relay, which was cross-host and unattended, whereas this is in-session and under a human's turn. That distinction should be settled on purpose rather than arriving as a side effect of a projection change. Naming it is this issue's job; deciding it is Kai's.Suggested first cut
Do not build the whole projection. Emit one role as a subagent definition, spawn it, and send it a message. That answers the questions no amount of design will:
Same tracer shape as #332, and independent of the #329 inversion.
Acceptance criteria for the tracer
Agentspawns it bysubagent_typeand it reports the correct role, meld, and boundary text.SendMessagereaches it by name and it replies into the session.Related
Correction: cross-session messaging exists, and the issue body is wrong about it
Read from the docs at
code.claude.comon 2026-08-25, after filing.The body claims
SendMessageis within-session only and that twoatermwindows cannot be bridged. That is false. There is a third mechanism the body missed, and it is the one that matches Kai's setup.The three mechanisms, correctly
.claude/agents/*.md, spawned by theAgenttool inside one session, results return to the caller. What the body describes.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1. A lead spawns teammates as independent Claude Code instances with a shared task list and a mailbox at~/.claude/teams/{team-name}/inboxes/{agent-name}.json. Teammates message each other by name. One team per session, no nested teams, lead is fixed.ListAgentsdiscovers,SendMessagedelivers./list-agents(alias/peers) lists reachable sessions. Same-machine delivery runs over a per-session Unix domain socket and never passes through Anthropic servers. Sessions answer to the name set by/renameor the--nameflag.The third one is two
atermwindows talking. It needs no projection change, no subagent definition, and no team.Version gate, checked on this host
Cross-session messaging requires v2.1.224 or later on macOS and Linux. This host is three patch releases short, which is why the capability has not shown up in the setup.
/list-agentsnot being recognized is the documented way to confirm a session lacks it.This changes the boundary question, and mostly settles it
The body flagged
AGENTS.md's "there is no autonomous agent-to-agent command channel" as needing a deliberate decision. Kai's stated reason for the o2r archive was capacity rather than a design objection, so that line records an absence rather than a prohibition. It is also now factually wrong as a description of the estate once any host passes v2.1.224, and it should be rewritten rather than defended.What the archive was protecting against is already enforced by the harness, which matters more than the doctrine line:
CLAUDE.md, or other configuration because another session asked./compactin the body arrives as plain text.So a message carries information and cannot carry authority. That is the property the human-mediated rule existed to guarantee, and it now holds without the rule.
Controls worth setting deliberately
crossSessionInbound-accept,hold, orrefuseper session. With no value set, the default decides per message from the two sessions' permission-mode classes, and a receiving session that bypasses prompts holds everything for approval.isolatePeerMachines: true- requires explicit approval before any message leaves the machine, even underbypassPermissions. Atruefrom any settings scope applies and cannot be turned off by a lower scope.SendMessageandListAgentsturn off sending and listing. Note this also removes messaging to subagents and teammates, since one tool serves all three.Two environment facts that bite this estate specifically
warded.What survives from the original issue
The subagent-definition projection is still worth doing and is still untracked.
~/.claude/agents/does not exist on this host, andinternal/project/project.gostill emits only instructions and skills. The frontmatter schema maps onto a composed role card closely enough to be worth the tracer:name,description,tools,disallowedTools,model,permissionMode,skills,mcpServers,hooks,memory,effort,isolation, andcolor.One gotcha for a skill-composed roster: the docs state that
skillsandmcpServersin a subagent definition are not applied when that definition runs as a teammate. Teammates load skills from project and user settings like a normal session. Since role identity here is carried by skills, a role projected as a subagent and the same role run as a teammate would not compose identically. That belongs in the tracer's acceptance criteria.Follow-up owed
AGENTS.mdagent-to-agent line once a host is on v2.1.224 or later. Not filed yet.