Skip to content

[DRAFT] - Subagents, reborn#2716

Draft
krissetto wants to merge 2 commits into
docker:mainfrom
krissetto:subagents-v2
Draft

[DRAFT] - Subagents, reborn#2716
krissetto wants to merge 2 commits into
docker:mainfrom
krissetto:subagents-v2

Conversation

@krissetto
Copy link
Copy Markdown
Contributor

No description provided.

@aheritier aheritier added area/agent For work that has to do with the general agent loop/agentic features of the app priority:high status/needs-design Requires architectural discussion or design review labels May 11, 2026
krissetto added 2 commits May 13, 2026 16:30
Introduces a self-contained subagent execution stack that lets the
runtime spawn, supervise, and persist arbitrarily-nested child agents
without any external orchestration. The feature is contained behind the
LocalRuntime and its pkg/subagent dependencies; existing embedder-facing
APIs are unchanged.

## Config
- Adds config schema v9 with a top-level `sub_agents` list. Each entry
  names an agent defined elsewhere in the team and configures execution
  policy (max_depth, max_turns). The previous schema is frozen as v8.
- agent-schema.json and pkg/config/latest/types.go updated accordingly.
- Example: examples/subagents.yaml.

## pkg/subagent
New package that owns the subagent lifecycle independently of the
runtime loop:
- Manager: registry + supervisor for all live child agents. Controls
  max-depth/max-descendants limits, per-child Interrupt/Close/Stop and
  typed Send (steer / follow-up).
- Handle: per-child coordination handle returned to tool callers.
- Inbox (via pkg/inbox): bounded, back-pressured steer/follow-up queue
  with coalesced ready-signal channel.
- toolset.go: the six agent_ tools exposed to the model
  (subagent_start/send/inspect/list/finalize/stop).
- Status-only envelopes let interrupted child turns notify parent UI
  state without waking the parent agent loop or adding transcript noise.
- Parked interrupted children remain in-flight until they publish a real
  turn-completed envelope, ensuring parents continue waiting for their
  eventual completion.

## pkg/runtime
- session_state.go: per-RunStream coordination bundle (queues, wake
  policy, isChild flag) replacing scattered pointer parameters.
- wake_policy.go: rootWakePolicy and childWakePolicy; child sessions
  park between parent messages, root sessions use the existing Steer/
  FollowUp queues. drainParentEnvelopesMidTurn extracts the mid-turn
  envelope flush from the hot loop body.
- EventBus (eventbus.go): fan-out hub for broadcasting events to
  multiple subscribers (live-session SSE, TUI, tests). The recorder is
  registered here instead of being hard-wired into RunStream.
- SessionRecorder (recorder.go): replaces PersistenceObserver as the
  canonical persistence writer. Handles positional user-message inserts
  (idempotent replay), streaming-message lifecycle, compaction snapshots,
  and token usage. PersistenceObserver becomes a deprecated no-op stub.
- SubagentRunner / subagent_envelopes.go: inject child results back into
  the parent context as implicit user messages with kind=subagent_envelope.
  SubagentEnvelopeMessage constructor in pkg/session keeps the stamp
  logic in one place.
- session_tree.go / live_registry.go / live_event_source.go: live-tree
  snapshot and SSE fan-out for the /sessions/:id/tree and
  /live-sessions/… API surface.
- observability.go: SteerSessionByID / FollowUpSessionByID / …SessionByID
  unified via resolveSessionControl helper.
- initSubagentManager extracts the manager wiring from NewLocalRuntime.
- New events: SubAgentStarted/Sent/Update, ParentIdle/Resume,
  LiveSessionTreeChanged, TurnStarted/TurnEnded,
  ConnectionLost/ConnectionRestored.
- Remote client registry extended with all new event types.

## pkg/session
- AddMessageAt / PositionalStore interface: idempotent insert by index.
- AppendMessage: returns position alongside the usual append.
- SubagentEnvelopeMessage constructor.
- Migration adds the `implicit` and `kind` columns.

## pkg/server
- /sessions/:id/tree, /live-sessions/… SSE and control endpoints wired
  to the new live-session infrastructure. api.LiveSessionNode includes
  display fields (Title, Depth, LastPreview, CreatedAt, LastUpdateAt).

## pkg/app
- WithAttachedTeam / WithSnapshotController options plumbed for
  runtime-managed child tabs.
Adds TUI support for the runtime-managed subagent infrastructure
introduced in the preceding commit. No runtime logic is modified here;
this commit is purely UI wiring and new components.

## Sidebar
- Subagents section renders live child-agent rows with per-row status
  badges, preview text, and elapsed time. Rows highlight on hover and
  trigger ClickSubagent events for one-click attach.
- Hover/click zones are built post-render and kept in sync with
  subagentClickZones so mouse motion always hits the right row.
- Parent-session line click zones are also derived from rendered lines,
  so wrapped working-directory text cannot shift the parent hitbox.
- ParentIdle/Resume events dim the spinner while waiting on children;
  TurnStarted/TurnEnded drive workingAgent rather than StreamStartedEvent
  so the spinner correctly tracks turn-level activity, not session-level.
- Stream lifetime keeps the shared spinner ticking between StreamStarted
  and the first TurnStarted.
- ESC (StreamCancelledMsg) no longer marks subagents as terminal:
  child lifecycles are owned by the runtime, not by the parent turn.
- Status-only subagent updates refresh sidebar rows after attached-tab
  interrupts without adding transcript cards.
- Collapsed-mode shows a subagent count badge and parent-session back-
  link for sub-session tabs.

## Attached / live-child tabs
- NewAttached creates an App that forwards messages to a parent
  runtime via attachedSend rather than driving its own loop.
- WithAttachedTeam seeds the full parent team list so colour indices
  and sidebar agent rows stay consistent across tabs.
- focusEditorForNewTab / clearTransientUIForLeavingCurrentPage helpers
  keep hover state consistent on tab switches.

## Tool views
- New pkg/tui/components/tool/subagent package renders subagent_start /
  send / inspect / list / finalize / stop tool calls with status badges
  and truncated previews.
- factory.go maps all six agent_ tool names to the new renderer.

## Dialog
- tool_confirmation.go adds a subagent_start delegation card showing
  the delegating agent, the target agent name, and the task summary.
- session_tree dialog for browsing the live tree and opening child tabs.

## Performance / TUI improvements from main (merged via rebase)
- IncrementalRenderer in message.go avoids full re-parse on every
  streaming chunk; only the trailing region is re-rendered.
- URL span cache (urlSpanCache) in messages.go deduplicates link
  detection work across frames.
- Coalesced scroll handling (WheelCoalescedMsg) reduces re-render
  frequency under fast wheel input.
- tickPaused flag gates animation ticks while the model is idle,
  eliminating redundant View() calls.
@aheritier aheritier added status/needs-rebase PR has merge conflicts or is out of date with main kind/feat PR adds a new feature (maps to feat: commit prefix) labels May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent For work that has to do with the general agent loop/agentic features of the app kind/feat PR adds a new feature (maps to feat: commit prefix) status/needs-design Requires architectural discussion or design review status/needs-rebase PR has merge conflicts or is out of date with main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants