GET / → 200 · a rust runtime for sandboxed backends · pre-1.0

The backend runtime for the agent era.

Where code is safe to run before anyone reads it.

Every service in RS2 – prebuilt, custom, or composed into a pipeline – is a sandboxed function on an HTTP message. The sandbox costs under 10 µs per dispatch, so untrusted code is the default: agents can author and assemble entire backends without a human auditing the code first.

  containment bench – two tenants, one node idle · baseline traffic

tenant: evil-corp deploys hostile code

// sandboxed JS, deployed as code:attack@v1
export default async () => {
  const hog = [];
  while (true) hog.push(new Array(65536));
};
– evil-corp request log –

tenant: your-app serves real traffic next door

neighbor p99 14.0 µs
isolate wall-clock / heap kill per-tenant admission circuit breaker · 503 + Retry-After
animated replay of the measured G3 containment benchmark (tests/g_benchmarks.rs) – the numbers are real, the timeline is compressed
attackneighbor p99 baselineunder attackattacker's outcome
infinite loop14.0 µs20.8 µs (1.5×)108 requests, all structured 503
allocation bomb14.0 µs78.8 µs200 requests, all structured 503

full dispatch path – router → tenancy → token verify → access → admission → breaker → idempotency – adds p99 < 10 µs over a direct call.

GET /the-one-idea

message message

A service is a function on an HTTP message. A file store, a schema-validated database, a stored query, a multi-step pipeline, and your own sandboxed code are all the same contract – so anything composes with anything. Most building is mounting and composing functions, writing code is a fallback.

A whole application is one declarative JSON document per tenant: version-controllable, diffable, hot-swapped atomically after a dry build – invalid config never reaches the running tenant.

every primitive here exists somewhere – isolate multitenancy (Cloudflare Workers), Wasm runtimes (Spin), message pipelines (Camel, n8n), schema-driven stores. RS2 is the synthesis under one cohesive whole.

{
  "mounts": [
    { "path": "/files", "service": "file" },
    { "path": "/data",  "service": "data",
      "config": { "enforceSchema": true } },
    { "path": "/auth",  "service": "auth" }
  ]
}

a streamed file store, a validated JSON database, and login + access control – no code written.

GET /.well-known/rs2/agent-surface

One surface for humans and agents to read.MCP-aware · ?surface=mcp

Every mount auto-emits OpenAPI 3.1 and a /.well-known/rs2/ surface where the advertised schema is the enforced schema – no drift, by construction. Effect classes and Idempotency-Key guidance are published; the whole catalogue is permission-filtered per caller, so an agent's tool manifest is exactly what you granted.

The proof of the discovery system is this: RS2's own admin UI builds itself from this same surface with zero per-service code. If a generic UI can drive any mount, so can your agent.

Orders

schema-validated record store at /data/orders

  • Create order POST · validated on write
  • Charge payment keyed effect · safe to retry
  • Open orders stored query · typed params

GET /.well-known/rs2/agent-surface – filtered by the caller's permissions

PUT /services/code/my-svc

Unmodified npm SDKs, keys the agent can never read.

Custom services are JS bundles or Wasm components under capability default-deny: a grant either exists or the capability doesn't. Outbound HTTP is host-allowlisted, and a disallowed host fails before any I/O leaves the box.

Credentials are injected host-side from a grant – Bearer, HMAC, AWS SigV4 – and are absent from everything the custom code can see. An agent can use an API key it can never read.

"grants": { "fetch": {
  "type": "httpOut",
  "hosts": ["api.stripe.com"],
  "inject": "infra:stripe-key" } }

official packages, bundled with esbuild, run in the sandbox as-is – 9 of a 10-SDK corpus:

stripe ✔ unmodified
openai ✔ unmodified
@anthropic-ai/sdk ✔ unmodified
@octokit/core ✔ unmodified
@supabase/supabase-js ✔ unmodified
resend ✔ unmodified
@google/generative-ai ✔ unmodified
@mistralai/mistralai ✔ unmodified
groq-sdk ✔ unmodified
@slack/web-api ✘ needs node:os

SDK retry backoffs (429 + Retry-After) complete instantly under virtual time – no real waits in the isolate.

POST /pipelines/checkout

Pipelines enable flexible composability.

[
  "GET /data/orders/${id} :$order",
  "if ($order.status == 'open') POST /payments/charge",
  { "receipt": "$order.id", "charged": "$_ok" }
]

serial / parallel / conditional / tee modes, JSONata transforms, fan-out with limits – and idempotency, effect classes, and retry policies live in the core, not in your code. each step re-enters full dispatch: auth, limits, and logging apply to internal hops too.