Skip to main content
General

Quickstart

Generate a backend, deploy it, and serve it through agentOS.

Prefer to read code? Clone the example repository. View on GitHub
Request Agent · Browser · API Your Node.js server Middleware Dynamic Apps router agentOS VM

Quickstart

Install

Use Node.js 22 or newer:

npm add @rivet-dev/dynamic-apps @hono/node-server hono
npm add --save-dev tsx
npm pkg set type=module

Set up the router

Mount the private Rivet callback separately from application traffic. The callback lets Rivet reach your server to manage deployments. Ordinary app requests are served by appsRouter through agentOS. Generated app code only exports a Fetch handler; it does not create its own listener.

import { serve } from "@hono/node-server";
import { appsRouter } from "@rivet-dev/dynamic-apps";
import { Hono } from "hono";

const server = new Hono();

// This is how the Rivet control plane communicates with your backend.
server.all("/api/rivet/*", (c) => appsRouter.fetch(c.req.raw));

// Mount every deployed application at /apps/:appId.
server.route("/apps", appsRouter);

// Serve the host router over HTTP.
serve({
	fetch: server.fetch,
	port: 3000,
});

Run the server normally:

npx tsx src/server.ts

Generate and deploy

An LLM writes the app as a set of files. Pass the skills from @rivet-dev/dynamic-apps as the system prompt so the model knows the supported project layout:

import { anthropic } from "@ai-sdk/anthropic";
import { rivetActorsSkill, webServerSkill } from "@rivet-dev/dynamic-apps";
import { generateObject } from "ai";
import { z } from "zod";

const { object } = await generateObject({
  model: anthropic("claude-sonnet-5"),
  // Skills teach the model the supported project layout.
  system: [webServerSkill, rivetActorsSkill].join("

"),
  schema: z.object({ files: z.record(z.string(), z.string()) }),
  prompt: "Build a team board.",
});

const { files } = object;

View the complete AI App Builder example.

Pass the generated files to deployApp(). This can be called by an agent, an upload endpoint, or another trusted control-plane process.

import { deployApp } from "@rivet-dev/dynamic-apps";

await deployApp({
  appId: "team-board",
  files,
});

Save this as src/deploy.ts and run it:

npx tsx src/deploy.ts

Visit the app

Open http://localhost:3000/apps/team-board/. The bare /apps/team-board path redirects to its trailing-slash form.

Deploy the host

By default, Rivet stores actor state on the local file system.

To scale Rivet in production, pick how much of it you want to run yourself:

If you are running your own workers, follow the guide for your hosting provider: