Agent Run

A brand-neutral AI agent run that thinks, calls tools against a real-seconds timer and streams a markdown answer in bursts

Installation
$ pnpm dlx shadcn@latest add @remocn/agent-run

Usage

AgentRun is the part of an AI product video that happens after the prompt. The panel shows the prompt someone just sent, a Thinking status over a short plan, then tool calls that resolve one after another while the header timer counts real seconds. Then the answer streams in as markdown, in bursts. It is brand-neutral: neutral surfaces, one accent for the running spinners and the citation chips, and a light or dark theme.

import { Backdrop } from "@/components/remocn/backdrop";
import { AgentRun } from "@/components/remocn/agent-run";
 
export const AgentScene = () => (
  <Backdrop
    fill={{ type: "color", value: "#ececea" }}
    padding={0}
    radius={0}
    shadow=""
  >
    <AgentRun />
  </Backdrop>
);

The component paints no background and centers its panel in the parent. Sizes are reference pixels at a 720px-tall frame. They scale by height / 720, capped so the 800px panel and its margins fit the width. The panel height follows the frame, so square and vertical compositions show more of the run at once. Everything derives from the Remotion frame and the seed, so seeking and rendering are deterministic.

The component uses the system font stack. If your project loads Inter and JetBrains Mono, for example with @remotion/google-fonts, it picks them up.

Your own run

Pass a run: the prompt, a short plan, the tool steps with their real durations in seconds, and the answer as markdown. The answer supports these:

  • # and ## headings
  • paragraphs
  • - bullets
  • **bold** and inline code
  • [n] citations
  • fenced code blocks

getAgentRunDuration(run) returns the composition length. If you also pass seed, compression or speed to the component, pass the same values as the second argument.

import { Composition } from "remotion";
import { Backdrop } from "@/components/remocn/backdrop";
import {
  AgentRun,
  type AgentRunScript,
  getAgentRunDuration,
} from "@/components/remocn/agent-run";
 
const run: AgentRunScript = {
  title: "Pro plan churn",
  prompt: "Which Pro accounts are likely to churn this month?",
  plan: [
    "Pull weekly active seats for every Pro account",
    "Compare them with renewal dates and support load",
  ],
  steps: [
    {
      icon: "database",
      name: "Run SQL",
      detail: "active seats by account, last 60 days",
      duration: 2.6,
    },
    {
      icon: "book",
      name: "Read 9 sources",
      duration: 1.8,
      sources: [
        "CRM notes",
        "Support tickets",
        "Renewal calendar",
        "billing.example.com",
        "Usage report",
        "QBR decks",
        "Churn survey",
        "Seat audit",
        "Pricing page",
      ],
    },
  ],
  answer: [
    "## 14 Pro accounts are at risk",
    "",
    "Active seats fell below 40% on 14 accounts that renew within 30 days [1].",
    "",
    "- 9 of them opened a billing ticket this month [2]",
    "- 3 lost the admin who set up their workspace",
    "",
    "**Next:** send the list to account managers today.",
  ].join("\n"),
};
 
const ChurnScene = () => (
  <Backdrop
    fill={{ type: "color", value: "#0a0a0a" }}
    padding={0}
    radius={0}
    shadow=""
  >
    <AgentRun run={run} theme="dark" accentColor="#22c55e" />
  </Backdrop>
);
 
export const RemotionRoot = () => (
  <Composition
    id="ChurnScene"
    component={ChurnScene}
    durationInFrames={getAgentRunDuration(run)}
    fps={30}
    width={1280}
    height={720}
  />
);

Timing

At 30 fps with the default run, seed={1}, compression={3} and speed={1}:

FramesBeat
0–14The panel fades up 14px, and the prompt bubble follows at 4–14
16The run starts: the timer reads 0.0s and Thinking fades in with its shimmer
30–48The three plan lines stream in bursts
56–64Thinking settles into Thought for 4s as the timer passes 4.0s
61–75Query analytics runs, and its spinner closes into a check beside 1.4s
80–103Run SQL, 2.3s on the timer
108–120Search logs, 1.1s
125–157Read 12 sources, 3.2s; five source chips and a +7 chip pop in at 129–148
165–178The heading streams in body style, then takes heading style when its line completes at 170
177–257The paragraph with its citations, then three bullets; the column starts gliding up at 201
262–275The code panel opens on its fence and four lines stream inside
280–294The fix line lands, and the run ends at 294 with the timer at 27.7s
294–310The header spinner closes into a check and the last chunk finishes fading; the column has glided 279px up
310–355The docs preview holds the finished answer

The answer arrives in chunks of 1–6 tokens that land on whole frames, 1–4 frames apart. Now and then a pause adds 4–7 more frames, and each new markdown block starts on a fresh chunk after a 2–4 frame beat. Each chunk fades in over 5 frames. So the text comes in bursts, never at a constant rate per character. seed changes the rhythm but not the content.

Every line's position is fixed in advance, and content only grows at the bottom. The column follows it with overlapping smoothstep glides of 24 frames, each starting 16 frames before its content arrives. A glide is three quarters done when its line lands, so a burst of new lines lands in view and nothing jumps.

compression sets how many real seconds pass per video second. A tool call lasts duration / compression on screen, clamped to 12–120 frames. The timer always advances by the step's real duration, so the rows and the header agree. agentRunLength is 310, the component's own motion for the default run. getAgentRunDuration(run, { seed, compression, speed }) adds a 45-frame hold and scales the motion by speed.

Props
PropTypeDefaultDescription
run
AgentRunScriptdefaultAgentRunThe prompt, plan, tool steps and markdown answer; see the tables below
theme
"light" | "dark""light"Neutral panel theme
accentColor
string"#2563eb"The one accent, used for running spinners and citation chips; any CSS color
compression
number3Real seconds per video second, clamped to 0.25–20; tool calls last duration / compression on screen, clamped to 12–120 frames
seed
number1Seeds the chunk sizes, intervals and pauses of the plan and answer streams
speed
number1Playback multiplier; 0 freezes the first frame
className
string—Optional class name on the full-frame root
AgentRunScript
PropTypeDefaultDescription
title
string—Thread title in the panel header
prompt
string—The message the user sent, shown as the bubble
plan
string[]—Two or three short plan lines that stream under Thinking
steps
AgentRunStep[]—Tool calls, run one after another
answer
string—Markdown answer with # and ## headings, paragraphs, - bullets, bold, inline code, [n] citations and fenced code
AgentRunStep
PropTypeDefaultDescription
name
string—Tool name, such as Run SQL
detail
string—Short argument shown muted after the name
duration
number—Real seconds; the timer advances by exactly this much during the step
icon
"chart" | "database" | "search" | "book" | "globe" | "terminal" | "file""book" with sources, else "terminal"Lucide icon for the row
sources
string[]—Source labels; chips pop in during the step and the rest collapse into a +N chip