Skip to content

feat(frontend): add sub-agent observability with orchestrator thinking and execution chain display #2365

Open
genni613 wants to merge 16 commits intobytedance:mainfrom
genni613:feat/subagent-observability
Open

feat(frontend): add sub-agent observability with orchestrator thinking and execution chain display #2365
genni613 wants to merge 16 commits intobytedance:mainfrom
genni613:feat/subagent-observability

Conversation

@genni613
Copy link
Copy Markdown

@genni613 genni613 commented Apr 19, 2026

Summary

Improve sub-agent observability in agent swarm mode by surfacing the orchestrator's thinking process and each subagent's internal execution chain (reasoning + tool calls with parameters).

Changes

  • Message history accumulation: Extended Subtask type with messageHistory field and implemented _appendMessage protocol in task context for deduplicated message accumulation from task_running SSE events
  • Orchestrator thinking display: New OrchestratorThinking component showing the lead agent's reasoning before splitting subtasks, with task decomposition count
  • Subagent execution chain: Enhanced SubtaskCard to render internal reasoning and tool calls with parameters in expanded state, using shared convertToSteps + ToolCall modules extracted from message-group.tsx
  • Reasoning fallback: When model doesn't output reasoning_content, fall back to text content as thinking indicator
  • Tool args display: Generic tool fallback now shows key string parameters instead of just tool name
  • Markdown line breaks: Added remark-breaks plugin so single newlines in reasoning text render as line breaks

Screenshots

Pasted Graphic 6 image

Test plan

  • Run pnpm check — lint + typecheck pass
  • Run pnpm test — 19/19 unit tests pass
  • In ultra mode, send a complex prompt that triggers subagent delegation
  • Verify OrchestratorThinking shows lead agent's analysis and task count
  • Expand SubtaskCard and verify internal reasoning + tool calls with parameters are visible
  • Switch to zh-CN locale and verify new i18n strings display correctly

Closes #2315

@WillemJiang WillemJiang requested a review from Copilot April 21, 2026 01:44
@WillemJiang WillemJiang added the reviewing The PR is in reviewing status label Apr 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves agent-swarm UX by surfacing additional execution details: the orchestrator’s pre-delegation “thinking” and each subagent’s internal message/tool-call chain, plus better markdown rendering for reasoning text.

Changes:

  • Extend Subtask to accumulate messageHistory from task_running SSE events (deduped).
  • Add OrchestratorThinking and enhance SubtaskCard to render reasoning + tool calls (via extracted shared message-steps utilities/components).
  • Improve markdown rendering of reasoning text by enabling single-newline line breaks (remark-breaks).

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/core/threads/hooks.ts Appends task_running messages into subtask state via _appendMessage.
frontend/src/core/tasks/types.ts Adds messageHistory?: AIMessage[] to Subtask.
frontend/src/core/tasks/context.tsx Implements _appendMessage protocol for deduped history accumulation.
frontend/src/core/streamdown/plugins.ts Adds remark-breaks to Streamdown plugin sets.
frontend/src/core/i18n/locales/zh-CN.ts Adds new subtask/orchestrator i18n strings (zh-CN).
frontend/src/core/i18n/locales/types.ts Extends Translations.subtasks typing with new keys.
frontend/src/core/i18n/locales/en-US.ts Adds new subtask/orchestrator i18n strings (en-US).
frontend/src/components/workspace/messages/subtask-card.tsx Renders subagent execution chain from messageHistory.
frontend/src/components/workspace/messages/orchestrator-thinking.tsx New component to display orchestrator analysis + decomposition count.
frontend/src/components/workspace/messages/message-steps.tsx Extracted shared “steps” conversion + ToolCall renderer.
frontend/src/components/workspace/messages/message-list.tsx Integrates OrchestratorThinking into subagent message groups.
frontend/src/components/workspace/messages/message-group.tsx Refactors to consume shared message-steps module.
frontend/package.json Adds remark-breaks dependency.
frontend/pnpm-lock.yaml Locks remark-breaks and transitive deps.
Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Language not supported

Comment thread frontend/src/components/workspace/messages/message-list.tsx Outdated
Comment thread frontend/src/components/workspace/messages/subtask-card.tsx Outdated
Comment thread frontend/src/core/threads/hooks.ts
Comment thread frontend/src/core/tasks/context.tsx Outdated
@WillemJiang
Copy link
Copy Markdown
Collaborator

@genni613 Here are some additional comments for the code

  1. _appendMessage convention is fragile (context.tsx:43)

Using an underscore-prefixed _appendMessage field that's destructured out and never makes it into the Subtask type is a side-channel pattern. It works but is easy to break accidentally — anyone reading Subtask type won't know this protocol exists.

Suggestion: Consider making updateSubtask accept a second parameter or use a discriminated union for the update payload instead of smuggling data through underscore-prefixed fields.

  1. CoTToolCallStep.result type mismatch with old code (message-steps.tsx:521)

In the old message-group.tsx, result was string | Record<string, unknown> (union). In the new message-steps.tsx, the interface declares it the same way, but convertToSteps assigns step.result = json where json is any (from JSON.parse). This means arrays also pass through — e.g., web_search results which are Array<...>. The type says Record<string, unknown> but arrays flow through fine at runtime. This isn't a bug, but the types are misleading.

Suggestion: Either broaden the type to unknown or add explicit handling.

  1. Redundant Array.isArray check (message-steps.tsx:167-168)

{Array.isArray(results) && (

{Array.isArray(results) &&

The outer guard already confirmed that the results are an array. The inner Array.isArray(results) is redundant.

…rtion safety

- Extract _appendMessage side-channel into explicit useAppendMessage hook
- Broaden CoTToolCallStep.result type to unknown for runtime accuracy
- Remove redundant Array.isArray check in image_search branch
- Guard toolCall.id with runtime check instead of non-null assertion
- Replace useSubtask()! with safe early return and reorder hooks

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@genni613 genni613 force-pushed the feat/subagent-observability branch from 3c31aba to 61d1946 Compare April 21, 2026 10:01
@WillemJiang
Copy link
Copy Markdown
Collaborator

@genni613 Please run the below comments to fix the lint error.

cd frontend
make format

@WillemJiang
Copy link
Copy Markdown
Collaborator

@genni613 Did you have a chance to try the latest frontend in your local box? My browser blocked when the backend started the subagent.

@genni613
Copy link
Copy Markdown
Author

@WillemJiang Already fixed. updateSubtask calls were moved from the render-phase groupMessages callback into a useEffect with a syncedTaskIdsRef dedup guard, breaking the render → setState → re-render loop.

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

Labels

reviewing The PR is in reviewing status

Projects

None yet

Development

Successfully merging this pull request may close these issues.

是否支持显示展示每一轮思考过程、工具规划,以方便完整显示模型执行全部路径

3 participants