You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Agents spend most of a turn running tools: searching the web, reading files, executing code. The chat has to show that work happening (which tool, on what, still running or done or failed) and then keep it in the transcript as a quiet, expandable record. flow_ui has nothing for this today. Hosts hand-roll it through FlowCustomPart, and stac_ai's tool loop has nothing to render its calls with. It pairs with the confirmation card (#22): confirmation is the ask, the tool card is the run.
What you'd like
A FlowTool card in the assistant turn: a tool icon and name, a one-line summary of the input ("flutter markdown parser", lib/main.dart), a status, and an expandable detail slot for any widget (the input, the result, a FlowCodeBlock of output).
Three states. State is data, as everywhere: the host passes the status in and re-renders. The card never flips itself.
Status
The card
The label
running
open, working
name shimmers (the FlowShimmerText idiom)
success
quieted, collapsed
settled ink, expandable
error
quieted, marked
error glyph; the failure reads without expanding
Running is the live moment; settled cards should recede. A transcript full of finished tool calls must scan as prose with small quiet rows in between, not as a wall of cards.
API sketch
FlowTool(
icon:Icons.travel_explore,
name:'Web Search',
summary:'"flutter markdown parser"', // host-written, one line
status:FlowToolStatus.running,
detail:FlowCodeBlock(code: result, language:'json'),
expanded: expanded, // disclosure is state too
onToggle: toggle, // intent out
padding: ..., // metric overrides, as everywhere
borderRadius: ...,
style:FlowToolStyle(...), // over FlowTheme.toolStyle
)
FlowToolStyle (proposed fields)
Follows the component-styles convention (#21): lives in lib/src/styles/, app-wide default on FlowTheme.toolStyle, widget wins over theme field by field, tokens under both.
backgroundColor: card fill. Defaults to the container ladder's low rung.
borderColor: card hairline. Defaults to outlineVariant.
iconColor: the tool glyph. Defaults to onSurfaceVariant.
nameStyle / summaryStyle: merged over their role defaults.
errorColor: the failed state's glyph and accent. Defaults to error.
Decisions to settle
Ship a FlowToolPart too, rendered by FlowMessage with expansion intent threaded through FlowThread. Same precedent as FlowErrorPart and the confirmation proposal (feat: FlowConfirmation, the approval card for agent actions #22). The part carries data (name, summary, status, detail text); a builder seam covers hosts whose detail is a widget.
Disclosure ownership: expanded/onToggle as host state (the package rule), or internal state with initiallyExpanded (the menus' precedent for ephemeral UI). Leaning host state: a restored transcript should reopen the way it was left.
Consecutive calls: agents often run three tools back to back. Do sequential cards group into one stack ("Searched 3 sources") or stay separate rows? Could ship separate first and group later without breaking.
While running, is the detail visible and growing, or hidden until settled? The code block already handles streaming content if we show it.
Accessibility
Status changes announce (a completed or failed run is news, like the error card's live region). The disclosure is a real button with the tool name as its label. The shimmer is decoration only; the name stays readable text.
Definition of done
FlowTool + FlowToolStatus, exported from the barrel
Metrics baked from the Figma frame; padding/borderRadius overrides
No shipped strings; name and summary host-written, doubling as accessible names
Playground demo with running/success/error variants and per-variant snippets
Docs page with a Restyling section; README row; roadmap flipped; CHANGELOG entry
Dogfooded in the example's Gemini flow as a mock tool-call turn
What you're doing instead
A custom FlowCustomPart with a host-built widget. Works, but every host redoes the status handling, the shimmer, the disclosure, and the accessibility story. For reference: assistant-ui ships tool UIs as a first-class concept, and Claude, ChatGPT, and Cursor all render the same shape (icon, name, one-line summary, expandable result).
What kind of request is this
A new component
The problem
Agents spend most of a turn running tools: searching the web, reading files, executing code. The chat has to show that work happening (which tool, on what, still running or done or failed) and then keep it in the transcript as a quiet, expandable record. flow_ui has nothing for this today. Hosts hand-roll it through
FlowCustomPart, and stac_ai's tool loop has nothing to render its calls with. It pairs with the confirmation card (#22): confirmation is the ask, the tool card is the run.What you'd like
A
FlowToolcard in the assistant turn: a tool icon and name, a one-line summary of the input ("flutter markdown parser",lib/main.dart), a status, and an expandable detail slot for any widget (the input, the result, aFlowCodeBlockof output).Three states. State is data, as everywhere: the host passes the status in and re-renders. The card never flips itself.
runningFlowShimmerTextidiom)successerrorRunning is the live moment; settled cards should recede. A transcript full of finished tool calls must scan as prose with small quiet rows in between, not as a wall of cards.
API sketch
FlowToolStyle (proposed fields)
Follows the component-styles convention (#21): lives in
lib/src/styles/, app-wide default onFlowTheme.toolStyle, widget wins over theme field by field, tokens under both.backgroundColor: card fill. Defaults to the container ladder's low rung.borderColor: card hairline. Defaults tooutlineVariant.iconColor: the tool glyph. Defaults toonSurfaceVariant.nameStyle/summaryStyle: merged over their role defaults.errorColor: the failed state's glyph and accent. Defaults toerror.Decisions to settle
FlowToolParttoo, rendered byFlowMessagewith expansion intent threaded throughFlowThread. Same precedent asFlowErrorPartand the confirmation proposal (feat: FlowConfirmation, the approval card for agent actions #22). The part carries data (name, summary, status, detail text); a builder seam covers hosts whose detail is a widget.expanded/onToggleas host state (the package rule), or internal state withinitiallyExpanded(the menus' precedent for ephemeral UI). Leaning host state: a restored transcript should reopen the way it was left.running, is the detail visible and growing, or hidden until settled? The code block already handles streaming content if we show it.Accessibility
Status changes announce (a completed or failed run is news, like the error card's live region). The disclosure is a real button with the tool name as its label. The shimmer is decoration only; the name stays readable text.
Definition of done
FlowTool+FlowToolStatus, exported from the barrelFlowToolPart+FlowMessage/FlowThreadwiring (decision 1)FlowToolStyleinlib/src/styles/+FlowTheme.toolStyle(feat: component styles on every widget with app-wide FlowTheme defaults #21 convention)padding/borderRadiusoverridesRestylingsection; README row; roadmap flipped; CHANGELOG entryWhat you're doing instead
A custom
FlowCustomPartwith a host-built widget. Works, but every host redoes the status handling, the shimmer, the disclosure, and the accessibility story. For reference: assistant-ui ships tool UIs as a first-class concept, and Claude, ChatGPT, and Cursor all render the same shape (icon, name, one-line summary, expandable result).