From 557f8d25f3508a2fa15fc59bbf455984f978886e Mon Sep 17 00:00:00 2001 From: "rivet-docs-sync[bot]" Date: Tue, 18 Aug 2026 22:49:01 +0000 Subject: [PATCH] docs(actors): sync from rivet-dev/actors@1d231c1 --- .../docs/content/integrations/vercel-eve.mdx | 14 +- .../content/integrations/vercel-workflows.mdx | 170 -------------- .../content/integrations/workflow-sdk.mdx | 209 ++++++++++++++++++ vendor/actors/docs/sidebar.json | 4 +- .../actors/examples/workflow-sdk/.env.example | 5 + .../actors/examples/workflow-sdk/.gitignore | 7 + vendor/actors/examples/workflow-sdk/README.md | 47 ++++ .../examples/workflow-sdk/nitro.config.ts | 8 + .../actors/examples/workflow-sdk/package.json | 37 ++++ .../examples/workflow-sdk/src/server.ts | 16 ++ .../examples/workflow-sdk/tsconfig.json | 19 ++ .../workflow-sdk/vitest.integration.config.ts | 11 + .../examples/workflow-sdk/vitest.setup.ts | 10 + .../workflows/order.integration.test.ts | 19 ++ .../examples/workflow-sdk/workflows/order.ts | 19 ++ 15 files changed, 416 insertions(+), 179 deletions(-) delete mode 100644 vendor/actors/docs/content/integrations/vercel-workflows.mdx create mode 100644 vendor/actors/docs/content/integrations/workflow-sdk.mdx create mode 100644 vendor/actors/examples/workflow-sdk/.env.example create mode 100644 vendor/actors/examples/workflow-sdk/.gitignore create mode 100644 vendor/actors/examples/workflow-sdk/README.md create mode 100644 vendor/actors/examples/workflow-sdk/nitro.config.ts create mode 100644 vendor/actors/examples/workflow-sdk/package.json create mode 100644 vendor/actors/examples/workflow-sdk/src/server.ts create mode 100644 vendor/actors/examples/workflow-sdk/tsconfig.json create mode 100644 vendor/actors/examples/workflow-sdk/vitest.integration.config.ts create mode 100644 vendor/actors/examples/workflow-sdk/vitest.setup.ts create mode 100644 vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts create mode 100644 vendor/actors/examples/workflow-sdk/workflows/order.ts diff --git a/vendor/actors/docs/content/integrations/vercel-eve.mdx b/vendor/actors/docs/content/integrations/vercel-eve.mdx index 57d5af7..a9e58ff 100644 --- a/vendor/actors/docs/content/integrations/vercel-eve.mdx +++ b/vendor/actors/docs/content/integrations/vercel-eve.mdx @@ -38,12 +38,12 @@ cd my-agent ```sh -npm add @rivet-dev/agentos @rivet-dev/agentos-eve @rivet-dev/vercel-world +npm add @rivet-dev/agentos @rivet-dev/agentos-eve @rivet-dev/workflow-world ``` - `@rivet-dev/agentos`: Provides the agentOS VM. - `@rivet-dev/agentos-eve`: Connects Eve's sandbox API to agentOS. -- `@rivet-dev/vercel-world`: Runs Eve workflows on [Rivet World](https://workflow-sdk.dev/worlds). +- `@rivet-dev/workflow-world`: Runs Eve workflows on [Rivet World](https://workflow-sdk.dev/worlds). @@ -63,7 +63,7 @@ export default defineAgent({ "@rivet-dev/agentos-eve", "@rivet-dev/agentos-runtime-core", "@rivet-dev/agentos-sidecar", - "@rivet-dev/vercel-world", + "@rivet-dev/workflow-world", "@rivetkit/engine-cli", ], }, @@ -92,7 +92,7 @@ Add the World module import to `package.json`: Create `world.ts`: ```ts title="world.ts" -import { createWorld as createRivetWorld } from "@rivet-dev/vercel-world"; +import { createWorld as createRivetWorld } from "@rivet-dev/workflow-world"; import { registry } from "./actors"; export const createWorld = () => createRivetWorld({ registry }); @@ -109,7 +109,7 @@ Create `actors.ts`: ```ts title="actors.ts" import { agentOS, setup } from "@rivet-dev/agentos"; -import { vercelWorldActors } from "@rivet-dev/vercel-world/registry"; +import { workflowWorldActors } from "@rivet-dev/workflow-world/registry"; const vm = agentOS({ // Configuration will go here. @@ -117,7 +117,7 @@ const vm = agentOS({ export const registry = setup({ use: { - ...vercelWorldActors, + ...workflowWorldActors, vm, }, }); @@ -177,4 +177,4 @@ agentOS is a drop-in replacement for any Eve sandbox backend. Rivet World stores Eve's runs in Rivet Actors so agents resume instead of restarting. -[Read the Rivet World + Vercel Eve documentation →](/integrations/vercel-workflows) +[Read the Rivet World + Vercel Eve documentation →](/actors/integrations/workflow-sdk) diff --git a/vendor/actors/docs/content/integrations/vercel-workflows.mdx b/vendor/actors/docs/content/integrations/vercel-workflows.mdx deleted file mode 100644 index 69c8a05..0000000 --- a/vendor/actors/docs/content/integrations/vercel-workflows.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: "Vercel Workflows (Beta)" -description: "Vercel Workflows backed by Rivet Actors." -skill: false ---- - - -This integration is in beta. APIs may change between releases. - - -`@rivet-dev/vercel-world` implements the Vercel [World](https://workflow-sdk.dev/worlds) API with native Rivet Actors. - -[View the complete example →](https://github.com/rivet-dev/rivet/tree/main/examples/vercel-workflow) - -## Quickstart - - - - - -Set up a Vercel Workflows project for your framework on Node.js 22 or newer. The -[Workflows getting-started guides](https://workflow-sdk.dev/docs/getting-started) -cover Next.js, Astro, Express, Fastify, Hono, Nitro, Nuxt, SvelteKit, TanStack -Start, and Vite. - - - - - -```sh -npm install workflow @rivet-dev/vercel-world -``` - - - - - -Create `workflows/order.ts`: - - - - - - - -The World starts Rivet lazily in the Workflows process. You do not need a -second server or a framework instrumentation hook. - - - - - -Create `app/api/orders/[id]/route.ts`: - -```ts app/api/orders/[id]/route.ts -import { start } from "workflow/api"; -import { processOrder } from "@/workflows/order"; - -export async function POST( - _request: Request, - { params }: { params: Promise<{ id: string }> }, -) { - const { id } = await params; - const run = await start(processOrder, [id]); - return Response.json({ runId: run.runId }); -} -``` - - - - - -Hono has no build system of its own, so use Nitro to compile the workflow and -serve its handler in the same process. - -Create `nitro.config.ts`: - - - -Create `src/server.ts`: - - - - - - - -Create `.env` with the variables under [Configuration](#configuration), then -build and run: - -```sh -npm run build -npm run dev -``` - - - - - -Start a run: - -```sh -curl -X POST http://localhost:3000/orders/42 -``` - -Use Vercel's Workflow Vitest harness. The first World operation starts the -native Rivet registry and Engine in the test process: - -```sh -npm test -``` - - - - - -## Configuration - -Select the World and configure its Rivet connection in the application process: - - - -| Variable | Required | Purpose | -| --- | --- | --- | -| `WORKFLOW_TARGET_WORLD` | Yes | Loads `@rivet-dev/vercel-world` through Vercel Workflows | -| `WORKFLOW_RUNTIME_URL` | Yes | Externally reachable base URL of the Workflows HTTP server | -| `WORKFLOW_QUEUE_NAMESPACE` | No | Shared queue namespace used by Workflows and crash-safe initial dispatch | -| `RIVET_ENDPOINT` | Remote only | Rivet control plane endpoint | -| `RIVET_NAMESPACE` | Remote only | Namespace containing the World actors | -| `RIVET_POOL` | Remote only | Pool that hosts the native World registry | -| `RIVET_TOKEN` | Cloud only | Token sent to Rivet | -| `RIVET_WORKFLOW_SECRET` | Recommended when public | Shared bearer secret for World-to-runtime delivery | - -Local development starts the native Rivet control plane automatically. For production, -configure the remote Rivet connection. Run the combined server at -`WORKFLOW_RUNTIME_URL`; its World client and native registry use the same Rivet -endpoint, namespace, and pool. - -## HTTP routes - -Your framework integration serves the combined workflow handler at -`.well-known/workflow/v1/flow`. `WORKFLOW_RUNTIME_URL` must resolve to the -service hosting that route. Do not point it at the Rivet control plane. If -`RIVET_WORKFLOW_SECRET` is set, delivery carries that value as a bearer token and -rejects requests without it. - -## Durability - -The World stores runs, event logs, queues, streams, hook tokens, and recovery -alarms in Rivet Actors. - -Recovery is local to each run; startup does not scan all actors. Queue an initial -workflow with the default namespace or `WORKFLOW_QUEUE_NAMESPACE`. The current -Vercel Workflows does not include a per-call `start({ namespace })` value in the -`run_created` event, so that per-call override cannot be reconstructed after a -crash and is not supported by this World. - -Application code continues to use `"use workflow"`, `"use step"`, -`workflow/api`, hooks, sleeps, and streams exactly as documented by Vercel. - -## Testing - - - - - -`waitForSleep` observes the durable sleep, `wakeUp` resumes that exact -correlation, and the assertions wait for the final persisted result. - -See the [Vercel Workflows documentation](https://useworkflow.dev) for the SDK itself. diff --git a/vendor/actors/docs/content/integrations/workflow-sdk.mdx b/vendor/actors/docs/content/integrations/workflow-sdk.mdx new file mode 100644 index 0000000..22d027f --- /dev/null +++ b/vendor/actors/docs/content/integrations/workflow-sdk.mdx @@ -0,0 +1,209 @@ +--- +title: "Workflow SDK (Beta)" +description: "Vercel's Workflow SDK backed by Rivet Actors." +skill: false +--- + + +This integration is in beta. APIs may change between releases. + + +`@rivet-dev/workflow-world` implements the Workflow SDK's [World](https://workflow-sdk.dev/worlds) API with native Rivet Actors. + +[View the complete example →](https://github.com/rivet-dev/rivet/tree/main/examples/workflow-sdk) + +## Quickstart + + + + + +Set up a [Workflow SDK](https://workflow-sdk.dev) project for your framework on +Node.js 22 or newer. The +[getting-started guides](https://workflow-sdk.dev/docs/getting-started) +cover Next.js, Astro, Express, Fastify, Hono, Nitro, Nuxt, SvelteKit, TanStack +Start, and Vite. + + + + + +```sh +npm install workflow @rivet-dev/workflow-world +``` + + + + + +Create `workflows/order.ts`: + + + + + + + +The World starts Rivet lazily in the Workflow SDK process. You do not need a +second server or a framework instrumentation hook. + + + + + +Mark `rivetkit` as a server external package. RivetKit loads its runtime through +a dynamic import that a bundler cannot resolve statically, so bundling it makes +the flow route fail at request time with `Cannot find module`: + +```ts next.config.ts +import { withWorkflow } from "workflow/next"; +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + serverExternalPackages: ["rivetkit"], +}; + +export default withWorkflow(nextConfig); +``` + + +List `rivetkit` here, not `@rivet-dev/workflow-world`. The two need opposite +treatment: `withWorkflow` resolves the target World through a build alias and +compiles it into the server bundle, while `serverExternalPackages` means the +package is left to Node at runtime. Next.js rejects a package asked to do both. + + +Create `app/api/orders/[id]/route.ts`: + +```ts app/api/orders/[id]/route.ts +import { start } from "workflow/api"; +import { processOrder } from "@/workflows/order"; + +export async function POST( + _request: Request, + { params }: { params: Promise<{ id: string }> }, +) { + const { id } = await params; + const run = await start(processOrder, [id]); + return Response.json({ runId: run.runId }); +} +``` + + + + + +Hono has no build system of its own, so use Nitro to compile the workflow and +serve its handler in the same process. + +Create `nitro.config.ts`: + + + +Create `src/server.ts`: + + + + + + + +Create `.env` with the variables under [Configuration](#configuration), then +build and run: + +```sh +npm run build +npm run dev +``` + + + + + +Start a run: + +```sh +curl -X POST http://localhost:3000/orders/42 +``` + +Use the Workflow SDK's Vitest harness. The first World operation starts the +native Rivet registry and control plane in the test process: + +```sh +npm test +``` + + + + + +## Configuration + +Select the World and point it at your own HTTP server: + + + +| Variable | Required | Purpose | +| --- | --- | --- | +| `WORKFLOW_TARGET_WORLD` | Yes | Loads `@rivet-dev/workflow-world` as the World | +| `WORKFLOW_RUNTIME_URL` | Yes | Externally reachable base URL of your Workflow SDK HTTP server | +| `WORKFLOW_QUEUE_NAMESPACE` | No | Shared queue namespace used by the Workflow SDK and crash-safe initial dispatch | +| `RIVET_WORKFLOW_SECRET` | Recommended when public | Shared bearer secret for World-to-runtime delivery | + +The World does not read the Rivet connection itself. It hands configuration to +RivetKit, so the [standard RivetKit environment +variables](/actors/docs/general/environment-variables) apply unchanged. Local +development starts the control plane automatically and needs none of them; set +them to run against a remote control plane. + +Run the combined server at `WORKFLOW_RUNTIME_URL`; its World client and native +registry use the same endpoint, namespace, and pool. + +## HTTP routes + +Your framework integration serves the combined workflow handler at +`.well-known/workflow/v1/flow`. `WORKFLOW_RUNTIME_URL` must resolve to the +service hosting that route. Do not point it at the control plane. If +`RIVET_WORKFLOW_SECRET` is set, delivery carries that value as a bearer token and +rejects requests without it. + +## Deploying + +Deploy the app as a Rivet worker like any other. See [Self-Host](/actors/self-host/workers) +for the per-platform guides. Two constraints come from this World specifically: + +- **The process must be long-lived.** The first World operation opens a + persistent worker connection and waits for it. This World does not use + RivetKit's serverless request handler, so a host that only runs per-request + functions cannot serve it. +- **`WORKFLOW_RUNTIME_URL` must be reachable from your workers**, not just from + browsers. The dispatcher calls it to run every queued step. Point it at the + app's load-balanced base URL when running more than one replica, and secure the + route as described in [HTTP routes](#http-routes) once it is publicly + reachable. + +## Durability + +The World stores runs, event logs, queues, streams, hook tokens, and recovery +alarms in Rivet Actors. + +Recovery is local to each run; startup does not scan all actors. Queue an initial +workflow with the default namespace or `WORKFLOW_QUEUE_NAMESPACE`. The current +Workflow SDK does not include a per-call `start({ namespace })` value in the +`run_created` event, so that per-call override cannot be reconstructed after a +crash and is not supported by this World. + +Application code continues to use `"use workflow"`, `"use step"`, +`workflow/api`, hooks, sleeps, and streams exactly as documented by the Workflow +SDK. + +## Testing + + + + + +`waitForSleep` observes the durable sleep, `wakeUp` resumes that exact +correlation, and the assertions wait for the final persisted result. + +See the [Workflow SDK documentation](https://workflow-sdk.dev) for the SDK itself. diff --git a/vendor/actors/docs/sidebar.json b/vendor/actors/docs/sidebar.json index d3feabc..f72d3bc 100644 --- a/vendor/actors/docs/sidebar.json +++ b/vendor/actors/docs/sidebar.json @@ -428,8 +428,8 @@ "href": "/actors/integrations/vercel-eve" }, { - "title": "Vercel Workflows (Beta)", - "href": "/actors/integrations/vercel-workflows" + "title": "Workflow SDK (Beta)", + "href": "/actors/integrations/workflow-sdk" } ] } diff --git a/vendor/actors/examples/workflow-sdk/.env.example b/vendor/actors/examples/workflow-sdk/.env.example new file mode 100644 index 0000000..084e37c --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/.env.example @@ -0,0 +1,5 @@ +WORKFLOW_TARGET_WORLD=@rivet-dev/workflow-world +WORKFLOW_RUNTIME_URL=http://127.0.0.1:3000 + +# The Rivet connection uses the standard RivetKit environment variables. Local +# development needs none of them. diff --git a/vendor/actors/examples/workflow-sdk/.gitignore b/vendor/actors/examples/workflow-sdk/.gitignore new file mode 100644 index 0000000..8272c54 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/.gitignore @@ -0,0 +1,7 @@ +node_modules +.env +.output +.swc +.well-known +.workflow-data +.workflow-vitest diff --git a/vendor/actors/examples/workflow-sdk/README.md b/vendor/actors/examples/workflow-sdk/README.md new file mode 100644 index 0000000..0251ce9 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/README.md @@ -0,0 +1,47 @@ +# Workflow SDK (Beta) + +A minimal Workflow SDK app backed by Rivet Actors. + +This integration is in beta. + +## Prerequisites + +- Node.js 22 or newer +- pnpm + +## Getting Started + +```sh +cp .env.example .env +pnpm build +pnpm dev +``` + +Start an order with `curl -X POST http://localhost:3000/orders/42`. The first +World operation lazily starts Rivet in the same process and waits until it is +ready; there is no separate Rivet server command. + +Run `pnpm test` for the Workflow SDK's official `@workflow/vitest` integration test. +The World package itself runs the `@workflow/world-testing` conformance suite +against an owned Rivet Engine. + +## Features + +- Workflow World backed by Rivet Actors +- Durable steps and waits +- The Workflow SDK's supported Vitest harness + +## Implementation + +- [Workflow](https://github.com/rivet-dev/rivet/blob/main/examples/workflow-sdk/workflows/order.ts) +- [Integration test](https://github.com/rivet-dev/rivet/blob/main/examples/workflow-sdk/workflows/order.integration.test.ts) +- [HTTP server](https://github.com/rivet-dev/rivet/blob/main/examples/workflow-sdk/src/server.ts) + +## Resources + +- [Rivet Workflow SDK guide](https://rivet.dev/actors/integrations/workflow-sdk) +- [Workflow SDK](https://workflow-sdk.dev) + +## License + +MIT diff --git a/vendor/actors/examples/workflow-sdk/nitro.config.ts b/vendor/actors/examples/workflow-sdk/nitro.config.ts new file mode 100644 index 0000000..9cfa08e --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/nitro.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "nitro"; + +export default defineConfig({ + modules: ["workflow/nitro"], + routes: { + "/**": "./src/server.ts", + }, +}); diff --git a/vendor/actors/examples/workflow-sdk/package.json b/vendor/actors/examples/workflow-sdk/package.json new file mode 100644 index 0000000..9833a95 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/package.json @@ -0,0 +1,37 @@ +{ + "name": "example-workflow-sdk", + "version": "2.0.21", + "private": true, + "type": "module", + "scripts": { + "build": "nitro build", + "check-types": "tsc --noEmit", + "dev": "nitro dev", + "test": "RIVET_RUN_ENGINE_PORT=16420 RIVETKIT_STORAGE_PATH=$PWD/.workflow-data vitest --config vitest.integration.config.ts run" + }, + "dependencies": { + "@rivet-dev/workflow-world": "workspace:*", + "hono": "^4.12.25", + "nitro": "3.0.260610-beta", + "rollup": "^4.62.2", + "workflow": "5.0.0-beta.35" + }, + "devDependencies": { + "@types/node": "^24.0.0", + "@workflow/vitest": "5.0.0-beta.35", + "typescript": "^5.9.3", + "vite": "^7.0.0", + "vitest": "^4.1.9" + }, + "engines": { + "node": ">=22.0.0" + }, + "template": { + "technologies": ["typescript", "workflow-sdk"], + "tags": ["workflow", "durable"], + "noFrontend": true, + "skipVercel": true + }, + "stableVersion": "2.3.5", + "license": "MIT" +} diff --git a/vendor/actors/examples/workflow-sdk/src/server.ts b/vendor/actors/examples/workflow-sdk/src/server.ts new file mode 100644 index 0000000..1b16785 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/src/server.ts @@ -0,0 +1,16 @@ +import { Hono } from "hono"; +import { getRun, start } from "workflow/api"; + +import { processOrder } from "../workflows/order.ts"; + +const app = new Hono() + .post("/orders/:id", async (c) => { + const run = await start(processOrder, [c.req.param("id")]); + return c.json({ runId: run.runId }); + }) + .get("/orders/:runId", async (c) => { + const run = getRun(c.req.param("runId")); + return c.json({ status: await run.status }); + }); + +export default app; diff --git a/vendor/actors/examples/workflow-sdk/tsconfig.json b/vendor/actors/examples/workflow-sdk/tsconfig.json new file mode 100644 index 0000000..05029d4 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2023", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "types": ["node"] + }, + "include": [ + "src/**/*.ts", + "workflows/**/*.ts", + "nitro.config.ts", + "vitest.integration.config.ts" + ] +} diff --git a/vendor/actors/examples/workflow-sdk/vitest.integration.config.ts b/vendor/actors/examples/workflow-sdk/vitest.integration.config.ts new file mode 100644 index 0000000..a10370c --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/vitest.integration.config.ts @@ -0,0 +1,11 @@ +import { workflow } from "@workflow/vitest"; +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + plugins: [workflow()], + test: { + include: ["workflows/**/*.integration.test.ts"], + setupFiles: ["./vitest.setup.ts"], + testTimeout: 60_000, + }, +}); diff --git a/vendor/actors/examples/workflow-sdk/vitest.setup.ts b/vendor/actors/examples/workflow-sdk/vitest.setup.ts new file mode 100644 index 0000000..efd68fa --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/vitest.setup.ts @@ -0,0 +1,10 @@ +import { registry } from "@rivet-dev/workflow-world/registry"; +import { afterAll } from "vitest"; + +registry.config.shutdown = { + disableSignalHandlers: true, + gracePeriodMs: 1_000, +}; +afterAll(async () => { + await registry.shutdown(); +}); diff --git a/vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts b/vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts new file mode 100644 index 0000000..c7b6690 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts @@ -0,0 +1,19 @@ +import { waitForSleep } from "@workflow/vitest"; +import { expect, test } from "vitest"; +import { getRun, start } from "workflow/api"; + +import { processOrder } from "./order.ts"; + +test("runs the workflow end to end", async () => { + const run = await start(processOrder, ["42"]); + const sleepId = await waitForSleep(run); + + await getRun(run.runId).wakeUp({ correlationIds: [sleepId] }); + + await expect(run.returnValue).resolves.toEqual({ + id: "42", + reservationId: "reservation-42", + status: "charged", + }); + expect(await run.status).toBe("completed"); +}); diff --git a/vendor/actors/examples/workflow-sdk/workflows/order.ts b/vendor/actors/examples/workflow-sdk/workflows/order.ts new file mode 100644 index 0000000..d834452 --- /dev/null +++ b/vendor/actors/examples/workflow-sdk/workflows/order.ts @@ -0,0 +1,19 @@ +import { sleep } from "workflow"; + +export async function processOrder(id: string) { + "use workflow"; + + const reserved = await reserveInventory(id); + await sleep("1 hour"); + return chargeOrder(reserved); +} + +async function reserveInventory(id: string) { + "use step"; + return { id, reservationId: `reservation-${id}` }; +} + +async function chargeOrder(order: { id: string; reservationId: string }) { + "use step"; + return { ...order, status: "charged" as const }; +}