ComponentsAI & chat

Tool Activity

Shows the tools an agent called while it worked: what ran, what is waiting, and what needs attention. ActivityPanel frames a live run above its result.

Every statusRetry is local; nothing is sent
  1. Searched the supplier inboxCompleted
  2. Reading the Q4 forecast tableIn progress
  3. Send the follow-up to NorthwindWaiting

    Waiting for approval or another action. Review the action details below.

  4. Update the investor pitchPending
  5. Read #financeAccess denied

    Access denied. Ask an administrator to review your permissions.

  6. Update the Northwind recordFailed

    The action failed. Retry, or check the app connection.

  7. Post the weekly updateCancelled
  8. Send follow-up emails to late suppliersOutcome unknown

    The outcome is unconfirmed. Check the action status before requesting it again.

Usage

Tools behind a replyTSX
import { BrandIcon } from "@tulipfarm/sprout/brand-icon";
import { ToolActivity } from "@tulipfarm/sprout/tool-activity";

<ToolActivity
  active={replyIsWorking}
  items={[
    {
      id: "call_1",
      label: "Searched the supplier inbox",
      status: "completed",
      visual: <BrandIcon brand="gmail" size="inline" />,
    },
    {
      id: "call_2",
      label: "Update the Northwind record",
      status: "failed",
      visual: <BrandIcon brand="hubspot" size="inline" />,
      detail: "The action failed. Retry, or check the app connection.",
      details: <Button variant="outline" size="sm" onClick={retry}>Retry update</Button>,
    },
  ]}
/>

  • status: "queued", "running","waiting", "completed","blocked", "failed","cancelled", or "unknown". Each has its own mark and a spoken name, such as “In progress” or “Outcome unknown”.
  • visual: a 14px icon or an inlineBrandIcon for the tool or app.
  • detail: one short line under the label. It turns red for failed and blocked.
  • details: extra content lined up with the label, such as a retry button or a “Details” toggle.
  • active: the reply is still working even when no step is running, so the trigger shows a spinner.

Variants

VariantsThe same settled run in each variant
  • "collapsible": the default. It opens while work is pending and closes once it settles. The trigger reads “Using 3 tools”, “2 tools waiting”, or “Used 3 tools · 1 needs attention”.
  • "transcript": starts closed under a chat reply. It reads “Working… Searching the web”, “Work pending”, or “Tool activity · 3 tools · Access denied”.
  • "stepper": always open, with no trigger. Items arrive newest first and show oldest first; inside anActivityPanel it scrolls to the newest step.

One tool

Agent request receiptOne Slack tool call with its live status

Request running. Tool running.

  1. Post to #launch-updatesIn progress

A single call, as on an agent request receipt. Pick a status to see its mark and how the summary changes.

In a chat reply

Chat replyStarts closed under the reply; opening it pauses follow-latest

Is UK services inflation still above 5%? Check our supplier terms too.

Services inflation was 5.1% in September, down from 5.3%. Northwind’s terms allow a price review above 5%.

Following the latest message

Transcript with web sourcesTSX
<ToolActivity
  variant="transcript"
  items={tools}
  active={isLatestTurn}
  activityLabel="Searching the web"
  sourceIcon={(url) => iconFor(new URL(url).hostname)}
  onToggle={() => pauseFollowLatest()}
/>

// A web search step
{
  id: "call_7",
  label: "Searched the web",
  status: "completed",
  visual: <Globe size={14} />,
  query: "UK services inflation September 2026",
  urls: ["https://www.ons.gov.uk/…", "https://www.bls.gov/…"],
  failedUrls: ["https://www.ft.com/…"],
  sources: [{ url: "https://www.ons.gov.uk/…", title: "Consumer price inflation, UK" }],
}

Web steps show their search text and up to four source chips; a “2 more” button shows the rest. A page in failedUrlsgets a warning icon. Chips without a title show the address withouthttps://www.. Only http andhttps addresses become links, which open in a new tab.

Pass sourceIcon to show page icons. It returns an image address for a page, or nothing for a globe; images that fail to load fall back to the globe. Sprõut never calls an icon service itself.

With no items, an active transcript shows “Thinking…” or the activityLabel. Other variants render nothing.

Activity panel

Agent runScroll to the top of the timeline to load earlier steps
  1. Read the Q4 forecast tableCompleted
  2. Searched the supplier inboxCompleted
  3. Looked up the Northwind recordIn progress

Supplier update

The draft appears here when the run finishes.

A live run above its resultTSX
import { ActivityPanel, ToolActivity } from "@tulipfarm/sprout/tool-activity";

<ActivityPanel working={running} activityLabel={currentStep} hasResult collapseWhenDone>
  <ToolActivity
    variant="stepper"
    items={steps}
    hasOlder={page.hasMore}
    loadingOlder={page.loading}
    olderError={page.failed}
    onLoadOlder={page.loadMore}
    onRetryOlder={page.loadMore}
  />
</ActivityPanel>

  • The panel takes at most 40% of its parent’s height and scrolls inside. A soft fade covers the top once it scrolls.
  • hasResult draws a line under the panel.collapseWhenDone closes it when work stops and reopens it when work restarts.
  • When hasOlder is set, scrolling within 40px of the top callsonLoadOlder once. WhileloadingOlder it says “Loading earlier activity…”; onolderError it shows “Retry loading”.

Recorded activity

Recorded activityA result card opens the stepper timeline

Recorded activity

ActivitySome outcomes are unconfirmed

A finished run can sit behind a ResultCard. Its details show the stepper without a panel.

Empty

Before any tool runsWith no items, only an active transcript shows progress

Transcript, active

Thinking…

Transcript, active, with a label

Planning the supplier follow-up

Collapsible or stepper, no items

Nothing renders.

Accessibility

The trigger is a button named by its summary, and the summary is a live status. Steps are an ordered list named “Tool activity” (set label to rename it). Each step says its status, such as “Failed”; a running step’s status is announced outside the transcript. Source chips sit in a list named “Web sources”, and failed pages say “Page unavailable”.

ActivityPanel is a region named “Chat activity”. Its timeline is a focusable region named “Activity timeline”, so it scrolls by keyboard. Older-load errors are an alert.

Steps fade in over 180ms and the chevron turns in 120ms. With reduced motion, steps appear at once and running marks stop spinning. On touch screens the trigger and source chips grow to 44px.

Theme tokens

Rows use --sprout-text and --sprout-muted. Marks use --sprout-success (running),--sprout-primary (completed), --sprout-info(waiting), and --sprout-danger. Chips use--sprout-secondary and --sprout-hover. Set--sprout-activity-panel-fade to the panel’s background when it is not --sprout-surface.