From 2e48fb91c4d4d554deb3e8ce5bfd1f334970236d Mon Sep 17 00:00:00 2001 From: Nicholas Kissel Date: Sat, 20 Jun 2026 16:43:10 -0700 Subject: [PATCH 1/2] Add Agent OS homepage diagrams: harness architecture + cold-start comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two native React + inline SVG + Tailwind + framer-motion visuals on the Agent OS homepage, themed to the site palette: - HarnessArchitecture: a cross diagram framed as Agent OS — a cycling agent logo at the center routes requests/responses to Tools, Session, Sandbox, and Orchestration with animated flow dots; collapses to a stacked layout on mobile. - ColdStartRace: a containers-vs-Agent OS cold-start comparison. Each container boots on its own (red→green + mini bar) carrying its own ~1 GB; Agent OS packs all agents into one shared process at ~131 MB each. Includes live ms counters, a speed slider to control playback, and a stats row (92x faster, 8x less memory, 32x cheaper) sourced from bench.ts. Also bundles pre-existing in-progress site changes from this workspace: Navigation, Footer, registry (RegistryPageClient, registry.ts, registry-icons.ts, registry/[slug].astro), pricing page, and favicon. Co-Authored-By: Claude Opus 4.8 --- website/.astro/content-modules.mjs | 2 +- website/public/favicon.svg | 36 ++- website/src/components/Footer.tsx | 29 +- website/src/components/Navigation.tsx | 22 +- .../marketing/diagrams/ColdStartRace.tsx | 265 +++++++++++++++++ .../diagrams/HarnessArchitecture.tsx | 276 ++++++++++++++++++ .../marketing/registry/RegistryPageClient.tsx | 5 +- .../marketing/solutions/AgentOSPage.tsx | 61 +++- .../solutions/AgentOSPricingPage.tsx | 2 +- website/src/data/registry-icons.ts | 15 + website/src/data/registry.ts | 19 +- website/src/pages/registry/[slug].astro | 3 +- 12 files changed, 686 insertions(+), 49 deletions(-) create mode 100644 website/src/components/marketing/diagrams/ColdStartRace.tsx create mode 100644 website/src/components/marketing/diagrams/HarnessArchitecture.tsx create mode 100644 website/src/data/registry-icons.ts diff --git a/website/.astro/content-modules.mjs b/website/.astro/content-modules.mjs index 0efe088f7..e070527f8 100644 --- a/website/.astro/content-modules.mjs +++ b/website/.astro/content-modules.mjs @@ -2,8 +2,8 @@ export default new Map([ ["src/content/docs/docs/agent-to-agent.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagent-to-agent.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/authentication.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fauthentication.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/benchmarks.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fbenchmarks.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/configuration.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fconfiguration.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/benchmarks.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fbenchmarks.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/core.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcore.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/crash-course.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcrash-course.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/cron.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcron.mdx&astroContentModuleFlag=true")], diff --git a/website/public/favicon.svg b/website/public/favicon.svg index d7119e885..33655f670 100644 --- a/website/public/favicon.svg +++ b/website/public/favicon.svg @@ -1,8 +1,30 @@ - - - - - - - + + + + + + + + + + + + + + + + + + OS + + + + diff --git a/website/src/components/Footer.tsx b/website/src/components/Footer.tsx index 3f48ff37c..93b459816 100644 --- a/website/src/components/Footer.tsx +++ b/website/src/components/Footer.tsx @@ -1,7 +1,6 @@ "use client"; import { motion } from "framer-motion"; -import { MessageCircle } from "lucide-react"; const footer = { product: [ @@ -14,16 +13,15 @@ const footer = { { name: "Changelog", href: "https://github.com/rivet-dev/agent-os/releases" }, { name: "GitHub", href: "https://github.com/rivet-dev/agent-os" }, ], - legal: [ - { name: "Terms", href: "https://rivet.dev/terms" }, - { name: "Privacy Policy", href: "https://rivet.dev/privacy" }, - { name: "Acceptable Use", href: "https://rivet.dev/acceptable-use" }, - ], social: [ { name: "Discord", href: "https://rivet.dev/discord", - icon: , + icon: ( + + + + ), }, { name: "GitHub", @@ -59,7 +57,7 @@ export function Footer() { className="space-y-6 xl:col-span-4" > - Agent OS + Agent OS

A portable open-source operating system for agents.

@@ -78,7 +76,7 @@ export function Footer() {
-
+

Product

    @@ -104,19 +102,6 @@ export function Footer() { ))}
- - -

Legal

- -
diff --git a/website/src/components/Navigation.tsx b/website/src/components/Navigation.tsx index e9ea9f03c..6d48e8fdb 100644 --- a/website/src/components/Navigation.tsx +++ b/website/src/components/Navigation.tsx @@ -1,9 +1,23 @@ "use client"; import { useState, useEffect } from "react"; -import { Menu, X, MessageCircle } from "lucide-react"; +import { Menu, X } from "lucide-react"; import { GitHubStars } from "./GitHubStars"; +function DiscordIcon({ className }: { className?: string }) { + return ( + + ); +} + const NAV_LINKS = [ { href: "/use-cases", label: "Use Cases" }, { href: "/pricing", label: "Pricing" }, @@ -53,7 +67,7 @@ export function Navigation() {
Agent OS @@ -74,7 +88,7 @@ export function Navigation() { className="inline-flex h-10 items-center justify-center whitespace-nowrap rounded-md border border-ink/15 px-4 py-2 text-sm text-ink-soft transition-colors hover:border-ink/30 hover:text-ink" aria-label="Discord" > - + setMobileMenuOpen(false)} aria-label="Discord" > - + Discord green + mini bar) and carries its own ~1 GB of memory. +// Agent OS — every agent is packed into ONE shared process: a single box +// that boots once and shares memory, ~131 MB per agent. +// The contrast (four separate boots vs one grouped boot) is the point. Numbers +// come from bench.ts so they stay accurate. +// --------------------------------------------------------------------------- + +const AGENTOS_MARK = '/images/agent-os/agentos-logo-ink.svg'; +const AGENT_LOGOS = [ + '/images/agent-logos/pi.svg', + '/images/agent-logos/claude-code.svg', + '/images/agent-logos/codex.svg', + '/images/agent-logos/opencode.svg', + '/images/agent-logos/amp.svg', +]; +const agentAt = (i: number) => AGENT_LOGOS[(i * 7) % AGENT_LOGOS.length]; + +const RED = '#d6453a'; +const GREEN = '#3f9a59'; +const BORDER_RED = 'rgba(214,69,58,0.6)'; +const BORDER_GREEN = 'rgba(63,154,89,0.65)'; + +// ---- Sourced numbers ------------------------------------------------------- +const cold = benchColdStart[0]; // p50 +const AOS_MS = Math.round(cold.agentOS); // ~5 ms +const CONTAINER_MS = cold.sandbox; // ~440 ms +const SPEEDUP = Math.round(cold.sandbox / cold.agentOS); // ~92x +const mem = benchWorkloads.agent.memory; // { agentOS:"~131 MB", sandbox:"~1024 MB", multiplier:"8x smaller" } +const cost = benchWorkloads.agent.cost[0]; // AWS ARM { ratio, multiplier } +const MEM_X = mem.multiplier.split('x')[0]; // "8" +const CONTAINER_MEM = '~1 GB'; // ~1024 MB sandbox baseline, rounded for the chip +const AOS_MEM = mem.agentOS; // "~131 MB" + +// ---- Animation timing ------------------------------------------------------ +const BOOT_SEC = 2.7; // base animation seconds for the container boot (speed-adjustable) +const AOS_DONE = 0.04; // fraction of the timeline at which Agent OS is finished +// The speed slider maps to a playback-rate multiplier on the looping boot. +const speedFromSlider = (s: number) => 0.2 * Math.pow(30, s / 100); // 0.2x .. 6x +const slowdownLabel = (speed: number) => { + const factor = (BOOT_SEC * 1000) / CONTAINER_MS / speed; // ~6 / speed + return factor < 1.4 ? 'real time' : `slowed ~${Math.round(factor)}×`; +}; + +// A dashed grey box showing a memory figure. +const MemBox = ({ value, sub }: { value: string; sub: string }) => ( + + {value} + {sub} + +); + +const MiniBar = ({ width, color }: { width: MotionValue; color: MotionValue }) => ( +
+ +
+); + +// One container: its own agent + its own memory, booting on its own. +const ContainerBox = ({ progress, lo, hi, logo }: { progress: MotionValue; lo: number; hi: number; logo: string }) => { + const border = useTransform(progress, [lo, hi], [BORDER_RED, BORDER_GREEN]); + const barWidth = useTransform(progress, [lo, hi], ['14%', '100%']); + const barColor = useTransform(progress, [lo, hi], [RED, GREEN]); + return ( +
+ + + + + +
+ ); +}; + +// Agent OS: all agents packed inside ONE process box that boots once. +const SharedProcessBox = ({ progress, count }: { progress: MotionValue; count: number }) => { + const border = useTransform(progress, [0, AOS_DONE], [BORDER_RED, BORDER_GREEN]); + const barWidth = useTransform(progress, [0, AOS_DONE], ['14%', '100%']); + const barColor = useTransform(progress, [0, AOS_DONE], [RED, GREEN]); + return ( +
+ +
+ {Array.from({ length: count }).map((_, i) => ( + + + + ))} + +
+
+ +
+ ); +}; + +type HostCfg = { + name: ReactNode; + finalMs: number; + doneAt: number; + units: number; + grouped: boolean; // Agent OS packs all agents into one process box + accent: boolean; + badge?: ReactNode; +}; + +const Host = ({ cfg, progress }: { cfg: HostCfg; progress: MotionValue }) => { + const counter = useTransform(progress, (p) => `~${Math.round(Math.min(1, p / cfg.doneAt) * cfg.finalMs)} ms`); + const checkOpacity = useTransform(progress, [0, cfg.doneAt * 0.95, cfg.doneAt], [0, 0, 1]); + return ( +
+
+ {cfg.name} +
+ {cfg.badge} + + {counter} +
+
+ {cfg.grouped ? ( + + ) : ( +
+ {Array.from({ length: cfg.units }).map((_, i) => { + const lo = (i / cfg.units) * 0.08; + return ; + })} +
+ )} +
+ ); +}; + +const Stat = ({ value, label, sub }: { value: string; label: string; sub: string }) => ( +
+
{value}
+
{label}
+
{sub}
+
+); + +export const ColdStartRace = () => { + const reduced = useReducedMotion(); + const ref = useRef(null); + const inView = useInView(ref, { once: true, margin: '-15% 0px' }); + const progress = useMotionValue(0); + const [slider, setSlider] = useState(50); + const speed = speedFromSlider(slider); + const speedRef = useRef(speed); + speedRef.current = speed; + const controlsRef = useRef(null); + + // Create the looping boot once it scrolls into view; speed is adjusted live. + useEffect(() => { + if (reduced) { + progress.set(1); + return; + } + if (!inView) return; + const controls = animate(progress, [0, 1], { duration: BOOT_SEC, ease: 'easeInOut', repeat: Infinity, repeatDelay: 0.9 }); + controls.speed = speedRef.current; + controlsRef.current = controls; + return () => controls.stop(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [inView, reduced]); + + useEffect(() => { + if (controlsRef.current) controlsRef.current.speed = speed; + }, [speed]); + + return ( +
+ +
+
+ Cold start · spinning up agents +
+ Slow + setSlider(Number(e.target.value))} + aria-label='Animation playback speed' + className='h-1.5 w-28 cursor-pointer accent-accent' + /> + Fast + {slowdownLabel(speed)} +
+
+ +
+ +
+ +

