Skip to content

(WIP) feat: subagent & workflow observability — Agents panel#4220

Open
t3dotgg wants to merge 10 commits into
mainfrom
t3code/subagent-workflow-sidebar
Open

(WIP) feat: subagent & workflow observability — Agents panel#4220
t3dotgg wants to merge 10 commits into
mainfrom
t3code/subagent-workflow-sidebar

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Jul 21, 2026

Copy link
Copy Markdown
Member

Subagent & workflow observability: Agents panel

Live visibility into delegated work — Claude Code subagents and workflows, and Codex v2 collab agents — directly in the thread UI: who is running, what they're doing right now, token burn, elapsed time, and result summaries.

Plans (reviewed by Fable + gpt-5.6-sol, rev 3): docs/project/plans/subagent-observability-spec.html · docs/project/plans/subagent-observability-ui.html

Design in one paragraph

No new pipeline. Adapters normalize provider signals into the existing task.* runtime-event family (extended with typed usage and agent-linkage fields); an in-memory reducer in ProviderRuntimeIngestion folds them into one ThreadAgentSnapshot per agent and, on material transitions only, appends the full roster as a single agent.snapshot activity through the existing thread.activity.append command. The client derives panel state latest-wins from the newest such activity — the same pattern the context-window meter already uses. No new WS event types, subscriptions, projection tables, or capability flags; old clients decode the new activity kind as a benign info row.

What's included

  • contracts: ThreadAgentSnapshot (identity + activations model: Codex agents are resumable, so idlecompleted; activationCount, firstStartedAt/lastActivityAt), agent.snapshot payload schema, task.updated runtime event, typed RuntimeTaskUsage, agent-linkage fields (incl. workflow phases, scriptPath, runId, outputFile) with a timelineBypass marker.
  • ClaudeAdapter: carries previously-dropped fields (subagent_type, tool_use_id, workflow_name, prompt, output_file); handles task_updated (was: unknown-subtype warning); schema-guarded parse of the undeclared workflow_progress into per-workflow-agent child task events (label, phase, model, state, tokens, attempt); captures WorkflowOutput.scriptPath/runId from tool results.
  • CodexSessionRuntime/CodexAdapter (probe-gated slice): learns v2 collab children from subAgentActivity items (a live wire probe on codex-cli 0.144.1 confirmed children emit no thread/started; nicknames come from agentPath), diverts their auto-subscribed notifications into synthetic collab/agentActivity events, and maps them to timeline-bypassing task.* events. turn/completedidle (resumable), waitingOnApprovalwaiting, per-child token breakdowns from thread/tokenUsage/updated.
  • Ingestion reducer: material-transition filter (status/name/model/phase/activity changes, 25k-token usage steps — 1s ticks stay in memory), hydration from the latest persisted snapshot on restart, orphan sweep to stopped on session exit, 50-cap settled retention, dispatch counter.
  • Web: new agents right-panel surface (tab, "+" menu, empty-state card) with grouped cards — workflow phase headers (✓ done / running counts / pending), status dots in the existing pill color language, self-ticking elapsed timers (no React commits), token counters (deliberately not bars — burn has no denominator), expandable recent-activity feed, "{} script" affordance; plus a collapsed live strip above the composer that opens the panel. Shared derivation helpers live in client-runtime for mobile reuse.

Verification

  • Focused vitest: 152 tests across ClaudeAdapter, ProviderRuntimeIngestion (reducer: material filtering, latest-wins roster, orphan sweep, activation counts, retention), CodexAdapter (collab mapping), CodexSessionRuntime — all passing.
  • tsgo --noEmit clean for contracts, client-runtime, server, web; vp lint clean on changed files.
  • Integrated web verification: isolated vp run dev environment, paired browser, real Claude subagent spawn — panel, live strip, settled card, and empty state confirmed (screenshots in PR comments if useful).
  • Codex v2 protocol behavior established by a live app-server wire probe (/tmp/codex-v2-probe/report.md) rather than source-reading alone.

Deliberately out of scope (per plan)

Per-agent stop/steer (needs provider command plumbing), full transcript drill-in RPC (phase 2; outputFile is already captured), ACP providers (no wire signal), cost USD attribution, mobile surfaces (derivation helpers are shared and ready).

🤖 Generated with Claude Code


Note

