Skip to content

Docs

Components

ToolCallTimeline

Every tool call with its state, a measured duration and a waterfall; errors inline.

Example

  1. ENOENT: no such file or directory, open 'middleware.ts'

  2. !
Read file finished in 450 milliseconds

Interactive, and the same on the components page. Try the keyboard below on it.

Installation

npm i @dgesteves/agent-ui-kit ai
import { ToolCallTimeline } from '@dgesteves/agent-ui-kit';
// Once per app (with Tailwind v4: @import '@dgesteves/agent-ui-kit/tailwind.css'; in your CSS)
import '@dgesteves/agent-ui-kit/styles.css';

The styles are once per app; Getting started has the Tailwind v4 and plain CSS options.

Usage

<ToolCallTimeline
  parts={message.parts}
  tools={{
    read_file: { label: 'Read file', summary: (input) => (input as { path?: string }).path },
    run_command: { label: 'Run command', risk: 'high' },
  }}
  // Once the run has ended, calls that never settled read "Stopped".
  active={status === 'submitted' || status === 'streaming'}
/>

API reference

Generated from the types the package ships, so it matches the version you install.

ToolCallTimeline

A vertical timeline of tool calls with live states, durations, a waterfall, and expandable input/output. Follows the WAI-ARIA disclosure pattern; Arrow Up/Down, Home and End move between calls.

Props

partsrequired
readonly AnyUIPart[]

Tool parts, or every part of a message: non-tool parts are ignored.

tools
Record<string, ToolMeta>
timings
ToolTimings

Externally measured timings by toolCallId. Measured client-side when omitted.

expanded
readonly string[]

Controlled set of expanded toolCallIds.

defaultExpanded
readonly string[]
onExpandedChange
(expanded: string[]) => void
expandErrors
booleanDefault false

Expand calls automatically when they fail. Default false: the error message is always shown inline under a failed call, with details on demand.

waterfall
booleanDefault true

Show a per-call waterfall bar relative to the whole timeline.

announce
booleanDefault true

Announce completions and failures to screen readers.

renderExtra
(part: ToolPart) => ReactNode

Extra content under a call, e.g. an approval card.

label
stringDefault 'Tool calls'

Accessible name for the list.

active
booleanDefault true

Whether the run can still make progress. Pass false once it has ended (stopped, failed, or restored from history): calls still streaming their input or running then read "Stopped" and their clocks stop, instead of counting up forever.

Other props go to the root <div>: className (merged with tailwind-merge), id, aria-*, data-* and event handlers.

ToolMeta

Per-tool presentation. Every field is optional.

label
string

Display label. Defaults to the humanized tool name.

icon
ReactNode
summary
(input: unknown, part: ToolPart) => ReactNode

One-line summary shown next to the label. Defaults to the most descriptive input field. Not called before any input has arrived; while the input streams it can be partial.

renderOutput
(output: unknown, part: ToolPart) => ReactNode

Replace the default JSON output view.

risk
RiskLevel | ((input: unknown) => RiskLevel)

Risk shown on approval requests for this tool.

ToolTiming

startedAt
number

First time the call was observed (input started streaming).

runningAt
number

When execution began: input complete, or approval granted.

endedAt
number

When the call settled (output, error or denial).

RiskLevel

type RiskLevel = 'low' | 'medium' | 'high' | 'critical';

Accessibility

Keyboard
KeysAction
↑↓Previous or next call
HomeEndFirst or last call
EnterSpaceShow or hide the call’s input and output
  • An ordered list named by label ("Tool calls"). Each call is a disclosure button with aria-expanded, as in the WAI-ARIA accordion pattern; the arrow keys move between them.
  • A call’s name, summary, state and duration are in its button’s accessible name. In narrow containers the summary is hidden visually but still read.
  • Completions and failures are announced through a polite live region, such as "Read file finished in 1.2 seconds" or "Read file failed: ENOENT…". Turn it off with announce={false} when something else announces them.
  • States are never color alone: each has an icon and a word ("Failed", "Needs approval", "Denied").
  • The expand and collapse animation runs only without prefers-reduced-motion.

Theming

Every color, radius and font is a CSS variable, so the overrides in Theming apply, on :root or scoped to any element. These hooks are read from the component's markup.

Slots (data-slot)
tool-call-triggertool-call-timelinetool-call
State attributes
data-phaseon tool-call'denied' | 'awaiting-approval' | 'error' | 'streaming' | 'running' | 'success'data-stateon tool-call'input-streaming' | 'input-available' | 'approval-requested' | 'approval-responded' | 'output-available' | 'output-error' | 'output-denied'data-interruptedon tool-callset once the run ended before the call settled
Tokens it uses
--aui-accent--aui-accent-fg--aui-bg--aui-border--aui-border-strong--aui-fg--aui-fg-muted--aui-fg-subtle--aui-font-mono--aui-font-sans--aui-hot--aui-hot-fg--aui-ring--aui-surface-2
app/globals.css
/* Only this component, and only inside .settings-panel */
.settings-panel [data-slot='tool-call-timeline'] {
  --aui-radius: 4px;
}

[data-slot='tool-call'][data-phase='denied'] {
  outline: 1px solid var(--aui-accent);
}