+ Same host, same memory. Each container is its own process with its own ~1 GB; Agent OS packs every agent into one shared process at {AOS_MEM} each ({MEM_X}× less memory). Real cold start: ~{AOS_MS} ms vs ~{CONTAINER_MS} ms ({SPEEDUP}× faster) — drag the slider to set playback speed. +

+
+
+ + + + + + +
+ ); +}; diff --git a/website/src/components/marketing/diagrams/HarnessArchitecture.tsx b/website/src/components/marketing/diagrams/HarnessArchitecture.tsx new file mode 100644 index 000000000..88f20a163 --- /dev/null +++ b/website/src/components/marketing/diagrams/HarnessArchitecture.tsx @@ -0,0 +1,276 @@ +'use client'; + +import { AnimatePresence, motion, useReducedMotion } from 'framer-motion'; +import { useEffect, useState } from 'react'; +import type { ReactNode } from 'react'; +import { Briefcase, ListChecks, SquareTerminal, Workflow } from 'lucide-react'; +import { EASE, VIEWPORT } from '../motion'; + +// --------------------------------------------------------------------------- +// Harness architecture diagram. A plus/cross layout branded as Agent OS: the +// running agent sits at the center (cycling through every supported agent) and +// the harness brokers bidirectional request/response traffic out to Tools, +// Session, Sandbox, and Orchestration. Flow dots animate along the arrows to +// show that everything routes through Agent OS. +// --------------------------------------------------------------------------- + +const ARROW_COLOR = '#8A8478'; // ink-faint +const ACCENT = '#CB5A33'; +const AGENTOS_MARK = '/images/agent-os/agentos-logo-ink.svg'; + +const AGENT_LOGOS = [ + { src: '/images/agent-logos/pi.svg', name: 'Pi' }, + { src: '/images/agent-logos/claude-code.svg', name: 'Claude Code' }, + { src: '/images/agent-logos/codex.svg', name: 'Codex' }, + { src: '/images/agent-logos/opencode.svg', name: 'OpenCode' }, + { src: '/images/agent-logos/amp.svg', name: 'Amp' }, +]; + +// The center node: cross-fades through every supported agent logo, conveying +// that any agent plugs into the harness. +const CyclingAgentLogo = ({ size }: { size: string }) => { + const reduced = useReducedMotion(); + const [i, setI] = useState(0); + useEffect(() => { + if (reduced) return; + const id = setInterval(() => setI((p) => (p + 1) % AGENT_LOGOS.length), 1900); + return () => clearInterval(id); + }, [reduced]); + const a = AGENT_LOGOS[i]; + return ( +
+ + + +
+ ); +}; + +// A single diagram card: a header strip with the title and a body with one icon. +const DiagramCard = ({ + title, + subtitle, + icon, + accent, +}: { + title: string; + subtitle?: string; + icon: ReactNode; + accent?: boolean; +}) => ( +
+
+
+ {title} +
+ {subtitle ?
{subtitle}
: null} +
+
{icon}
+
+); + +const SATELLITES = { + tools: { title: 'Tools', subtitle: '+ Resources / MCP', icon:
+ {/* Containers vs Isolate density comparison */} + +

+ Booting an agent in a container takes a full process and hundreds of milliseconds. Agent OS starts one in a lightweight isolate in about {Math.round(benchColdStart[0].agentOS)} ms — and packs far more into the same memory. +

+ +
+ {/* Benchmarks */} @@ -1959,6 +1975,34 @@ const TechnologyAndBenchmarks = () => ( ); +const HarnessSection = () => ( +
+
+ +

+ Everything routes through the harness. +

+

+ The harness is the kernel of every agent session — brokering requests and responses between your tools and MCP resources, session state, the sandbox where code runs, and the orchestration layer that ties agents together. Each piece stays isolated, yet composable. +

+
+ + + +
+
+); + // --- Before/After Slider --- const BeforeAfterSlider = ({ before, after }: { before: string; after: string }) => { const containerRef = useRef(null); @@ -2030,6 +2074,18 @@ const SisterProducts = () => { href: 'https://sandboxagent.dev/', cta: 'sandboxagent.dev', }, + { + name: 'Rivet Actors', + tagline: 'Durable, stateful serverless for agents and realtime apps.', + bullets: [ + 'Long-lived, in-memory state — no external database', + 'Built-in persistence, realtime, and workflow orchestration', + 'Deploy Agent OS sessions as durable actors', + 'Geo-distributed at the edge; scale to zero', + ], + href: 'https://rivet.dev/', + cta: 'rivet.dev', + }, ]; return ( @@ -2052,11 +2108,11 @@ const SisterProducts = () => { transition={{ duration: 0.5, delay: 0.1 }} className='text-base leading-relaxed text-ink-soft md:text-lg' > - Agent OS is where agents live. Secure Exec is how you safely run the code they generate. Sandbox Agent SDK is how you control coding agents over HTTP. + Agent OS is where agents live. Secure Exec is how you safely run the code they generate. Sandbox Agent SDK is how you control coding agents over HTTP. Rivet Actors is how you deploy and scale them as durable, stateful services. -
+
{products.map((product, idx) => ( + diff --git a/website/src/components/marketing/solutions/AgentOSPricingPage.tsx b/website/src/components/marketing/solutions/AgentOSPricingPage.tsx index 10bf6f2f8..70e555566 100644 --- a/website/src/components/marketing/solutions/AgentOSPricingPage.tsx +++ b/website/src/components/marketing/solutions/AgentOSPricingPage.tsx @@ -157,7 +157,7 @@ const CTASection = () => ( href='/docs' className='inline-flex items-center gap-2 rounded-md bg-accent-deep px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent' > - Start for Free + Get Started = { + HardDrive, + Database, + Monitor, +}; diff --git a/website/src/data/registry.ts b/website/src/data/registry.ts index 0b01eab14..60dd22e7d 100644 --- a/website/src/data/registry.ts +++ b/website/src/data/registry.ts @@ -1,5 +1,4 @@ -import type { LucideIcon } from "lucide-react"; -import { HardDrive, Database, Monitor } from "lucide-react"; +import type { RegistryIconName } from "./registry-icons"; export interface RegistryEntryBase { slug: string; @@ -7,8 +6,10 @@ export interface RegistryEntryBase { description: string; types: ("file-system" | "tool" | "agent" | "sandbox-extension" | "software")[]; featured?: boolean; - // Lucide icon component, used when no `image` is provided. - icon?: LucideIcon; + // Lucide icon name, resolved via REGISTRY_ICONS. Used when no `image` is + // provided. Must be a serializable string so it survives the Astro island + // prop boundary. + icon?: RegistryIconName; image?: string; } @@ -240,7 +241,7 @@ export const registry: RegistryEntry[] = [ description: "Mount and manage virtual filesystems with support for S3, local, and overlay drivers.", types: ["file-system"], - icon: HardDrive, + icon: "HardDrive", }, { slug: "s3", @@ -260,7 +261,7 @@ export const registry: RegistryEntry[] = [ description: "Mount a SQLite-backed virtual filesystem for persistent, queryable storage.", types: ["file-system"], - icon: Database, + icon: "Database", }, { slug: "postgres", @@ -269,7 +270,7 @@ export const registry: RegistryEntry[] = [ description: "Mount a Postgres-backed filesystem for shared, durable storage across agents.", types: ["file-system"], - icon: Database, + icon: "Database", }, { slug: "google-drive", @@ -292,7 +293,7 @@ export const registry: RegistryEntry[] = [ description: "Mount a sandbox filesystem and expose process management tools. Works with any Sandbox Agent provider.", types: ["tool", "file-system"], - icon: Monitor, + icon: "Monitor", }, { slug: "browserbase", @@ -313,7 +314,7 @@ export const registry: RegistryEntry[] = [ description: "Run sandboxes directly on the local machine for development and testing.", types: ["sandbox-extension"], - icon: Monitor, + icon: "Monitor", }, { slug: "docker", diff --git a/website/src/pages/registry/[slug].astro b/website/src/pages/registry/[slug].astro index c3dec9f98..b56c2bd2b 100644 --- a/website/src/pages/registry/[slug].astro +++ b/website/src/pages/registry/[slug].astro @@ -3,6 +3,7 @@ import Layout from "../../layouts/Layout.astro"; import { Navigation } from "../../components/Navigation"; import { Footer } from "../../components/Footer"; import { registry } from "../../data/registry"; +import { REGISTRY_ICONS } from "../../data/registry-icons"; import { InkChip } from "../../components/marketing/editorial/InkPanel"; export function getStaticPaths() { @@ -24,7 +25,7 @@ const TYPE_LABELS: Record = { const isComingSoon = entry.status === "coming-soon"; const installCmd = !isComingSoon ? `npm install ${entry.package}` : null; -const EntryIcon = entry.icon; +const EntryIcon = entry.icon ? REGISTRY_ICONS[entry.icon] : undefined; --- Date: Sun, 21 Jun 2026 00:35:26 -0700 Subject: [PATCH 2/2] Homepage: animated performance benchmarks + architecture copy fixes Replace the static benchmark cards with three animated, light-styled diagrams (cold-start race with p50/p95/p99 toggle, memory-overhead squares, execution-density packing), extract shared benchUI primitives (BenchToggle/CountUpStat/BenchInfoTooltip), add per-tier execs/costPerHour to bench.ts, link hero stats to their diagrams, and fix the info tooltips and the agentOS boot timing. Correct the architecture framing to match the product: an OS for all AI agents and arbitrary code, many lightweight in-process VMs packed into one process on an in-process kernel. Also bundles related in-progress homepage edits (navigation, footer, registry, pricing, use-cases, config). Co-Authored-By: Claude Opus 4.8 --- website/.astro/content-modules.mjs | 20 +- website/astro.config.mjs | 2 +- website/docs.config.mjs | 4 +- website/src/components/Footer.tsx | 4 +- website/src/components/Navigation.tsx | 25 +- .../marketing/diagrams/ColdStartRace.tsx | 260 ++++---- .../marketing/diagrams/ExecutionDensity.tsx | 222 +++++++ .../diagrams/HarnessArchitecture.tsx | 11 +- .../marketing/diagrams/MemoryOverhead.tsx | 144 +++++ .../components/marketing/diagrams/benchUI.tsx | 151 +++++ .../marketing/registry/RegistryPageClient.tsx | 2 +- .../marketing/solutions/AgentOSPage.tsx | 567 +++++++----------- .../solutions/AgentOSPricingPage.tsx | 8 +- .../solutions/AgentOSUseCasesPage.tsx | 4 +- website/src/data/bench.ts | 16 +- website/src/data/faqs/agent-os-pricing.ts | 10 +- website/src/data/registry.ts | 8 +- website/src/layouts/Layout.astro | 4 +- website/src/pages/index.astro | 6 +- website/src/pages/pricing.astro | 4 +- website/src/pages/registry/index.astro | 8 +- website/src/pages/use-cases.astro | 4 +- website/src/styles/global.css | 2 +- 23 files changed, 947 insertions(+), 539 deletions(-) create mode 100644 website/src/components/marketing/diagrams/ExecutionDensity.tsx create mode 100644 website/src/components/marketing/diagrams/MemoryOverhead.tsx create mode 100644 website/src/components/marketing/diagrams/benchUI.tsx diff --git a/website/.astro/content-modules.mjs b/website/.astro/content-modules.mjs index e070527f8..f29c754ec 100644 --- a/website/.astro/content-modules.mjs +++ b/website/.astro/content-modules.mjs @@ -1,15 +1,15 @@ export default new Map([ -["src/content/docs/docs/agent-to-agent.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagent-to-agent.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/authentication.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fauthentication.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/configuration.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fconfiguration.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/agent-to-agent.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagent-to-agent.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/benchmarks.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fbenchmarks.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/core.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcore.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/crash-course.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcrash-course.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/cron.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcron.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/deployment.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fdeployment.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/cron.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcron.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/crash-course.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcrash-course.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/events.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fevents.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/filesystem.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Ffilesystem.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/core.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fcore.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Findex.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/limitations.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Flimitations.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/llm-credentials.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fllm-credentials.mdx&astroContentModuleFlag=true")], @@ -18,23 +18,23 @@ export default new Map([ ["src/content/docs/docs/networking.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fnetworking.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/permissions.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fpermissions.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/persistence.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fpersistence.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/processes.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fprocesses.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/queues.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fqueues.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/processes.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fprocesses.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/quickstart.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fquickstart.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/sandbox.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsandbox.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/security-model.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsecurity-model.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/security.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsecurity.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/sessions.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsessions.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/software.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsoftware.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/sqlite.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsqlite.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/system-prompt.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsystem-prompt.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/tools.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Ftools.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/sessions.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fsessions.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/versus-sandbox.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fversus-sandbox.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/webhooks.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fwebhooks.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/workflows.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fworkflows.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/agents/amp.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Famp.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/agents/claude.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fclaude.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/agents/codex.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fcodex.mdx&astroContentModuleFlag=true")], ["src/content/docs/docs/agents/opencode.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fopencode.mdx&astroContentModuleFlag=true")], -["src/content/docs/docs/agents/pi.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fpi.mdx&astroContentModuleFlag=true")]]); +["src/content/docs/docs/agents/codex.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fcodex.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/agents/pi.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fpi.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/agents/amp.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Famp.mdx&astroContentModuleFlag=true")], +["src/content/docs/docs/agents/claude.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdocs%2Fagents%2Fclaude.mdx&astroContentModuleFlag=true")]]); \ No newline at end of file diff --git a/website/astro.config.mjs b/website/astro.config.mjs index b4772a49e..8b8f3d93c 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -18,7 +18,7 @@ export default defineConfig({ tailwind({ applyBaseStyles: false }), // The shared Rivet docs theme — wraps Starlight entirely. All docs // branding/chrome lives in @rivet-dev/docs-theme; docs.config.mjs maps - // Agent OS's identity, nav, and pages onto it. + // agentOS's identity, nav, and pages onto it. ...docsTheme(starlight, siteConfig), sitemap(), ], diff --git a/website/docs.config.mjs b/website/docs.config.mjs index a65753cc9..57ffa43f8 100644 --- a/website/docs.config.mjs +++ b/website/docs.config.mjs @@ -1,5 +1,5 @@ /** - * Agent OS docs configuration — the only non-content surface consumed by + * agentOS docs configuration — the only non-content surface consumed by * @rivet-dev/docs-theme. Everything visual (theme, header chrome, sidebar * icons, code blocks) lives in the package; this file maps agentOS's product * identity, navigation, and pages onto it. @@ -11,7 +11,7 @@ * @type {import('@rivet-dev/docs-theme').SiteConfig} */ export const siteConfig = { - product: "Agent OS", + product: "agentOS", productLogo: "/images/agent-os/agentos-hero-logo.svg", productHome: "/", favicon: "/favicon.svg", diff --git a/website/src/components/Footer.tsx b/website/src/components/Footer.tsx index 93b459816..cf3dff338 100644 --- a/website/src/components/Footer.tsx +++ b/website/src/components/Footer.tsx @@ -57,7 +57,7 @@ export function Footer() { className="space-y-6 xl:col-span-4" > - Agent OS + agentOS

A portable open-source operating system for agents.

@@ -112,7 +112,7 @@ export function Footer() { transition={{ duration: 0.5, delay: 0.3 }} className="mt-12 border-t border-ink/10 pt-8" > -

© {new Date().getFullYear()} Agent OS. Apache 2.0 licensed.

+

© {new Date().getFullYear()} agentOS. Apache 2.0 licensed.

diff --git a/website/src/components/Navigation.tsx b/website/src/components/Navigation.tsx index 6d48e8fdb..318fdc6b0 100644 --- a/website/src/components/Navigation.tsx +++ b/website/src/components/Navigation.tsx @@ -3,6 +3,7 @@ import { useState, useEffect } from "react"; import { Menu, X } from "lucide-react"; import { GitHubStars } from "./GitHubStars"; +import { registry } from "../data/registry"; function DiscordIcon({ className }: { className?: string }) { return ( @@ -18,20 +19,29 @@ function DiscordIcon({ className }: { className?: string }) { ); } -const NAV_LINKS = [ +const NAV_LINKS: { href: string; label: string; badge?: number }[] = [ { href: "/use-cases", label: "Use Cases" }, { href: "/pricing", label: "Pricing" }, - { href: "/registry", label: "Registry" }, + { href: "/registry", label: "Registry", badge: registry.length }, { href: "/docs", label: "Docs" }, ]; -function NavItem({ href, children }: { href: string; children: React.ReactNode }) { +function NavBadge({ count }: { count: number }) { + return ( + + {count} + + ); +} + +function NavItem({ href, children, badge }: { href: string; children: React.ReactNode; badge?: number }) { return ( {children} + {badge != null && } ); } @@ -68,14 +78,14 @@ export function Navigation() { Agent OS
{NAV_LINKS.map((link) => ( - + {link.label} ))} @@ -114,10 +124,11 @@ export function Navigation() { setMobileMenuOpen(false)} > {link.label} + {link.badge != null && } ))}
diff --git a/website/src/components/marketing/diagrams/ColdStartRace.tsx b/website/src/components/marketing/diagrams/ColdStartRace.tsx index eae5e3fb6..c147d6cf2 100644 --- a/website/src/components/marketing/diagrams/ColdStartRace.tsx +++ b/website/src/components/marketing/diagrams/ColdStartRace.tsx @@ -1,21 +1,23 @@ 'use client'; import { animate, motion, useInView, useMotionValue, useTransform, useReducedMotion } from 'framer-motion'; -import type { AnimationPlaybackControls, MotionValue } from 'framer-motion'; +import type { MotionValue } from 'framer-motion'; import { useEffect, useRef, useState } from 'react'; import type { ReactNode } from 'react'; import { Box, Check } from 'lucide-react'; -import { EASE, VIEWPORT, Reveal } from '../motion'; -import { benchColdStart, benchWorkloads } from '../../../data/bench'; +import { Reveal } from '../motion'; +import { BenchToggle, BenchInfoTooltip } from './benchUI'; +import { benchColdStart, SANDBOX_COLDSTART_PROVIDER, BENCHMARK_DATE } from '../../../data/bench'; // --------------------------------------------------------------------------- // Cold-start comparison. Two hosts spin up agents, once, when scrolled into view. // Containers — each agent gets its own process: a separate box that boots on -// its own (border red -> green + mini bar) and carries its own ~1 GB of memory. -// Agent OS — every agent is packed into ONE shared process: a single box -// that boots once and shares memory, ~131 MB per agent. -// The contrast (four separate boots vs one grouped boot) is the point. Numbers -// come from bench.ts so they stay accurate. +// its own (border red -> green + mini bar). +// agentOS — every agent is packed into ONE shared process: a single box +// that boots once. +// The contrast (four separate boots vs one grouped boot) is the point. The +// container boot is shown slowed ~6x so the wait is visible. Numbers come from +// bench.ts so they stay accurate. // --------------------------------------------------------------------------- const AGENTOS_MARK = '/images/agent-os/agentos-logo-ink.svg'; @@ -33,34 +35,25 @@ const GREEN = '#3f9a59'; const BORDER_RED = 'rgba(214,69,58,0.6)'; const BORDER_GREEN = 'rgba(63,154,89,0.65)'; -// ---- Sourced numbers ------------------------------------------------------- -const cold = benchColdStart[0]; // p50 -const AOS_MS = Math.round(cold.agentOS); // ~5 ms -const CONTAINER_MS = cold.sandbox; // ~440 ms -const SPEEDUP = Math.round(cold.sandbox / cold.agentOS); // ~92x -const mem = benchWorkloads.agent.memory; // { agentOS:"~131 MB", sandbox:"~1024 MB", multiplier:"8x smaller" } -const cost = benchWorkloads.agent.cost[0]; // AWS ARM { ratio, multiplier } -const MEM_X = mem.multiplier.split('x')[0]; // "8" -const CONTAINER_MEM = '~1 GB'; // ~1024 MB sandbox baseline, rounded for the chip -const AOS_MEM = mem.agentOS; // "~131 MB" - // ---- Animation timing ------------------------------------------------------ -const BOOT_SEC = 2.7; // base animation seconds for the container boot (speed-adjustable) -const AOS_DONE = 0.04; // fraction of the timeline at which Agent OS is finished -// The speed slider maps to a playback-rate multiplier on the looping boot. -const speedFromSlider = (s: number) => 0.2 * Math.pow(30, s / 100); // 0.2x .. 6x -const slowdownLabel = (speed: number) => { - const factor = (BOOT_SEC * 1000) / CONTAINER_MS / speed; // ~6 / speed - return factor < 1.4 ? 'real time' : `slowed ~${Math.round(factor)}×`; +// The boot is scaled to each percentile's REAL container cold start, always +// slowed 6x — so p99 crawls ~6x longer than p50, in true proportion. +const SLOWDOWN = 6; +// agentOS boots near-instantly, so its box snaps done in a fixed, snappy time — +// independent of the container's 6x slowdown. It must never appear to "wait". +const AOS_BOOT_SEC = 0.5; +const bootDuration = (containerMs: number) => (containerMs / 1000) * SLOWDOWN; +const slowdownFactor = (containerMs: number) => (bootDuration(containerMs) * 1000) / containerMs; +const slowdownLabel = (containerMs: number) => { + const factor = slowdownFactor(containerMs); + return factor < 1.4 ? 'in real time' : `slowed ~${Math.round(factor)}×`; +}; +// Pill copy for the containers row. Phrased as a playback note so it reads as a +// display speed, not a perf claim that would clash with agentOS's "Nx faster". +const slowdownPill = (containerMs: number) => { + const factor = slowdownFactor(containerMs); + return factor < 1.4 ? 'shown in real time' : `shown ~${Math.round(factor)}× slower`; }; - -// A dashed grey box showing a memory figure. -const MemBox = ({ value, sub }: { value: string; sub: string }) => ( - - {value} - {sub} - -); const MiniBar = ({ width, color }: { width: MotionValue; color: MotionValue }) => (
@@ -68,30 +61,29 @@ const MiniBar = ({ width, color }: { width: MotionValue; color: MotionVa
); -// One container: its own agent + its own memory, booting on its own. +// One container: its own agent, booting on its own. const ContainerBox = ({ progress, lo, hi, logo }: { progress: MotionValue; lo: number; hi: number; logo: string }) => { const border = useTransform(progress, [lo, hi], [BORDER_RED, BORDER_GREEN]); const barWidth = useTransform(progress, [lo, hi], ['14%', '100%']); const barColor = useTransform(progress, [lo, hi], [RED, GREEN]); return ( -
+
-
); }; -// Agent OS: all agents packed inside ONE process box that boots once. -const SharedProcessBox = ({ progress, count }: { progress: MotionValue; count: number }) => { - const border = useTransform(progress, [0, AOS_DONE], [BORDER_RED, BORDER_GREEN]); - const barWidth = useTransform(progress, [0, AOS_DONE], ['14%', '100%']); - const barColor = useTransform(progress, [0, AOS_DONE], [RED, GREEN]); +// agentOS: all agents packed inside ONE process box that boots once. +const SharedProcessBox = ({ progress, count, doneAt }: { progress: MotionValue; count: number; doneAt: number }) => { + const border = useTransform(progress, [0, doneAt], [BORDER_RED, BORDER_GREEN]); + const barWidth = useTransform(progress, [0, doneAt], ['14%', '100%']); + const barColor = useTransform(progress, [0, doneAt], [RED, GREEN]); return (
@@ -101,7 +93,6 @@ const SharedProcessBox = ({ progress, count }: { progress: MotionValue; ))} -
@@ -114,7 +105,7 @@ type HostCfg = { finalMs: number; doneAt: number; units: number; - grouped: boolean; // Agent OS packs all agents into one process box + grouped: boolean; // agentOS packs all agents into one process box accent: boolean; badge?: ReactNode; }; @@ -125,7 +116,7 @@ const Host = ({ cfg, progress }: { cfg: HostCfg; progress: MotionValue } return (
- {cfg.name} + {cfg.name}
{cfg.badge}
{cfg.grouped ? ( - + ) : (
{Array.from({ length: cfg.units }).map((_, i) => { @@ -148,118 +139,103 @@ const Host = ({ cfg, progress }: { cfg: HostCfg; progress: MotionValue } ); }; -const Stat = ({ value, label, sub }: { value: string; label: string; sub: string }) => ( -
-
{value}
-
{label}
-
{sub}
-
-); - export const ColdStartRace = () => { const reduced = useReducedMotion(); const ref = useRef(null); const inView = useInView(ref, { once: true, margin: '-15% 0px' }); - const progress = useMotionValue(0); - const [slider, setSlider] = useState(50); - const speed = speedFromSlider(slider); - const speedRef = useRef(speed); - speedRef.current = speed; - const controlsRef = useRef(null); - - // Create the looping boot once it scrolls into view; speed is adjusted live. + const progress = useMotionValue(0); // containers — slowed boot + const aosProgress = useMotionValue(0); // agentOS — fixed snappy boot + const [pct, setPct] = useState(0); // p50 by default + + const cold = benchColdStart[pct]; + const aosMs = Math.round(cold.agentOS); + const containerMs = cold.sandbox; + const speedup = Math.round(cold.sandbox / cold.agentOS); + const durationSec = bootDuration(containerMs); + + // Play the boot once it scrolls into view; replay when the percentile changes. + // The containers crawl over the slowed duration; agentOS snaps done in a fixed + // fast time so it never appears to scale with the container slowdown. useEffect(() => { if (reduced) { progress.set(1); + aosProgress.set(1); return; } if (!inView) return; - const controls = animate(progress, [0, 1], { duration: BOOT_SEC, ease: 'easeInOut', repeat: Infinity, repeatDelay: 0.9 }); - controls.speed = speedRef.current; - controlsRef.current = controls; - return () => controls.stop(); + progress.set(0); + aosProgress.set(0); + const c1 = animate(progress, [0, 1], { duration: durationSec, ease: 'easeInOut' }); + const c2 = animate(aosProgress, [0, 1], { duration: AOS_BOOT_SEC, ease: 'easeOut' }); + return () => { + c1.stop(); + c2.stop(); + }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [inView, reduced]); - - useEffect(() => { - if (controlsRef.current) controlsRef.current.speed = speed; - }, [speed]); + }, [inView, reduced, pct]); return ( -
- -
-
- Cold start · spinning up agents -
- Slow - setSlider(Number(e.target.value))} - aria-label='Animation playback speed' - className='h-1.5 w-28 cursor-pointer accent-accent' - /> - Fast - {slowdownLabel(speed)} -
+ +
+
+
+ Cold start + {slowdownPill(containerMs)}
- -
- -
-

- Same host, same memory. Each container is its own process with its own ~1 GB; Agent OS packs every agent into one shared process at {AOS_MEM} each ({MEM_X}× less memory). Real cold start: ~{AOS_MS} ms vs ~{CONTAINER_MS} ms ({SPEEDUP}× faster) — drag the slider to set playback speed. -

+
+ +
- - - - - - -
+

+ Each container is its own process that boots on its own; agentOS packs every agent into one shared process that boots once. Real {cold.label} cold start: ~{aosMs} ms vs ~{containerMs.toLocaleString()} ms ({speedup}× faster) — container boot shown {slowdownLabel(containerMs)}. +

+
+
); }; diff --git a/website/src/components/marketing/diagrams/ExecutionDensity.tsx b/website/src/components/marketing/diagrams/ExecutionDensity.tsx new file mode 100644 index 000000000..c53d4e605 --- /dev/null +++ b/website/src/components/marketing/diagrams/ExecutionDensity.tsx @@ -0,0 +1,222 @@ +'use client'; + +import { motion, useReducedMotion } from 'framer-motion'; +import { useEffect, useRef, useState } from 'react'; +import type { ReactNode } from 'react'; +import { Server, Container, SquareTerminal } from 'lucide-react'; +import { EASE, VIEWPORT, Reveal } from '../motion'; +import { BenchToggle, CountUpStat, BenchInfoTooltip } from './benchUI'; +import { benchWorkloads, SANDBOX_COST_PROVIDER, BENCHMARK_DATE, type WorkloadKey } from '../../../data/bench'; + +// --------------------------------------------------------------------------- +// Cost-per-execution-second, told as a density story. One server packs N +// concurrent executions (N = executions that fit per server at 70% utilization, +// from bench.ts) while a sandbox holds exactly one. The packed count is the +// denominator of the cost, so the packing animation resolves into the price: +// one $X/hr server / N executions = $Y per execution-second. +// Laid out as a full-width horizontal card. Driven by the shared workload toggle +// plus a local hardware-tier toggle. +// --------------------------------------------------------------------------- + +const WORKLOAD_KEYS = Object.keys(benchWorkloads) as WorkloadKey[]; +const AGENT_LOGOS = [ + '/images/agent-logos/pi.svg', + '/images/agent-logos/claude-code.svg', + '/images/agent-logos/codex.svg', + '/images/agent-logos/opencode.svg', + '/images/agent-logos/amp.svg', +]; +const CHIP_CAP = 48; // cap rendered chips; the rest fold into a "+N more" pill + +// Smoothly animates its own height to match its content. A ResizeObserver tracks +// the inner element's natural height (unaffected by child transforms), so when +// the packed-chip count changes the card grows/shrinks instead of jumping. The +// inner element keeps its real size — nothing is scaled — so no text distortion. +function AutoHeight({ children }: { children: ReactNode }) { + const reduced = useReducedMotion(); + const innerRef = useRef(null); + const [height, setHeight] = useState('auto'); + + useEffect(() => { + const el = innerRef.current; + if (!el) return; + const update = () => setHeight(el.offsetHeight); + update(); + const ro = new ResizeObserver(update); + ro.observe(el); + return () => ro.disconnect(); + }, []); + + return ( + +
{children}
+
+ ); +} + +export const ExecutionDensity = ({ workload, onWorkloadChange }: { workload: WorkloadKey; onWorkloadChange: (w: WorkloadKey) => void }) => { + const reduced = useReducedMotion(); + const [tierIdx, setTierIdx] = useState(0); // AWS ARM default + const [inView, setInView] = useState(false); + + const wl = benchWorkloads[workload]; + const tier = wl.cost[tierIdx]; + const execs = tier.execs; + const [mult, verb] = tier.multiplier.split(' '); // ['171x', 'cheaper'] + const shown = Math.min(execs, CHIP_CAP); + const overflow = execs - shown; + const activeIdx = WORKLOAD_KEYS.indexOf(workload); + + if (overflow > 0 && import.meta.env.DEV) { + console.info(`[ExecutionDensity] ${execs} execs (${workload}/${tier.label}); rendering ${shown} chips +${overflow} more (cap=${CHIP_CAP}).`); + } + + const chipGlyph = (i: number) => + workload === 'agent' ? ( + + ) : ( +
); -export const HarnessArchitecture = () => { +export const HarnessArchitecture = ({ footer }: { footer?: ReactNode }) => { const reduced = useReducedMotion(); return (
- Agent OS + agentOS + {footer}
); }; diff --git a/website/src/components/marketing/diagrams/MemoryOverhead.tsx b/website/src/components/marketing/diagrams/MemoryOverhead.tsx new file mode 100644 index 000000000..485342544 --- /dev/null +++ b/website/src/components/marketing/diagrams/MemoryOverhead.tsx @@ -0,0 +1,144 @@ +'use client'; + +import { motion, useReducedMotion } from 'framer-motion'; +import { useState } from 'react'; +import { VIEWPORT, Reveal } from '../motion'; +import { BenchToggle, CountUpStat, BenchInfoTooltip } from './benchUI'; +import { benchWorkloads, SANDBOX_COST_PROVIDER, BENCHMARK_DATE, type WorkloadKey } from '../../../data/bench'; + +// --------------------------------------------------------------------------- +// Memory-per-instance comparison, drawn as two side-by-side squares. A full +// reservation square (1 GiB sandbox) sits next to a smaller agentOS square whose +// AREA is proportional to the memory ratio — so the visible size gap equals the +// real reduction (131 MB -> ~13% area / 8x; 22 MB -> ~2% area / 47x). Toggling +// the workload (coding agent <-> execution) GROWS and SHRINKS the agentOS +// square; the floating MB caption rides its top edge and the headline multiplier +// re-counts. Laid out as a full-width horizontal card. Numbers from bench.ts. +// --------------------------------------------------------------------------- + +const WORKLOAD_KEYS = Object.keys(benchWorkloads) as WorkloadKey[]; + +// Ease-in-out (easeInOutCubic) so the agentOS square grows/shrinks on an S curve: +// slow start, quick middle, gentle settle. +const S_CURVE = [0.65, 0, 0.35, 1] as const; + +const Row = ({ label, value, highlight }: { label: React.ReactNode; value: string; highlight?: boolean }) => ( +
+ + {label} + + + {value} + +
+); + +export function MemoryOverhead({ workload, onWorkloadChange }: { workload: WorkloadKey; onWorkloadChange: (w: WorkloadKey) => void }) { + const reduced = useReducedMotion(); + const [inView, setInView] = useState(false); + + const mem = benchWorkloads[workload].memory; + const [mult, verb] = mem.multiplier.split(' '); // ['8x', 'smaller'] + // agentOSBar is the memory ratio as a percentage of the reservation, i.e. the + // target AREA of the inner square. Side = sqrt(area) keeps area proportional + // to memory: '35.8%' side (agent, ~13% area) | '14.5%' side (execution, ~2%). + const targetSide = `${(Math.sqrt(mem.agentOSBar / 100) * 100).toFixed(1)}%`; + const activeIdx = WORKLOAD_KEYS.indexOf(workload); + + return ( + + setInView(true)} + viewport={VIEWPORT} + > + {/* Header: eyebrow + workload toggle */} +
+ Memory Per Instance +
+ benchWorkloads[k].label)} + active={activeIdx} + onChange={(i) => onWorkloadChange(WORKLOAD_KEYS[i])} + /> +
+
+ + {/* Body: copy + ledger on the left, the squares visual on the right */} +
+
+ {/* Headline multiplier */} +
+ + + + {verb} +
+ + {/* Comparison ledger */} +
+ + agentOS + + What's measured: Memory footprint added per concurrent execution. +

+ Why the gap: In-process isolates share the host's memory. Each additional execution only adds its own heap and stack. Sandboxes allocate a dedicated environment with a minimum memory reservation, even if the code inside uses far less. +

+ Sandbox baseline: {SANDBOX_COST_PROVIDER}, the cheapest mainstream sandbox provider as of {BENCHMARK_DATE}. Default sandbox: 1 vCPU + 1 GiB RAM. +

+ agentOS: {workload === 'agent' ? `${benchWorkloads.agent.memory.agentOS} for a full Pi coding agent session with MCP servers and file system mounts.` : `${benchWorkloads.shell.memory.agentOS} for the minimal shell workload under sustained load.`} +
+ + } + value={mem.agentOS} + /> + +
+ +

Sandboxes reserve idle RAM per agent; agentOS isolates share the host.

+
+ + {/* Visual: two squares, bottom-aligned, area ∝ memory */} +
+ {/* Sandbox — full reservation square, static */} +
+
+ {mem.sandbox} +
+ Sandbox +
+ + {/* agentOS — proportional square, animated */} +
+
+ + + + + + +
+
+ +
+ agentOS +
+
+
+ + + ); +} diff --git a/website/src/components/marketing/diagrams/benchUI.tsx b/website/src/components/marketing/diagrams/benchUI.tsx new file mode 100644 index 000000000..7c693a4c1 --- /dev/null +++ b/website/src/components/marketing/diagrams/benchUI.tsx @@ -0,0 +1,151 @@ +'use client'; + +import { useId, useState, useEffect, useRef, useMemo } from 'react'; +import type { ReactNode } from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +// --------------------------------------------------------------------------- +// Shared primitives for the benchmark diagrams. Extracted from AgentOSPage so +// the cold-start / memory / execution diagram components can reuse them without +// importing from the page component. Styled for the light marketing cards. +// --------------------------------------------------------------------------- + +// A help icon with a hover tooltip. The popup is anchored to the icon itself +// (the wrapper is `relative`), so it works on any card regardless of the card's +// own positioning. It opens above the icon, left-aligned, with a mobile clamp, +// and resets inherited case/tracking from mono labels. +export function BenchInfoTooltip({ children }: { children: ReactNode }) { + return ( + + + + + + {children} + + + ); +} + +// Segmented control with a framer-motion layoutId pill. Used for the cold-start +// percentile toggle, the hardware-tier toggle, and the workload toggle. +export function BenchToggle({ options, active, onChange }: { options: string[]; active: number; onChange: (idx: number) => void }) { + const layoutId = useId(); + const columns = + options.length === 4 ? 'grid-cols-2 sm:grid-cols-4' : options.length === 3 ? 'grid-cols-3' : 'grid-cols-2'; + + return ( +
+ {options.map((label, i) => { + const isActive = i === active; + return ( + onChange(i)} + aria-pressed={isActive} + whileTap={{ scale: 0.94 }} + className={`relative flex h-7 min-w-0 items-center justify-center rounded-md px-1.5 text-center font-mono text-[10px] uppercase tracking-[0.12em] transition-colors ${ + isActive ? 'text-cream' : 'text-ink-soft hover:text-ink' + }`} + > + {isActive && ( + + )} + {label} + + ); + })} +
+ ); +} + +// Splits a stat string into a leading symbol prefix, the numeric portion, and a +// trailing unit suffix so the number can be counted up while the units stay put. +// Returns null when there is no number to animate (e.g. "Infinite"). +export function parseStatNumber(text: string) { + const match = text.match(/^([^\d-]*)(-?[\d,]*\.?\d+)(.*)$/); + if (!match) return null; + const [, prefix, rawNumber, suffix] = match; + const normalized = rawNumber.replace(/,/g, ''); + const decimals = normalized.includes('.') ? normalized.split('.')[1].length : 0; + return { + prefix, + suffix, + value: Number.parseFloat(normalized), + decimals, + grouped: rawNumber.includes(','), + }; +} + +// Counts the numeric part of a stat from 0 up to its value. The first run is +// gated on `active` (the card scrolling into view) and only fires once; later +// value changes (toggling workload or tier) re-trigger the count from the +// previous value. Honors reduced-motion by rendering the final value outright. +export function CountUpStat({ text, active }: { text: string; active: boolean }) { + const parsed = useMemo(() => parseStatNumber(text), [text]); + const reducedMotion = useReducedMotion(); + const target = parsed?.value ?? 0; + + const [display, setDisplay] = useState(0); + const startedRef = useRef(false); + const fromRef = useRef(0); + const rafRef = useRef(0); + + useEffect(() => { + if (!parsed) return; + if (reducedMotion) { + setDisplay(target); + fromRef.current = target; + startedRef.current = true; + return; + } + // Not yet scrolled into view: stay primed at zero for the first count-up. + if (!active) { + if (!startedRef.current) setDisplay(0); + return; + } + const from = startedRef.current ? fromRef.current : 0; + startedRef.current = true; + const duration = 850; + let start = 0; + const step = (now: number) => { + if (!start) start = now; + const t = Math.min(1, (now - start) / duration); + const eased = 1 - (1 - t) ** 3; + setDisplay(from + (target - from) * eased); + if (t < 1) { + rafRef.current = requestAnimationFrame(step); + } else { + fromRef.current = target; + } + }; + rafRef.current = requestAnimationFrame(step); + return () => cancelAnimationFrame(rafRef.current); + }, [parsed, target, active, reducedMotion]); + + if (!parsed) return <>{text}; + + const formatted = parsed.grouped + ? display.toLocaleString(undefined, { + minimumFractionDigits: parsed.decimals, + maximumFractionDigits: parsed.decimals, + }) + : display.toFixed(parsed.decimals); + + return ( + + {parsed.prefix} + {formatted} + {parsed.suffix} + + ); +} diff --git a/website/src/components/marketing/registry/RegistryPageClient.tsx b/website/src/components/marketing/registry/RegistryPageClient.tsx index f9fa7de58..91ea4e92b 100644 --- a/website/src/components/marketing/registry/RegistryPageClient.tsx +++ b/website/src/components/marketing/registry/RegistryPageClient.tsx @@ -28,7 +28,7 @@ const CATEGORY_ORDER: { type: string; label: string; description: string }[] = [ type: "sandbox-extension", label: "Sandbox Mounting", description: - "Agent OS is a hybrid OS. Mount sandbox file systems and interact with them via tools for heavier workloads. Use Agent OS natively for lightweight tasks.", + "agentOS is a hybrid OS. Mount sandbox file systems and interact with them via tools for heavier workloads. Use agentOS natively for lightweight tasks.", }, { type: "software", diff --git a/website/src/components/marketing/solutions/AgentOSPage.tsx b/website/src/components/marketing/solutions/AgentOSPage.tsx index 348bdfcbb..9c5645d5a 100644 --- a/website/src/components/marketing/solutions/AgentOSPage.tsx +++ b/website/src/components/marketing/solutions/AgentOSPage.tsx @@ -18,7 +18,6 @@ import { HardDrive, Code, Cpu, - Package, Users, Webhook, Workflow, @@ -38,6 +37,8 @@ import { GLOW_PILL_CLASS, handleGlowPillMouseMove } from '../glowPill'; import { registry } from '../../../data/registry'; import { HarnessArchitecture } from '../diagrams/HarnessArchitecture'; import { ColdStartRace } from '../diagrams/ColdStartRace'; +import { MemoryOverhead } from '../diagrams/MemoryOverhead'; +import { ExecutionDensity } from '../diagrams/ExecutionDensity'; interface HeroTabCode { key: string; @@ -785,16 +786,11 @@ const heroTabMeta: Array<{ key: string; icon?: typeof Bot; label: string; docsHr { key: 'permissions', icon: ShieldCheck, label: 'Permissions', docsHref: '/docs/permissions' }, ]; -const Hero = ({ heroTabs }: { heroTabs: HeroTabCode[] }) => { - const [activeTab, setActiveTab] = useState(0); +const Hero = () => { const [hoveredAgent, setHoveredAgent] = useState<{ src: string; name: string } | null>(null); const [autoPlayAgent, setAutoPlayAgent] = useState<{ src: string; name: string } | null>(null); const [autoPlayComplete, setAutoPlayComplete] = useState(false); - - const getStartedTabs = heroTabMeta.map((tab) => ({ - ...tab, - ...heroTabs.find((heroTab) => heroTab.key === tab.key), - })); + const [statsIn, setStatsIn] = useState(false); // Auto-cycle through agents starting 2.5s before stroke animation ends useEffect(() => { @@ -825,66 +821,157 @@ const Hero = ({ heroTabs }: { heroTabs: HeroTabCode[] }) => { // Displayed agent is either hovered (if autoplay complete) or autoplay agent const displayedAgent = autoPlayComplete ? hoveredAgent : autoPlayAgent; + // Highlight stats — best-case "up to" figures, sourced from bench.ts. + const heroStats = [ + { value: `${Math.round(benchColdStart[2].sandbox / benchColdStart[2].agentOS)}×`, label: 'faster cold starts', sub: 'vs. fastest sandbox', href: '#bench-cold-start' }, + { value: `${benchWorkloads.agent.memory.multiplier.split('x')[0]}×`, label: 'less memory', sub: 'per agent · vs. sandbox', href: '#bench-memory' }, + { value: `${Math.max(...Object.values(benchWorkloads).flatMap((w) => w.cost.map((t) => t.ratio)))}×`, label: 'cheaper to run', sub: 'vs. cheapest sandbox', href: '#bench-cost' }, + ]; + return (
-
- {/* Title */} +
+ {/* Top row: copy left, architecture image right */} +
+ {/* Left column */} +
+ {/* Brand mark */} + + + + + {/* Lead line (carries the hero now that the title is gone) */} + + An open-source computer for agents that you can run anywhere.{' '} + Faster, cheaper, and less memory than sandboxes. + + + {/* Supported Harnesses */} + + Works with +
+ {agents.map((agent) => ( +
autoPlayComplete && setHoveredAgent(agent)} + onMouseLeave={() => autoPlayComplete && setHoveredAgent(null)} + > + {agent.name} + {agent.name}{agent.comingSoon && '*'} +
+ ))} +
+ *Coming Soon +
+ + {/* CTAs */} + + + Get started + + + + +
+ + {/* Right column — architecture image, right-aligned */} + + + +
+ + {/* Bottom row: larger stat cards */} setStatsIn(true)} + className='mt-12 grid grid-cols-1 gap-4 sm:grid-cols-3' > -
- - Beta -
+ {heroStats.map((stat) => ( + +
+ Up to +
+
+ +
+
{stat.label}
+
{stat.sub}
+
+ ))}
+
+
+ ); +}; - {/* Subtitle */} - - A portable open-source operating system for agents. ~6 ms coldstarts, 32x cheaper than sandboxes. Powered by WebAssembly and V8 isolates. - - {/* Supported Harnesses */} +// --- Quickstart --- +const Quickstart = ({ heroTabs }: { heroTabs: HeroTabCode[] }) => { + const [activeTab, setActiveTab] = useState(0); + const getStartedTabs = heroTabMeta.map((tab) => ({ + ...tab, + ...heroTabs.find((heroTab) => heroTab.key === tab.key), + })); + + return ( +
+
- Works with -
- {agents.map((agent) => ( -
autoPlayComplete && setHoveredAgent(agent)} - onMouseLeave={() => autoPlayComplete && setHoveredAgent(null)} - > - {agent.name} - {agent.name}{agent.comingSoon && '*'} -
- ))} -
- *Coming Soon +