Medium Risk
Touches orchestration ingestion and provider adapters on the hot path for runtime events; behavior is heavily tested but snapshot persistence and session-exit roster logic could affect thread activity ordering or stale UI if edge cases misfire.

Overview
Adds live observability for Claude subagents/workflows and Codex v2 collab children without a new wire protocol: adapters emit richer task.* events (including new task.updated, typed usage, workflow phases, and timelineBypass for reducer-only child traffic); ingestion folds them into per-thread rosters and persists latest-wins agent.snapshot activities only on material changes (with session-exit orphan sweep, hydration, and settled-agent retention).

Web gets an agents right-panel surface (AgentsPanel, composer AgentsLiveStrip) driven by shared client-runtime derivation from the newest snapshot; work logs skip snapshot rows. Codex diverts foreign child-thread notifications through collab/agentActivity mapping; Claude handles task_updated, workflow_progress, and Workflow tool metadata.

Right-panel persisted state bumps to v8 (may reset saved layouts). task.updated / bypass events no longer create transcript timeline rows.

Reviewed by Cursor Bugbot for commit b7534b6. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add Agents panel to the right panel for subagent and workflow observability

  • Introduces an Agents right-panel surface showing live agent/workflow status, activity feeds, elapsed timers, usage stats, and phase groupings via the new AgentsPanel component (AgentsPanel.tsx).
  • Adds an AgentsLiveStrip above the chat composer that shows a one-line summary of active agents and opens the Agents panel on click.
  • Extends providerRuntime contracts with a task.updated event, normalized RuntimeTaskUsage, and TaskAgentLinkage fields to carry agent/workflow metadata through task lifecycle events.
  • The ClaudeAdapter and CodexAdapter now map provider-specific task/workflow/collab events into typed task.* runtime events, including child agent lifecycle via synthetic collab/agentActivity notifications in the Codex session runtime.
  • ProviderRuntimeIngestion maintains a per-thread in-memory agent roster, folds task events into ThreadAgentSnapshot state, and appends agent.snapshot activities on material changes; deriveLatestAgentSnapshot and deriveAgentPanelState on the client decode and group these snapshots for display.
  • agent.snapshot activities and task.updated/timelineBypass events are excluded from the work log and timeline to avoid noise.
  • Behavioral Change: right-panel storage version bumped from 7 to 8, which may trigger a reset of persisted panel state.

Macroscope summarized b7534b6.

t3dotgg and others added 8 commits July 20, 2026 20:22
…lity

ThreadAgentSnapshot + agent.snapshot activity payload, typed task usage,
task.updated runtime event, and agent-linkage fields on task payloads.
Includes the reviewed HTML plans.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New right-panel 'agents' surface (Option A) + collapsed live strip near the
composer (Option B). Roster derived latest-wins from agent.snapshot
activities via shared client-runtime helpers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CodexSessionRuntime learns children from subAgentActivity items (probe:
no child thread/started arrives) and diverts their notifications into
synthetic collab/agentActivity events; CodexAdapter maps those to
timeline-bypassing task.* events (turn lifecycle, waiting flags, token
usage, item summaries). turn/completed maps to idle, not terminal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…reducer

ClaudeAdapter carries subagent linkage (agentType/toolUseId/workflowName/
prompt/outputFile), handles task_updated, parses workflow_progress into
child workflow_agent task events, normalizes task usage, and captures
Workflow tool results (scriptPath/runId). Ingestion folds task.* events
into per-thread ThreadAgentSnapshot rosters with material-transition
filtering, projection hydration, orphan sweep, and 50-cap retention,
appended as agent.snapshot activities.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… payload

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bile work log

Codex review P2: active-with-no-flags thread status now maps back to
running so agents don't stay 'waiting' after an approval resolves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b7698719-df4f-400e-92d9-e5b5aa27d124

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/subagent-workflow-sidebar

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Jul 21, 2026
@t3dotgg

t3dotgg commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

Integrated verification note: in the browser run (isolated dev env, real Claude subagent), the settled card briefly showed Σ 0 tok — usage for very short agents arrives only on the terminal task_notification, and the final roster snapshot (verified in SQLite: totalTokens 22798) updates the panel when it lands. Screenshots live at /tmp/codex-computer-use.lvQ4hP/ locally; FILE_HOST_TOKEN was unset in this session so they aren't embedded here.

