acompose and aterm cannot pass --nested, so the one-hop nesting capability is unreachable #1336

Open
opened 2026-08-28 04:33:52 +00:00 by coilyco-ops · 0 comments
Owner

What is wrong

agent-compose launch gained --nested in 65030ee, which lets one composed session start a second seat, bounded to one hop. No consumer surface in this repository can reach it, so the capability exists and cannot be used.

The flag is positional-first only. cmd/agent-compose/main.go:48:

func splitNativeLaunchFlags(args []string) (bool, []string) {
	if len(args) > 0 && args[0] == nestedLaunchFlag {
		return true, args[1:]
	}
	return false, args
}

It reads args[0] and nothing else. Every wrapper here puts the role in that slot.

shell/common.sh:240 and :243:

command aos _native-shadow --harness "$harness" --role "$role" \
  --assigned-role -- agent-compose launch "$role" "$harness" "$@"
...
command agent-compose launch "$role" "$harness" "$@"

So acompose eval claude --nested puts the flag in position three, where launch forwards it to the harness as a task argument. It is silently accepted and does nothing. There is no argument ordering a caller can use to reach the parser, and aterm runs the same wrapper.

The symptom, unchanged

aterm eval claude from inside a composed session still refuses with:

native role launch cannot start inside another agent-compose launch

Kai reported this originally as a UX limit. coilyco-flight-deck/agent-compose#348 traced it, the engine half landed, and this repository is where the remaining half lives.

Why it is silent rather than an error

The flag reaches the harness as a prompt fragment. Nothing rejects an unknown token there, because harness arguments pass through verbatim by design. So a caller who reads the launch usage line, sees [--nested], and types it gets no flag, no warning, and a refusal that does not mention the flag they just passed.

That is the shape where a capability looks broken rather than unreachable, and the two get debugged very differently.

Options, not decided here

  • Pass it from the wrapper. acompose detects AGENT_COMPOSE_LAUNCH and prepends --nested itself, so nesting works by default and the flag stays an engine-level detail. Changes behaviour without the caller asking, which is the argument against.
  • Forward it explicitly. acompose accepts --nested in its own argument list and moves it to the front. Keeps the opt-in deliberate, and costs a small parser in shell.
  • Widen the engine parser so the flag is accepted anywhere before the harness arguments. Belongs in agent-compose rather than here, and is ambiguous against harness arguments that legitimately start with a dash.

The second is the smallest change that preserves the deliberateness 65030ee was designed around, but the choice is the platform seat's.

Acceptance criteria

  • From inside a composed session, a caller can start a second seat through acompose and through aterm, without invoking agent-compose directly.
  • The one-hop bound still holds: a third level refuses.
  • A caller who passes the flag where it cannot be parsed gets a refusal naming the flag, rather than silent pass-through into the harness prompt.
  • docs/aterm.md states whether nesting is available and how, since it currently documents neither.

Provenance

Found from the eval seat while working the headless backlog, verified by reading splitNativeLaunchFlags and shell/common.sh rather than by running the command. The engine-side evidence and the timeline are in agent-compose#348.

## What is wrong `agent-compose launch` gained `--nested` in `65030ee`, which lets one composed session start a second seat, bounded to one hop. **No consumer surface in this repository can reach it**, so the capability exists and cannot be used. The flag is positional-first only. `cmd/agent-compose/main.go:48`: ```go func splitNativeLaunchFlags(args []string) (bool, []string) { if len(args) > 0 && args[0] == nestedLaunchFlag { return true, args[1:] } return false, args } ``` It reads `args[0]` and nothing else. Every wrapper here puts the role in that slot. `shell/common.sh:240` and `:243`: ```sh command aos _native-shadow --harness "$harness" --role "$role" \ --assigned-role -- agent-compose launch "$role" "$harness" "$@" ... command agent-compose launch "$role" "$harness" "$@" ``` So `acompose eval claude --nested` puts the flag in position three, where `launch` forwards it to the harness as a task argument. It is silently accepted and does nothing. There is no argument ordering a caller can use to reach the parser, and `aterm` runs the same wrapper. ## The symptom, unchanged `aterm eval claude` from inside a composed session still refuses with: ``` native role launch cannot start inside another agent-compose launch ``` Kai reported this originally as a UX limit. `coilyco-flight-deck/agent-compose#348` traced it, the engine half landed, and this repository is where the remaining half lives. ## Why it is silent rather than an error The flag reaches the harness as a prompt fragment. Nothing rejects an unknown token there, because harness arguments pass through verbatim by design. So a caller who reads the `launch` usage line, sees `[--nested]`, and types it gets no flag, no warning, and a refusal that does not mention the flag they just passed. That is the shape where a capability looks broken rather than unreachable, and the two get debugged very differently. ## Options, not decided here * **Pass it from the wrapper.** `acompose` detects `AGENT_COMPOSE_LAUNCH` and prepends `--nested` itself, so nesting works by default and the flag stays an engine-level detail. Changes behaviour without the caller asking, which is the argument against. * **Forward it explicitly.** `acompose` accepts `--nested` in its own argument list and moves it to the front. Keeps the opt-in deliberate, and costs a small parser in shell. * **Widen the engine parser** so the flag is accepted anywhere before the harness arguments. Belongs in agent-compose rather than here, and is ambiguous against harness arguments that legitimately start with a dash. The second is the smallest change that preserves the deliberateness `65030ee` was designed around, but the choice is the platform seat's. ## Acceptance criteria - [ ] From inside a composed session, a caller can start a second seat through `acompose` and through `aterm`, without invoking `agent-compose` directly. - [ ] The one-hop bound still holds: a third level refuses. - [ ] A caller who passes the flag where it cannot be parsed gets a refusal naming the flag, rather than silent pass-through into the harness prompt. - [ ] `docs/aterm.md` states whether nesting is available and how, since it currently documents neither. ## Provenance Found from the eval seat while working the headless backlog, verified by reading `splitNativeLaunchFlags` and `shell/common.sh` rather than by running the command. The engine-side evidence and the timeline are in agent-compose#348.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#1336
No description provided.