Repository navigation
An agent's subagents are invisible: the processes section lists OS processes only - #417
Merged
Merged
Conversation
The crate a subagent is modelled in: what one is, how its run ends, and the single event shape both feeds reduce to. No recognizers yet. SubagentState is closed with no default, deliberately unlike the settings vocabularies. Those degrade an unrecognized value to a default so one bad field cannot take a whole document down; here the opposite is required - defaulting a failure to Finished would report a subagent succeeded when the agent said it did not. An unknown word is an error, and the caller's job on one is to record nothing. SubagentKind is open, like agent_type: the set of kinds is the user's own configuration. The one thing the code decides is whether a kind was stated at all, which is why it is not a String - a report naming no kind and a report naming the kind "unstated" are different facts, and an empty string makes them the same one. Display writes nothing for the absent case rather than inventing English the catalogue owns. Subagent carries an `ended` instant the change's task sketch did not name. The spec requires a finished record's elapsed time to stop at completion, and a start instant plus a state word cannot say when that was. It sits beside the state rather than inside Finished so the vocabulary stays one: two failures with different end instants are still one state. Completing twice keeps the first instant, so a duplicate report cannot stretch a finished subagent's runtime. elapsed() takes `now` rather than reading the clock, so one frame renders a whole list against a single consistent reading and the arithmetic tests without sleeping. Refs #411 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
paulyhedral
added a commit
that referenced
this pull request
Sep 25, 2026
PR #417 merged after its first commit only, so groups 2-11 of the agent-subagent-visibility change never reached develop. Bring the branch up to date so they can land. Conflicts resolved by keeping both sides: the subagent reporting column beside the MCP columns in the agent_type roster, the boxed ToolCall variant beside the new Shell entry, the subagent repaint flag beside the MCP probe tick, and the subagent clear beside the MCP section forget. The accordion layout develop added to processes_pane.rs is ported into the split processes_pane/section.rs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Implements the
agent-subagent-visibilityOpenSpec change — showing an agent's subagents in the agent pane's processes section, told apart from the OS child processes already listed there.Proposal PR: #409 (merged). All 48 tasks across 11 groups complete.
The gap
Knot had no runtime representation of a subagent anywhere in
crates/.SessionUpdatehad no such variant,ToolCallCardkeptkindas an opaque passthrough, andagent_type::ALLmodelled no parent/child relation.Nor could
pssupply it: Claude Code runs a subagent inside the parent's own process. An agent quiet for four minutes read asnode +2 morewhether it was stuck, compiling, or waiting on three delegations.What landed
knot-subagents— the model (Subagent,SubagentState,SubagentKind,SubagentEvent), the registry, and one recognizer per agent type. Runtime-agnostic and UI-free; every recognizer is a pure function from JSON to an optional event.knot-acpcarriesrawInputand_metathroughToolCallStart/ToolCallUpdate, which it previously discarded.Arcreached through a GPUI global.SubagentReportingon theagent_typeroster —None | ToolCalls | Hooks | Either, resolved against view mode.render/processes_pane.rssplit by concern before the second row kind landed.Four things worth a reviewer's attention
A quiet bug the adapter source caught.
claudeCodeMetaFromToolUsestampssubagent: true, but the completion path never calls it — it builds{ toolName, ...nonExecution }inline. Keying recognition on the flag alone would have matched every dispatch and no completion, leaving every subagent on screen as permanently running. Recognition keys on the flag ortoolName ∈ {Task, Agent}; the fold treats an absent_metaas "no change" so a completion cannot erase the marker. Both have tests.Claude ships as
ToolCalls, notEither. The hook emitter is a plugin outside this repo, so a Terminal-mode Claude agent reads as subagent reporting unavailable rather than confidently claiming it dispatched nothing. Flipping the column is a one-line follow-up once that plugin ships, and the roster test names that so the value is not read as an oversight.The dedicated ACP channel was declined, not missed. The same adapter offers first-class
subagent_spawned/subagent_state_updateupdates with four states and acancelcapability — gated on a capability Knot does not advertise. The file calls itself a temporary surface for an unshipped ACP draft (agentclientprotocol/agent-client-protocol#1992), and advertising the capability rescopes a subagent's nested tool calls onto a child sessionacp-panel-uidoes not model. Two requirements here — no terminate action, and a two-valuedOutcome— are correct only for the channel built; design.md says so rather than leaving them looking universal. Tracked as pilgrimagesoftware/Knot-App#15.PanelMessage::ToolCallis now boxed. The two new fields pushedToolCallCardpast clippy'slarge_enum_variantthreshold, but the imbalance predates them: an unboxed 264-byte card made every plain-text entry in a conversation cost the card's width.Two corrections to this change's own artifacts
Both made in-branch rather than worked around:
rawInput's tool name was the only available signal. Reading the adapter showed it stamps a metadata marker for exactly this purpose. Corrected, with the measurement for the rejected alternative (kindis"think", shared with ordinary reasoning calls).nodescenario had already established the opposite. The code was right; the scenario was not.Checks
makepasses: fmt-check, size-check (462 files, none over 700 lines), declared-check (394 modules), clippy with-D warnings, 1653 tests.openspec validate agent-subagent-visibility --strictpasses.Not in scope
Terminating or interrupting a subagent; attributing an OS process to one; nesting subagents; parsing the agent's transcript; shipping the hook emitter. Each is named in the proposal's non-goals with its reason.
Unrelated flakiness surfaced while running the fuller suite is filed separately as pilgrimagesoftware/Knot-App#19 — a pre-existing wall-clock race in
panel_session, untouched here.Closes pilgrimagesoftware/Knot-App#129
🤖 Generated with Claude Code