Xzero UI
Pro library

Agent routinesPro

Scheduled agents in one card: each routine reads as a sentence with its schedule, next run countdown, connectors and destination, and opens smoothly to edit or run it now.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/agent-routines
Live · keyboard ready

Pass routines with onToggle, onRun and onChange to wire your scheduler; with no props it shows sample routines with live countdowns.

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/agent-routines

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { AgentRoutines, type Routine } from "@/components/xzero/blocks/agent-routines/agent-routines";

export function Routines({ routines }: { routines: Routine[] }) {
  return (
    <AgentRoutines
      routines={routines}
      onRun={async routine => {
        const result = await api.routines.run(routine.id); // { id, status, summary, durationMs, report }
        return {
          run: { id: result.id, status: result.status, at: Date.now(), summary: result.summary, durationMs: result.durationMs },
          report: result.report,
        };
      }}
      onToggle={(id, enabled) => api.routines.update(id, { enabled })}
      onSave={(routine, { created }) => created ? api.routines.create(routine) : api.routines.update(routine.id, routine)}
    />
  );
}

// A routine
const triage: Routine = {
  id: "morning-triage",
  name: "Morning triage",
  instruction: "Read new Linear issues, match them to Sentry errors and post a ranked list to #triage.",
  schedule: { frequency: "weekdays", time: "09:00" },
  sources: ["linear", "sentry"],
  destination: "#triage",
  model: "claude-sonnet-5-5",
  enabled: true,
  steps: ["Reading new Linear issues", "Matching Sentry errors", "Ranking by customer impact", "Posting to #triage"],
  history: [{ id: "r-1", status: "success", at: "2026-10-19T09:00:00", durationMs: 41000, summary: "Triaged 9 issues, 2 urgent" }],
  report: "Triage for Monday 19 October\n- ENG-2141 Checkout button stays disabled. Urgent, assigned to Priya.\n9 issues reviewed, 2 urgent.",
};

API reference

AgentRoutines

Scheduled agents in one card. Each row reads as a sentence: the routine's name and an on and off switch, its schedule in plain words with a live countdown to the next run and the last run on the right, then the connectors it reads, the Slack destination and the model as small colored marks in a fixed slot that never wraps, beside its last 14 runs as small tinted ticks with a tooltip each. Run now sits in a reserved slot that shows on hover or focus; a run fills a thin line under the row in the routine's series color, shimmers a Running label with the current step, then slides a new tick into the history and updates the last run. Clicking a row opens it in place, one at a time, with the latest run's output as a short formatted report, the instruction prompt and a compact schedule editor. New routine opens an inline row where a sentence is read into editable chips for the schedule, sources and destination.

PropTypeDefaultDescription
routinesRoutine[]four sample routinesThe routines: id, name, instruction, schedule ({ frequency: "hourly" | "daily" | "weekdays" | "weekly", time: "HH:MM", day?: 0-6 }), sources (connector ids: linear, github, sentry, google-calendar, notion), destination ("#channel" or "Direct message"), model (claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, gpt-6-luna, gemini-3-8-flash), enabled, history (oldest first), an optional report, optional step labels and an optional accent (1 to 4, the series color for its progress). Passing a new array replaces the list; changes made in the card are kept until then.
onRun(routine: Routine) => Promise<RoutineRunResult> | RoutineRunResult | void–Called when a run starts, from Run now or when a schedule comes due while the card is open. Return a promise of { run, report? } to drive the row from your backend: the steps advance while it is pending, the result lands when it resolves, and a rejection shows its message as the error. Return nothing to keep the built-in simulation, which says so in the status region.
onToggle(id: string, enabled: boolean) => void–Called when a routine's schedule switch changes.
onSave(routine: Routine, meta: { created: boolean }) => void–Called with the full routine when its schedule changes in the open row, and with created: true when New routine adds one.
nownumber | Date–The current time for countdowns and run times. Without it the card uses a demo clock that starts on Tuesday 20 October 2026 at 6:45 when no routines are passed, and the real clock otherwise.
defaultOpenIdstring | nullnullThe routine that starts open. Opening another closes it.
titlestring"Routines"The card title, also the list's accessible name.
classNamestring–Class on the root element.

Keyboard interactions

KeysAction
TabMoves through New routine, then for each row the routine name, Run now, the schedule switch and the run ticks, then the open row's schedule editor.
Enter, SpaceOn a routine name, opens or closes the row. On Run now, starts a run; while it runs the same button stops it.
Arrow up / Arrow down, Home, EndOn a routine name, moves focus to the previous, next, first or last routine.
Arrow left / Arrow right, Home, EndInside the run ticks, moves between runs; each run shows its result, time, duration and summary in a tooltip. In the frequency control, changes the frequency.
EnterIn the New routine sentence field, adds the routine. A sentence typed a moment ago is read at once.
EscapeIn the sentence field, cancels New routine and returns focus to its button. In a chip's popover, closes the popover.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components