ADR-0232proposed

Vercel Workflow `world-restate` Adapter

Status

proposed

Context

Vercel’s Workflow DevKit (useworkflow.dev) provides a durable workflow SDK with event-sourced runs, type-safe steps, hooks/webhooks, DurableAgent, trace viewer, and encryption. The SDK is substrate-agnostic through the World interface — implementations exist for local filesystem, Postgres, and Vercel Cloud.

joelclaw has a proven Restate + Redis + Typesense runtime (ADR-0207/0217/0230) with a custom dagOrchestrator for wave-based DAG execution. This works but lacks:

  • Event-sourced run history (we have OTEL events but not a formal event log)
  • Type-safe workflow definitions (our DAG nodes are config-driven, not code-defined)
  • DurableAgent support (for agent loops with client-side tool pausing)
  • Built-in observability (trace viewer, encryption-aware o11y)
  • A standards-based workflow model that other tools can integrate with

Building a world-restate adapter gives us Vercel’s SDK ergonomics on our proven substrate.

Decision

Core principle: Bridge, don’t replace

Implement the Vercel Workflow World interface on top of joelclaw’s existing Restate + Redis + Typesense infrastructure. Keep the custom dagOrchestrator for config-driven parallel DAG patterns. Use Workflow SDK for code-defined sequential/branching workflows and DurableAgent.

World interface mapping

World ComponentInterfacejoelclaw Implementation
Storage.runsget/listRestate virtual objects (execution state) + Typesense (queryable index)
Storage.stepsget/listRestate step memoization + OTEL events
Storage.eventscreate/listRedis streams (append-only log) + Typesense (search)
Storage.hooksget/getByToken/listRedis hash keys (token lookup) + Typesense (audit)
Queuequeue/createQueueHandlerRestate service invocations via ingress API
Streamerwrite/close/readFromStreamRedis pub/sub (real-time) + Redis streams (durability)

Package structure

packages/world-restate/
├── src/
│   ├── index.ts          # World implementation
│   ├── storage.ts        # Event log + entity materialization
│   ├── queue.ts          # World queue → Restate invocation bridge
│   ├── streamer.ts       # Dual-path streaming
│   └── types.ts          # Shared types
├── __tests__/
└── package.json          # depends on @workflow/core, @restatedev/restate-sdk, ioredis

Dual execution model

PatternEngineWhen to use
Config-driven DAG (waves, parallel, dependency graph)dagOrchestrator (existing)Complex multi-node pipelines dispatched by the workload planner
Code-defined workflow (sequential steps, sleep, hooks)Workflow SDK via world-restateType-safe agent workflows, DurableAgent loops, webhook-driven flows
One-shot inference/shelldagWorker handlers (existing)Simple single-step tasks

Implementation Plan

Phase 1: Storage adapter

  • Implement event log on Redis streams (joelclaw:workflow:events:{runId})
  • Materialize run/step/hook entities from events into Restate virtual objects
  • Index into Typesense for list/search queries
  • Pass Vercel’s E2E test suite

Phase 2: Queue adapter

  • Translate queue() calls into Restate service invocations
  • Map createQueueHandler() to Restate service handler registration
  • Preserve retry policies and idempotency

Phase 3: Streamer adapter

  • Redis pub/sub for low-latency write/read
  • Redis streams as durable backing store
  • Stream lifecycle tied to workflow run terminal states

Phase 4: Integration + DurableAgent

  • Wire world-restate into joelclaw workload system
  • Enable DurableAgent workflows (agent loops with client-side tool pausing)
  • Connect to existing pi/codex execution in the k8s agent image

Phase 5: Observability

  • Wire Workflow SDK trace events into joelclaw OTEL pipeline
  • Connect to existing Typesense otel_events collection
  • Optionally: self-host Workflow DevKit web UI for trace viewing

Consequences

Positive

  • Standards-based workflow model compatible with Vercel ecosystem
  • DurableAgent support for sophisticated agent loops
  • Event-sourced run history with formal replay capability
  • Type-safe workflow definitions instead of config-driven JSON
  • Built-in trace viewer and observability
  • Community-tested E2E test suite validates the adapter
  • Can publish as open-source world-restate package

Negative

  • Two workflow execution models to maintain (dagOrchestrator + Workflow SDK)
  • Event log adds storage requirements (Redis streams + Typesense)
  • Vercel SDK is beta (0.x) — API may change
  • Additional dependency surface (@workflow/core)

Risks

  • State consistency between Restate execution and event log materialization
  • Queue semantics mismatch between World expectations and Restate’s deterministic execution
  • Vercel SDK may evolve in directions incompatible with self-hosted patterns
  • Workflow SDK’s sequential step model may not map well to our wave-based parallelism

Research Source

This ADR was researched through the joelclaw Restate DAG pipeline (dogfood):

  • 3-stage chained workflow: analyze-world-interface → map-dagworker → draft-adr
  • Executed via dagOrchestrator with infer handler (pi → Claude Sonnet)
  • Total pipeline time: ~46s
  • Full research outputs preserved in session transcript

References