Up and running in seconds.

+

+ A full agent — sessions, tools, and isolated code execution — in a few lines. It's just an npm package. +

- - {/* Code snippets */} - {/* Tabs */} - - {/* Code block */}
@@ -892,7 +979,7 @@ const Hero = ({ heroTabs }: { heroTabs: HeroTabCode[] }) => {
{getStartedTabs[activeTab]?.fileName ?? 'index.ts'}
-
+
{
+ - - {/* Buttons */} - - - Read the Docs - - - -
); }; - // --- Feature Card --- const FeatureCard = ({ icon: IconComponent, @@ -1069,7 +1134,7 @@ const themedSections: ThemedSection[] = [ { icon: Terminal, title: 'Easy to deploy on prem', description: 'A single npm package. No Kubernetes operators, no sidecar containers. Just install and run.', docsHref: '/docs/deployment' }, { icon: Clock, title: 'Low overhead', description: 'No VMs to boot. No containers to pull. Start in milliseconds with minimal memory footprint.' }, { icon: FolderOpen, title: 'Mount anything as a file system', description: 'S3, GitHub, databases. No per-agent credentials needed. The host handles access scoping.', docsHref: '/docs/filesystem' }, - { icon: Shield, title: 'Extend with a sandbox when needed', description: 'Agent OS handles most tasks, but pairs seamlessly with sandboxes for heavier workloads.', docsHref: '/docs/sandbox' }, + { icon: Shield, title: 'Extend with a sandbox when needed', description: 'agentOS handles most tasks, but pairs seamlessly with sandboxes for heavier workloads.', docsHref: '/docs/sandbox' }, ], }, { @@ -1121,15 +1186,11 @@ const StackingFeatureCards = () => { return () => observer.disconnect(); }, []); - const coldStartP99 = benchColdStart[2]; // p99 - const awsArmAgentCost = benchWorkloads.agent.cost[0]; // AWS ARM - const stackFeatures = [ - { icon: Clock, title: 'Low overhead and cost.', description: 'No VMs to boot. No containers to pull. Start in milliseconds with minimal memory footprint.', detail: 'Traditional sandboxes take seconds to spin up and consume hundreds of megabytes. Agent OS starts instantly and runs lean, so you can scale to thousands of agents without the cost. More details in benchmarks below.', metrics: [{ value: `~${Math.round(coldStartP99.agentOS)}ms`, label: 'p99 coldstart' }, { value: `${awsArmAgentCost.ratio}x`, label: 'cheaper than sandboxes' }] }, { icon: Terminal, title: 'Embed in your backend.', detail: 'Your APIs. Your toolchains. No complex agent authentication needed. Just JavaScript functions or hooks.' }, - { icon: FolderOpen, title: 'Mount anything as a file system.', description: 'S3, SQLite, Google Drive, or the host file system. No per-agent credentials needed.', detail: 'Agents think in files. Agent OS lets you expose any storage backend as a familiar directory tree. The host handles credential scoping, so agents never see API keys or secrets.' }, + { icon: FolderOpen, title: 'Mount anything as a file system.', description: 'S3, SQLite, Google Drive, or the host file system. No per-agent credentials needed.', detail: 'Agents think in files. agentOS lets you expose any storage backend as a familiar directory tree. The host handles credential scoping, so agents never see API keys or secrets.' }, { icon: Shield, title: 'Granular security.', detail: 'Fully configurable network and file system security. Control rate limits, bandwidth limits, and file system permissions. Set precise CPU and memory limitations per agent.' }, - { icon: Globe, title: 'Your laptop, your infra, or on-prem.', description: 'Railway, Vercel, Kubernetes, and more. Deploy wherever your code already runs.', detail: 'Agent OS is just an npm package. No vendor lock-in, no special infrastructure. Your agents run in your stack, on your terms.', tags: ['Railway', 'Vercel', 'Kubernetes', 'ECS', 'Lambda', 'Google Cloud Run'] }, + { icon: Globe, title: 'Your laptop, your infra, or on-prem.', description: 'Rivet, Railway, Vercel, Kubernetes, and more. Deploy wherever your code already runs.', detail: 'agentOS is just an npm package. No vendor lock-in, no special infrastructure. Your agents run in your stack, on your terms.', tags: ['Rivet', 'Railway', 'Vercel', 'Kubernetes', 'ECS', 'Lambda', 'Google Cloud Run'] }, ]; return ( @@ -1471,7 +1532,7 @@ const RegistryCallout = () => ( >

- Agent OS Registry + agentOS Registry

A marketplace for agent capabilities. Browse and install pre-built tools, integrations, file systems, databases, and sandboxes — one command away. @@ -1501,7 +1562,6 @@ const AgentOSFeatures = () => (

-
); @@ -1733,15 +1793,15 @@ function BenchColdStartChart() { { label: ( <> - Agent OS + agentOS What's measured: Time from requesting an execution to first code running.

- Why the gap: Agent OS runs agents in-process — V8 isolates and Wasm inside your host. No VM to boot, no network hop, no disk image. Sandboxes must boot an entire environment, allocate memory, and establish a network connection before code can run. + Why the gap: agentOS runs agents in-process — V8 isolates and Wasm inside your host. No VM to boot, no network hop, no disk image. Sandboxes must boot an entire environment, allocate memory, and establish a network connection before code can run.

Sandbox baseline: {SANDBOX_COLDSTART_PROVIDER}, the fastest mainstream sandbox provider as of {BENCHMARK_DATE}.

- Agent OS: Median of 10,000 runs (100 iterations x 100 samples) on Intel i7-12700KF. + agentOS: Median of 10,000 runs (100 iterations x 100 samples) on Intel i7-12700KF.
), @@ -1767,7 +1827,7 @@ function BenchMemoryBar({ workload }: { workload: WorkloadKey }) { { label: ( <> - Agent OS + agentOS What's measured: Memory footprint added per concurrent execution.

@@ -1775,7 +1835,7 @@ function BenchMemoryBar({ workload }: { workload: WorkloadKey }) {

Sandbox baseline: {SANDBOX_COST_PROVIDER}, the cheapest mainstream sandbox provider as of {BENCHMARK_DATE}. Default sandbox: 1 vCPU + 1 GiB RAM.

- Agent OS: {workload === 'agent' ? `${benchWorkloads.agent.memory.agentOS} for a full Pi coding agent session with MCP servers and file system mounts.` : `${benchWorkloads.shell.memory.agentOS} for the minimal shell workload under sustained load.`} + agentOS: {workload === 'agent' ? `${benchWorkloads.agent.memory.agentOS} for a full Pi coding agent session with MCP servers and file system mounts.` : `${benchWorkloads.shell.memory.agentOS} for the minimal shell workload under sustained load.`}
), @@ -1806,7 +1866,7 @@ function BenchCostChart({ workload }: { workload: WorkloadKey }) { { label: ( <> - Agent OS + agentOS What's measured: server price per second / concurrent executions per server

@@ -1814,7 +1874,7 @@ function BenchCostChart({ workload }: { workload: WorkloadKey }) {

Sandbox baseline: {SANDBOX_COST_PROVIDER}, the cheapest mainstream sandbox provider as of {BENCHMARK_DATE}. Default sandbox: 1 vCPU + 1 GiB RAM at $0.0504/vCPU-h + $0.0162/GiB-h.

- Agent OS: {benchWorkloads[workload].memory.agentOS} baseline per execution, assuming 70% utilization (industry-standard HPA scaling threshold). Select a hardware tier above to compare. + agentOS: {benchWorkloads[workload].memory.agentOS} baseline per execution, assuming 70% utilization (industry-standard HPA scaling threshold). Select a hardware tier above to compare.
), @@ -1829,75 +1889,23 @@ function BenchCostChart({ workload }: { workload: WorkloadKey }) { } function BenchmarkSection() { - const [workload, setWorkload] = useState('agent'); - const wl = benchWorkloads[workload]; + // Each card owns its own workload toggle so they switch independently. + const [memoryWorkload, setMemoryWorkload] = useState('agent'); + const [costWorkload, setCostWorkload] = useState('agent'); return ( - -
-

- Performance benchmarks -

-

- Agent OS vs. traditional sandboxes. -

+
+
+
- -
-

- Workload:{' '} - - - {wl.description} - - -

-
- {(Object.keys(benchWorkloads) as WorkloadKey[]).map((key) => { - const isActive = workload === key; - return ( - setWorkload(key)} - aria-pressed={isActive} - whileTap={{ scale: 0.96 }} - className={`relative rounded-md px-2.5 py-1 text-xs font-medium transition-colors max-sm:flex max-sm:min-h-10 max-sm:w-full max-sm:items-center max-sm:justify-center max-sm:rounded-lg max-sm:py-2 max-sm:text-center ${ - isActive ? 'text-cream' : 'text-ink-soft hover:text-ink' - }`} - > - {isActive && ( - - )} - {benchWorkloads[key].label} - - ); - })} -
+
+
- -
- - - +
+
-

+

Measured on Intel i7-12700KF. Cold start baseline: {SANDBOX_COLDSTART_PROVIDER}, the fastest mainstream sandbox provider as of {BENCHMARK_DATE}. Cost baseline: {SANDBOX_COST_PROVIDER}, the cheapest mainstream sandbox provider as of {BENCHMARK_DATE} (1 vCPU + 1 GiB default). Cost assumes 70% utilization on self-hosted hardware vs. per-second sandbox billing.{' '}

- +
); } -const TechnologyAndBenchmarks = () => ( -
+const FoundationCard = ({ icon, title, body }: { icon: React.ReactNode; title: string; body: string }) => ( +
+
+
{icon}
+

{title}

+
+

{body}

+
+); + +const reveal = { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true }, + transition: { duration: 0.5 }, +} as const; + +// The architecture section: one narrative in three movements — the OS framing, +// the harness (structure + the isolate foundation it runs on), then the payoff +// (cold start, memory, and cost diagrams that prove the model). +const OperatingSystemArchitecture = () => ( +
- {/* Technology intro */} - + {/* 1 — Framing */} +

A new operating system architecture.

-

- Built from the ground up for lightweight agents. Agent OS provides the flexibility of Linux with lower overhead than sandboxes. +

+ agentOS gives every agent — and the code it runs — its own lightweight VM: a V8 isolate with WebAssembly, not a full sandbox, with many packed into a single process. It's a real operating system for agents: an in-process kernel hands each VM its own filesystem, processes, and network, exposes your backend functions as host tools the agent calls directly, and schedules and bounds every isolate on its own — the flexibility of Linux at a fraction of the overhead.

-
-
-
-
- WebAssembly -
-

WebAssembly + V8 Isolates

-
-

- High-performance virtualization without specialized infrastructure. The same battle-hardened isolation technology that powers Google Chrome. -

-
-
-
-
- -
-

Battle-tested technology

-
-

- You're probably using this technology right now to view this page. Bring the same power to your agents. No VMs, no containers, no overhead. -

+ + + {/* 2 — The harness (structure) + the foundation it runs on */} + +
+

+ One OS for every agent. +

+

+ The agent sits at the center. The OS brokers Tools & Resources over MCP and host tools, persists Session state, mounts a Sandbox for heavier code, and drives Orchestration — so any supported agent gets the same capabilities with no bespoke glue. +

+
+
+
- {/* Containers vs Isolate density comparison */} - -

- Booting an agent in a container takes a full process and hundreds of milliseconds. Agent OS starts one in a lightweight isolate in about {Math.round(benchColdStart[0].agentOS)} ms — and packs far more into the same memory. + {/* 3 — The payoff (proof) */} + +

+ Faster, lighter, cheaper than sandboxes. +

+

+ No VM to boot, no container to pull, no full gigabyte reserved per idle agent. agentOS cold-starts in about {Math.round(benchColdStart[0].agentOS)} ms and packs far more work into the same memory.

-
- {/* Benchmarks */} - -
-
-); - -const HarnessSection = () => ( -
-
- -

- Everything routes through the harness. -

-

- The harness is the kernel of every agent session — brokering requests and responses between your tools and MCP resources, session state, the sandbox where code runs, and the orchestration layer that ties agents together. Each piece stays isolated, yet composable. -

-
- - -
); @@ -2041,111 +2030,13 @@ const BeforeAfterSlider = ({ before, after }: { before: string; after: string }) Unix Operators
- Agent OS Operators + agentOS Operators
); }; // --- Pairs With --- -const SisterProducts = () => { - const products = [ - { - name: 'Secure Exec', - tagline: 'Secure Node.js execution without a sandbox.', - bullets: [ - 'V8 isolates with bridged Node APIs', - 'npm-compatible: fs, child_process, http', - '176x faster cold start than containers', - 'Just `npm install` — no Docker, no VMs', - ], - href: 'https://secureexec.dev/', - cta: 'secureexec.dev', - }, - { - name: 'Sandbox Agent SDK', - tagline: 'Run coding agents in sandboxes. Control them over HTTP.', - bullets: [ - 'One interface for Claude Code, Codex, OpenCode, Amp', - 'Streams events, handles permissions, manages sessions', - 'Replay, audit, and retain full transcripts', - 'Swap agents with a config change', - ], - href: 'https://sandboxagent.dev/', - cta: 'sandboxagent.dev', - }, - { - name: 'Rivet Actors', - tagline: 'Durable, stateful serverless for agents and realtime apps.', - bullets: [ - 'Long-lived, in-memory state — no external database', - 'Built-in persistence, realtime, and workflow orchestration', - 'Deploy Agent OS sessions as durable actors', - 'Geo-distributed at the edge; scale to zero', - ], - href: 'https://rivet.dev/', - cta: 'rivet.dev', - }, - ]; - - return ( -
-
-
- - Pairs with Agent OS. - - - Agent OS is where agents live. Secure Exec is how you safely run the code they generate. Sandbox Agent SDK is how you control coding agents over HTTP. Rivet Actors is how you deploy and scale them as durable, stateful services. - -
- -
- {products.map((product, idx) => ( - -

{product.name}

-

{product.tagline}

-
    - {product.bullets.map((bullet) => ( -
  • - - {bullet} -
  • - ))} -
-
- {product.cta} - -
-
- ))} -
-
-
- ); -}; const FromUnixToAgents = () => (
@@ -2197,11 +2088,11 @@ export default function AgentOSPage({ heroTabs }: AgentOSPageProps) { return (
- - - + + + + -
diff --git a/website/src/components/marketing/solutions/AgentOSPricingPage.tsx b/website/src/components/marketing/solutions/AgentOSPricingPage.tsx index 70e555566..ec18ff0f5 100644 --- a/website/src/components/marketing/solutions/AgentOSPricingPage.tsx +++ b/website/src/components/marketing/solutions/AgentOSPricingPage.tsx @@ -16,7 +16,7 @@ import { HERO_H1_CLASS, SECTION_H2_CLASS } from '../typography'; const pricingTiers = [ { name: 'Free', - description: 'Run Agent OS anywhere. Free forever.', + description: 'Run agentOS anywhere. Free forever.', price: 'Free', priceSuffix: 'Apache 2.0', icon: Server, @@ -25,7 +25,7 @@ const pricingTiers = [ copyCommand: 'npm install @agent-os/core', highlight: false, features: [ - { text: 'Full Agent OS runtime', included: true }, + { text: 'Full agentOS runtime', included: true }, { text: 'Unlimited agents', included: true }, { text: 'WebAssembly + V8 isolation', included: true }, { text: 'File system mounting (S3, local, etc.)', included: true }, @@ -150,7 +150,7 @@ const CTASection = () => (

Ready to get started?

- Deploy Agent OS today. Start with the open source version or contact us for enterprise support. + Deploy agentOS today. Start with the open source version or contact us for enterprise support.

diff --git a/website/src/components/marketing/solutions/AgentOSUseCasesPage.tsx b/website/src/components/marketing/solutions/AgentOSUseCasesPage.tsx index 97cb69141..190e562f3 100644 --- a/website/src/components/marketing/solutions/AgentOSUseCasesPage.tsx +++ b/website/src/components/marketing/solutions/AgentOSUseCasesPage.tsx @@ -188,7 +188,7 @@ export default function AgentOSUseCasesPage() { transition={{ duration: 0.5, delay: 0.05 }} className='mx-auto max-w-2xl text-lg text-ink-soft md:text-xl' > - From personal assistants to enterprise fleets, Agent OS powers every kind of AI agent. + From personal assistants to enterprise fleets, agentOS powers every kind of AI agent.
@@ -223,7 +223,7 @@ export default function AgentOSUseCasesPage() { transition={{ duration: 0.5, delay: 0.1 }} className='mb-8 text-base leading-relaxed text-ink-soft' > - Get started with Agent OS in minutes. One npm install, zero infrastructure. + Get started with agentOS in minutes. One npm install, zero infrastructure. - + diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index 883d7bb89..7bc48e535 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -174,7 +174,7 @@ const vm = await AgentOs.create({ mounts: [{ path: "/mnt/data", driver: s3 }], }); -await vm.writeFile("/mnt/data/notes.txt", "Hello from Agent OS!"); +await vm.writeFile("/mnt/data/notes.txt", "Hello from agentOS!"); const content = await vm.readFile("/mnt/data/notes.txt"); console.log(content);` }, @@ -311,7 +311,7 @@ const vm = await AgentOs.create({ }); // Write a file through the mounted sandbox filesystem -await vm.writeFile("/sandbox/hello.txt", "Hello from Agent OS!"); +await vm.writeFile("/sandbox/hello.txt", "Hello from agentOS!"); const content = await vm.readFile("/sandbox/hello.txt"); console.log(new TextDecoder().decode(content)); @@ -357,7 +357,7 @@ const heroTabs = await Promise.all( --- diff --git a/website/src/pages/pricing.astro b/website/src/pages/pricing.astro index eb698e306..faf2175de 100644 --- a/website/src/pages/pricing.astro +++ b/website/src/pages/pricing.astro @@ -8,8 +8,8 @@ import { agentOsPricingFaqs } from "../data/faqs/agent-os-pricing"; --- diff --git a/website/src/pages/registry/index.astro b/website/src/pages/registry/index.astro index 2ba32a630..55ef181f6 100644 --- a/website/src/pages/registry/index.astro +++ b/website/src/pages/registry/index.astro @@ -8,18 +8,18 @@ import { HERO_H1_CLASS } from "../../components/marketing/typography"; ---