Agent Timeline

Pro

A chart of the work your agents did over time, wired to a board of what came out of it. Point at a moment and its cards light up; select a stretch and the board shows only that stretch.

October close, overnight run

finished
216
for your sign-off
4
stopped
2
Agent work over time. Press Enter on a bar to show only that time, Shift and Enter to widen it, Escape to show all.
hourFinishedWaiting on youStopped
19:002200
20:003100
21:002700
22:001800
23:002400
00:001201
01:00910
02:00601
03:00810
04:001100
05:001510
06:001910
07:001400

Your sign-off4

  • Post the hosting accrual

    Ledger agent · 01:10 · €12,400

  • Write off a €38 rounding gap on the EU account

    Reconciliation agent · 03:25

  • Release the supplier payment run

    Payables agent · 05:40 · 27 payments

Nothing left to sign off.

Stuck2

  • Match the October card statement

    Reconciliation agent · 00:20

    The bank feed stopped at 28 October. Three pulls came back empty.

  • Revalue the USD balances

    Ledger agent · 02:45

    No rate published for 31 October yet. Nothing was posted.

Nothing stuck in this window.

Closed out216

  • 212 bank lines matched to the ledger

  • 48 invoices coded to cost centres

  • 9 intercompany balances agreed

  • 31 late receipts chased by email

Nothing closed out in this window.

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Activate your Pro license (once per machine)npx koalaui-cli@latest login <key># Add this component (its dependencies come along)npx koalaui-cli@latest add agent-timeline

Usage#

Give the root one row per time bucket and give each card the buckets it belongs to. The rest follows: the chart and the board point at each other, a selected stretch filters the board, and the figures add up over that stretch. When the reader acts on a card, remove it and move its bucket from one series to the other, and the chart, the counts and the board change together. It fetches nothing, so it fits any agent product, from a support desk to a release pipeline.

This example is part of Koala UI Pro

The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.

Have a license? Unlock it here

Anatomy#

import {  AgentTimeline,  AgentTimelineHeader,  AgentTimelineHeading,  AgentTimelineTitle,  AgentTimelineWindow,  AgentTimelineCounts,  AgentTimelineCount,  AgentTimelineChart,  AgentTimelineRange,  AgentTimelineBoard,  AgentTimelineColumn,  AgentTimelineColumnHeader,  AgentTimelineList,  AgentTimelineItem,  AgentTimelineItemTitle,  AgentTimelineItemCount,  AgentTimelineItemMeta,  AgentTimelineItemDetail,  AgentTimelineItemActions,  AgentTimelineRevert,  AgentTimelineEmpty,} from "@/components/ui/agent-timeline"

Chart and board#

A column and its band on the chart share one tone. Point at a card and the chart dims everything but the moments it happened; point at a bar and the cards from other moments step back. Drag across the chart to keep only that stretch: cards outside it fold away and the counts add up again. This release night opens on the stretch around midnight.

Agent work over time. Press Enter on a bar to show only that time, Shift and Enter to widen it, Escape to show all.
slotFinishedStopped
22:0040
22:3070
23:0052
23:3090
00:00120
00:3061
01:0030
01:3020
Only 23:00 to 00:30

Rolled back3

  • Search service, eu-west

    Health checks failed twice

  • Billing worker, us-east

    Migration lock held for 10 min

  • Image resizer, ap-south

    Memory over the limit

No rollbacks in this window.

Shipped32

  • 16 web services

  • 21 background workers

  • 11 edge functions

Nothing shipped in this window.

Long columns#

Finished work reads best summarised, one line per kind of task with its count. Past limit the lines fold behind a button and unfold one after another in place.

Closed out216

  • 212 bank lines matched to the ledger

  • 48 invoices coded to cost centres

Empty columns#

An empty column can say so with AgentTimelineEmpty, or step out of the board with hideWhenEmpty. Nothing got stuck here, so that column is gone and the other two share the row.

