Dock the Run-Chrome Yourself
The Task Check List and Subagent List are run-level chrome — they describe the state of the whole turn, not of any one message. So the SDK docks them in a fixed strip that sits outside the thread's scroll box, between it and the composer.
Dock the Run-Chrome Yourself
By default the SDK docks the Task Check List and Subagent panels in a fixed strip between the thread and the composer. Set hideRunChrome to true and the built-in panels are no longer rendered — you place the exported <TaskList> / <SubagentList> wherever you like, e.g. a right rail or a separate tab.
import {
Chatbot, TaskList, SubagentList, AsgardThemeScope,
} from '@asgard-js/react';
import { deriveTasks, deriveSubagents } from '@asgard-js/core';
// conversation comes from useAsgardContext()
const tasks = deriveTasks(conversation);
const subagents = deriveSubagents(conversation);
<Chatbot hideRunChrome {...rest} />
<AsgardThemeScope theme={myTheme}>
<SubagentList subagents={subagents} locale="en-US" />
<TaskList tasks={tasks} locale="en-US" />
</AsgardThemeScope>Outside the <Chatbot> subtree the design tokens the chat shell emits are gone, so wrap them in <AsgardThemeScope> — otherwise they fall back to the light-themed defaults.
Why Outside the Scroll Box
They used to render at the tail of the thread and scroll with the messages. The result: during a streaming run the thread kept growing and auto-scrolling, shoving the panels around. Moved into a fixed strip, they now stay put while a run streams.
The strip has two more rules:
- Capped at 50% of the body height, scrolling internally past that — the thread always keeps the other half
- When there is no chrome, the strip does not exist and takes no space — the composer sits flush against the last message
Placing Them Yourself
<Chatbot hideRunChrome {...rest} />
With that set, the built-in panels are not rendered and you can put the exported
<TaskList> / <SubagentList> anywhere — a right rail, a drawer, a separate tab.
import { TaskList, SubagentList, AsgardThemeScope } from "@asgard-js/react";
import { deriveTasks, deriveSubagents } from "@asgard-js/core";
// conversation comes from useAsgardContext()
const tasks = deriveTasks(conversation);
const subagents = deriveSubagents(conversation);
<AsgardThemeScope theme={theme}>
<SubagentList subagents={subagents} locale="en-US" />
<TaskList tasks={tasks} locale="en-US" />
</AsgardThemeScope>
AsgardThemeScopeOutside <Chatbot> the panels miss the design tokens the chat shell emits and fall
back to the light-themed defaults. See
Re-establish the Theme.
Where the Data Comes From
Both panels take plain arrays — they are not coupled to SDK state:
function TaskList(props: { tasks: Task[]; locale?: Locale }): ReactNode;
function SubagentList(props: { subagents: Subagent[]; locale?: Locale }): ReactNode;
deriveTasks / deriveSubagents fold both out of a Conversation. To subscribe
rather than recompute, core also offers createDerivedStores, with tasksEqual /
subagentsEqual for comparison.
import {
deriveTasks, deriveSubagents,
tasksEqual, subagentsEqual,
createDerivedStores,
} from "@asgard-js/core";
Types
interface Task {
id: string;
subject: string; // Noun-form title; shown when not in progress
activeForm?: string; // Present-continuous label; preferred while in progress
description?: string; // Full detail, shown when the row is expanded
status: "pending" | "in_progress" | "completed";
}
interface Subagent {
parentToolUseId: string; // Correlation key = the Agent tool-call that spawned it
agentId?: string;
subagentType?: string; // e.g. general-purpose
description?: string;
status: "running" | "completed" | "failed" | "cancelled";
summary?: string;
tools: SubagentToolCall[]; // The child tool-calls this subagent ran
}
A subagent's terminal status comes only from the subagent.complete event — it is
never inferred from the Agent tool-call's own completion (async subagents complete
their tool-call early with async_launched).
See Also
- Task Check List, Subagent List — the built-in versions
- Re-establish the Theme
- Locales — per-panel
locale - Headless — draw everything yourself