You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Fix: Label workflow subagents in the agentop timeline - #1757
The agentop timeline pane labels each agent that Claude Code's Workflow tool starts as subagent <id>. Such an agent has no Agent tool call on the wire, so the server has no description for it. Fixes#1756.
Change
Harvest (core/observe/claude/harvest.go):
readSubagents also reads subagents/workflows/<run>/agent-<id>.meta.json, where Claude Code writes the workflow agents' labels.
An incremental harvest that skips an unchanged transcript still re-reads that session's meta files. A workflow starts agents without a write to the main transcript, so the transcript mtime does not show new agents.
Timeline pane (cmd/agentop/tui/timeline_pane.go):
An agent with no spawn call uses its harvested description. An agent that a spawn call names keeps its wire label.
When the pane shows an agent with no label, it asks for a harvest, at most once per 15 s.
Cost
Measured on a real ~/.claude tree with 1,424 sessions: an incremental harvest went from 33 ms to about 68 ms. It found 716 subagent labels, up from 679. The 37 new ones are workflow agents. The harvest runs in the background, not on the UI thread.
Tests
TestHarvest_ReadsWorkflowSubagentsWhenTranscriptIsUnchanged: a workflow agent that starts after the first harvest is found while the transcript is skipped. It fails without the harvest change.
TestTimeline_WorkflowAgentUsesHarvestedLabel: the harvested label replaces subagent <id>, a spawned agent keeps its wire label, and the harvest request stops when every agent has a label.
go vet and gofmt on both modules. scripts/dev/go-test-shards.sh -race cmd/agentop (975 tests) and the sub-packages with -race pass.
Known limit
A teammate or a non-Claude-Code agent never has a meta file. While such an agent is on the timeline, the pane asks for a harvest every 15 s. Each one costs about 70 ms in the background.
The timeline pane labeled each agent that Claude Code's Workflow tool
starts as "subagent <id>". Such an agent has no Agent tool call on the
wire, so the server has no description for it.
Claude Code writes the label to disk, in
subagents/workflows/<run>/agent-<id>.meta.json. The harvest now reads
that folder. An incremental harvest also re-reads the meta files of a
session whose transcript did not change, because a workflow starts
agents without a write to the main transcript.
The timeline pane uses the harvested description for an agent with no
spawn call. It asks for a harvest when such an agent has no label, at
most once per 15 s.
Fixesrossoctl#1756
Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Hai Huang <huang195@gmail.com>
The change reads workflow subagent metadata during incremental session harvests. The timeline requests harvests for eligible unlabeled agents and displays harvested descriptions when available.
Changes: Workflow subagent timeline labels
Layer / File(s)
Summary
Read workflow metadata during incremental harvest core/observe/claude/harvest.go, core/observe/claude/harvest_test.go
Harvesting reads metadata from regular and workflow subagent directories. For unchanged transcripts, it returns a session entry when its subagent map changes. The test covers newly added workflow metadata while retaining existing labels and the session title.
Harvest and display timeline labels cmd/agentop/tui/app.go, cmd/agentop/tui/timeline_pane.go, cmd/agentop/tui/timeline_pane_test.go
After a timeline loads, the app can start a harvest. The timeline requests harvests at most once every 15 seconds when eligible unlabeled agents are present. It uses harvested descriptions for agents without a SpawnTool and retains wire labels for spawned agents. The test covers harvest requests, label selection, and the no-harvest case.
rossoctl/cortex#1517: This PR introduced the Timeline pane and agent rows that this change updates to show harvested workflow subagent descriptions.
Suggested reviewers:evaline-ju, esnible
Merge Risk: Minimal · up to eafc9
The labeling change is mergeable after normal checks. The remaining observations describe bounded harvest behavior, not a demonstrated blocker.
Pre-merge checks: 5
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title clearly summarizes the main change: labeling workflow subagents in the agentop timeline.
Linked Issues check
Issue #1756 requests workflow-agent metadata harvesting, metadata refresh when an unchanged transcript is skipped, harvested labels in the timeline when no spawn call exists, and a harvest request for…
Out of Scope Changes check
The changes in core/observe/claude/harvest.go, cmd/agentop/tui/timeline_pane.go, and cmd/agentop/tui/app.go implement the harvesting and timeline behavior requested by issue #1756. The added tes…
Docstring Coverage
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Full details: Linked Issues check
Explanation
Issue #1756 requests workflow-agent metadata harvesting, metadata refresh when an unchanged transcript is skipped, harvested labels in the timeline when no spawn call exists, and a harvest request for unlabeled agents no more often than every 15 seconds. readSubagents now reads workflow-run metadata, and ReadSessions refreshes changed subagent metadata on the skipped-transcript path. The timeline uses harvested descriptions only when SpawnTool is empty and preserves spawn-call labels. harvestForTimeline applies the 15-second interval. The new harvest and timeline tests cover these behaviors.
Full details: Out of Scope Changes check
Explanation
The changes in core/observe/claude/harvest.go, cmd/agentop/tui/timeline_pane.go, and cmd/agentop/tui/app.go implement the harvesting and timeline behavior requested by issue #1756. The added tests verify those changes. No unrelated change is evident in the whole-PR diff.
Full details: Docstring Coverage
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 5 functions across 5 files.
Finishing Touches
Generate unit tests (beta)
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
The reason will be displayed to describe this comment to others. Learn more.
Additional comments: 2
cmd/agentop/tui/app.go: 1
1639-1639: Trivial · Maintainability & Code Quality · Low value
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
The timeline harvest stamp can delay the sessions pane harvest.
harvestForTimeline writes m.lastHarvest. The sessions pane gate compares now.Sub(m.lastHarvest) against untitledBackoff, so a timeline harvest delays the next sessions harvest by up to the backoff. The delay is bounded and the existing comment documents this class of coupling. The effect is minor.
If this matters, add a separate lastTimelineHarvest field. The timeline gate would read that field, and the sessions gate would keep lastHarvest.
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
Agents without a meta file trigger a harvest every 15 seconds.
Teammates and non-Claude-Code agents have SpawnTool == "" and no meta file. harvestedLabel stays empty for them, so each timelineLoadedMsg after 15 seconds starts another full incremental harvest. The PR documents this limit.
A per-session set of agent IDs already harvested would stop the repeat. Add agent IDs to the set after a harvest completes, and skip them in the loop. This is a recommended follow-up, not a blocker.
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: defaults
Review profile: CHILL
Plan: Advanced
Run ID: 7a893459-2ff9-4657-97a6-1702713ec0fd
Commits
Reviewing files that changed from the base of the PR and between 045fff6 and eafc90b.
Files selected for processing: 5
cmd/agentop/tui/app.go
cmd/agentop/tui/timeline_pane.go
cmd/agentop/tui/timeline_pane_test.go
core/observe/claude/harvest.go
core/observe/claude/harvest_test.go
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Summary
This is a clean, focused fix. The harvest now reads subagents/workflows/<run>/agent-<id>.meta.json. It also re-reads a session's meta files when the transcript skip fires, which closes the gap the old comment assumed away ("a session only gains a subagent by appending the Agent tool call"). The timeline uses the harvested description only for agents with no spawn call, so wire labels stay authoritative for every other agent. I checked that both new tests are load-bearing. With the !maps.Equal re-read disabled, TestHarvest_ReadsWorkflowSubagentsWhenTranscriptIsUnchanged fails (b2 is missing). core/observe/claude and the cmd/agentop/tui timeline tests pass locally on head. The harvest gate shares m.harvesting and lastHarvest with the other paths, so it can't stack scans, and harvestedMsg stays the only place that clears the flag. I also rendered a CJK + ANSI/newline description through agentLine. The row stays inside the pane width (159/160), and the label is sanitised and cut by width as before. Two non-blocking notes are inline.
Author: huang195 (MEMBER — maintainer) Areas reviewed: Go (core/observe/claude harvest, cmd/agentop/tui timeline pane + app update loop), tests Agent/IDE config (.claude/.vscode): none Commits: 1 commit, all signed-off: yes CI status: passing (Spellcheck skipped)
The reason will be displayed to describe this comment to others. Learn more.
suggestion: The gate keys on the description rather than on whether the harvest found the agent at all. A meta file that has agentType but no description has a Subagents[id] entry, so further harvests can't add anything for it. Even so, harvestedLabel returns "" for it. The row stays subagent <id>, and on a live session this asks for a harvest every 15 s for as long as the pane is open. That's the same cost as the teammate "known limit", but here it comes from an agent the harvest did find. subagentLabel in events_blocks.go already falls back from Description to AgentType. Two changes would fix this: have the gate test key presence (_, ok := m.sessionsData[s].Subagents[a.ID]), and have the label use the same Description → AgentType fallback, so both panes name such an agent the same way. Not blocking: the 15 s floor already bounds the cost.
The reason will be displayed to describe this comment to others. Learn more.
nit: After this change, a skipped session can appear in the returned map. The ReadSessions doc comment above still says "Skipped sessions are absent from the returned map rather than copied into it", so it needs an update. A related effect: such a session now counts in both res.Skipped and res.Harvested. That's harmless today, because Kept is derived and the Incremental caller in main.go prints neither. But it no longer matches Harvested's doc ("entries this run read from transcripts"), so one sentence on each would keep the counters honest.
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
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.
Problem
The agentop timeline pane labels each agent that Claude Code's Workflow tool starts as
subagent <id>. Such an agent has no Agent tool call on the wire, so the server has no description for it. Fixes #1756.Change
core/observe/claude/harvest.go):readSubagentsalso readssubagents/workflows/<run>/agent-<id>.meta.json, where Claude Code writes the workflow agents' labels.cmd/agentop/tui/timeline_pane.go):Cost
Measured on a real
~/.claudetree with 1,424 sessions: an incremental harvest went from 33 ms to about 68 ms. It found 716 subagent labels, up from 679. The 37 new ones are workflow agents. The harvest runs in the background, not on the UI thread.Tests
TestHarvest_ReadsWorkflowSubagentsWhenTranscriptIsUnchanged: a workflow agent that starts after the first harvest is found while the transcript is skipped. It fails without the harvest change.TestTimeline_WorkflowAgentUsesHarvestedLabel: the harvested label replacessubagent <id>, a spawned agent keeps its wire label, and the harvest request stops when every agent has a label.go vetandgofmton both modules.scripts/dev/go-test-shards.sh -race cmd/agentop(975 tests) and the sub-packages with-racepass.Known limit
A teammate or a non-Claude-Code agent never has a meta file. While such an agent is on the timeline, the pane asks for a harvest every 15 s. Each one costs about 70 ms in the background.
Assisted-By: Claude (Anthropic AI) noreply@anthropic.com
Summary by CodeRabbit