Your sign-off0

    Nothing left to sign off.

    Stuck0

      Closed out216

      • 212 bank lines matched to the ledger

      • 48 invoices coded to cost centres

      Narrow containers#

      The timeline reads its own width, not the window's. In a side panel the counts wrap, the columns stack and the actions drop below the text, with density="compact" for tighter rows.

      October close

      finished
      216
      for your sign-off
      4
      Agent work over time. Press Enter on a bar to show only that time, Shift and Enter to widen it, Escape to show all.
      hourFinishedWaiting on youStopped
      19:002200
      20:003100
      21:002700
      22:001800
      23:002400
      00:001201
      01:00910
      02:00601
      03:00810
      04:001100
      05:001510
      06:001910
      07:001400

      Your sign-off4

      • Post the hosting accrual

        Ledger agent · 01:10 · €12,400

      Closed out216

      • 212 bank lines matched to the ledger

      • 48 invoices coded to cost centres

      API reference#

      AgentTimeline

      Holds the series, the selected stretch and the link between the chart and the board. It is a size container: the columns sit side by side when it is wide and stack when it is narrow. Every part accepts className, merged last.

      PropTypeDefaultDescription
      data*ChartDatum[]-One row per time bucket, such as { hour: "02:00", done: 6, failed: 1 }. Keys named after a status take its tone.
      index*string-The key that names each bucket.
      configChartConfig-Labels and colours per series, merged over the status tones.
      rangereadonly [number, number] | null-The selected stretch, as first and last bucket, when you control it.
      defaultRangereadonly [number, number] | nullnullThe stretch selected on the first render.
      onRangeChange(range) => void-The reader selected a stretch, or cleared it.
      variant"card" | "plain""card"A framed surface, or no chrome for a full page.
      density"comfortable" | "compact"-Padding and row spacing. Reads DensityProvider when unset.
      Data attributeDescription
      data-rangedPresent while a stretch is selected.

      AgentTimelineWindow

      The time the timeline covers, as "18:40 yesterday to 07:40 · 13 h". It formats on the client, in the reader's time zone. Children replace the text.

      PropTypeDefaultDescription
      fromDate | number-Where the window starts.
      toDate | number-Where it ends. Now, when unset.
      localestring"en-US"Formats the times and the day word.
      joinerstring"to"The word between the two times. Use it to translate.
      formatSpan(ms: number) => string-Writes the length: 45 min, 13 h or 3 d by default.

      AgentTimelineCount

      One figure in AgentTimelineCounts. Without count it adds up its series over the selected stretch, so it follows the chart. Pointing at it brings its band forward on the chart.

      PropTypeDefaultDescription
      status*"working" | "waiting" | "idle" | "done" | "failed"-Sets the dot and the default label.
      seriesstring-The data key it adds up. The status, when unset.
      countnumber-A figure of your own, in place of the sum.

      AgentTimelineChart

      Stacked bars on Koala's Chart, one band per series in the tone of its column. Drag across it, or click a bar, to select a stretch; from the keyboard, focus it, move with the arrows, press Enter to select, Shift and Enter to widen and Escape to clear. Extra children render inside the Chart.

      PropTypeDefaultDescription
      markersreadonly AgentTimelineMarker[][]{ at, title, description?, label?, status? }, pinned above a bucket. Hover a marker or its bar to read it.
      selectablebooleantrueTurns selecting a stretch off.
      plotClassNamestring"h-28"Sizes the chart itself.
      tickFormatter(value, index) => string-Writes the bucket names on the axis.
      valueFormatter(value: number) => string-Writes the values in the tooltip.
      totalLabelstring"All"Names the total row of the tooltip.
      labelstring-The chart's accessible name, with the keys it takes.
      Data attributeDescription
      data-selectingPresent while the reader drags a stretch.

      AgentTimelineRange

      Says which stretch is selected, with a button that shows everything again. Renders nothing while no stretch is selected.

      PropTypeDefaultDescription
      children(from: string, to: string) => ReactNode-Writes the line from the first and last bucket names.
      clearLabelReactNode"Show all"The button's label.

      AgentTimelineColumn

      One column of the board. Its items that fall outside the selected stretch fold away, and AgentTimelineEmpty inside it shows only when none are left.

      PropTypeDefaultDescription
      status*"working" | "waiting" | "idle" | "done" | "failed"-Sets the tone of the column and the default title.
      seriesstring-The chart series the column stands for. The status, when unset.
      hideWhenEmptybooleanfalseHides the column while it has nothing to show.

      AgentTimelineColumnHeader

      The column's dot, title and count. Pointing at it brings its band forward on the chart. Children replace the default title.

      PropTypeDefaultDescription
      countnumber | null-The figure at the end. The column's series summed over the stretch, when unset; null hides it.

      AgentTimelineList

      The items of a column. Give each a stable key: an item that leaves collapses out while the others close the gap, and one that comes back grows into its old place.

      PropTypeDefaultDescription
      limitnumber-Folds the items past this many behind a button.
      defaultExpandedbooleanfalseOpens the fold on the first render.
      expandedboolean-Whether the fold is open, when you control it.
      onExpandedChange(expanded: boolean) => void-The reader opened or closed the fold.
      foldLabel(hidden: number, expanded: boolean) => string-Writes the fold button. Use it to translate.

      AgentTimelineItem

      One card of the board: a thing that waits on the reader, a stop, or a summary of many finished things. Pointing at it, or focusing inside it, lights the moments it happened on the chart.

      PropTypeDefaultDescription
      atnumber | string | readonly (number | string)[]-The buckets the item belongs to, by index or name. An item without one is never filtered.
      Data attributeDescription
      data-enteringPresent on an item that arrived after the first render.
      data-leavingPresent while the item collapses out.
      data-filteredPresent while the item falls outside the selected stretch.
      data-dimmedPresent while the reader points at a bucket the item is not in.
      data-foldedPresent while the item is folded past the limit.

      AgentTimelineItemCount

      The leading figure of a summary line.

      PropTypeDefaultDescription
      value*number-The figure, in tabular numerals.

      AgentTimelineItemActions

      The item's buttons, at the end of the row. Two or more drop below the text in a narrow column; a single one stays beside it. Use xs buttons.

      AgentTimelineRevert

      A quiet button that takes an action back. You handle the click: put the thing back in your state and the board returns it.

      PropTypeDefaultDescription
      size"xs" | "sm""xs"The button size.

      useAgentTimeline

      Reads the timeline from any part inside it: range, setRange, the bucket being pointed at, and inRange(bucket), to work out figures of your own for the stretch.

      FAQ#

      From you. Count what your agents did per bucket for the chart, and pass the cards for the board from whatever your agents report to. The timeline redraws when that state changes.