@github-actions github-actions Bot added the size:XXL 1,000+ changed lines (additions + deletions). label Jul 21, 2026
Comment thread packages/client-runtime/src/state/threadAgents.ts
Comment thread apps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment thread apps/web/src/components/AgentsPanel.tsx Outdated
Comment thread apps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment thread apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
Comment thread apps/web/src/components/AgentsPanel.tsx
Comment thread apps/server/src/provider/Layers/CodexAdapter.ts Outdated
Comment thread apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts Outdated
Comment thread apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
Comment thread packages/contracts/src/threadAgents.ts
Comment thread apps/server/src/provider/Layers/CodexAdapter.ts
@macroscopeapp

macroscopeapp Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found. This WIP feature PR adds significant new functionality (Agents panel, server-side agent tracking, new schemas) with unresolved review comments identifying potential runtime bugs — including a high-severity issue where failed snapshot appends could block subsequent event processing.

You can customize Macroscope's approvability policy. Learn more.

- CI: client-runtime test imports @effect/vitest (vitest types unresolved
  in package context)
- CodexSessionRuntime: divert child-thread events that arrive before
  subAgentActivity registers them (probe: child status/changed lands
  first); emit a terminal event on subAgent interruption
- CodexAdapter: systemError -> failed; cumulative totalProcessedTokens
  for child usage (last-turn count can shrink on follow-ups)
- Ingestion: waiting agents counted as active in roster summaries;
  reactivation clears stale resultSummary/errorMessage; usage fields
  validated as non-negative integers; failed snapshot dispatch drops the
  hydration marker so the roster re-syncs from persisted state
- Panel/strip: idle counts as settled everywhere; phase labels show
  active counts (not '0 running'); parseTimestampDate for ISO parsing
- Drop docs/project/plans HTML files

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts Outdated
return loadedThreadDetail;
});

if (!hydratedAgentThreads.has(thread.id)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium Layers/ProviderRuntimeIngestion.ts:1526

Hydrating the agent roster from the latest persisted agent.snapshot activity breaks when the projector evicts that activity (it keeps only the newest 500). After 500+ unrelated activities are appended without a material agent transition, the snapshot is sliced off, so this code hydrates an empty roster. The next agent event then publishes a roster that has lost all other agents, and the panel already lost its latest visible state before the restart. Agent state should be stored somewhere not subject to the generic activity cap, or the snapshot needs a retention/refresh guarantee independent of the activity list.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts around line 1526:

Hydrating the agent roster from the latest persisted `agent.snapshot` activity breaks when the projector evicts that activity (it keeps only the newest 500). After 500+ unrelated activities are appended without a material agent transition, the snapshot is sliced off, so this code hydrates an empty roster. The next agent event then publishes a roster that has lost all other agents, and the panel already lost its latest visible state before the restart. Agent state should be stored somewhere not subject to the generic activity cap, or the snapshot needs a retention/refresh guarantee independent of the activity list.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in b7534b6 with a documented boundary rather than new storage: hydration reads the same 500-capped activities projection clients derive from, so when a snapshot ages past the cap, both sides have already lost it — hydrating empty is consistent with what the panel can show, not a divergence. A dedicated store (rev-2's projection table design, preserved in the plan's git history) remains the graduation path if cap-scale threads with live agents show up in practice; per-thread dispatch metrics are in place to detect that.

Comment thread apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts Outdated
- session.exited now releases the per-thread reducer state after the
  final snapshot persists (unbounded retention leak)
- failed snapshot dispatch keeps the newer in-memory roster and flags
  the thread for re-dispatch on the next event instead of discarding
  memory (previous fix could lose transitions)
- document the 500-cap hydration boundary: past the cap both server and
  clients have lost the snapshot, so empty hydration is consistent

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@t3dotgg t3dotgg changed the title feat: subagent & workflow observability — Agents panel (WIP) feat: subagent & workflow observability — Agents panel Jul 21, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b7534b6. Configure here.

activity,
createdAt: activity.createdAt,
});
pendingRosterRedispatch.delete(thread.id);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retry blocks later event processing

High Severity

After a failed agent.snapshot append, pendingRosterRedispatch forces every later runtime event for that thread to re-attempt the append before any other ingestion work. A repeated failure aborts the whole processRuntimeEvent via yield*, so streamed content, session lifecycle, turn completion, and timeline activities for those events are dropped until an append succeeds.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b7534b6. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚧 In Progress size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant