Multi-level orchestration: depth-capable client core and drill-down UI - #14762
Conversation
Makes the client depth-capable for multi-level agent orchestration (server-gated by OrchestrationMaxDepth; behavior is unchanged at today's depth of 1): - A mid-tree node blocked on wait_for_events now registers as a parent (behind the WaitForEventsParentRegistration dogfood flag), so it discovers and streams its own children. - A child conversation's run_agents auto-executes: hidden panes cannot show confirmation cards, so blocking policies surface as a graceful Denied tool result instead of hanging an invisible card. - The orchestration pill bar becomes a drill-down: it renders one level (the anchored conversation's direct children), children that are themselves orchestrators render as group pills with a rolled-up subtree badge, and breadcrumbs lead back to the root and the direct parent. - ESC and the back button navigate one level up (repeated ESC walks up the tree), with the parent named in the label; navigation and the agents-panel root card roll up the whole subtree via the recursive topology walkers. - The run_agents confirmation card discloses that launched agents may start their own sub-agents (dogfood-flagged). Co-Authored-By: Warp Agent <agent@warp.dev>
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR adds client support for multi-level orchestration: depth-aware run-agents behavior, mid-tree event streaming, recursive status rollups, drill-down pill-bar navigation, breadcrumbs, and back-button behavior for nested agents.
Concerns
- The change is user-facing (pill bar drill-down, breadcrumbs, back-button labeling/navigation, and run-agents card copy), but the provided PR description does not include screenshots or a screen recording. For this user-facing change, please include screenshots or a screen recording demonstrating it working end to end.
Verdict
Found: 0 critical, 1 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
cephalonaut
left a comment
There was a problem hiding this comment.
Ordered by priority.
Daniel - looks good overall. Reviewed with an agent, so feel free to push back on
any of these or skip altogether.
Highest value
1. Should the multi-level work get its own flag? — run_agents.rs:438, run_agents_card_view.rs:1546, warp_features/src/lib.rs:706
Today the disclosure is gated on WaitForEventsParentRegistration, whose doc covers only the
streamer registration, and the child auto-execute isn't gated at all. QUALITY-919 plans to
promote and then remove that flag, which would ship the disclosure without anyone deciding to.
A separate flag would cover both, and would keep the auto-execute from running ahead of the
server's depth budget.
2. What happens on restore from disk? — orchestration_pill_bar.rs:684, :1789, terminal/view.rs:28645
The badge counts descendants from the children index, including ones not loaded yet. The child
list filters those out, and the bar returns None when the filtered list is empty — so a pill
could show "3" and drilling in makes the bar disappear. There are now three separate fallbacks
for an unloaded ancestor (this count, the breadcrumb label, the back-button label). Is an
unloaded ancestor actually reachable here? If not, those fallbacks may be hiding a bug.
3. Two different parent lookups — orchestration_pill_bar.rs:735 and :714
drill_down_anchor_id resolves via the links helper (agent-id + server-token); breadcrumb_ids
and the root walk use the history model's (agent-id only). With server-token-only linkage you
can drill in and have no breadcrumb back. Use the same one in both?
4. The bar and keyboard nav can now disagree — orchestration_pill_bar.rs:637, orchestration_topology.rs:214, :288
The comments still say these can't drift. The row now shows one level while next/prev cycles the
whole tree, so cycling can land on an agent that isn't in the bar and the bar re-anchors under
you. Comments need a tweak either way — and do you want cycling to reach agents that aren't
visible?
Smaller
5. Back-button truncation — terminal/view.rs:28625
ActionButton already ellipsizes once max_label_width is set (action_button.rs:369, :789);
the back button sets neither. Counting characters misses wide glyphs, so a CJK name still
overflows. with_max_label_width would replace the constant, the branch, and its test.
6. A test still asserts the removed short-circuit — wait_for_events_tests.rs:84
It expects zero get_ambient_agent_task calls for a child. It passes only because App::test
never drives the spawned future, so times(1) wouldn't work either. Pulling the guard chain in
register_parent_on_wait into a plain predicate would make it testable — and would cover the
child case, which the new streamer test doesn't (it calls finish_register_parent_on_wait
directly).
7. Leaf children now refetch on every wait — orchestration_event_streamer.rs:556
Without the short-circuit a leaf never becomes a parent, so it refetches each time it waits.
Heads up that #14473/#14480 are in review and should remove the need for this fetch — worth
keeping an eye on so the two don't collide.
8. drill_down_anchor_id isn't tested — orchestration_pill_bar_tests.rs:318
The new tests cover breadcrumb_ids only. build_three_level_tree would cover the anchor rules
in a few asserts, including the depth-1 equivalence the PR claims.
9. One more label case — view_tests.rs:8496
"for parent agent" (nested parent, empty name) isn't covered. One assert on the existing
fixture.
Nits
10. Telemetry — orchestration_pill_bar.rs:1834, :816
Breadcrumb clicks look identical to pill switches, and source_conversation_id now means the
anchor rather than the root. Probably wants a look before anyone reads these numbers.
11. Double walk — orchestration_pill_bar.rs:684
Count and aggregated status walk each subtree separately, per child, per render. Could be one
walk if it's easy.
12. Breadcrumb pill re-derives the pill chrome — orchestration_pill_bar.rs:1762
Will drift next time pills get restyled.
13. Leftover? — orchestration_topology.rs:300
history.conversation(&active_conversation_id)?; discards its result. Still needed?
14. Parent resolved twice — terminal/view.rs:11336
is_child_agent is just label != "for terminal".
15. "sub-agents" — run_agents_card_view.rs:1550
Elsewhere we say "child agents", including the denial message on this same path.
…en is assigned A remote child's run-id/server-token linkage can arrive after StartedNewConversation, and pill contents keyed on run linkage previously stayed stale until an unrelated status event fired. Co-Authored-By: Warp Agent <agent@warp.dev>
- Gate the client-side multi-level surfaces on a new MultiLevelOrchestration dogfood flag: the confirmation-card disclosure moves off WaitForEventsParentRegistration, and a child conversation's run_agents call is denied gracefully when the flag is off (children still auto-execute so the Denied result renders instead of a card hanging in a hidden pane). - Compute group-pill subtree badges with a single walk over loaded descendants (new loaded_subtree_rollup topology helper), so the badge count covers exactly the set the aggregated status inspects. - Unify parent resolution in the history model's resolver; the orchestration-links helper is now a thin wrapper. Token-linked children index under their parent (restore-time behavior pinned by tests). - Ellipsize the back-button label pixel-based via the button's max label width instead of a char-count truncation. - Extract the wait-time parent-registration guard chain into a testable should_register_parent_on_wait predicate; fix the stale wait_for_events test that still described the removed child short-circuit. - Telemetry: breadcrumb clicks report PillBarPillKind::Breadcrumb and pill bar payloads carry root_conversation_id alongside the drill-down anchor. - Comment/doc fixes for the shared per-level ordering vs tree-wide cycling, the intentional existence bail in adjacent navigation, and card copy (sub-agents -> child agents). New tests for drill-down anchoring, empty-name back labels, rollup counts, and flag-state execution paths. Co-Authored-By: Warp Agent <agent@warp.dev>
|
Thanks for the thorough review — addressed in 4942833. Point-by-point:
Validation: (Posted by Warp Agent on Daniel's behalf.) |
The mock's Err return can be refetched by the streamer's restore-retry loop; whether a retry lands before test teardown is platform timing (macOS passed, Linux/Windows hit a second call). The test's claim is that children now trigger the registration fetch at all — strictly more than the removed short-circuit's zero — so expect at least one call. Co-Authored-By: Warp Agent <agent@warp.dev>

Description
Client side of multi-level (configurable-depth) agent orchestration. Today only the root "lead" agent can start child agents; the server is making depth configurable via
OrchestrationMaxDepth(root = depth 0, a run may orchestrate iffdepth < max, default 1 = today's behavior, dogfood = 2). This PR makes the client behave correctly when a tree is more than one level deep:wait_for_eventsnow confirms parent status against the server and registers for the ancestor event stream, instead of being short-circuited by the old one-level-tree invariant (still behind theWaitForEventsParentRegistrationdogfood flag).run_agents. Child conversations live in hidden panes where a confirmation card would be invisible and hang the run. Theirrun_agentscalls auto-execute; interactive policy blocks (never-allow profile, missing harness key, disapproved config) still surface as a gracefulDeniedtool result. The multi-level surfaces are gated on a newMultiLevelOrchestrationdogfood flag: with the flag off, a child'srun_agentscall is denied outright ("Multi-level orchestration is not enabled on this client.") instead of falling through to the interactive card path. Run-wide settings carry over via the existing per-surface execution-profile inheritance. The server gates tool exposure by depth, so this path is unreachable at depth 1.MultiLevelOrchestrationflag, since the client cannot cheaply know the server depth budget).Everything is inert at orchestration depth 1: the server never grants children the
run_agentstool, trees never exceed one level, and the drill-down anchor resolution matches the old root-anchored behavior exactly.Linked Issue
Part of the multi-level orchestration work (client side); pairs with the warp-server
OrchestrationMaxDepthchanges.Testing
MultiLevelOrchestrationflag states, recursive rooting / spawn-order cycling with 3-level fixtures, direct-children pill ordering, drill-down anchor resolution, breadcrumb target resolution (including token-only parent linkage), loaded-subtree rollup counts, and back-button labels at depth (truncation is pixel-based via the button's label clip).cargo check -p warp --lib,cargo clippy -p warp --all-targets --tests -- -D warnings, and./script/formatare clean at this stack state../script/run(depth-2 trees against a server withOrchestrationMaxDepth=2)https://www.loom.com/share/beffa1541c5e4032914442baf93bde1b
Agent Mode
Co-Authored-By: Warp Agent agent@warp.dev