Summary
Add first-class support for Claude Code dynamic workflows in Threadlines. The goal is to let users intentionally trigger Claude workflows, see when Ultracode causes Claude to orchestrate work in the background, and inspect workflow/subagent activity without flooding the main chat transcript.
This issue is intended as the design/reference ticket before implementation. It combines the current repo shape with current Claude workflow/Agent SDK capabilities.
Why this matters
Claude workflows can spawn many agents and perform a lot of background coordination. If Threadlines only renders the final assistant text, users lose trust because the app appears idle while expensive work is happening. If Threadlines dumps every subagent stream into chat, the conversation becomes unusable. We need a middle path: compact chat status plus a dedicated workflow surface for details, costs, subagents, raw activity, and final results.
Research snapshot
Current Claude behavior/capabilities to design around:
- Claude Code supports dynamic workflows that can be triggered by asking Claude to use/run a workflow, by selecting Ultracode behavior, or via workflow tooling in SDK contexts.
- The
/workflows view in Claude surfaces run progress, agent activity, and token usage. Threadlines needs an equivalent web-native surface.
- Workflows may spawn up to 16 concurrent agents and up to 1,000 agents total per run. The UI must assume high cardinality and avoid one chat row per internal update.
- Workflow scripts coordinate agents but do not directly access shell/filesystem; agents do the work.
- Workflow runs can have names, run ids, task ids, summaries, transcript directories, script paths, statuses, and token usage.
- The Claude Agent SDK can expose richer internals through options/events:
includePartialMessages: true already exists in our adapter.
forwardSubagentText?: boolean can forward subagent text/thinking blocks with parent_tool_use_id; by default only subagent tool_use/tool_result blocks are emitted.
includeHookEvents?: boolean can emit hook events.
- Hooks include
SubagentStart, SubagentStop, TaskCreated, TaskCompleted, and related metadata such as agent_id, agent_type, session_id, transcript_path, cwd, and effort.
- The SDK
Workflow tool returns fields such as status, taskId, taskType, workflowName, runId, summary, transcriptDir, and scriptPath.
Relevant official docs:
Current Threadlines repo context
Backend/provider:
apps/server/src/provider/Layers/ClaudeAdapter.ts already uses @anthropic-ai/claude-agent-sdk and includePartialMessages: true.
- The adapter already handles stream deltas, tool input deltas, Claude task messages, permission events, and plan/task projection.
Workflow currently falls through to a generic dynamic tool call path rather than a first-class workflow item.
Agent, Task, and related subagent tool names are already classified as collab_agent_tool_call.
- Claude Ultracode is already represented in model effort handling. The adapter maps
ultracode to SDK effort xhigh while setting settings.ultracode = true.
Contracts/orchestration:
packages/contracts/src/providerRuntime.ts already has canonical task lifecycle events: task.started, task.progress, task.completed.
- It also has item lifecycle, hook, tool progress, and content delta event families.
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts already treats provider task events as pending background work and can synthesize subagent.result activity from child provider output.
apps/server/src/orchestration/Layers/ProviderActivityProjection.ts already projects task/hook/tool progress into OrchestrationThreadActivity.
Web/UI:
apps/web/src/session-logic.ts already derives subagent progress, subagent result rows, work log entries, and timeline entries.
apps/web/src/components/chat/ThreadActivityPopover.tsx already has a compact header popover for tasks/subagents/background runs.
apps/web/src/components/chat/MessagesTimeline.tsx already renders subagent result rows outside the normal assistant message flow.
apps/web/src/components/chat/TraitsPicker.tsx already gives Ultracode a special model/effort presentation.
apps/web/src/components/ChatRightPanelInlineSidebar.tsx already provides a resizable right panel pattern we can reuse or generalize for a workflow inspector.
Product goals
- Let users intentionally trigger a Claude workflow from Threadlines.
- Make Ultracode workflow behavior visible and understandable without requiring users to know Claude CLI internals.
- Keep the main chat readable by default.
- Provide a dedicated workflow inspector for users who want the full background picture.
- Preserve enough raw detail for debugging provider issues and understanding cost.
- Make workflow progress survive reconnects/restarts as well as our existing event log allows.
- Avoid making this Claude-specific UI impossible to reuse for future Codex/background orchestration surfaces.
Non-goals for the first implementation
- Do not build a visual workflow authoring canvas.
- Do not attempt to edit or persist custom workflow scripts from the GUI in the MVP.
- Do not dump every subagent token into the chat transcript.
- Do not make workflows the default for every Claude turn.
- Do not change existing Codex behavior as part of this work unless shared UI components require small contract-safe generalization.
Suggested user-facing UX
1. Composer entry point: Run mode selector
Add a compact run-mode control near the composer send controls. It should feel like an execution mode, not a full settings panel.
Suggested modes:
Normal - current behavior.
Workflow - asks Claude to use a workflow for this turn when available.
Auto or Ultracode - shown when the selected Claude model/effort supports Ultracode; indicates Claude may decide to orchestrate workflow-style background work.
Possible UI shape:
- Segmented control or small dropdown next to Send.
- Icon: use a workflow/network/branches-style icon from lucide if available.
- Tooltip text should be concise: ?Use Claude workflow orchestration for this turn.?
- If the selected provider/model does not support workflows, disable with a tooltip: ?Claude workflows require a compatible Claude Code runtime/model.?
Behavior details:
- Selecting
Workflow should be turn-scoped by default. After sending, return to the previous default unless the user pins it.
- Provide a small pin/remember option in the dropdown, not as a separate persistent visible toggle.
- When
Workflow is active and the user sends, add a provider turn directive rather than permanently mutating the user's prompt text if possible.
- If provider turn directives are not ready, first implementation can prepend a hidden/internal instruction such as ?Use a workflow for this task if appropriate,? but it should be represented in provider metadata so the UI can explain why a workflow started.
2. Ultracode tie-in
We already expose Ultracode as a reasoning level for Claude models that support it. Workflow UX should build on that instead of adding a competing concept.
Recommended behavior:
- Keep Ultracode in the model/effort selector as the high-effort reasoning option.
- Add a short affordance in the Ultracode option/tooltip: ?May use Claude workflow orchestration for complex tasks.?
- When Ultracode is selected, show the workflow inspector affordance only after actual workflow/task/subagent activity appears. Do not pre-open a heavy panel for every Ultracode turn.
- If the user explicitly chooses
Workflow while Ultracode is selected, treat it as one unified request: high-effort + workflow orchestration. Do not duplicate prompts or show two separate modes.
- If Ultracode is unavailable for the selected Claude model, the run-mode control should still allow
Workflow only if the runtime supports the Workflow tool independently. Otherwise disable it.
3. Main chat transcript
Main chat should stay high-signal.
Render at most:
- A compact workflow status row/card at the start of a workflow run.
- Important workflow phase changes.
- Final workflow summary/result.
- Failure/cancellation/permission-required states.
Avoid:
- Streaming every subagent thought/text block into main chat.
- Rendering hundreds of task updates inline.
- Intermixing raw hook/tool events with normal assistant messages.
Suggested chat card content:
- Workflow name or inferred title.
- Status: queued/running/paused/failed/completed.
- Agent count: active/completed/failed.
- Current phase or last meaningful activity.
- Token/cost summary when available.
- ?Open details? button that opens/focuses the workflow inspector.
4. Header activity popover
Extend the existing ThreadActivityPopover so workflow runs are included alongside tasks, subagents, and background runs.
Collapsed row example:
Workflow: Refactor auth flow
6 agents active, 14 completed
Last update: running tests
- Progress/status chip.
The popover should be a quick glance, not the detailed surface. It should deep-link/open the inspector for the selected run.
5. Dedicated workflow inspector surface
Add a right-side ?Workflow? panel. This can reuse the existing resizable right panel pattern, but should not be jammed into the source-control panel permanently. Ideally the right panel becomes a generic session sidebar with tabs or modes:
- Source Control
- Workflow
- Activity / Logs (future)
If that is too much for MVP, add a workflow drawer/panel opened from the chat card and header popover.
Recommended inspector layout:
Header
- Workflow name.
- Run id / task id copy affordance.
- Status chip.
- Started time / elapsed time.
- Model and effort, including Ultracode when active.
- Token usage/cost summary when available.
- Stop/cancel/resume actions if supported and safe.
Overview tab
- Current phase.
- Short workflow summary.
- User trigger source: explicit workflow mode, Ultracode auto-orchestration, prompt-requested workflow, resumed workflow.
- Agent totals: active, completed, failed, cancelled.
- Permission waits.
- Recent notable events.
Agents tab
A dense list/table of spawned agents:
- Agent id.
- Agent type/name.
- Status.
- Parent workflow/run id.
- Current tool or last activity.
- Started/ended time.
- Token usage if available.
- Final summary/result.
- Transcript/path indicator if available and safe to expose.
Rows should be expandable. Expanded rows can show:
- Tool calls/results summary.
- Final assistant text/result.
- Errors.
- Raw event snippets.
Default should be collapsed and grouped by status/phase so a 100-agent run remains navigable.
Timeline tab
Chronological event stream with filtering:
- Workflow started/completed.
- Task created/completed.
- Subagent started/stopped.
- Permission requested/resolved.
- Tool call started/completed.
- Summary/result emitted.
Filters:
- All.
- Workflow.
- Agents.
- Tools.
- Permissions.
- Errors.
This is where verbose activity belongs, not the chat transcript.
Raw tab
For debugging and development builds:
- Canonical provider event JSON.
- Native Claude event JSON when captured.
- Copy button.
- Redaction guard if paths/prompts/secrets may be included.
This tab can be behind a developer toggle if needed.
Backend implementation plan
Phase 1: Capture spike with fixtures
Goal: prove exactly what Claude emits for workflow runs in our environment before committing the contract shape.
Tasks:
- Create one or more local manual capture scripts or temporary tests that run Claude through the existing SDK version.
- Capture examples for:
- Explicit prompt: ?use a workflow?.
- Ultracode effort.
- Workflow with multiple subagents.
- Workflow failure/cancel/permission wait if feasible.
- Capture with and without:
forwardSubagentText: true.
includeHookEvents: true.
- Save sanitized fixtures for tests.
Decision needed after spike:
- Whether
forwardSubagentText should be default-on, default-off, or enabled only while the workflow inspector is open/developer mode is active.
- Whether hook events provide enough stable lifecycle metadata to drive the inspector.
Phase 2: Provider adapter changes
In apps/server/src/provider/Layers/ClaudeAdapter.ts:
- Classify
Workflow tool calls as a first-class workflow item or a specialized task item rather than generic dynamic_tool_call.
- Add a
Workflow title in titleForToolName.
- Preserve Workflow tool output fields:
status
taskId
taskType
workflowName
runId
summary
transcriptDir
scriptPath
- Preserve
workflow_name from SDK task-started messages when present.
- Consider adding
includeHookEvents: true for Claude sessions, at least when workflows are active or when the user has enabled detailed activity.
- Consider enabling
forwardSubagentText: true behind a feature flag or workflow-detail setting.
- Ensure
settings.ultracode = true remains tied to the existing Ultracode effort selection.
- Add a provider-level concept of turn trigger/source:
- normal
- explicit workflow mode
- ultracode-selected
- prompt-requested workflow
- resumed workflow
Potential risk:
- Forwarding subagent text may substantially increase event volume. The adapter should have clear throttling/backpressure behavior and should not block the main assistant stream.
Phase 3: Contracts
In packages/contracts/src/providerRuntime.ts, add enough schema to represent workflows without baking in Claude-only assumptions.
Two possible approaches:
Option A: Extend task events
Extend existing TaskStartedPayload, TaskProgressPayload, and TaskCompletedPayload with optional fields:
workflowRunId?: string
workflowName?: string
parentTaskId?: string
agentId?: string
agentType?: string
transcriptPath?: string
triggerSource?: 'explicit' | 'ultracode' | 'prompt' | 'resume' | 'unknown'
usage?: ProviderUsageLike
Pros:
- Smaller contract change.
- Reuses existing ingestion/projection paths.
Cons:
- Workflows become overloaded task events.
- UI derivation may become harder as workflow complexity grows.
Option B: Add workflow event family
Add provider runtime events such as:
workflow.started
workflow.progress
workflow.agent.started
workflow.agent.progress
workflow.agent.completed
workflow.completed
Pros:
- Cleaner UI state model.
- Easier future support for other providers/orchestrators.
- Avoids overloading generic task events.
Cons:
- Larger contract/projection work.
Recommendation:
- Use Option B if the capture spike confirms stable workflow identifiers are available.
- Use Option A as an MVP if Claude emits workflow data mostly through existing task messages and tool outputs.
Phase 4: Orchestration ingestion/projection
In provider runtime ingestion/projection:
- Group workflow-related events by
workflowRunId or taskId fallback.
- Track workflow status and agent counts separately from generic pending background tasks.
- Avoid double-counting one workflow plus all child agents as many independent background tasks in the header.
- Link child subagent output to the parent workflow.
- Preserve final subagent results but keep them out of the main chat unless summarized.
- Add stable activity ids so reconnects do not duplicate rows.
- Include enough data in
OrchestrationThreadActivity for web-only derivation without needing native Claude event parsing in the browser.
Phase 5: Web state derivation
In apps/web/src/session-logic.ts:
- Add
WorkflowProgressState and WorkflowRunRecord derivation.
- Collect workflow records from canonical runtime/orchestration activities.
- Associate subagent records with workflow records when parent ids match.
- Derive compact chat timeline entries:
- workflow status entry
- final workflow result/summary entry
- failure entry
- Keep verbose workflow internals out of
workLogEntries unless user has opened a detailed log view.
- Make settled workflow records remain visible in the inspector for the latest turn, even if the compact activity popover hides completed items.
Phase 6: UI implementation
Components to add or extend:
WorkflowRunCard for main chat compact status.
WorkflowInspectorPanel for the dedicated right panel/drawer.
WorkflowAgentList for dense agent table/list.
WorkflowTimeline for filtered event history.
WorkflowStatusBadge shared by cards/popover/panel.
- Extend
ThreadActivityPopover with a workflow section.
- Extend composer controls with a run-mode selector.
- Extend
TraitsPicker Ultracode copy/tooltip to mention workflow orchestration where appropriate.
UI principles:
- Dense, operational, and scannable.
- No marketing-style hero sections.
- No nested card stacks.
- Use existing design tokens/components where possible.
- Avoid long text in small chips/buttons.
- Use icons with tooltips for actions like open, copy, cancel, filter, expand.
Suggested MVP scope
MVP should answer three user questions well:
- ?Is Claude doing workflow/subagent work right now??
- ?What agents/tasks are running and what are they doing??
- ?What did the workflow cost/do/result in??
MVP deliverables:
- Composer run-mode control with
Workflow when supported.
- Ultracode tooltip/copy update.
- Backend capture of Workflow tool/task metadata.
- First-class workflow grouping in orchestration activities.
- Compact workflow chat card.
- Workflow section in header activity popover.
- Right-side inspector with Overview and Agents tabs.
- Tests for contract parsing, adapter mapping, ingestion grouping, and web derivation.
Defer until after MVP:
- Raw event tab.
- Full timeline filters.
- Resume workflow UI.
- Custom workflow script creation/editing.
- Per-agent transcript browser.
- Cost charts/history.
Permissions, safety, and cost considerations
- Workflow mode should not silently bypass existing permission UX.
- If
Workflow is added to allowedTools, decide whether it is always allowed or only allowed after explicit user workflow-mode selection.
- If workflows can spawn many agents, show clear cost/usage signals as soon as usage is available.
- Provide a clear stop/cancel affordance if Claude SDK/runtime supports it through our session cancellation path.
- Transcript paths may reveal local directories; avoid displaying full paths in the default UI. Use copy/raw views for developer-oriented inspection.
- Treat subagent text as potentially verbose and sensitive. Store/project only what we need for UX unless the user enables detailed capture.
Open questions
- What exact SDK events are emitted for workflows in our current Claude CLI/SDK combination during real runs?
- Does
forwardSubagentText: true create too much event pressure for our current WebSocket/event-log path?
- Can we reliably identify workflow child agents using
parent_tool_use_id, hook agent_id, task ids, or a combination?
- Should explicit
Workflow mode be available for all Claude models with the runtime support, or only for models that expose Ultracode in our selector?
- Should workflow mode be per-turn, sticky per session, or both?
- How much raw native event data should be persisted versus kept only in memory/dev logs?
- Can workflow resume be supported through
resumeFromRunId, and does it fit our existing session resume model?
Acceptance criteria
- Users can trigger a Claude workflow from the composer without editing their prompt manually.
- Users selecting Ultracode get clear UI that workflow orchestration may happen, and actual workflow activity is surfaced if it happens.
- Main chat remains readable during a multi-agent workflow run.
- Workflow/subagent progress is visible in a dedicated workflow UI surface.
- Workflow agent counts, statuses, summaries, and token usage are displayed when available.
- Workflow activity survives reconnects to the same degree as existing provider runtime events.
- Generic subagent/task rendering for non-workflow Claude behavior does not regress.
- Codex provider behavior does not regress.
- Required repo checks pass before closing implementation work:
vp fmt
vp lint
vp run typecheck
- Do not run
bun test; this repo uses vp run test for the full Vitest suite.
Suggested test coverage
- Claude adapter fixture tests for Workflow tool calls/results.
- Claude adapter fixture tests for hook events and subagent events.
- Contract schema tests for any new workflow payloads.
- Provider runtime ingestion tests for workflow grouping and child agent association.
- Projection tests for workflow activities.
session-logic tests for workflow progress derivation and compact timeline rows.
- UI tests for:
- composer workflow mode availability/disabled states
- Ultracode copy/tooltip behavior
- workflow chat card
- workflow inspector agent grouping
- header activity popover workflow section
Implementation notes
Start with a capture spike before changing contracts. The highest-risk part is not rendering; it is making sure we map Claude's actual workflow/subagent event shape into a stable provider-neutral model without overwhelming the event log or chat UI.
A good implementation sequence:
- Capture and sanitize real Claude workflow fixtures.
- Decide contract shape from evidence.
- Add adapter mapping and tests.
- Add ingestion/projection grouping and tests.
- Add web derivation tests.
- Add compact chat/popover UI.
- Add dedicated inspector panel.
- Polish Ultracode/run-mode UX.
- Run
vp fmt, vp lint, and vp run typecheck.
Summary
Add first-class support for Claude Code dynamic workflows in Threadlines. The goal is to let users intentionally trigger Claude workflows, see when Ultracode causes Claude to orchestrate work in the background, and inspect workflow/subagent activity without flooding the main chat transcript.
This issue is intended as the design/reference ticket before implementation. It combines the current repo shape with current Claude workflow/Agent SDK capabilities.
Why this matters
Claude workflows can spawn many agents and perform a lot of background coordination. If Threadlines only renders the final assistant text, users lose trust because the app appears idle while expensive work is happening. If Threadlines dumps every subagent stream into chat, the conversation becomes unusable. We need a middle path: compact chat status plus a dedicated workflow surface for details, costs, subagents, raw activity, and final results.
Research snapshot
Current Claude behavior/capabilities to design around:
/workflowsview in Claude surfaces run progress, agent activity, and token usage. Threadlines needs an equivalent web-native surface.includePartialMessages: truealready exists in our adapter.forwardSubagentText?: booleancan forward subagent text/thinking blocks withparent_tool_use_id; by default only subagent tool_use/tool_result blocks are emitted.includeHookEvents?: booleancan emit hook events.SubagentStart,SubagentStop,TaskCreated,TaskCompleted, and related metadata such asagent_id,agent_type,session_id,transcript_path,cwd, andeffort.Workflowtool returns fields such asstatus,taskId,taskType,workflowName,runId,summary,transcriptDir, andscriptPath.Relevant official docs:
Current Threadlines repo context
Backend/provider:
apps/server/src/provider/Layers/ClaudeAdapter.tsalready uses@anthropic-ai/claude-agent-sdkandincludePartialMessages: true.Workflowcurrently falls through to a generic dynamic tool call path rather than a first-class workflow item.Agent,Task, and related subagent tool names are already classified ascollab_agent_tool_call.ultracodeto SDK effortxhighwhile settingsettings.ultracode = true.Contracts/orchestration:
packages/contracts/src/providerRuntime.tsalready has canonical task lifecycle events:task.started,task.progress,task.completed.apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.tsalready treats provider task events as pending background work and can synthesizesubagent.resultactivity from child provider output.apps/server/src/orchestration/Layers/ProviderActivityProjection.tsalready projects task/hook/tool progress intoOrchestrationThreadActivity.Web/UI:
apps/web/src/session-logic.tsalready derives subagent progress, subagent result rows, work log entries, and timeline entries.apps/web/src/components/chat/ThreadActivityPopover.tsxalready has a compact header popover for tasks/subagents/background runs.apps/web/src/components/chat/MessagesTimeline.tsxalready renders subagent result rows outside the normal assistant message flow.apps/web/src/components/chat/TraitsPicker.tsxalready gives Ultracode a special model/effort presentation.apps/web/src/components/ChatRightPanelInlineSidebar.tsxalready provides a resizable right panel pattern we can reuse or generalize for a workflow inspector.Product goals
Non-goals for the first implementation
Suggested user-facing UX
1. Composer entry point: Run mode selector
Add a compact run-mode control near the composer send controls. It should feel like an execution mode, not a full settings panel.
Suggested modes:
Normal- current behavior.Workflow- asks Claude to use a workflow for this turn when available.AutoorUltracode- shown when the selected Claude model/effort supports Ultracode; indicates Claude may decide to orchestrate workflow-style background work.Possible UI shape:
Behavior details:
Workflowshould be turn-scoped by default. After sending, return to the previous default unless the user pins it.Workflowis active and the user sends, add a provider turn directive rather than permanently mutating the user's prompt text if possible.2. Ultracode tie-in
We already expose Ultracode as a reasoning level for Claude models that support it. Workflow UX should build on that instead of adding a competing concept.
Recommended behavior:
Workflowwhile Ultracode is selected, treat it as one unified request: high-effort + workflow orchestration. Do not duplicate prompts or show two separate modes.Workflowonly if the runtime supports the Workflow tool independently. Otherwise disable it.3. Main chat transcript
Main chat should stay high-signal.
Render at most:
Avoid:
Suggested chat card content:
4. Header activity popover
Extend the existing
ThreadActivityPopoverso workflow runs are included alongside tasks, subagents, and background runs.Collapsed row example:
Workflow: Refactor auth flow6 agents active, 14 completedLast update: running testsThe popover should be a quick glance, not the detailed surface. It should deep-link/open the inspector for the selected run.
5. Dedicated workflow inspector surface
Add a right-side ?Workflow? panel. This can reuse the existing resizable right panel pattern, but should not be jammed into the source-control panel permanently. Ideally the right panel becomes a generic session sidebar with tabs or modes:
If that is too much for MVP, add a workflow drawer/panel opened from the chat card and header popover.
Recommended inspector layout:
Header
Overview tab
Agents tab
A dense list/table of spawned agents:
Rows should be expandable. Expanded rows can show:
Default should be collapsed and grouped by status/phase so a 100-agent run remains navigable.
Timeline tab
Chronological event stream with filtering:
Filters:
This is where verbose activity belongs, not the chat transcript.
Raw tab
For debugging and development builds:
This tab can be behind a developer toggle if needed.
Backend implementation plan
Phase 1: Capture spike with fixtures
Goal: prove exactly what Claude emits for workflow runs in our environment before committing the contract shape.
Tasks:
forwardSubagentText: true.includeHookEvents: true.Decision needed after spike:
forwardSubagentTextshould be default-on, default-off, or enabled only while the workflow inspector is open/developer mode is active.Phase 2: Provider adapter changes
In
apps/server/src/provider/Layers/ClaudeAdapter.ts:Workflowtool calls as a first-class workflow item or a specialized task item rather than genericdynamic_tool_call.Workflowtitle intitleForToolName.statustaskIdtaskTypeworkflowNamerunIdsummarytranscriptDirscriptPathworkflow_namefrom SDK task-started messages when present.includeHookEvents: truefor Claude sessions, at least when workflows are active or when the user has enabled detailed activity.forwardSubagentText: truebehind a feature flag or workflow-detail setting.settings.ultracode = trueremains tied to the existing Ultracode effort selection.Potential risk:
Phase 3: Contracts
In
packages/contracts/src/providerRuntime.ts, add enough schema to represent workflows without baking in Claude-only assumptions.Two possible approaches:
Option A: Extend task events
Extend existing
TaskStartedPayload,TaskProgressPayload, andTaskCompletedPayloadwith optional fields:workflowRunId?: stringworkflowName?: stringparentTaskId?: stringagentId?: stringagentType?: stringtranscriptPath?: stringtriggerSource?: 'explicit' | 'ultracode' | 'prompt' | 'resume' | 'unknown'usage?: ProviderUsageLikePros:
Cons:
Option B: Add workflow event family
Add provider runtime events such as:
workflow.startedworkflow.progressworkflow.agent.startedworkflow.agent.progressworkflow.agent.completedworkflow.completedPros:
Cons:
Recommendation:
Phase 4: Orchestration ingestion/projection
In provider runtime ingestion/projection:
workflowRunIdortaskIdfallback.OrchestrationThreadActivityfor web-only derivation without needing native Claude event parsing in the browser.Phase 5: Web state derivation
In
apps/web/src/session-logic.ts:WorkflowProgressStateandWorkflowRunRecordderivation.workLogEntriesunless user has opened a detailed log view.Phase 6: UI implementation
Components to add or extend:
WorkflowRunCardfor main chat compact status.WorkflowInspectorPanelfor the dedicated right panel/drawer.WorkflowAgentListfor dense agent table/list.WorkflowTimelinefor filtered event history.WorkflowStatusBadgeshared by cards/popover/panel.ThreadActivityPopoverwith a workflow section.TraitsPickerUltracode copy/tooltip to mention workflow orchestration where appropriate.UI principles:
Suggested MVP scope
MVP should answer three user questions well:
MVP deliverables:
Workflowwhen supported.Defer until after MVP:
Permissions, safety, and cost considerations
Workflowis added toallowedTools, decide whether it is always allowed or only allowed after explicit user workflow-mode selection.Open questions
forwardSubagentText: truecreate too much event pressure for our current WebSocket/event-log path?parent_tool_use_id, hookagent_id, task ids, or a combination?Workflowmode be available for all Claude models with the runtime support, or only for models that expose Ultracode in our selector?resumeFromRunId, and does it fit our existing session resume model?Acceptance criteria
vp fmtvp lintvp run typecheckbun test; this repo usesvp run testfor the full Vitest suite.Suggested test coverage
session-logictests for workflow progress derivation and compact timeline rows.Implementation notes
Start with a capture spike before changing contracts. The highest-risk part is not rendering; it is making sure we map Claude's actual workflow/subagent event shape into a stable provider-neutral model without overwhelming the event log or chat UI.
A good implementation sequence:
vp fmt,vp lint, andvp run typecheck.