Hey Theo and team,
Context up front: this is about the Agents panel that shipped in #5219 (native subagent & workflow observability). I updated to 0.0.32-nightly.20260806.1014 this afternoon, took the new panel for a spin within the hour, and hit this. So it's a fresh-feature report, not a regression from something older.
Bug first, thank you note at the end - and I mean the second part more than the first.
What happens
When a background subagent finishes and is later resumed (same task id, new run), its row in the Agents panel stays under Earlier, frozen at the first run's duration with its check mark. It never moves back up to Direct spawns, and the elapsed time never changes.
The odd part: the token counter does keep climbing. So the row is clearly still receiving events. Only the run state is stuck.
Repro
- Spawn a background subagent from a thread and let it finish.
- Send it another message, so the harness resumes it from its transcript.
- Watch the Agents panel.
I did this four times on the same agent this afternoon. Roughly nine minutes of work across the four runs. The row still reads 1m 39s, which is exactly the length of run #1.
The data is fine
Checked projection_thread_activities in the local db. All four runs are recorded, in order, on the same task id:
task.started 14:11:04
task.completed 14:12:44
task.started 14:13:09
task.completed 14:15:25
task.started 14:17:52
task.completed 14:21:26
task.started 14:27:39
task.completed 14:27:57
The events arrive. The fold just doesn't act on them.
Likely cause
packages/client-runtime/src/state/subagentRuntime.ts, in the task.started case:
if (agent.activationCount === 0 && !isTerminalSubagentStatus(agent.status)) {
...
} else if (agent.status === "idle") {
applyStatus(agent, "running", at);
}
After the first run the agent is completed, which is terminal but not idle. So the second task.started falls to the else if, fails the idle check, and quietly does nothing.
The comment above it explains the intent, and the intent is sound:
a start row arriving after a terminal state is a late/out-of-order delivery and only fills metadata - it must not reopen the run. Reactivation comes exclusively from explicit status transitions (task.updated / progress status).
The guard was clearly added for a real bug ("a late start reopened a failed child"). The snag is that at this point a genuine resume and a stale duplicate look identical: both are a task.started on a settled agent. And in my case the resume never follows up with a task.progress or task.updated carrying an explicit running, so nothing else picks up the slack.
I deliberately haven't sent a patch, because the right fix depends on what the adapter can be trusted to emit. Something in the payload that separates a fresh run from a replayed row - a run counter, or a start timestamp newer than completedAt - would let the guard stay and still let real resumes through. You'll know which of those is actually safe far better than I would.
Worth saying: this isn't a blocker. Everything works, the reports come back, nothing is lost. It just makes a panel that's genuinely useful look like it has gone to sleep.
Version
0.0.32-nightly.20260806.1014, migration 36. Client and server both on that build - server running headless on a Mac mini, client on macOS. The panel itself is the one from #5219; I have no older build to compare against, since this is the first release where the surface exists.
And the part I actually wanted to write
Thank you. Sincerely.
T3 Code is a dream for me, and I don't use that word loosely. I run a nutrition clinic in Romania, and most of my real thinking happens away from a desk - between patients, in a car, late in the evening. Being able to pick up a Claude session on my phone and keep going has changed how I work more than any tool I've adopted in years.
This very release is a good example of why. Until today I fired off subagents and then simply guessed what they were up to. Now I can watch them. The fact that I found a rough edge within an hour of updating says more about how much I'm using the thing than about the edge.
So please read the above as coming from someone who lives in this app all day and wants it to be even better - not from someone complaining. Thank you for building it, and for shipping at a pace that makes filing a bug feel worth the effort.
Hey Theo and team,
Context up front: this is about the Agents panel that shipped in #5219 (native subagent & workflow observability). I updated to
0.0.32-nightly.20260806.1014this afternoon, took the new panel for a spin within the hour, and hit this. So it's a fresh-feature report, not a regression from something older.Bug first, thank you note at the end - and I mean the second part more than the first.
What happens
When a background subagent finishes and is later resumed (same task id, new run), its row in the Agents panel stays under Earlier, frozen at the first run's duration with its check mark. It never moves back up to Direct spawns, and the elapsed time never changes.
The odd part: the token counter does keep climbing. So the row is clearly still receiving events. Only the run state is stuck.
Repro
I did this four times on the same agent this afternoon. Roughly nine minutes of work across the four runs. The row still reads
1m 39s, which is exactly the length of run #1.The data is fine
Checked
projection_thread_activitiesin the local db. All four runs are recorded, in order, on the same task id:The events arrive. The fold just doesn't act on them.
Likely cause
packages/client-runtime/src/state/subagentRuntime.ts, in thetask.startedcase:After the first run the agent is
completed, which is terminal but notidle. So the secondtask.startedfalls to theelse if, fails theidlecheck, and quietly does nothing.The comment above it explains the intent, and the intent is sound:
The guard was clearly added for a real bug ("a late start reopened a failed child"). The snag is that at this point a genuine resume and a stale duplicate look identical: both are a
task.startedon a settled agent. And in my case the resume never follows up with atask.progressortask.updatedcarrying an explicitrunning, so nothing else picks up the slack.I deliberately haven't sent a patch, because the right fix depends on what the adapter can be trusted to emit. Something in the payload that separates a fresh run from a replayed row - a run counter, or a start timestamp newer than
completedAt- would let the guard stay and still let real resumes through. You'll know which of those is actually safe far better than I would.Worth saying: this isn't a blocker. Everything works, the reports come back, nothing is lost. It just makes a panel that's genuinely useful look like it has gone to sleep.
Version
0.0.32-nightly.20260806.1014, migration 36. Client and server both on that build - server running headless on a Mac mini, client on macOS. The panel itself is the one from #5219; I have no older build to compare against, since this is the first release where the surface exists.And the part I actually wanted to write
Thank you. Sincerely.
T3 Code is a dream for me, and I don't use that word loosely. I run a nutrition clinic in Romania, and most of my real thinking happens away from a desk - between patients, in a car, late in the evening. Being able to pick up a Claude session on my phone and keep going has changed how I work more than any tool I've adopted in years.
This very release is a good example of why. Until today I fired off subagents and then simply guessed what they were up to. Now I can watch them. The fact that I found a rough edge within an hour of updating says more about how much I'm using the thing than about the edge.
So please read the above as coming from someone who lives in this app all day and wants it to be even better - not from someone complaining. Thank you for building it, and for shipping at a pace that makes filing a bug feel worth the effort.