Networking & Previews
Proxy HTTP traffic into agentOS VMs, configure network access, and create shareable preview URLs for services started by coding agents.
Proxy buffered HTTP requests into VM services with httpRequest and create time-limited, actor-only preview URLs (with configurable expiration, revocation, and CORS), all carried over one transport (the kernel socket table) that is loopback-only by default under a three-layer confinement model.
Run an HTTP server in the VM
Guest code runs a normal Node HTTP server: it binds a loopback port inside the VM exactly like any Node process. Write the server file and spawn it.
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
const agent = client.vm.getOrCreate("my-agent");
// Write a simple Node HTTP server and run it inside the VM. It binds a loopback
// port (3000) exactly like any normal Node process.
await agent.filesystem.writeFile(
"/home/agentos/server.js",
`const http = require("http");
http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from inside the VM");
}).listen(3000, () => console.log("listening on http://127.0.0.1:3000"));`,
);
const { pid } = await agent.process.spawn("node", ["/home/agentos/server.js"]);
console.log("server pid:", pid);
import { agentOS, setup } from "@rivet-dev/agentos";
const vm = agentOS({ software: [] });
export const registry = setup({ use: { vm } });
registry.start();
Fetch from a VM service
With the HTTP server running in the VM (above), send requests to it with httpRequest, including custom methods, headers, and body.
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
const agent = client.vm.getOrCreate("my-agent");
// Fetch from the VM service started above.
const response = await agent.network.httpRequest({ port: 3000, path: "/" });
console.log("Status:", response.status);
console.log("Body:", new TextDecoder().decode(response.body));
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
const response = await client.vm.getOrCreate("my-agent").network.httpRequest({
port: 3000,
path: "/api/data",
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key: "value" }),
});
console.log("Status:", response.status, response.statusText);
console.log("Headers:", response.headers);
console.log("Body:", new TextDecoder().decode(response.body));
import { agentOS, setup } from "@rivet-dev/agentos";
const vm = agentOS({ software: [] });
export const registry = setup({ use: { vm } });
registry.start();
Preview URLs
Preview URLs are port forwarding for VM services: a time-limited, public URL that proxies HTTP to a port inside the VM, for browser or external access (use httpRequest for server-to-server). Preview creation is intentionally actor-only through the native createPreviewUrl and expirePreviewUrl actions; tokens survive sleep/wake and CORS is enabled. See Security for details.
Create a preview URL
Token lifetimes are configured under the preview key:
import { agentOS, setup } from "@rivet-dev/agentos";
const vm = agentOS({
software: [],
preview: {
defaultExpiresInSeconds: 3600, // 1 hour default
maxExpiresInSeconds: 86400, // 24 hour maximum
},
});
export const registry = setup({ use: { vm } });
registry.start();
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
const agent = client.vm.getOrCreate("my-agent");
// Start a web app in the VM
await agent.process.spawn("node", ["/home/agentos/app.js"]);
// Create a preview URL for port 3000, valid for 1 hour
const preview = await agent.createPreviewUrl(3000, 3600);
console.log("Preview path:", preview.path);
console.log("Token:", preview.token);
console.log("Expires at:", new Date(preview.expiresAt));
// Create a preview URL with a shorter expiration
const shortPreview = await agent.createPreviewUrl(3000, 300); // 5 minutes
console.log("Short-lived preview:", shortPreview.path);
Revoke a preview URL
Mint short-lived preview tokens so access expires automatically; the lifetime is capped by preview.maxExpiresInSeconds.
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
// Mint a short-lived preview token so access expires automatically.
const agent = client.vm.getOrCreate("my-agent");
const preview = await agent.createPreviewUrl(3000, 300); // 5 minutes
console.log("Preview path:", preview.path);
console.log("Expires at:", new Date(preview.expiresAt));
import { agentOS, setup } from "@rivet-dev/agentos";
const vm = agentOS({ software: [] });
export const registry = setup({ use: { vm } });
registry.start();
Permissions
Network access is governed by the VM permission policy. By default the guest cannot reach the network; grant it, or allow only specific destinations:
const vm = agentOS({
permissions: {
network: {
default: "deny",
rules: [{ mode: "allow", operations: ["*"], patterns: ["api.example.com"] }],
},
},
});
See Permissions for the full configuration.