- The runtime owns durability and
- state. The harness executes AI work.
- The channel is where your agent gets
- surfaced.
+ Each capability is its own open-source SDK — workflows, AI, sandbox, connections, and
+ channels. Swap any backend and self-host the whole runtime, with zero
+ managed-infrastructure dependencies.
- );
-}
diff --git a/apps/docs/app/[lang]/(home)/components/feature-grid.tsx b/apps/docs/app/[lang]/(home)/components/feature-grid.tsx
index 4a88e4dad..d42a878cf 100644
--- a/apps/docs/app/[lang]/(home)/components/feature-grid.tsx
+++ b/apps/docs/app/[lang]/(home)/components/feature-grid.tsx
@@ -1,78 +1,73 @@
-import { Bot, Database, FlaskConical, MessageSquare, Shield, Terminal } from "lucide-react";
-import { FeatureCard } from "./feature-card";
-import { ChannelsVisual } from "./visuals/channels";
-import { DurabilityVisual } from "./visuals/durability";
-import { EvalsVisual } from "./visuals/evals";
-import { HITLVisual } from "./visuals/hitl";
-import { SandboxVisual } from "./visuals/sandbox";
-import { SubagentsVisual } from "./visuals/subagents";
+import type { JSX, ReactNode } from "react";
+import {
+ IconLogs,
+ IconMessage,
+ IconRobot,
+ IconSandbox,
+ IconUser,
+ IconWorkflow,
+} from "@/components/geistcn-icons";
-const features = [
+const FEATURES: { icon: ReactNode; label: string; description: string }[] = [
{
- title: "Durable Execution",
+ icon: ,
+ label: "Durable Execution",
description:
"Workflows survive crashes and restarts. Every step is checkpointed. Agents park when waiting, resume on the next message.",
- icon: ,
- visual: ,
- href: "/docs/concepts/sessions-runs-and-streaming",
},
{
- title: "Sandboxed Compute",
+ icon: ,
+ label: "Sandboxed Compute",
description:
- "Agents spin up isolated VMs on demand. File system access, bash execution, and code runs, all completely isolated.",
- icon: ,
- visual: ,
- href: "/docs/sandbox",
+ "Agents run code in isolated sandboxes. File system access, bash execution, and code, all fully isolated.",
},
{
- title: "Multi-Channel Delivery",
+ icon: ,
+ label: "Multi-Channel Delivery",
description: "One agent codebase deploys to web chat, Slack, API, cron, CLI, and custom apps.",
- icon: ,
- visual: ,
- href: "/docs/channels/overview",
},
{
- title: "Human-in-the-Loop",
+ icon: ,
+ label: "Human-in-the-Loop",
description:
"Tools that need confirmation trigger approval gates. Sessions park until resolved, then resume seamlessly.",
- icon: ,
- visual: ,
- href: "/docs/tools",
},
{
- title: "Subagents",
+ icon: ,
+ label: "Subagents",
description:
"Delegate specialized work to child agents with their own prompts, tools, and sandbox.",
- icon: ,
- visual: ,
- href: "/docs/subagents",
},
{
- title: "Evaluations",
+ icon: ,
+ label: "Evaluations",
description:
"Define test suites with scoring rubrics. Run evals on every deployment and on a schedule.",
- icon: ,
- visual: ,
- href: "/docs/evals/overview",
},
];
-export function FeatureGrid() {
+export function FeatureGrid(): JSX.Element {
return (
-
+
Everything you need for production agents
- Enterprise governance, observability, and sandboxed compute come standard. Focus on
- building, not infrastructure.
+ Durability, sandboxing, human-in-the-loop, and evals are built into the framework. Focus
+ on building your agent.
-
- {features.map((feature) => (
-
+
+ {FEATURES.map((feature) => (
+
+
+ {feature.icon}
+ {feature.label}
+
+
{feature.description}
+
))}
-
+
);
diff --git a/apps/docs/app/[lang]/(home)/components/file-tree-view.tsx b/apps/docs/app/[lang]/(home)/components/file-tree-view.tsx
new file mode 100644
index 000000000..9ef69ddb0
--- /dev/null
+++ b/apps/docs/app/[lang]/(home)/components/file-tree-view.tsx
@@ -0,0 +1,157 @@
+"use client";
+
+import { type ReactNode, useState } from "react";
+import { IconCheck, IconPlusCircle, IconTrash } from "@/components/geistcn-icons";
+import { cn } from "@/lib/utils";
+
+export interface FileTreeItem {
+ name: string;
+ fileName: string;
+ /** Short, what-this-file-does line shown under the code panel header. */
+ description: string;
+ /** File-type icon shown beside the file name in the code panel header. */
+ icon: ReactNode;
+ /** Pre-highlighted code, rendered on the server through the geistdocs CodeBlock. */
+ code: ReactNode;
+}
+
+export function FileTreeView({ items }: { items: FileTreeItem[] }) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ // The first file is "added" by default; every other file is optional and
+ // only counts as added once the user clicks it.
+ const [visited, setVisited] = useState>(() => new Set([0]));
+ const selected = items[selectedIndex];
+
+ function select(index: number) {
+ // Clicking the active, already-added file deselects it again. The default
+ // file (instructions.md) is always present and can't be removed.
+ if (index !== 0 && index === selectedIndex && visited.has(index)) {
+ const next = new Set(visited);
+ next.delete(index);
+ setVisited(next);
+ const remaining = [...next];
+ setSelectedIndex(remaining.length > 0 ? Math.max(...remaining) : 0);
+ return;
+ }
+ setSelectedIndex(index);
+ setVisited((prev) => new Set(prev).add(index));
+ }
+
+ function reset() {
+ setSelectedIndex(0);
+ setVisited(new Set([0]));
+ }
+
+ return (
+ // Full-width container so the header divider can bleed to the page frame's
+ // vertical borders, forming a cross with the layout grid.
+
+ {/* Grid line aligned exactly with the card header's border-b. */}
+
+
+
+
+ {/* Sidebar */}
+
+
+ agent/
+ {/* Counter slides left as the reset button reveals once more
+ than the default file is selected. */}
+
+ {/* Re-keyed per file so the code subtly flies in on selection. */}
+
+ {selected.code}
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/docs/app/[lang]/(home)/components/file-tree.tsx b/apps/docs/app/[lang]/(home)/components/file-tree.tsx
index 53b5838d9..fcfec91c5 100644
--- a/apps/docs/app/[lang]/(home)/components/file-tree.tsx
+++ b/apps/docs/app/[lang]/(home)/components/file-tree.tsx
@@ -1,443 +1,221 @@
-"use client";
-
-import type { LucideIcon } from "lucide-react";
+import { CodeBlock } from "@vercel/geistdocs/components/code-block";
+import { geistShikiTheme } from "@vercel/geistdocs/shiki-theme";
+import { highlight } from "fumadocs-core/highlight";
+import type { ComponentProps, JSX } from "react";
import {
- Bot,
- Clock,
- FileText,
- MessageSquare,
- Plug,
- Settings,
- Terminal,
- Wrench,
-} from "lucide-react";
-import { motion, useInView } from "motion/react";
-import type { ReactNode } from "react";
-import { useRef, useState } from "react";
+ IconAcronymTs,
+ IconAgents,
+ IconClock,
+ IconFileText,
+ IconLinked,
+ IconMessage,
+ type IconProps,
+ IconSandbox,
+ IconWrench,
+} from "@/components/geistcn-icons";
+import { cn } from "@/lib/utils";
+import { FileTreeView } from "./file-tree-view";
-function Kw({ children }: { children: ReactNode }) {
- return {children};
-}
-function Str({ children }: { children: ReactNode }) {
- return {children};
-}
-function Fn({ children }: { children: ReactNode }) {
- return {children};
-}
-function Ty({ children }: { children: ReactNode }) {
- return {children};
-}
-function Pl({ children, className }: { children: ReactNode; className?: string }) {
- return {children};
-}
-
-interface TreeItem {
+interface Snippet {
name: string;
fileName: string;
- icon: LucideIcon;
- color: string;
+ lang: string;
+ Icon: (props: IconProps) => JSX.Element;
description: string;
- codeHighlighted: ReactNode;
- indent: number;
+ code: string;
}
-const treeItems: TreeItem[] = [
- {
- name: "agent.ts",
- fileName: "agent.ts",
- icon: Settings,
- color: "text-purple-600",
- description: "Model and runtime configuration.",
- codeHighlighted: (
- <>
- import{"{ "}
- defineAgent
- {" }"}from{'"eve"'}
- ;
- {"\n"}
- {"\n"}
- export defaultdefineAgent
- {"({"}
- {"\n"}
- {" "}
- model
- :{'"openai/gpt-5.4-mini"'}
- ,
- {"\n"}
- {"});"}
- >
- ),
- indent: 1,
- },
+const snippets: Snippet[] = [
{
name: "instructions.md",
fileName: "instructions.md",
- icon: FileText,
- color: "text-green-600",
- description: "Always-on instructions. The agent's core identity.",
- codeHighlighted: (
- <>
- {"# Identity"}
- {"\n"}
- {"\n"}
- You are an expert weather assistant.
- {"\n"}
- You can fetch the weather for any
- {"\n"}
- city in the world.
- >
- ),
- indent: 1,
+ lang: "markdown",
+ Icon: IconFileText,
+ description:
+ "An instructions.md file is a complete agent — describe its role in Markdown, then run eve.",
+ code: `# Identity
+
+You are an expert weather assistant.
+You can fetch the weather for any
+city in the world.`,
+ },
+ {
+ name: "agent.ts",
+ fileName: "agent.ts",
+ lang: "typescript",
+ Icon: IconAcronymTs,
+ description:
+ "eve uses a default model. Add agent.ts when you want to choose a model or configure the runtime.",
+ code: `import { defineAgent } from "eve";
+
+export default defineAgent({
+ model: "openai/gpt-5.4-mini",
+});`,
},
{
name: "skills/",
fileName: "skills/research.md",
- icon: FileText,
- color: "text-amber-600",
- description: "On-demand procedures loaded only when relevant.",
- codeHighlighted: (
- <>
- {"---"}
- {"\n"}
- name
- :research
- {"\n"}
- description
- :Research unfamiliar topics
- {"\n"}
- {"---"}
- {"\n"}
- {"\n"}
- When the task is novel or ambiguous,
- {"\n"}
- gather evidence first, then answer.
- >
- ),
- indent: 1,
+ lang: "markdown",
+ Icon: IconFileText,
+ description:
+ "Skills are Markdown playbooks loaded only when relevant, so the agent gets focused guidance without carrying it in every prompt.",
+ code: `---
+name: research
+description: Research unfamiliar topics
+---
+
+When the task is novel or ambiguous,
+gather evidence first, then answer.`,
},
{
name: "tools/",
fileName: "tools/get_weather.ts",
- icon: Wrench,
- color: "text-orange-600",
- description: "Typed integrations exposed to the model. File name becomes the tool name.",
- codeHighlighted: (
- <>
- import{"{ "}
- defineTool
- {" }"}from{'"eve/tools"'}
- ;
- {"\n"}
- importzfrom{'"zod"'}
- ;
- {"\n"}
- {"\n"}
- export defaultdefineTool
- {"({"}
- {"\n"}
- {" "}
- description
- :{'"Get the weather for a city"'}
- ,
- {"\n"}
- {" "}
- inputSchema
- :z.
- object
- {"({"}
- {"\n"}
- {" "}
- cityName
- :z.
- string
- (),
- {"\n"}
- {" "}
- {"}),"}
- {"\n"}
- {" "}
- asyncexecute
- {"(input) {"}
- {"\n"}
- {" "}
- constres =awaitfetch
- (
- {"\n"}
- {" "}
- {"`${"}
- process.env.WEATHER_API_URL
- {"}/current?city=${"}
- input.cityName
- {"}`"}
- {"\n"}
- {" "}
- );
- {"\n"}
- {" "}
- constdata =awaitres.
- json
- ();
- {"\n"}
- {" "}
- returndata.current_condition[
- 0
- ];
- {"\n"}
- {" "}
- {"},"}
- {"\n"}
- {"});"}
- >
- ),
- indent: 1,
+ lang: "typescript",
+ Icon: IconWrench,
+ description:
+ "Drop a TypeScript file in tools/ and the model can call it — the filename becomes the tool name, no registration required.",
+ code: `import { defineTool } from "eve/tools";
+import z from "zod";
+
+export default defineTool({
+ description: "Get the weather for a city",
+ inputSchema: z.object({
+ cityName: z.string(),
+ }),
+ async execute(input) {
+ const res = await fetch(
+ \`\${process.env.WEATHER_API_URL}/current?city=\${input.cityName}\`
+ );
+ const data = await res.json();
+ return data.current_condition[0];
+ },
+});`,
},
{
name: "sandbox/",
fileName: "sandbox/sandbox.ts",
- icon: Terminal,
- color: "text-red-600",
- description: "Isolated compute environments with lifecycle hooks.",
- codeHighlighted: (
- <>
- import{"{ "}
- defineSandbox
- {" }"}from
- {"\n"}
- {" "}
- {'"eve/sandbox"'}
- ;
- {"\n"}
- {"\n"}
- export defaultdefineSandbox
- {"({"}
- {"\n"}
- {" "}
- asyncbootstrap
- {"({ sandbox }) {"}
- {"\n"}
- {" "}
- awaitsandbox.
- run
- (
- {"\n"}
- {" "}
- {'"git clone repo /workspace"'}
- {"\n"}
- {" "}
- );
- {"\n"}
- {" "}
- {"},"}
- {"\n"}
- {"});"}
- >
- ),
- indent: 1,
+ lang: "typescript",
+ Icon: IconSandbox,
+ description:
+ "Every agent includes an isolated sandbox. Add sandbox/sandbox.ts to swap in any backend or customize its setup.",
+ code: `import { defineSandbox } from
+ "eve/sandbox";
+
+export default defineSandbox({
+ async bootstrap({ sandbox }) {
+ await sandbox.run(
+ "git clone repo /workspace"
+ );
+ },
+});`,
},
{
name: "channels/",
fileName: "channels/slack.ts",
- icon: MessageSquare,
- color: "text-cyan-600",
- description: "HTTP, Slack, and custom delivery surfaces.",
- codeHighlighted: (
- <>
- import{"{ "}
- slackChannel
- {" }"}from
- {"\n"}
- {" "}
- {'"eve/channels/slack"'}
- ;
- {"\n"}
- {"\n"}
- export defaultslackChannel
- {"({"}
- {"\n"}
- {" "}
- botName
- :{'"my-agent"'}
- ,
- {"\n"}
- {"});"}
- >
- ),
- indent: 1,
+ lang: "typescript",
+ Icon: IconMessage,
+ description: "Add channel files to use the same agent in Slack, Discord, Teams, or the web.",
+ code: `import { slackChannel } from
+ "eve/channels/slack";
+
+export default slackChannel({
+ botName: "my-agent",
+});`,
},
{
name: "connections/",
fileName: "connections/linear.ts",
- icon: Plug,
- color: "text-pink-600",
- description: "External MCP services.",
- codeHighlighted: (
- <>
- import{"{ "}
- defineMcpClientConnection
- {" }"}
- {"\n"}
- {" "}
- from{'"eve/connections"'}
- ;
- {"\n"}
- {"\n"}
- export defaultdefineMcpClientConnection
- {"({"}
- {"\n"}
- {" "}
- url
- :{'"https://mcp.linear.app/mcp"'}
- ,
- {"\n"}
- {"});"}
- >
- ),
- indent: 1,
+ lang: "typescript",
+ Icon: IconLinked,
+ description:
+ "Connections handle auth for services like GitHub, Stripe, and Linear, so tools can call them without managing tokens.",
+ code: `import { defineMcpClientConnection }
+ from "eve/connections";
+
+export default defineMcpClientConnection({
+ url: "https://mcp.linear.app/mcp",
+});`,
},
{
name: "subagents/",
fileName: "subagents/researcher/agent.ts",
- icon: Bot,
- color: "text-indigo-600",
- description: "Specialist child agents.",
- codeHighlighted: (
- <>
- import{"{ "}
- defineAgent
- {" }"}from
- {"\n"}
- {" "}
- {'"eve"'}
- ;
- {"\n"}
- {"\n"}
- export defaultdefineAgent
- {"({"}
- {"\n"}
- {" "}
- description
- :{'"Investigate questions"'}
- ,
- {"\n"}
- {" "}
- model
- :{'"openai/gpt-5.4"'}
- ,
- {"\n"}
- {"});"}
- >
- ),
- indent: 1,
+ lang: "typescript",
+ Icon: IconAgents,
+ description:
+ "Add subagents for specialized work — the main agent delegates tasks and combines the results.",
+ code: `import { defineAgent } from
+ "eve";
+
+export default defineAgent({
+ description: "Investigate questions",
+ model: "openai/gpt-5.4",
+});`,
},
{
name: "schedules/",
fileName: "schedules/daily-report.md",
- icon: Clock,
- color: "text-emerald-600",
- description: "Recurring cron jobs.",
- codeHighlighted: (
- <>
- {"---"}
- {"\n"}
- cron
- :{'"0 8 * * *"'}
- {"\n"}
- {"---"}
- {"\n"}
- {"\n"}
- Send the user a daily weather
- {"\n"}
- digest for their saved cities.
- >
- ),
- indent: 1,
+ lang: "markdown",
+ Icon: IconClock,
+ description:
+ "Schedules run agents automatically for jobs like daily reports and weekly digests, continuing durably without an active session.",
+ code: `---
+cron: "0 8 * * *"
+---
+
+Send the user a daily weather
+digest for their saved cities.`,
},
];
-const CODE_BOX_HEIGHT = 280;
-
-export function FileTree() {
- const ref = useRef(null);
- const isInView = useInView(ref, { once: true, amount: 0.3 });
- const [selectedIndex, setSelectedIndex] = useState(0);
+export async function FileTree() {
+ const rendered = await Promise.all(
+ snippets.map((snippet) =>
+ highlight(snippet.code, {
+ lang: snippet.lang,
+ theme: geistShikiTheme,
+ components: {
+ // Render the highlighted output through the geistdocs CodeBlock so the
+ // snippets match the docs (line numbers, copy button, geist theme),
+ // with its default border/background stripped to sit flush in the panel.
+ pre: ({ children, ...props }: ComponentProps<"pre">) => (
+
+ {children}
+
+ ),
+ },
+ }),
+ ),
+ );
- const selected = treeItems[selectedIndex];
+ const items = snippets.map((snippet, i) => ({
+ name: snippet.name,
+ fileName: snippet.fileName,
+ description: snippet.description,
+ icon: ,
+ code: rendered[i],
+ }));
return (
-
+
-
+
An agent is a directory
- Define instructions and skills in markdown, tools in TypeScript, and deploy. The framework
- compiles the directory, wires up durable workflows, and connects channels.
+ Define instructions and skills in markdown, tools in TypeScript, and deploy anywhere. The
+ framework compiles the directory, wires up durable workflows, and connects channels.
+ Wrap your config with withEve() and the agent runs
+ alongside your app. useEveAgent() finds the
+ mounted routes on its own — no CORS to configure and no URL env vars to keep in sync.
+
+
+ {/* A single gradient-bordered frame around both code blocks. */}
+
+
+ {/* Re-keyed per mode so the stack cross-fades on toggle. px-5 insets the
+ grid by the gradient cards' padding so these cards line up with the
+ inner cards (AI SDK, Connection SDK, …) in the section above. */}
+